futurize stage1 vui
This commit is contained in:
parent
89b4eb5e15
commit
00db0fd0ad
561
joy/vui/core.py
561
joy/vui/core.py
|
|
@ -1,280 +1,281 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright © 2019 Simon Forman
|
# Copyright © 2019 Simon Forman
|
||||||
#
|
#
|
||||||
# This file is part of Thun
|
# This file is part of Thun
|
||||||
#
|
#
|
||||||
# Thun is free software: you can redistribute it and/or modify
|
# Thun is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# Thun is distributed in the hope that it will be useful,
|
# Thun is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Thun. If not see <http://www.gnu.org/licenses/>.
|
# along with Thun. If not see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
'''
|
'''
|
||||||
|
|
||||||
Core
|
Core
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
The core module defines a bunch of system-wide "constants" (some colors
|
The core module defines a bunch of system-wide "constants" (some colors
|
||||||
and PyGame event groups), the message classes for Oberon-style message
|
and PyGame event groups), the message classes for Oberon-style message
|
||||||
passing, a "world" class that holds the main context for the system, and
|
passing, a "world" class that holds the main context for the system, and
|
||||||
a mainloop class that manages the, uh, main loop (the PyGame event queue.)
|
a mainloop class that manages the, uh, main loop (the PyGame event queue.)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
from sys import stderr
|
from __future__ import print_function
|
||||||
from traceback import format_exc
|
from sys import stderr
|
||||||
import pygame
|
from traceback import format_exc
|
||||||
from joy.joy import run
|
import pygame
|
||||||
from joy.utils.stack import stack_to_string
|
from joy.joy import run
|
||||||
|
from joy.utils.stack import stack_to_string
|
||||||
|
|
||||||
COMMITTER = 'Joy <auto-commit@example.com>'
|
|
||||||
|
COMMITTER = 'Joy <auto-commit@example.com>'
|
||||||
|
|
||||||
BLACK = FOREGROUND = 0, 0, 0
|
|
||||||
GREY = 127, 127, 127
|
BLACK = FOREGROUND = 0, 0, 0
|
||||||
WHITE = BACKGROUND = 255, 255, 255
|
GREY = 127, 127, 127
|
||||||
BLUE = 100, 100, 255
|
WHITE = BACKGROUND = 255, 255, 255
|
||||||
GREEN = 70, 200, 70
|
BLUE = 100, 100, 255
|
||||||
|
GREEN = 70, 200, 70
|
||||||
|
|
||||||
MOUSE_EVENTS = frozenset({
|
|
||||||
pygame.MOUSEMOTION,
|
MOUSE_EVENTS = frozenset({
|
||||||
pygame.MOUSEBUTTONDOWN,
|
pygame.MOUSEMOTION,
|
||||||
pygame.MOUSEBUTTONUP
|
pygame.MOUSEBUTTONDOWN,
|
||||||
})
|
pygame.MOUSEBUTTONUP
|
||||||
'PyGame mouse events.'
|
})
|
||||||
|
'PyGame mouse events.'
|
||||||
ARROW_KEYS = frozenset({
|
|
||||||
pygame.K_UP,
|
ARROW_KEYS = frozenset({
|
||||||
pygame.K_DOWN,
|
pygame.K_UP,
|
||||||
pygame.K_LEFT,
|
pygame.K_DOWN,
|
||||||
pygame.K_RIGHT
|
pygame.K_LEFT,
|
||||||
})
|
pygame.K_RIGHT
|
||||||
'PyGame arrow key events.'
|
})
|
||||||
|
'PyGame arrow key events.'
|
||||||
|
|
||||||
TASK_EVENTS = tuple(range(pygame.USEREVENT, pygame.NUMEVENTS))
|
|
||||||
'Keep track of all possible task events.'
|
TASK_EVENTS = tuple(range(pygame.USEREVENT, pygame.NUMEVENTS))
|
||||||
|
'Keep track of all possible task events.'
|
||||||
AVAILABLE_TASK_EVENTS = set(TASK_EVENTS)
|
|
||||||
'Task IDs that have not been assigned to a task.'
|
AVAILABLE_TASK_EVENTS = set(TASK_EVENTS)
|
||||||
|
'Task IDs that have not been assigned to a task.'
|
||||||
ALLOWED_EVENTS = [pygame.QUIT, pygame.KEYUP, pygame.KEYDOWN]
|
|
||||||
ALLOWED_EVENTS.extend(MOUSE_EVENTS)
|
ALLOWED_EVENTS = [pygame.QUIT, pygame.KEYUP, pygame.KEYDOWN]
|
||||||
ALLOWED_EVENTS.extend(TASK_EVENTS)
|
ALLOWED_EVENTS.extend(MOUSE_EVENTS)
|
||||||
'Event "mask" for PyGame event queue, we are only interested in these event types.'
|
ALLOWED_EVENTS.extend(TASK_EVENTS)
|
||||||
|
'Event "mask" for PyGame event queue, we are only interested in these event types.'
|
||||||
|
|
||||||
ERROR = -1
|
|
||||||
PENDING = 0
|
ERROR = -1
|
||||||
SUCCESS = 1
|
PENDING = 0
|
||||||
# 'Message status codes... dunno if this is a good idea or not...
|
SUCCESS = 1
|
||||||
|
# 'Message status codes... dunno if this is a good idea or not...
|
||||||
|
|
||||||
class Message(object):
|
|
||||||
'''Message base class. Contains ``sender`` field.'''
|
class Message(object):
|
||||||
def __init__(self, sender):
|
'''Message base class. Contains ``sender`` field.'''
|
||||||
self.sender = sender
|
def __init__(self, sender):
|
||||||
|
self.sender = sender
|
||||||
|
|
||||||
class CommandMessage(Message):
|
|
||||||
'''For commands, adds ``command`` field.'''
|
class CommandMessage(Message):
|
||||||
def __init__(self, sender, command):
|
'''For commands, adds ``command`` field.'''
|
||||||
Message.__init__(self, sender)
|
def __init__(self, sender, command):
|
||||||
self.command = command
|
Message.__init__(self, sender)
|
||||||
|
self.command = command
|
||||||
|
|
||||||
class ModifyMessage(Message):
|
|
||||||
'''
|
class ModifyMessage(Message):
|
||||||
For when resources are modified, adds ``subject`` and ``details``
|
'''
|
||||||
fields.
|
For when resources are modified, adds ``subject`` and ``details``
|
||||||
'''
|
fields.
|
||||||
def __init__(self, sender, subject, **details):
|
'''
|
||||||
Message.__init__(self, sender)
|
def __init__(self, sender, subject, **details):
|
||||||
self.subject = subject
|
Message.__init__(self, sender)
|
||||||
self.details = details
|
self.subject = subject
|
||||||
|
self.details = details
|
||||||
|
|
||||||
class OpenMessage(Message):
|
|
||||||
'''
|
class OpenMessage(Message):
|
||||||
For when resources are modified, adds ``name``, content_id``,
|
'''
|
||||||
``status``, and ``traceback`` fields.
|
For when resources are modified, adds ``name``, content_id``,
|
||||||
'''
|
``status``, and ``traceback`` fields.
|
||||||
def __init__(self, sender, name):
|
'''
|
||||||
Message.__init__(self, sender)
|
def __init__(self, sender, name):
|
||||||
self.name = name
|
Message.__init__(self, sender)
|
||||||
self.content_id = self.thing = None
|
self.name = name
|
||||||
self.status = PENDING
|
self.content_id = self.thing = None
|
||||||
self.traceback = None
|
self.status = PENDING
|
||||||
|
self.traceback = None
|
||||||
|
|
||||||
class PersistMessage(Message):
|
|
||||||
'''
|
class PersistMessage(Message):
|
||||||
For when resources are modified, adds ``content_id`` and ``details``
|
'''
|
||||||
fields.
|
For when resources are modified, adds ``content_id`` and ``details``
|
||||||
'''
|
fields.
|
||||||
def __init__(self, sender, content_id, **details):
|
'''
|
||||||
Message.__init__(self, sender)
|
def __init__(self, sender, content_id, **details):
|
||||||
self.content_id = content_id
|
Message.__init__(self, sender)
|
||||||
self.details = details
|
self.content_id = content_id
|
||||||
|
self.details = details
|
||||||
|
|
||||||
class ShutdownMessage(Message):
|
|
||||||
'''Signals that the system is shutting down.'''
|
class ShutdownMessage(Message):
|
||||||
|
'''Signals that the system is shutting down.'''
|
||||||
|
|
||||||
# Joy Interpreter & Context
|
|
||||||
|
# Joy Interpreter & Context
|
||||||
|
|
||||||
class World(object):
|
|
||||||
'''
|
class World(object):
|
||||||
This object contains the system context, the stack, dictionary, a
|
'''
|
||||||
reference to the display broadcast method, and the log.
|
This object contains the system context, the stack, dictionary, a
|
||||||
'''
|
reference to the display broadcast method, and the log.
|
||||||
|
'''
|
||||||
def __init__(self, stack_id, stack_holder, dictionary, notify, log):
|
|
||||||
self.stack_holder = stack_holder
|
def __init__(self, stack_id, stack_holder, dictionary, notify, log):
|
||||||
self.dictionary = dictionary
|
self.stack_holder = stack_holder
|
||||||
self.notify = notify
|
self.dictionary = dictionary
|
||||||
self.stack_id = stack_id
|
self.notify = notify
|
||||||
self.log = log.lines
|
self.stack_id = stack_id
|
||||||
self.log_id = log.content_id
|
self.log = log.lines
|
||||||
|
self.log_id = log.content_id
|
||||||
def handle(self, message):
|
|
||||||
'''
|
def handle(self, message):
|
||||||
Deal with updates to the stack and commands.
|
'''
|
||||||
'''
|
Deal with updates to the stack and commands.
|
||||||
if (isinstance(message, ModifyMessage)
|
'''
|
||||||
and message.subject is self.stack_holder
|
if (isinstance(message, ModifyMessage)
|
||||||
):
|
and message.subject is self.stack_holder
|
||||||
self._log_lines('', '%s <-' % self.format_stack())
|
):
|
||||||
if not isinstance(message, CommandMessage):
|
self._log_lines('', '%s <-' % self.format_stack())
|
||||||
return
|
if not isinstance(message, CommandMessage):
|
||||||
c, s, d = message.command, self.stack_holder[0], self.dictionary
|
return
|
||||||
self._log_lines('', '-> %s' % (c,))
|
c, s, d = message.command, self.stack_holder[0], self.dictionary
|
||||||
self.stack_holder[0], _, self.dictionary = run(c, s, d)
|
self._log_lines('', '-> %s' % (c,))
|
||||||
mm = ModifyMessage(self, self.stack_holder, content_id=self.stack_id)
|
self.stack_holder[0], _, self.dictionary = run(c, s, d)
|
||||||
self.notify(mm)
|
mm = ModifyMessage(self, self.stack_holder, content_id=self.stack_id)
|
||||||
|
self.notify(mm)
|
||||||
def _log_lines(self, *lines):
|
|
||||||
self.log.extend(lines)
|
def _log_lines(self, *lines):
|
||||||
self.notify(ModifyMessage(self, self.log, content_id=self.log_id))
|
self.log.extend(lines)
|
||||||
|
self.notify(ModifyMessage(self, self.log, content_id=self.log_id))
|
||||||
def format_stack(self):
|
|
||||||
try:
|
def format_stack(self):
|
||||||
return stack_to_string(self.stack_holder[0])
|
try:
|
||||||
except:
|
return stack_to_string(self.stack_holder[0])
|
||||||
print >> stderr, format_exc()
|
except:
|
||||||
return str(self.stack_holder[0])
|
print(format_exc(), file=stderr)
|
||||||
|
return str(self.stack_holder[0])
|
||||||
|
|
||||||
def push(sender, item, notify, stack_name='stack.pickle'):
|
|
||||||
'''
|
def push(sender, item, notify, stack_name='stack.pickle'):
|
||||||
Helper function to push an item onto the system stack with message.
|
'''
|
||||||
'''
|
Helper function to push an item onto the system stack with message.
|
||||||
om = OpenMessage(sender, stack_name)
|
'''
|
||||||
notify(om)
|
om = OpenMessage(sender, stack_name)
|
||||||
if om.status == SUCCESS:
|
notify(om)
|
||||||
om.thing[0] = item, om.thing[0]
|
if om.status == SUCCESS:
|
||||||
notify(ModifyMessage(sender, om.thing, content_id=om.content_id))
|
om.thing[0] = item, om.thing[0]
|
||||||
return om.status
|
notify(ModifyMessage(sender, om.thing, content_id=om.content_id))
|
||||||
|
return om.status
|
||||||
|
|
||||||
def open_viewer_on_string(sender, content, notify):
|
|
||||||
'''
|
def open_viewer_on_string(sender, content, notify):
|
||||||
Helper function to open a text viewer on a string.
|
'''
|
||||||
Typically used to show tracebacks.
|
Helper function to open a text viewer on a string.
|
||||||
'''
|
Typically used to show tracebacks.
|
||||||
push(sender, content, notify)
|
'''
|
||||||
notify(CommandMessage(sender, 'good_viewer_location open_viewer'))
|
push(sender, content, notify)
|
||||||
|
notify(CommandMessage(sender, 'good_viewer_location open_viewer'))
|
||||||
|
|
||||||
# main loop
|
|
||||||
|
# main loop
|
||||||
|
|
||||||
class TheLoop(object):
|
|
||||||
'''
|
class TheLoop(object):
|
||||||
The main loop manages tasks and the PyGame event queue
|
'''
|
||||||
and framerate clock.
|
The main loop manages tasks and the PyGame event queue
|
||||||
'''
|
and framerate clock.
|
||||||
|
'''
|
||||||
FRAME_RATE = 24
|
|
||||||
|
FRAME_RATE = 24
|
||||||
def __init__(self, display, clock):
|
|
||||||
self.display = display
|
def __init__(self, display, clock):
|
||||||
self.clock = clock
|
self.display = display
|
||||||
self.tasks = {}
|
self.clock = clock
|
||||||
self.running = False
|
self.tasks = {}
|
||||||
|
self.running = False
|
||||||
def install_task(self, F, milliseconds):
|
|
||||||
'''
|
def install_task(self, F, milliseconds):
|
||||||
Install a task to run every so many milliseconds.
|
'''
|
||||||
'''
|
Install a task to run every so many milliseconds.
|
||||||
try:
|
'''
|
||||||
task_event_id = AVAILABLE_TASK_EVENTS.pop()
|
try:
|
||||||
except KeyError:
|
task_event_id = AVAILABLE_TASK_EVENTS.pop()
|
||||||
raise RuntimeError('out of task ids')
|
except KeyError:
|
||||||
self.tasks[task_event_id] = F
|
raise RuntimeError('out of task ids')
|
||||||
pygame.time.set_timer(task_event_id, milliseconds)
|
self.tasks[task_event_id] = F
|
||||||
return task_event_id
|
pygame.time.set_timer(task_event_id, milliseconds)
|
||||||
|
return task_event_id
|
||||||
def remove_task(self, task_event_id):
|
|
||||||
'''
|
def remove_task(self, task_event_id):
|
||||||
Remove an installed task.
|
'''
|
||||||
'''
|
Remove an installed task.
|
||||||
assert task_event_id in self.tasks, repr(task_event_id)
|
'''
|
||||||
pygame.time.set_timer(task_event_id, 0)
|
assert task_event_id in self.tasks, repr(task_event_id)
|
||||||
del self.tasks[task_event_id]
|
pygame.time.set_timer(task_event_id, 0)
|
||||||
AVAILABLE_TASK_EVENTS.add(task_event_id)
|
del self.tasks[task_event_id]
|
||||||
|
AVAILABLE_TASK_EVENTS.add(task_event_id)
|
||||||
def __del__(self):
|
|
||||||
# Best effort to cancel all running tasks.
|
def __del__(self):
|
||||||
for task_event_id in self.tasks:
|
# Best effort to cancel all running tasks.
|
||||||
pygame.time.set_timer(task_event_id, 0)
|
for task_event_id in self.tasks:
|
||||||
|
pygame.time.set_timer(task_event_id, 0)
|
||||||
def run_task(self, task_event_id):
|
|
||||||
'''
|
def run_task(self, task_event_id):
|
||||||
Give a task its time to shine.
|
'''
|
||||||
'''
|
Give a task its time to shine.
|
||||||
task = self.tasks[task_event_id]
|
'''
|
||||||
try:
|
task = self.tasks[task_event_id]
|
||||||
task()
|
try:
|
||||||
except:
|
task()
|
||||||
traceback = format_exc()
|
except:
|
||||||
self.remove_task(task_event_id)
|
traceback = format_exc()
|
||||||
print >> stderr, traceback
|
self.remove_task(task_event_id)
|
||||||
print >> stderr, 'TASK removed due to ERROR', task
|
print(traceback, file=stderr)
|
||||||
open_viewer_on_string(self, traceback, self.display.broadcast)
|
print('TASK removed due to ERROR', task, file=stderr)
|
||||||
|
open_viewer_on_string(self, traceback, self.display.broadcast)
|
||||||
def loop(self):
|
|
||||||
'''
|
def loop(self):
|
||||||
The actual main loop machinery.
|
'''
|
||||||
|
The actual main loop machinery.
|
||||||
Maintain a ``running`` flag, pump the PyGame event queue and
|
|
||||||
handle the events (dispatching to the display), tick the clock.
|
Maintain a ``running`` flag, pump the PyGame event queue and
|
||||||
|
handle the events (dispatching to the display), tick the clock.
|
||||||
When the loop is exited (by clicking the window close button or
|
|
||||||
pressing the ``escape`` key) it broadcasts a ``ShutdownMessage``.
|
When the loop is exited (by clicking the window close button or
|
||||||
'''
|
pressing the ``escape`` key) it broadcasts a ``ShutdownMessage``.
|
||||||
self.running = True
|
'''
|
||||||
while self.running:
|
self.running = True
|
||||||
for event in pygame.event.get():
|
while self.running:
|
||||||
if event.type == pygame.QUIT:
|
for event in pygame.event.get():
|
||||||
self.running = False
|
if event.type == pygame.QUIT:
|
||||||
elif event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:
|
self.running = False
|
||||||
self.running = False
|
elif event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:
|
||||||
elif event.type in self.tasks:
|
self.running = False
|
||||||
self.run_task(event.type)
|
elif event.type in self.tasks:
|
||||||
else:
|
self.run_task(event.type)
|
||||||
self.display.dispatch_event(event)
|
else:
|
||||||
pygame.display.update()
|
self.display.dispatch_event(event)
|
||||||
self.clock.tick(self.FRAME_RATE)
|
pygame.display.update()
|
||||||
self.display.broadcast(ShutdownMessage(self))
|
self.clock.tick(self.FRAME_RATE)
|
||||||
|
self.display.broadcast(ShutdownMessage(self))
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,19 @@
|
||||||
import sys, traceback
|
from __future__ import absolute_import
|
||||||
|
import sys, traceback
|
||||||
# To enable "hot" reloading in the IDLE shell.
|
|
||||||
for name in 'core main display viewer text_viewer stack_viewer persist_task'.split():
|
# To enable "hot" reloading in the IDLE shell.
|
||||||
try:
|
for name in 'core main display viewer text_viewer stack_viewer persist_task'.split():
|
||||||
del sys.modules[name]
|
try:
|
||||||
except KeyError:
|
del sys.modules[name]
|
||||||
pass
|
except KeyError:
|
||||||
|
pass
|
||||||
import main
|
|
||||||
|
from . import main
|
||||||
try:
|
|
||||||
A = A # (screen, clock, pt), three things that we DON'T want to recreate
|
try:
|
||||||
# each time we restart main().
|
A = A # (screen, clock, pt), three things that we DON'T want to recreate
|
||||||
except NameError:
|
# each time we restart main().
|
||||||
A = main.init()
|
except NameError:
|
||||||
|
A = main.init()
|
||||||
d = main.main(*A)
|
|
||||||
|
d = main.main(*A)
|
||||||
|
|
|
||||||
1009
joy/vui/display.py
1009
joy/vui/display.py
File diff suppressed because it is too large
Load Diff
|
|
@ -1,186 +1,187 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright © 2019 Simon Forman
|
# Copyright © 2019 Simon Forman
|
||||||
#
|
#
|
||||||
# This file is part of Thun
|
# This file is part of Thun
|
||||||
#
|
#
|
||||||
# Thun is free software: you can redistribute it and/or modify
|
# Thun is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# Thun is distributed in the hope that it will be useful,
|
# Thun is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Thun. If not see <http://www.gnu.org/licenses/>.
|
# along with Thun. If not see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
from StringIO import StringIO
|
from __future__ import print_function
|
||||||
import base64, zlib
|
from StringIO import StringIO
|
||||||
|
import base64, zlib
|
||||||
|
|
||||||
def create(fn='Iosevka12.BMP'):
|
|
||||||
with open(fn, 'rb') as f:
|
def create(fn='Iosevka12.BMP'):
|
||||||
data = f.read()
|
with open(fn, 'rb') as f:
|
||||||
return base64.encodestring(zlib.compress(data))
|
data = f.read()
|
||||||
|
return base64.encodestring(zlib.compress(data))
|
||||||
|
|
||||||
data = StringIO(zlib.decompress(base64.decodestring('''\
|
|
||||||
eJztnWdwVceSx/1qt7Zq98N+2dqqrbLJSWQJESQQIHLOiAwGk3MOItjknDOYZEBkm5yDQWCTbIKw
|
data = StringIO(zlib.decompress(base64.decodestring('''\
|
||||||
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
|
||||||
lnalXc/9SsNb2vUirzS8pV0v8gJv/w/2vRht''')))
|
rKkAuQAzdoDo66n1ePjlv8uVhrenlly3fgPZDd7Be/XtqfLE1GsYECfIQEijwZVHPR5++e9y/X3x
|
||||||
|
lnalXc/9SsNb2vUirzS8pV0v8gJv/w/2vRht''')))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
print create()
|
if __name__ == '__main__':
|
||||||
|
print(create())
|
||||||
|
|
|
||||||
|
|
@ -1,275 +1,276 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright © 2019 Simon Forman
|
# Copyright © 2019 Simon Forman
|
||||||
#
|
#
|
||||||
# This file is part of Thun
|
# This file is part of Thun
|
||||||
#
|
#
|
||||||
# Thun is free software: you can redistribute it and/or modify
|
# Thun is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# Thun is distributed in the hope that it will be useful,
|
# Thun is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Thun. If not see <http://www.gnu.org/licenses/>.
|
# along with Thun. If not see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
'''
|
'''
|
||||||
Utility module to help with setting up the initial contents of the
|
Utility module to help with setting up the initial contents of the
|
||||||
JOY_HOME directory.
|
JOY_HOME directory.
|
||||||
|
|
||||||
These contents are kept in this Python module as a base64-encoded zip
|
These contents are kept in this Python module as a base64-encoded zip
|
||||||
file, so you can just do, e.g.:
|
file, so you can just do, e.g.:
|
||||||
|
|
||||||
import init_joy_home
|
import init_joy_home
|
||||||
init_joy_home.initialize(JOY_HOME)
|
init_joy_home.initialize(JOY_HOME)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
import base64, os, StringIO, zipfile
|
from __future__ import print_function
|
||||||
|
import base64, os, StringIO, zipfile
|
||||||
|
|
||||||
def initialize(joy_home):
|
|
||||||
Z.extractall(joy_home)
|
def initialize(joy_home):
|
||||||
|
Z.extractall(joy_home)
|
||||||
|
|
||||||
def create_data(from_dir='./default_joy_home'):
|
|
||||||
f = StringIO.StringIO()
|
def create_data(from_dir='./default_joy_home'):
|
||||||
z = zipfile.ZipFile(f, mode='w')
|
f = StringIO.StringIO()
|
||||||
for fn in os.listdir(from_dir):
|
z = zipfile.ZipFile(f, mode='w')
|
||||||
from_fn = os.path.join(from_dir, fn)
|
for fn in os.listdir(from_dir):
|
||||||
z.write(from_fn, fn)
|
from_fn = os.path.join(from_dir, fn)
|
||||||
z.close()
|
z.write(from_fn, fn)
|
||||||
return base64.encodestring(f.getvalue())
|
z.close()
|
||||||
|
return base64.encodestring(f.getvalue())
|
||||||
|
|
||||||
Z = zipfile.ZipFile(StringIO.StringIO(base64.decodestring('''\
|
|
||||||
UEsDBBQAAAAAAORmeE794BlRfgMAAH4DAAAPAAAAZGVmaW5pdGlvbnMudHh0c2VlX3N0YWNrID09
|
Z = zipfile.ZipFile(StringIO.StringIO(base64.decodestring('''\
|
||||||
IGdvb2Rfdmlld2VyX2xvY2F0aW9uIG9wZW5fc3RhY2sNCnNlZV9yZXNvdXJjZXMgPT0gbGlzdF9y
|
UEsDBBQAAAAAAORmeE794BlRfgMAAH4DAAAPAAAAZGVmaW5pdGlvbnMudHh0c2VlX3N0YWNrID09
|
||||||
ZXNvdXJjZXMgZ29vZF92aWV3ZXJfbG9jYXRpb24gb3Blbl92aWV3ZXINCm9wZW5fcmVzb3VyY2Vf
|
IGdvb2Rfdmlld2VyX2xvY2F0aW9uIG9wZW5fc3RhY2sNCnNlZV9yZXNvdXJjZXMgPT0gbGlzdF9y
|
||||||
YXRfZ29vZF9sb2NhdGlvbiA9PSBnb29kX3ZpZXdlcl9sb2NhdGlvbiBvcGVuX3Jlc291cmNlDQpz
|
ZXNvdXJjZXMgZ29vZF92aWV3ZXJfbG9jYXRpb24gb3Blbl92aWV3ZXINCm9wZW5fcmVzb3VyY2Vf
|
||||||
ZWVfbG9nID09ICJsb2cudHh0IiBvcGVuX3Jlc291cmNlX2F0X2dvb2RfbG9jYXRpb24NCnNlZV9k
|
YXRfZ29vZF9sb2NhdGlvbiA9PSBnb29kX3ZpZXdlcl9sb2NhdGlvbiBvcGVuX3Jlc291cmNlDQpz
|
||||||
ZWZpbml0aW9ucyA9PSAiZGVmaW5pdGlvbnMudHh0IiBvcGVuX3Jlc291cmNlX2F0X2dvb2RfbG9j
|
ZWVfbG9nID09ICJsb2cudHh0IiBvcGVuX3Jlc291cmNlX2F0X2dvb2RfbG9jYXRpb24NCnNlZV9k
|
||||||
YXRpb24NCnJvdW5kX3RvX2NlbnRzID09IDEwMCAqICsrIGZsb29yIDEwMCAvDQpyZXNldF9sb2cg
|
ZWZpbml0aW9ucyA9PSAiZGVmaW5pdGlvbnMudHh0IiBvcGVuX3Jlc291cmNlX2F0X2dvb2RfbG9j
|
||||||
PT0gImRlbCBsb2cubGluZXNbMTpdIDsgbG9nLmF0X2xpbmUgPSAwIiBldmFsdWF0ZQ0Kc2VlX21l
|
YXRpb24NCnJvdW5kX3RvX2NlbnRzID09IDEwMCAqICsrIGZsb29yIDEwMCAvDQpyZXNldF9sb2cg
|
||||||
bnUgPT0gIm1lbnUudHh0IiBnb29kX3ZpZXdlcl9sb2NhdGlvbiBvcGVuX3Jlc291cmNlDQoNCiMg
|
PT0gImRlbCBsb2cubGluZXNbMTpdIDsgbG9nLmF0X2xpbmUgPSAwIiBldmFsdWF0ZQ0Kc2VlX21l
|
||||||
T3JkZXJlZCBCaW5hcnkgVHJlZSBkYXRhc3RydWN0dXJlIGZ1bmN0aW9ucy4NCkJUcmVlLW5ldyA9
|
bnUgPT0gIm1lbnUudHh0IiBnb29kX3ZpZXdlcl9sb2NhdGlvbiBvcGVuX3Jlc291cmNlDQoNCiMg
|
||||||
PSBzd2FwIFtbXSBbXV0gY29ucyBjb25zDQogX0JUcmVlLVAgPT0gb3ZlciBbcG9wb3AgcG9wb3Ag
|
T3JkZXJlZCBCaW5hcnkgVHJlZSBkYXRhc3RydWN0dXJlIGZ1bmN0aW9ucy4NCkJUcmVlLW5ldyA9
|
||||||
Zmlyc3RdIG51bGxhcnkNCiBfQlRyZWUtVD4gPT0gW2NvbnMgY29ucyBkaXBkZF0gY29ucyBjb25z
|
PSBzd2FwIFtbXSBbXV0gY29ucyBjb25zDQogX0JUcmVlLVAgPT0gb3ZlciBbcG9wb3AgcG9wb3Ag
|
||||||
IGNvbnMgaW5mcmENCiBfQlRyZWUtVDwgPT0gW2NvbnMgY29ucyBkaXBkXSBjb25zIGNvbnMgY29u
|
Zmlyc3RdIG51bGxhcnkNCiBfQlRyZWUtVD4gPT0gW2NvbnMgY29ucyBkaXBkZF0gY29ucyBjb25z
|
||||||
cyBpbmZyYQ0KIF9CVHJlZS1FID09IHBvcCBzd2FwIHJvbGw8IHJlc3QgcmVzdCBjb25zIGNvbnMN
|
IGNvbnMgaW5mcmENCiBfQlRyZWUtVDwgPT0gW2NvbnMgY29ucyBkaXBkXSBjb25zIGNvbnMgY29u
|
||||||
CiBfQlRyZWUtcmVjdXIgPT0gX0JUcmVlLVAgW19CVHJlZS1UPl0gW19CVHJlZS1FXSBbX0JUcmVl
|
cyBpbmZyYQ0KIF9CVHJlZS1FID09IHBvcCBzd2FwIHJvbGw8IHJlc3QgcmVzdCBjb25zIGNvbnMN
|
||||||
LVQ8XSBjbXANCkJUcmVlLWFkZCA9PSBbcG9wb3Agbm90XSBbW3BvcF0gZGlwZCBCVHJlZS1uZXdd
|
CiBfQlRyZWUtcmVjdXIgPT0gX0JUcmVlLVAgW19CVHJlZS1UPl0gW19CVHJlZS1FXSBbX0JUcmVl
|
||||||
IFtdIFtfQlRyZWUtcmVjdXJdIGdlbnJlYw0KUEsDBBQAAAAAACFrpk7/HHjxGBYAABgWAAAKAAAA
|
LVQ8XSBjbXANCkJUcmVlLWFkZCA9PSBbcG9wb3Agbm90XSBbW3BvcF0gZGlwZCBCVHJlZS1uZXdd
|
||||||
bGlicmFyeS5weScnJw0KVGhpcyBmaWxlIGlzIGV4ZWNmaWxlKCknZCB3aXRoIGEgbmFtZXNwYWNl
|
IFtdIFtfQlRyZWUtcmVjdXJdIGdlbnJlYw0KUEsDBBQAAAAAACFrpk7/HHjxGBYAABgWAAAKAAAA
|
||||||
IGNvbnRhaW5pbmc6DQoNCiAgRCAtIHRoZSBKb3kgZGljdGlvbmFyeQ0KICBkIC0gdGhlIERpc3Bs
|
bGlicmFyeS5weScnJw0KVGhpcyBmaWxlIGlzIGV4ZWNmaWxlKCknZCB3aXRoIGEgbmFtZXNwYWNl
|
||||||
YXkgb2JqZWN0DQogIHB0IC0gdGhlIFBlcnNpc3RUYXNrIG9iamVjdA0KICBsb2cgLSB0aGUgbG9n
|
IGNvbnRhaW5pbmc6DQoNCiAgRCAtIHRoZSBKb3kgZGljdGlvbmFyeQ0KICBkIC0gdGhlIERpc3Bs
|
||||||
LnR4dCB2aWV3ZXINCiAgbG9vcCAtIHRoZSBUaGVMb29wIG1haW4gbG9vcCBvYmplY3QNCiAgc3Rh
|
YXkgb2JqZWN0DQogIHB0IC0gdGhlIFBlcnNpc3RUYXNrIG9iamVjdA0KICBsb2cgLSB0aGUgbG9n
|
||||||
Y2tfaG9sZGVyIC0gdGhlIFB5dGhvbiBsaXN0IG9iamVjdCB0aGF0IGhvbGRzIHRoZSBKb3kgc3Rh
|
LnR4dCB2aWV3ZXINCiAgbG9vcCAtIHRoZSBUaGVMb29wIG1haW4gbG9vcCBvYmplY3QNCiAgc3Rh
|
||||||
Y2sgdHVwbGUNCiAgd29ybGQgLSB0aGUgSm95IGVudmlyb25tZW50DQoNCicnJw0KZnJvbSBqb3ku
|
Y2tfaG9sZGVyIC0gdGhlIFB5dGhvbiBsaXN0IG9iamVjdCB0aGF0IGhvbGRzIHRoZSBKb3kgc3Rh
|
||||||
bGlicmFyeSBpbXBvcnQgKA0KICAgIERlZmluaXRpb25XcmFwcGVyLA0KICAgIEZ1bmN0aW9uV3Jh
|
Y2sgdHVwbGUNCiAgd29ybGQgLSB0aGUgSm95IGVudmlyb25tZW50DQoNCicnJw0KZnJvbSBqb3ku
|
||||||
cHBlciwNCiAgICBTaW1wbGVGdW5jdGlvbldyYXBwZXIsDQogICAgKQ0KZnJvbSBqb3kudXRpbHMu
|
bGlicmFyeSBpbXBvcnQgKA0KICAgIERlZmluaXRpb25XcmFwcGVyLA0KICAgIEZ1bmN0aW9uV3Jh
|
||||||
c3RhY2sgaW1wb3J0IGxpc3RfdG9fc3RhY2ssIGNvbmNhdA0KZnJvbSBqb3kudnVpIGltcG9ydCBj
|
cHBlciwNCiAgICBTaW1wbGVGdW5jdGlvbldyYXBwZXIsDQogICAgKQ0KZnJvbSBqb3kudXRpbHMu
|
||||||
b3JlLCB0ZXh0X3ZpZXdlciwgc3RhY2tfdmlld2VyDQoNCg0KZGVmIGluc3RhbGwoY29tbWFuZCk6
|
c3RhY2sgaW1wb3J0IGxpc3RfdG9fc3RhY2ssIGNvbmNhdA0KZnJvbSBqb3kudnVpIGltcG9ydCBj
|
||||||
IERbY29tbWFuZC5uYW1lXSA9IGNvbW1hbmQNCg0KDQpAaW5zdGFsbA0KQFNpbXBsZUZ1bmN0aW9u
|
b3JlLCB0ZXh0X3ZpZXdlciwgc3RhY2tfdmlld2VyDQoNCg0KZGVmIGluc3RhbGwoY29tbWFuZCk6
|
||||||
V3JhcHBlcg0KZGVmIGxpc3RfcmVzb3VyY2VzKHN0YWNrKToNCiAgICAnJycNCiAgICBQdXQgYSBz
|
IERbY29tbWFuZC5uYW1lXSA9IGNvbW1hbmQNCg0KDQpAaW5zdGFsbA0KQFNpbXBsZUZ1bmN0aW9u
|
||||||
dHJpbmcgb24gdGhlIHN0YWNrIHdpdGggdGhlIG5hbWVzIG9mIGFsbCB0aGUga25vd24gcmVzb3Vy
|
V3JhcHBlcg0KZGVmIGxpc3RfcmVzb3VyY2VzKHN0YWNrKToNCiAgICAnJycNCiAgICBQdXQgYSBz
|
||||||
Y2VzDQogICAgb25lLXBlci1saW5lLg0KICAgICcnJw0KICAgIHJldHVybiAnXG4nLmpvaW4ocHQu
|
dHJpbmcgb24gdGhlIHN0YWNrIHdpdGggdGhlIG5hbWVzIG9mIGFsbCB0aGUga25vd24gcmVzb3Vy
|
||||||
c2NhbigpKSwgc3RhY2sNCg0KDQpAaW5zdGFsbA0KQFNpbXBsZUZ1bmN0aW9uV3JhcHBlcg0KZGVm
|
Y2VzDQogICAgb25lLXBlci1saW5lLg0KICAgICcnJw0KICAgIHJldHVybiAnXG4nLmpvaW4ocHQu
|
||||||
IG9wZW5fc3RhY2soc3RhY2spOg0KICAgICcnJw0KICAgIEdpdmVuIGEgY29vcmRpbmF0ZSBwYWly
|
c2NhbigpKSwgc3RhY2sNCg0KDQpAaW5zdGFsbA0KQFNpbXBsZUZ1bmN0aW9uV3JhcHBlcg0KZGVm
|
||||||
IFt4IHldIChpbiBwaXhlbHMpIG9wZW4gYSBTdGFja1ZpZXdlciB0aGVyZS4NCiAgICAnJycNCiAg
|
IG9wZW5fc3RhY2soc3RhY2spOg0KICAgICcnJw0KICAgIEdpdmVuIGEgY29vcmRpbmF0ZSBwYWly
|
||||||
ICAoeCwgKHksIF8pKSwgc3RhY2sgPSBzdGFjaw0KICAgIFYgPSBkLm9wZW5fdmlld2VyKHgsIHks
|
IFt4IHldIChpbiBwaXhlbHMpIG9wZW4gYSBTdGFja1ZpZXdlciB0aGVyZS4NCiAgICAnJycNCiAg
|
||||||
IHN0YWNrX3ZpZXdlci5TdGFja1ZpZXdlcikNCiAgICBWLmRyYXcoKQ0KICAgIHJldHVybiBzdGFj
|
ICAoeCwgKHksIF8pKSwgc3RhY2sgPSBzdGFjaw0KICAgIFYgPSBkLm9wZW5fdmlld2VyKHgsIHks
|
||||||
aw0KDQoNCkBpbnN0YWxsDQpAU2ltcGxlRnVuY3Rpb25XcmFwcGVyDQpkZWYgb3Blbl9yZXNvdXJj
|
IHN0YWNrX3ZpZXdlci5TdGFja1ZpZXdlcikNCiAgICBWLmRyYXcoKQ0KICAgIHJldHVybiBzdGFj
|
||||||
ZShzdGFjayk6DQogICAgJycnDQogICAgR2l2ZW4gYSBjb29yZGluYXRlIHBhaXIgW3ggeV0gKGlu
|
aw0KDQoNCkBpbnN0YWxsDQpAU2ltcGxlRnVuY3Rpb25XcmFwcGVyDQpkZWYgb3Blbl9yZXNvdXJj
|
||||||
IHBpeGVscykgYW5kIHRoZSBuYW1lIG9mIGEgcmVzb3VyY2UNCiAgICAoZnJvbSBsaXN0X3Jlc291
|
ZShzdGFjayk6DQogICAgJycnDQogICAgR2l2ZW4gYSBjb29yZGluYXRlIHBhaXIgW3ggeV0gKGlu
|
||||||
cmNlcyBjb21tYW5kKSBvcGVuIGEgdmlld2VyIG9uIHRoYXQgcmVzb3VyY2UgYXQgdGhhdA0KICAg
|
IHBpeGVscykgYW5kIHRoZSBuYW1lIG9mIGEgcmVzb3VyY2UNCiAgICAoZnJvbSBsaXN0X3Jlc291
|
||||||
IGxvY2F0aW9uLg0KICAgICcnJw0KICAgICgoeCwgKHksIF8pKSwgKG5hbWUsIHN0YWNrKSkgPSBz
|
cmNlcyBjb21tYW5kKSBvcGVuIGEgdmlld2VyIG9uIHRoYXQgcmVzb3VyY2UgYXQgdGhhdA0KICAg
|
||||||
dGFjaw0KICAgIG9tID0gY29yZS5PcGVuTWVzc2FnZSh3b3JsZCwgbmFtZSkNCiAgICBkLmJyb2Fk
|
IGxvY2F0aW9uLg0KICAgICcnJw0KICAgICgoeCwgKHksIF8pKSwgKG5hbWUsIHN0YWNrKSkgPSBz
|
||||||
Y2FzdChvbSkNCiAgICBpZiBvbS5zdGF0dXMgPT0gY29yZS5TVUNDRVNTOg0KICAgICAgICBWID0g
|
dGFjaw0KICAgIG9tID0gY29yZS5PcGVuTWVzc2FnZSh3b3JsZCwgbmFtZSkNCiAgICBkLmJyb2Fk
|
||||||
ZC5vcGVuX3ZpZXdlcih4LCB5LCB0ZXh0X3ZpZXdlci5UZXh0Vmlld2VyKQ0KICAgICAgICBWLmNv
|
Y2FzdChvbSkNCiAgICBpZiBvbS5zdGF0dXMgPT0gY29yZS5TVUNDRVNTOg0KICAgICAgICBWID0g
|
||||||
bnRlbnRfaWQsIFYubGluZXMgPSBvbS5jb250ZW50X2lkLCBvbS50aGluZw0KICAgICAgICBWLmRy
|
ZC5vcGVuX3ZpZXdlcih4LCB5LCB0ZXh0X3ZpZXdlci5UZXh0Vmlld2VyKQ0KICAgICAgICBWLmNv
|
||||||
YXcoKQ0KICAgIHJldHVybiBzdGFjaw0KDQoNCkBpbnN0YWxsDQpAU2ltcGxlRnVuY3Rpb25XcmFw
|
bnRlbnRfaWQsIFYubGluZXMgPSBvbS5jb250ZW50X2lkLCBvbS50aGluZw0KICAgICAgICBWLmRy
|
||||||
cGVyDQpkZWYgbmFtZV92aWV3ZXIoc3RhY2spOg0KICAgICcnJw0KICAgIEdpdmVuIGEgc3RyaW5n
|
YXcoKQ0KICAgIHJldHVybiBzdGFjaw0KDQoNCkBpbnN0YWxsDQpAU2ltcGxlRnVuY3Rpb25XcmFw
|
||||||
IG5hbWUgb24gdGhlIHN0YWNrLCBpZiB0aGUgY3VycmVudGx5IGZvY3VzZWQgdmlld2VyIGlzDQog
|
cGVyDQpkZWYgbmFtZV92aWV3ZXIoc3RhY2spOg0KICAgICcnJw0KICAgIEdpdmVuIGEgc3RyaW5n
|
||||||
ICAgYW5vbnltb3VzLCBuYW1lIHRoZSB2aWV3ZXIgYW5kIHBlcnNpc3QgaXQgaW4gdGhlIHJlc291
|
IG5hbWUgb24gdGhlIHN0YWNrLCBpZiB0aGUgY3VycmVudGx5IGZvY3VzZWQgdmlld2VyIGlzDQog
|
||||||
cmNlIHN0b3JlIHVuZGVyDQogICAgdGhhdCBuYW1lLg0KICAgICcnJw0KICAgIG5hbWUsIHN0YWNr
|
ICAgYW5vbnltb3VzLCBuYW1lIHRoZSB2aWV3ZXIgYW5kIHBlcnNpc3QgaXQgaW4gdGhlIHJlc291
|
||||||
ID0gc3RhY2sNCiAgICBhc3NlcnQgaXNpbnN0YW5jZShuYW1lLCBzdHIpLCByZXByKG5hbWUpDQog
|
cmNlIHN0b3JlIHVuZGVyDQogICAgdGhhdCBuYW1lLg0KICAgICcnJw0KICAgIG5hbWUsIHN0YWNr
|
||||||
ICAgaWYgZC5mb2N1c2VkX3ZpZXdlciBhbmQgbm90IGQuZm9jdXNlZF92aWV3ZXIuY29udGVudF9p
|
ID0gc3RhY2sNCiAgICBhc3NlcnQgaXNpbnN0YW5jZShuYW1lLCBzdHIpLCByZXByKG5hbWUpDQog
|
||||||
ZDoNCiAgICAgICAgZC5mb2N1c2VkX3ZpZXdlci5jb250ZW50X2lkID0gbmFtZQ0KICAgICAgICBw
|
ICAgaWYgZC5mb2N1c2VkX3ZpZXdlciBhbmQgbm90IGQuZm9jdXNlZF92aWV3ZXIuY29udGVudF9p
|
||||||
bSA9IGNvcmUuUGVyc2lzdE1lc3NhZ2Uod29ybGQsIG5hbWUsIHRoaW5nPWQuZm9jdXNlZF92aWV3
|
ZDoNCiAgICAgICAgZC5mb2N1c2VkX3ZpZXdlci5jb250ZW50X2lkID0gbmFtZQ0KICAgICAgICBw
|
||||||
ZXIubGluZXMpDQogICAgICAgIGQuYnJvYWRjYXN0KHBtKQ0KICAgICAgICBkLmZvY3VzZWRfdmll
|
bSA9IGNvcmUuUGVyc2lzdE1lc3NhZ2Uod29ybGQsIG5hbWUsIHRoaW5nPWQuZm9jdXNlZF92aWV3
|
||||||
d2VyLmRyYXdfbWVudSgpDQogICAgcmV0dXJuIHN0YWNrDQoNCg0KIyNAaW5zdGFsbA0KIyNAU2lt
|
ZXIubGluZXMpDQogICAgICAgIGQuYnJvYWRjYXN0KHBtKQ0KICAgICAgICBkLmZvY3VzZWRfdmll
|
||||||
cGxlRnVuY3Rpb25XcmFwcGVyDQojI2RlZiBwZXJzaXN0X3ZpZXdlcihzdGFjayk6DQojIyAgICBp
|
d2VyLmRyYXdfbWVudSgpDQogICAgcmV0dXJuIHN0YWNrDQoNCg0KIyNAaW5zdGFsbA0KIyNAU2lt
|
||||||
ZiBzZWxmLmZvY3VzZWRfdmlld2VyOg0KIyMgICAgICAgIA0KIyMgICAgICAgIHNlbGYuZm9jdXNl
|
cGxlRnVuY3Rpb25XcmFwcGVyDQojI2RlZiBwZXJzaXN0X3ZpZXdlcihzdGFjayk6DQojIyAgICBp
|
||||||
ZF92aWV3ZXIuY29udGVudF9pZCA9IG5hbWUNCiMjICAgICAgICBzZWxmLmZvY3VzZWRfdmlld2Vy
|
ZiBzZWxmLmZvY3VzZWRfdmlld2VyOg0KIyMgICAgICAgIA0KIyMgICAgICAgIHNlbGYuZm9jdXNl
|
||||||
LmRyYXdfbWVudSgpDQojIyAgICByZXR1cm4gc3RhY2sNCg0KDQpAaW5zdGFsbA0KQFNpbXBsZUZ1
|
ZF92aWV3ZXIuY29udGVudF9pZCA9IG5hbWUNCiMjICAgICAgICBzZWxmLmZvY3VzZWRfdmlld2Vy
|
||||||
bmN0aW9uV3JhcHBlcg0KZGVmIGluc2NyaWJlKHN0YWNrKToNCiAgICAnJycNCiAgICBDcmVhdGUg
|
LmRyYXdfbWVudSgpDQojIyAgICByZXR1cm4gc3RhY2sNCg0KDQpAaW5zdGFsbA0KQFNpbXBsZUZ1
|
||||||
YSBuZXcgSm95IGZ1bmN0aW9uIGRlZmluaXRpb24gaW4gdGhlIEpveSBkaWN0aW9uYXJ5LiAgQQ0K
|
bmN0aW9uV3JhcHBlcg0KZGVmIGluc2NyaWJlKHN0YWNrKToNCiAgICAnJycNCiAgICBDcmVhdGUg
|
||||||
ICAgIGRlZmluaXRpb24gaXMgZ2l2ZW4gYXMgYSBzdHJpbmcgd2l0aCBhIG5hbWUgZm9sbG93ZWQg
|
YSBuZXcgSm95IGZ1bmN0aW9uIGRlZmluaXRpb24gaW4gdGhlIEpveSBkaWN0aW9uYXJ5LiAgQQ0K
|
||||||
YnkgYSBkb3VibGUNCiAgICBlcXVhbCBzaWduIHRoZW4gb25lIG9yIG1vcmUgSm95IGZ1bmN0aW9u
|
ICAgIGRlZmluaXRpb24gaXMgZ2l2ZW4gYXMgYSBzdHJpbmcgd2l0aCBhIG5hbWUgZm9sbG93ZWQg
|
||||||
cywgdGhlIGJvZHkuIGZvciBleGFtcGxlOg0KDQogICAgICAgIHNxciA9PSBkdXAgbXVsDQoNCiAg
|
YnkgYSBkb3VibGUNCiAgICBlcXVhbCBzaWduIHRoZW4gb25lIG9yIG1vcmUgSm95IGZ1bmN0aW9u
|
||||||
ICBJZiB5b3Ugd2FudCB0aGUgZGVmaW5pdGlvbiB0byBwZXJzaXN0IG92ZXIgcmVzdGFydHMsIGVu
|
cywgdGhlIGJvZHkuIGZvciBleGFtcGxlOg0KDQogICAgICAgIHNxciA9PSBkdXAgbXVsDQoNCiAg
|
||||||
dGVyIGl0IGludG8NCiAgICB0aGUgZGVmaW5pdGlvbnMudHh0IHJlc291cmNlLg0KICAgICcnJw0K
|
ICBJZiB5b3Ugd2FudCB0aGUgZGVmaW5pdGlvbiB0byBwZXJzaXN0IG92ZXIgcmVzdGFydHMsIGVu
|
||||||
ICAgIGRlZmluaXRpb24sIHN0YWNrID0gc3RhY2sNCiAgICBEZWZpbml0aW9uV3JhcHBlci5hZGRf
|
dGVyIGl0IGludG8NCiAgICB0aGUgZGVmaW5pdGlvbnMudHh0IHJlc291cmNlLg0KICAgICcnJw0K
|
||||||
ZGVmKGRlZmluaXRpb24sIEQpDQogICAgcmV0dXJuIHN0YWNrDQoNCg0KQGluc3RhbGwNCkBTaW1w
|
ICAgIGRlZmluaXRpb24sIHN0YWNrID0gc3RhY2sNCiAgICBEZWZpbml0aW9uV3JhcHBlci5hZGRf
|
||||||
bGVGdW5jdGlvbldyYXBwZXINCmRlZiBvcGVuX3ZpZXdlcihzdGFjayk6DQogICAgJycnDQogICAg
|
ZGVmKGRlZmluaXRpb24sIEQpDQogICAgcmV0dXJuIHN0YWNrDQoNCg0KQGluc3RhbGwNCkBTaW1w
|
||||||
R2l2ZW4gYSBjb29yZGluYXRlIHBhaXIgW3ggeV0gKGluIHBpeGVscykgYW5kIGEgc3RyaW5nLCBv
|
bGVGdW5jdGlvbldyYXBwZXINCmRlZiBvcGVuX3ZpZXdlcihzdGFjayk6DQogICAgJycnDQogICAg
|
||||||
cGVuIGEgbmV3DQogICAgdW5uYW1lZCB2aWV3ZXIgb24gdGhhdCBzdHJpbmcgYXQgdGhhdCBsb2Nh
|
R2l2ZW4gYSBjb29yZGluYXRlIHBhaXIgW3ggeV0gKGluIHBpeGVscykgYW5kIGEgc3RyaW5nLCBv
|
||||||
dGlvbi4NCiAgICAnJycNCiAgICAoKHgsICh5LCBfKSksIChjb250ZW50LCBzdGFjaykpID0gc3Rh
|
cGVuIGEgbmV3DQogICAgdW5uYW1lZCB2aWV3ZXIgb24gdGhhdCBzdHJpbmcgYXQgdGhhdCBsb2Nh
|
||||||
Y2sNCiAgICBWID0gZC5vcGVuX3ZpZXdlcih4LCB5LCB0ZXh0X3ZpZXdlci5UZXh0Vmlld2VyKQ0K
|
dGlvbi4NCiAgICAnJycNCiAgICAoKHgsICh5LCBfKSksIChjb250ZW50LCBzdGFjaykpID0gc3Rh
|
||||||
ICAgIFYubGluZXMgPSBjb250ZW50LnNwbGl0bGluZXMoKQ0KICAgIFYuZHJhdygpDQogICAgcmV0
|
Y2sNCiAgICBWID0gZC5vcGVuX3ZpZXdlcih4LCB5LCB0ZXh0X3ZpZXdlci5UZXh0Vmlld2VyKQ0K
|
||||||
dXJuIHN0YWNrDQoNCg0KQGluc3RhbGwNCkBTaW1wbGVGdW5jdGlvbldyYXBwZXINCmRlZiBnb29k
|
ICAgIFYubGluZXMgPSBjb250ZW50LnNwbGl0bGluZXMoKQ0KICAgIFYuZHJhdygpDQogICAgcmV0
|
||||||
X3ZpZXdlcl9sb2NhdGlvbihzdGFjayk6DQogICAgJycnDQogICAgTGVhdmUgYSBjb29yZGluYXRl
|
dXJuIHN0YWNrDQoNCg0KQGluc3RhbGwNCkBTaW1wbGVGdW5jdGlvbldyYXBwZXINCmRlZiBnb29k
|
||||||
IHBhaXIgW3ggeV0gKGluIHBpeGVscykgb24gdGhlIHN0YWNrIHRoYXQgd291bGQNCiAgICBiZSBh
|
X3ZpZXdlcl9sb2NhdGlvbihzdGFjayk6DQogICAgJycnDQogICAgTGVhdmUgYSBjb29yZGluYXRl
|
||||||
IGdvb2QgbG9jYXRpb24gYXQgd2hpY2ggdG8gb3BlbiBhIG5ldyB2aWV3ZXIuICAoVGhlIGhldXJp
|
IHBhaXIgW3ggeV0gKGluIHBpeGVscykgb24gdGhlIHN0YWNrIHRoYXQgd291bGQNCiAgICBiZSBh
|
||||||
c3RpYw0KICAgIGVtcGxveWVkIGlzIHRvIHRha2UgdXAgdGhlIGJvdHRvbSBoYWxmIG9mIHRoZSBj
|
IGdvb2QgbG9jYXRpb24gYXQgd2hpY2ggdG8gb3BlbiBhIG5ldyB2aWV3ZXIuICAoVGhlIGhldXJp
|
||||||
dXJyZW50bHkgb3BlbiB2aWV3ZXINCiAgICB3aXRoIHRoZSBncmVhdGVzdCBhcmVhLikNCiAgICAn
|
c3RpYw0KICAgIGVtcGxveWVkIGlzIHRvIHRha2UgdXAgdGhlIGJvdHRvbSBoYWxmIG9mIHRoZSBj
|
||||||
JycNCiAgICB2aWV3ZXJzID0gbGlzdChkLml0ZXJfdmlld2VycygpKQ0KICAgIGlmIHZpZXdlcnM6
|
dXJyZW50bHkgb3BlbiB2aWV3ZXINCiAgICB3aXRoIHRoZSBncmVhdGVzdCBhcmVhLikNCiAgICAn
|
||||||
DQogICAgICAgIHZpZXdlcnMuc29ydChrZXk9bGFtYmRhIChWLCB4LCB5KTogVi53ICogVi5oKQ0K
|
JycNCiAgICB2aWV3ZXJzID0gbGlzdChkLml0ZXJfdmlld2VycygpKQ0KICAgIGlmIHZpZXdlcnM6
|
||||||
ICAgICAgICBWLCB4LCB5ID0gdmlld2Vyc1stMV0NCiAgICAgICAgY29vcmRzID0gKHggKyAxLCAo
|
DQogICAgICAgIHZpZXdlcnMuc29ydChrZXk9bGFtYmRhIChWLCB4LCB5KTogVi53ICogVi5oKQ0K
|
||||||
eSArIFYuaCAvIDIsICgpKSkNCiAgICBlbHNlOg0KICAgICAgICBjb29yZHMgPSAoMCwgKDAsICgp
|
ICAgICAgICBWLCB4LCB5ID0gdmlld2Vyc1stMV0NCiAgICAgICAgY29vcmRzID0gKHggKyAxLCAo
|
||||||
KSkNCiAgICByZXR1cm4gY29vcmRzLCBzdGFjaw0KDQoNCkBpbnN0YWxsDQpARnVuY3Rpb25XcmFw
|
eSArIFYuaCAvIDIsICgpKSkNCiAgICBlbHNlOg0KICAgICAgICBjb29yZHMgPSAoMCwgKDAsICgp
|
||||||
cGVyDQpkZWYgY21wXyhzdGFjaywgZXhwcmVzc2lvbiwgZGljdGlvbmFyeSk6DQogICAgJycnDQog
|
KSkNCiAgICByZXR1cm4gY29vcmRzLCBzdGFjaw0KDQoNCkBpbnN0YWxsDQpARnVuY3Rpb25XcmFw
|
||||||
ICAgVGhlIGNtcCBjb21iaW5hdG9yIHRha2VzIHR3byB2YWx1ZXMgYW5kIHRocmVlIHF1b3RlZCBw
|
cGVyDQpkZWYgY21wXyhzdGFjaywgZXhwcmVzc2lvbiwgZGljdGlvbmFyeSk6DQogICAgJycnDQog
|
||||||
cm9ncmFtcyBvbiB0aGUNCiAgICBzdGFjayBhbmQgcnVucyBvbmUgb2YgdGhlIHRocmVlIGRlcGVu
|
ICAgVGhlIGNtcCBjb21iaW5hdG9yIHRha2VzIHR3byB2YWx1ZXMgYW5kIHRocmVlIHF1b3RlZCBw
|
||||||
ZGluZyBvbiB0aGUgcmVzdWx0cyBvZiBjb21wYXJpbmcNCiAgICB0aGUgdHdvIHZhbHVlczoNCg0K
|
cm9ncmFtcyBvbiB0aGUNCiAgICBzdGFjayBhbmQgcnVucyBvbmUgb2YgdGhlIHRocmVlIGRlcGVu
|
||||||
ICAgICAgICAgICBhIGIgW0ddIFtFXSBbTF0gY21wDQogICAgICAgIC0tLS0tLS0tLS0tLS0tLS0t
|
ZGluZyBvbiB0aGUgcmVzdWx0cyBvZiBjb21wYXJpbmcNCiAgICB0aGUgdHdvIHZhbHVlczoNCg0K
|
||||||
LS0tLS0tLS0gYSA+IGINCiAgICAgICAgICAgICAgICBHDQoNCiAgICAgICAgICAgYSBiIFtHXSBb
|
ICAgICAgICAgICBhIGIgW0ddIFtFXSBbTF0gY21wDQogICAgICAgIC0tLS0tLS0tLS0tLS0tLS0t
|
||||||
RV0gW0xdIGNtcA0KICAgICAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGEgPSBiDQogICAg
|
LS0tLS0tLS0gYSA+IGINCiAgICAgICAgICAgICAgICBHDQoNCiAgICAgICAgICAgYSBiIFtHXSBb
|
||||||
ICAgICAgICAgICAgICAgIEUNCg0KICAgICAgICAgICBhIGIgW0ddIFtFXSBbTF0gY21wDQogICAg
|
RV0gW0xdIGNtcA0KICAgICAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGEgPSBiDQogICAg
|
||||||
ICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gYSA8IGINCiAgICAgICAgICAgICAgICAgICAg
|
ICAgICAgICAgICAgICAgIEUNCg0KICAgICAgICAgICBhIGIgW0ddIFtFXSBbTF0gY21wDQogICAg
|
||||||
ICAgIEwNCg0KICAgICcnJw0KICAgIEwsIChFLCAoRywgKGIsIChhLCBzdGFjaykpKSkgPSBzdGFj
|
ICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gYSA8IGINCiAgICAgICAgICAgICAgICAgICAg
|
||||||
aw0KICAgIGV4cHJlc3Npb24gPSBjb25jYXQoRyBpZiBhID4gYiBlbHNlIEwgaWYgYSA8IGIgZWxz
|
ICAgIEwNCg0KICAgICcnJw0KICAgIEwsIChFLCAoRywgKGIsIChhLCBzdGFjaykpKSkgPSBzdGFj
|
||||||
ZSBFLCBleHByZXNzaW9uKQ0KICAgIHJldHVybiBzdGFjaywgZXhwcmVzc2lvbiwgZGljdGlvbmFy
|
aw0KICAgIGV4cHJlc3Npb24gPSBjb25jYXQoRyBpZiBhID4gYiBlbHNlIEwgaWYgYSA8IGIgZWxz
|
||||||
eQ0KDQoNCkBpbnN0YWxsDQpAU2ltcGxlRnVuY3Rpb25XcmFwcGVyDQpkZWYgbGlzdF92aWV3ZXJz
|
ZSBFLCBleHByZXNzaW9uKQ0KICAgIHJldHVybiBzdGFjaywgZXhwcmVzc2lvbiwgZGljdGlvbmFy
|
||||||
KHN0YWNrKToNCiAgICAnJycNCiAgICBQdXQgYSBzdHJpbmcgb24gdGhlIHN0YWNrIHdpdGggc29t
|
eQ0KDQoNCkBpbnN0YWxsDQpAU2ltcGxlRnVuY3Rpb25XcmFwcGVyDQpkZWYgbGlzdF92aWV3ZXJz
|
||||||
ZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgY3VycmVudGx5DQogICAgb3BlbiB2aWV3ZXJzLCBvbmUt
|
KHN0YWNrKToNCiAgICAnJycNCiAgICBQdXQgYSBzdHJpbmcgb24gdGhlIHN0YWNrIHdpdGggc29t
|
||||||
cGVyLWxpbmUuICBUaGlzIGlzIGtpbmQgb2YgYSBkZW1vIGZ1bmN0aW9uLCByYXRoZXINCiAgICB0
|
ZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgY3VycmVudGx5DQogICAgb3BlbiB2aWV3ZXJzLCBvbmUt
|
||||||
aGFuIHNvbWV0aGluZyByZWFsbHkgdXNlZnVsLg0KICAgICcnJw0KICAgIGxpbmVzID0gW10NCiAg
|
cGVyLWxpbmUuICBUaGlzIGlzIGtpbmQgb2YgYSBkZW1vIGZ1bmN0aW9uLCByYXRoZXINCiAgICB0
|
||||||
ICBmb3IgeCwgVCBpbiBkLnRyYWNrczoNCiAgICAgICAgI2xpbmVzLmFwcGVuZCgneDogJWksIHc6
|
aGFuIHNvbWV0aGluZyByZWFsbHkgdXNlZnVsLg0KICAgICcnJw0KICAgIGxpbmVzID0gW10NCiAg
|
||||||
ICVpLCAlcicgJSAoeCwgVC53LCBUKSkNCiAgICAgICAgZm9yIHksIFYgaW4gVC52aWV3ZXJzOg0K
|
ICBmb3IgeCwgVCBpbiBkLnRyYWNrczoNCiAgICAgICAgI2xpbmVzLmFwcGVuZCgneDogJWksIHc6
|
||||||
ICAgICAgICAgICAgbGluZXMuYXBwZW5kKCd4OiAlaSB5OiAlaSBoOiAlaSAlciAlcicgJSAoeCwg
|
ICVpLCAlcicgJSAoeCwgVC53LCBUKSkNCiAgICAgICAgZm9yIHksIFYgaW4gVC52aWV3ZXJzOg0K
|
||||||
eSwgVi5oLCBWLmNvbnRlbnRfaWQsIFYpKQ0KICAgIHJldHVybiAnXG4nLmpvaW4obGluZXMpLCBz
|
ICAgICAgICAgICAgbGluZXMuYXBwZW5kKCd4OiAlaSB5OiAlaSBoOiAlaSAlciAlcicgJSAoeCwg
|
||||||
dGFjaw0KDQoNCkBpbnN0YWxsDQpAU2ltcGxlRnVuY3Rpb25XcmFwcGVyDQpkZWYgc3BsaXRsaW5l
|
eSwgVi5oLCBWLmNvbnRlbnRfaWQsIFYpKQ0KICAgIHJldHVybiAnXG4nLmpvaW4obGluZXMpLCBz
|
||||||
cyhzdGFjayk6DQogICAgJycnDQogICAgR2l2ZW4gYSBzdHJpbmcgb24gdGhlIHN0YWNrIHJlcGxh
|
dGFjaw0KDQoNCkBpbnN0YWxsDQpAU2ltcGxlRnVuY3Rpb25XcmFwcGVyDQpkZWYgc3BsaXRsaW5l
|
||||||
Y2UgaXQgd2l0aCBhIGxpc3Qgb2YgdGhlIGxpbmVzIGluDQogICAgdGhlIHN0cmluZy4NCiAgICAn
|
cyhzdGFjayk6DQogICAgJycnDQogICAgR2l2ZW4gYSBzdHJpbmcgb24gdGhlIHN0YWNrIHJlcGxh
|
||||||
JycNCiAgICB0ZXh0LCBzdGFjayA9IHN0YWNrDQogICAgYXNzZXJ0IGlzaW5zdGFuY2UodGV4dCwg
|
Y2UgaXQgd2l0aCBhIGxpc3Qgb2YgdGhlIGxpbmVzIGluDQogICAgdGhlIHN0cmluZy4NCiAgICAn
|
||||||
c3RyKSwgcmVwcih0ZXh0KQ0KICAgIHJldHVybiBsaXN0X3RvX3N0YWNrKHRleHQuc3BsaXRsaW5l
|
JycNCiAgICB0ZXh0LCBzdGFjayA9IHN0YWNrDQogICAgYXNzZXJ0IGlzaW5zdGFuY2UodGV4dCwg
|
||||||
cygpKSwgc3RhY2sNCg0KDQpAaW5zdGFsbA0KQFNpbXBsZUZ1bmN0aW9uV3JhcHBlcg0KZGVmIGhp
|
c3RyKSwgcmVwcih0ZXh0KQ0KICAgIHJldHVybiBsaXN0X3RvX3N0YWNrKHRleHQuc3BsaXRsaW5l
|
||||||
eWEoc3RhY2spOg0KICAgICcnJw0KICAgIERlbW8gZnVuY3Rpb24gdG8gaW5zZXJ0ICJIaSBXb3Js
|
cygpKSwgc3RhY2sNCg0KDQpAaW5zdGFsbA0KQFNpbXBsZUZ1bmN0aW9uV3JhcHBlcg0KZGVmIGhp
|
||||||
ZCEiIGludG8gdGhlIGN1cnJlbnQgdmlld2VyLCBpZiBhbnkuDQogICAgJycnDQogICAgaWYgZC5m
|
eWEoc3RhY2spOg0KICAgICcnJw0KICAgIERlbW8gZnVuY3Rpb24gdG8gaW5zZXJ0ICJIaSBXb3Js
|
||||||
b2N1c2VkX3ZpZXdlcjoNCiAgICAgICAgZC5mb2N1c2VkX3ZpZXdlci5pbnNlcnQoJ0hpIFdvcmxk
|
ZCEiIGludG8gdGhlIGN1cnJlbnQgdmlld2VyLCBpZiBhbnkuDQogICAgJycnDQogICAgaWYgZC5m
|
||||||
IScpDQogICAgcmV0dXJuIHN0YWNrDQpQSwMEFAAAAAAA5GZ4TkXs5NYLAAAACwAAAAcAAABsb2cu
|
b2N1c2VkX3ZpZXdlcjoNCiAgICAgICAgZC5mb2N1c2VkX3ZpZXdlci5pbnNlcnQoJ0hpIFdvcmxk
|
||||||
dHh0Sm95cHkgbG9nDQpQSwMEFAAAAAAA5GZ4Tmf2u80CBQAAAgUAAAgAAABtZW51LnR4dCAgbmFt
|
IScpDQogICAgcmV0dXJuIHN0YWNrDQpQSwMEFAAAAAAA5GZ4TkXs5NYLAAAACwAAAAcAAABsb2cu
|
||||||
ZV92aWV3ZXINCiAgbGlzdF9yZXNvdXJjZXMNCiAgb3Blbl9yZXNvdXJjZV9hdF9nb29kX2xvY2F0
|
dHh0Sm95cHkgbG9nDQpQSwMEFAAAAAAA5GZ4Tmf2u80CBQAAAgUAAAgAAABtZW51LnR4dCAgbmFt
|
||||||
aW9uDQogIGdvb2Rfdmlld2VyX2xvY2F0aW9uDQogIG9wZW5fdmlld2VyDQogIHNlZV9zdGFjaw0K
|
ZV92aWV3ZXINCiAgbGlzdF9yZXNvdXJjZXMNCiAgb3Blbl9yZXNvdXJjZV9hdF9nb29kX2xvY2F0
|
||||||
ICBzZWVfcmVzb3VyY2VzDQogIHNlZV9kZWZpbml0aW9ucw0KICBzZWVfbG9nDQogIHJlc2V0X2xv
|
aW9uDQogIGdvb2Rfdmlld2VyX2xvY2F0aW9uDQogIG9wZW5fdmlld2VyDQogIHNlZV9zdGFjaw0K
|
||||||
Zw0KDQogIGluc2NyaWJlDQogIGV2YWx1YXRlDQoNCiAgcG9wIGNsZWFyICAgIGR1cCBzd2FwDQoN
|
ICBzZWVfcmVzb3VyY2VzDQogIHNlZV9kZWZpbml0aW9ucw0KICBzZWVfbG9nDQogIHJlc2V0X2xv
|
||||||
CiAgYWRkIHN1YiBtdWwgZGl2IHRydWVkaXYgbW9kdWx1cyBkaXZtb2QNCiAgcG0gKysgLS0gc3Vt
|
Zw0KDQogIGluc2NyaWJlDQogIGV2YWx1YXRlDQoNCiAgcG9wIGNsZWFyICAgIGR1cCBzd2FwDQoN
|
||||||
IHByb2R1Y3QgcG93IHNxciBzcXJ0DQogIDwgPD0gPSA+PSA+IDw+DQogICYgPDwgPj4NCg0KICBp
|
CiAgYWRkIHN1YiBtdWwgZGl2IHRydWVkaXYgbW9kdWx1cyBkaXZtb2QNCiAgcG0gKysgLS0gc3Vt
|
||||||
IGR1cGRpcA0KDQohPSAlICYgKiAqZnJhY3Rpb24gKmZyYWN0aW9uMCArICsrIC0gLS0gLyA8IDw8
|
IHByb2R1Y3QgcG93IHNxciBzcXJ0DQogIDwgPD0gPSA+PSA+IDw+DQogICYgPDwgPj4NCg0KICBp
|
||||||
IDw9IDw+ID0gPiA+PSA+PiA/IF4NCmFicyBhZGQgYW5hbW9ycGhpc20gYW5kIGFwcDEgYXBwMiBh
|
IGR1cGRpcA0KDQohPSAlICYgKiAqZnJhY3Rpb24gKmZyYWN0aW9uMCArICsrIC0gLS0gLyA8IDw8
|
||||||
cHAzIGF0IGF2ZXJhZ2UNCmIgYmluYXJ5IGJyYW5jaA0KY2hvaWNlIGNsZWFyIGNsZWF2ZSBjb25j
|
IDw9IDw+ID0gPiA+PSA+PiA/IF4NCmFicyBhZGQgYW5hbW9ycGhpc20gYW5kIGFwcDEgYXBwMiBh
|
||||||
YXQgY29ucw0KZGluZnJpcnN0IGRpcCBkaXBkIGRpcGRkIGRpc2Vuc3RhY2tlbiBkaXYgZGl2bW9k
|
cHAzIGF0IGF2ZXJhZ2UNCmIgYmluYXJ5IGJyYW5jaA0KY2hvaWNlIGNsZWFyIGNsZWF2ZSBjb25j
|
||||||
IGRvd25fdG9femVybyBkcm9wDQpkdWRpcGQgZHVwIGR1cGQgZHVwZGlwDQplbnN0YWNrZW4gZXEN
|
YXQgY29ucw0KZGluZnJpcnN0IGRpcCBkaXBkIGRpcGRkIGRpc2Vuc3RhY2tlbiBkaXYgZGl2bW9k
|
||||||
CmZpcnN0IGZsYXR0ZW4gZmxvb3IgZmxvb3JkaXYNCmdjZCBnZSBnZW5yZWMgZ2V0aXRlbSBncmFu
|
IGRvd25fdG9femVybyBkcm9wDQpkdWRpcGQgZHVwIGR1cGQgZHVwZGlwDQplbnN0YWNrZW4gZXEN
|
||||||
ZF9yZXNldCBndA0KaGVscA0KaSBpZCBpZnRlIGluZnJhIGluc2NyaWJlDQprZXlfYmluZGluZ3MN
|
CmZpcnN0IGZsYXR0ZW4gZmxvb3IgZmxvb3JkaXYNCmdjZCBnZSBnZW5yZWMgZ2V0aXRlbSBncmFu
|
||||||
CmxlIGxlYXN0X2ZyYWN0aW9uIGxvb3AgbHNoaWZ0IGx0DQptYXAgbWF4IG1pbiBtb2QgbW9kdWx1
|
ZF9yZXNldCBndA0KaGVscA0KaSBpZCBpZnRlIGluZnJhIGluc2NyaWJlDQprZXlfYmluZGluZ3MN
|
||||||
cyBtb3VzZV9iaW5kaW5ncyBtdWwNCm5lIG5lZyBub3QgbnVsbGFyeQ0Kb2Ygb3Igb3Zlcg0KcGFt
|
CmxlIGxlYXN0X2ZyYWN0aW9uIGxvb3AgbHNoaWZ0IGx0DQptYXAgbWF4IG1pbiBtb2QgbW9kdWx1
|
||||||
IHBhcnNlIHBpY2sgcG0gcG9wIHBvcGQgcG9wZGQgcG9wb3AgcG93IHByZWQgcHJpbXJlYyBwcm9k
|
cyBtb3VzZV9iaW5kaW5ncyBtdWwNCm5lIG5lZyBub3QgbnVsbGFyeQ0Kb2Ygb3Igb3Zlcg0KcGFt
|
||||||
dWN0DQpxdW90ZWQNCnJhbmdlIHJhbmdlX3RvX3plcm8gcmVtIHJlbWFpbmRlciByZW1vdmUgcmVz
|
IHBhcnNlIHBpY2sgcG0gcG9wIHBvcGQgcG9wZGQgcG9wb3AgcG93IHByZWQgcHJpbXJlYyBwcm9k
|
||||||
ZXRfbG9nIHJlc3QgcmV2ZXJzZQ0Kcm9sbDwgcm9sbD4gcm9sbGRvd24gcm9sbHVwIHJzaGlmdCBy
|
dWN0DQpxdW90ZWQNCnJhbmdlIHJhbmdlX3RvX3plcm8gcmVtIHJlbWFpbmRlciByZW1vdmUgcmVz
|
||||||
dW4NCnNlY29uZCBzZWxlY3Qgc2hhcmluZyBzaG93X2xvZyBzaHVudCBzaXplIHNvcnQgc3FyIHNx
|
ZXRfbG9nIHJlc3QgcmV2ZXJzZQ0Kcm9sbDwgcm9sbD4gcm9sbGRvd24gcm9sbHVwIHJzaGlmdCBy
|
||||||
cnQgc3RhY2sgc3RlcA0Kc3RlcF96ZXJvIHN1YiBzdWNjIHN1bSBzd2FhY2sgc3dhcCBzd29uY2F0
|
dW4NCnNlY29uZCBzZWxlY3Qgc2hhcmluZyBzaG93X2xvZyBzaHVudCBzaXplIHNvcnQgc3FyIHNx
|
||||||
IHN3b25zDQp0YWtlIHRlcm5hcnkgdGhpcmQgdGltZXMgdHJ1ZWRpdiB0cnV0aHkgdHVjaw0KdW5h
|
cnQgc3RhY2sgc3RlcA0Kc3RlcF96ZXJvIHN1YiBzdWNjIHN1bSBzd2FhY2sgc3dhcCBzd29uY2F0
|
||||||
cnkgdW5jb25zIHVuaXF1ZSB1bml0IHVucXVvdGVkIHVuc3RhY2sNCnZvaWQNCndhcnJhbnR5IHdo
|
IHN3b25zDQp0YWtlIHRlcm5hcnkgdGhpcmQgdGltZXMgdHJ1ZWRpdiB0cnV0aHkgdHVjaw0KdW5h
|
||||||
aWxlIHdvcmRzDQp4IHhvcg0KemlwDQpQSwMEFAAAAAAA5GZ4TgCrPcaOEAAAjhAAAAsAAABzY3Jh
|
cnkgdW5jb25zIHVuaXF1ZSB1bml0IHVucXVvdGVkIHVuc3RhY2sNCnZvaWQNCndhcnJhbnR5IHdo
|
||||||
dGNoLnR4dFdoYXQgaXMgaXQ/DQoNCkEgc2ltcGxlIEdyYXBoaWNhbCBVc2VyIEludGVyZmFjZSBm
|
aWxlIHdvcmRzDQp4IHhvcg0KemlwDQpQSwMEFAAAAAAA5GZ4TgCrPcaOEAAAjhAAAAsAAABzY3Jh
|
||||||
b3IgdGhlIEpveSBwcm9ncmFtbWluZyBsYW5ndWFnZSwNCndyaXR0ZW4gdXNpbmcgUHlnYW1lIHRv
|
dGNoLnR4dFdoYXQgaXMgaXQ/DQoNCkEgc2ltcGxlIEdyYXBoaWNhbCBVc2VyIEludGVyZmFjZSBm
|
||||||
IGJ5cGFzcyBYMTEgZXQuIGFsLiwgbW9kZWxlZCBvbiB0aGUgT2Jlcm9uIE9TLCBhbmQNCmludGVu
|
b3IgdGhlIEpveSBwcm9ncmFtbWluZyBsYW5ndWFnZSwNCndyaXR0ZW4gdXNpbmcgUHlnYW1lIHRv
|
||||||
ZGVkIHRvIGJlIGp1c3QgZnVuY3Rpb25hbCBlbm91Z2ggdG8gc3VwcG9ydCBib290c3RyYXBwaW5n
|
IGJ5cGFzcyBYMTEgZXQuIGFsLiwgbW9kZWxlZCBvbiB0aGUgT2Jlcm9uIE9TLCBhbmQNCmludGVu
|
||||||
IGZ1cnRoZXIgSm95DQpkZXZlbG9wbWVudC4NCg0KSXQncyBiYXNpYyBmdW5jdGlvbmFsaXR5IGlz
|
ZGVkIHRvIGJlIGp1c3QgZnVuY3Rpb25hbCBlbm91Z2ggdG8gc3VwcG9ydCBib290c3RyYXBwaW5n
|
||||||
IG1vcmUtb3ItbGVzcyBhcyBhIGNydWRlIHRleHQgZWRpdG9yIGFsb25nIHdpdGgNCmEgc2ltcGxl
|
IGZ1cnRoZXIgSm95DQpkZXZlbG9wbWVudC4NCg0KSXQncyBiYXNpYyBmdW5jdGlvbmFsaXR5IGlz
|
||||||
IEpveSBydW50aW1lIChpbnRlcnByZXRlciwgc3RhY2ssIGFuZCBkaWN0aW9uYXJ5LikgIEl0IGF1
|
IG1vcmUtb3ItbGVzcyBhcyBhIGNydWRlIHRleHQgZWRpdG9yIGFsb25nIHdpdGgNCmEgc2ltcGxl
|
||||||
dG8tIHNhdmVzDQphbnkgbmFtZWQgZmlsZXMgKGluIGEgdmVyc2lvbmVkIGhvbWUgZGlyZWN0b3J5
|
IEpveSBydW50aW1lIChpbnRlcnByZXRlciwgc3RhY2ssIGFuZCBkaWN0aW9uYXJ5LikgIEl0IGF1
|
||||||
KSBhbmQgeW91IGNhbiB3cml0ZSBuZXcgSm95DQpwcmltaXRpdmVzIGluIFB5dGhvbiBhbmQgSm95
|
dG8tIHNhdmVzDQphbnkgbmFtZWQgZmlsZXMgKGluIGEgdmVyc2lvbmVkIGhvbWUgZGlyZWN0b3J5
|
||||||
IGRlZmluaXRpb25zIGFuZCBpbW1lZGlhdGVseSBpbnN0YWxsIGFuZCB1c2UNCnRoZW0sIGFzIHdl
|
KSBhbmQgeW91IGNhbiB3cml0ZSBuZXcgSm95DQpwcmltaXRpdmVzIGluIFB5dGhvbiBhbmQgSm95
|
||||||
bGwgYXMgcmVjb3JkaW5nIHRoZW0gZm9yIHJldXNlIChhZnRlciByZXN0YXJ0cy4pDQoNCkN1cnJl
|
IGRlZmluaXRpb25zIGFuZCBpbW1lZGlhdGVseSBpbnN0YWxsIGFuZCB1c2UNCnRoZW0sIGFzIHdl
|
||||||
bnRseSwgdGhlcmUgYXJlIG9ubHkgdHdvIGtpbmRzIG9mIChpbnRlcmVzdGluZykgdmlld2Vyczog
|
bGwgYXMgcmVjb3JkaW5nIHRoZW0gZm9yIHJldXNlIChhZnRlciByZXN0YXJ0cy4pDQoNCkN1cnJl
|
||||||
VGV4dFZpZXdlcnMNCmFuZCBTdGFja1ZpZXdlci4gVGhlIFRleHRWaWV3ZXJzIGFyZSBjcnVkZSB0
|
bnRseSwgdGhlcmUgYXJlIG9ubHkgdHdvIGtpbmRzIG9mIChpbnRlcmVzdGluZykgdmlld2Vyczog
|
||||||
ZXh0IGVkaXRvcnMuICBUaGV5IHByb3ZpZGUNCmp1c3QgZW5vdWdoIGZ1bmN0aW9uYWxpdHkgdG8g
|
VGV4dFZpZXdlcnMNCmFuZCBTdGFja1ZpZXdlci4gVGhlIFRleHRWaWV3ZXJzIGFyZSBjcnVkZSB0
|
||||||
bGV0IHRoZSB1c2VyIHdyaXRlIHRleHQgYW5kIGNvZGUgKFB5dGhvbiBhbmQNCkpveSkgYW5kIGV4
|
ZXh0IGVkaXRvcnMuICBUaGV5IHByb3ZpZGUNCmp1c3QgZW5vdWdoIGZ1bmN0aW9uYWxpdHkgdG8g
|
||||||
ZWN1dGUgSm95IGZ1bmN0aW9ucy4gIE9uZSBpbXBvcnRhbnQgdGhpbmcgdGhleSBkbyBpcw0KYXV0
|
bGV0IHRoZSB1c2VyIHdyaXRlIHRleHQgYW5kIGNvZGUgKFB5dGhvbiBhbmQNCkpveSkgYW5kIGV4
|
||||||
b21hdGljYWxseSBzYXZlIHRoZWlyIGNvbnRlbnQgYWZ0ZXIgY2hhbmdlcy4gIE5vIG1vcmUgbG9z
|
ZWN1dGUgSm95IGZ1bmN0aW9ucy4gIE9uZSBpbXBvcnRhbnQgdGhpbmcgdGhleSBkbyBpcw0KYXV0
|
||||||
dCB3b3JrLg0KDQpUaGUgU3RhY2tWaWV3ZXIgaXMgYSBzcGVjaWFsaXplZCBUZXh0Vmlld2VyIHRo
|
b21hdGljYWxseSBzYXZlIHRoZWlyIGNvbnRlbnQgYWZ0ZXIgY2hhbmdlcy4gIE5vIG1vcmUgbG9z
|
||||||
YXQgc2hvd3MgdGhlIGNvbnRlbnRzIG9mIHRoZQ0KSm95IHN0YWNrIG9uZSBsaW5lIHBlciBzdGFj
|
dCB3b3JrLg0KDQpUaGUgU3RhY2tWaWV3ZXIgaXMgYSBzcGVjaWFsaXplZCBUZXh0Vmlld2VyIHRo
|
||||||
ayBpdGVtLiAgSXQncyBhIHZlcnkgaGFuZHkgdmlzdWFsIGFpZCB0byBrZWVwDQp0cmFjayBvZiB3
|
YXQgc2hvd3MgdGhlIGNvbnRlbnRzIG9mIHRoZQ0KSm95IHN0YWNrIG9uZSBsaW5lIHBlciBzdGFj
|
||||||
aGF0J3MgZ29pbmcgb24uICBUaGVyZSdzIGFsc28gYSBsb2cudHh0IGZpbGUgdGhhdCBnZXRzIHdy
|
ayBpdGVtLiAgSXQncyBhIHZlcnkgaGFuZHkgdmlzdWFsIGFpZCB0byBrZWVwDQp0cmFjayBvZiB3
|
||||||
aXR0ZW4NCnRvIHdoZW4gY29tbWFuZHMgYXJlIGV4ZWN1dGVkLCBhbmQgc28gcmVjb3JkcyB0aGUg
|
aGF0J3MgZ29pbmcgb24uICBUaGVyZSdzIGFsc28gYSBsb2cudHh0IGZpbGUgdGhhdCBnZXRzIHdy
|
||||||
bG9nIG9mIHVzZXIgYWN0aW9ucyBhbmQNCnN5c3RlbSBldmVudHMuICBJdCB0ZW5kcyB0byBmaWxs
|
aXR0ZW4NCnRvIHdoZW4gY29tbWFuZHMgYXJlIGV4ZWN1dGVkLCBhbmQgc28gcmVjb3JkcyB0aGUg
|
||||||
IHVwIHF1aWNrbHkgc28gdGhlcmUncyBhIHJlc2V0X2xvZyBjb21tYW5kDQp0aGF0IGNsZWFycyBp
|
bG9nIG9mIHVzZXIgYWN0aW9ucyBhbmQNCnN5c3RlbSBldmVudHMuICBJdCB0ZW5kcyB0byBmaWxs
|
||||||
dCBvdXQuDQoNClZpZXdlcnMgaGF2ZSAiZ3JvdyIgYW5kICJjbG9zZSIgaW4gdGhlaXIgbWVudSBi
|
IHVwIHF1aWNrbHkgc28gdGhlcmUncyBhIHJlc2V0X2xvZyBjb21tYW5kDQp0aGF0IGNsZWFycyBp
|
||||||
YXJzLiAgVGhlc2UgYXJlIGJ1dHRvbnMuDQpXaGVuIHlvdSByaWdodC1jbGljayBvbiBncm93IGEg
|
dCBvdXQuDQoNClZpZXdlcnMgaGF2ZSAiZ3JvdyIgYW5kICJjbG9zZSIgaW4gdGhlaXIgbWVudSBi
|
||||||
dmlld2VyIGEgY29weSBpcyBjcmVhdGVkIHRoYXQgY292ZXJzIHRoYXQNCnZpZXdlcidzIGVudGly
|
YXJzLiAgVGhlc2UgYXJlIGJ1dHRvbnMuDQpXaGVuIHlvdSByaWdodC1jbGljayBvbiBncm93IGEg
|
||||||
ZSB0cmFjay4gIElmIHlvdSBncm93IGEgdmlld2VyIHRoYXQgYWxyZWFkeSB0YWtlcyB1cCBpdHMN
|
dmlld2VyIGEgY29weSBpcyBjcmVhdGVkIHRoYXQgY292ZXJzIHRoYXQNCnZpZXdlcidzIGVudGly
|
||||||
Cndob2xlIHRyYWNrIHRoZW4gYSBjb3B5IGlzIGNyZWF0ZWQgdGhhdCB0YWtlcyB1cCBhbiBhZGRp
|
ZSB0cmFjay4gIElmIHlvdSBncm93IGEgdmlld2VyIHRoYXQgYWxyZWFkeSB0YWtlcyB1cCBpdHMN
|
||||||
dGlvbmFsIHRyYWNrLCB1cA0KdG8gdGhlIHdob2xlIHNjcmVlbi4gIENsb3NpbmcgYSB2aWV3ZXIg
|
Cndob2xlIHRyYWNrIHRoZW4gYSBjb3B5IGlzIGNyZWF0ZWQgdGhhdCB0YWtlcyB1cCBhbiBhZGRp
|
||||||
anVzdCBkZWxldGVzIHRoYXQgdmlld2VyLCBhbmQgd2hlbg0KYSB0cmFjayBoYXMgbm8gbW9yZSB2
|
dGlvbmFsIHRyYWNrLCB1cA0KdG8gdGhlIHdob2xlIHNjcmVlbi4gIENsb3NpbmcgYSB2aWV3ZXIg
|
||||||
aWV3ZXJzLCBpdCBpcyBkZWxldGVkIGFuZCB0aGF0IGV4cG9zZXMgYW55IHByZXZpb3VzDQp0cmFj
|
anVzdCBkZWxldGVzIHRoYXQgdmlld2VyLCBhbmQgd2hlbg0KYSB0cmFjayBoYXMgbm8gbW9yZSB2
|
||||||
a3MgYW5kIHZpZXdlcnMgdGhhdCB3ZXJlIGhpZGRlbi4NCg0KKE5vdGU6IGlmIHlvdSBldmVyIGNs
|
aWV3ZXJzLCBpdCBpcyBkZWxldGVkIGFuZCB0aGF0IGV4cG9zZXMgYW55IHByZXZpb3VzDQp0cmFj
|
||||||
b3NlIGFsbCB0aGUgdmlld2VycyBhbmQgYXJlIHNpdHRpbmcgYXQgYSBibGFuayBzY3JlZW4NCndp
|
a3MgYW5kIHZpZXdlcnMgdGhhdCB3ZXJlIGhpZGRlbi4NCg0KKE5vdGU6IGlmIHlvdSBldmVyIGNs
|
||||||
dGggIG5vd2hlcmUgdG8gdHlwZSBhbmQgZXhlY3V0ZSBjb21tYW5kcywgcHJlc3MgdGhlIFBhdXNl
|
b3NlIGFsbCB0aGUgdmlld2VycyBhbmQgYXJlIHNpdHRpbmcgYXQgYSBibGFuayBzY3JlZW4NCndp
|
||||||
L0JyZWFrIGtleS4NClRoaXMgd2lsbCBvcGVuIGEgbmV3ICJ0cmFwIiB2aWV3ZXIgd2hpY2ggeW91
|
dGggIG5vd2hlcmUgdG8gdHlwZSBhbmQgZXhlY3V0ZSBjb21tYW5kcywgcHJlc3MgdGhlIFBhdXNl
|
||||||
IGNhbiB0aGVuIHVzZSB0byByZWNvdmVyLikNCg0KQ29waWVzIG9mIGEgdmlld2VyIGFsbCBzaGFy
|
L0JyZWFrIGtleS4NClRoaXMgd2lsbCBvcGVuIGEgbmV3ICJ0cmFwIiB2aWV3ZXIgd2hpY2ggeW91
|
||||||
ZSB0aGUgc2FtZSBtb2RlbCBhbmQgdXBkYXRlIHRoZWlyIGRpc3BsYXkgYXMgaXQNCmNoYW5nZXMu
|
IGNhbiB0aGVuIHVzZSB0byByZWNvdmVyLikNCg0KQ29waWVzIG9mIGEgdmlld2VyIGFsbCBzaGFy
|
||||||
IChJZiB5b3UgaGF2ZSB0d28gdmlld2VycyBvcGVuIG9uIHRoZSBzYW1lIG5hbWVkIHJlc291cmNl
|
ZSB0aGUgc2FtZSBtb2RlbCBhbmQgdXBkYXRlIHRoZWlyIGRpc3BsYXkgYXMgaXQNCmNoYW5nZXMu
|
||||||
IGFuZCBlZGl0DQpvbmUgeW91J2xsIHNlZSB0aGUgb3RoZXIgdXBkYXRlIGFzIHlvdSB0eXBlLikN
|
IChJZiB5b3UgaGF2ZSB0d28gdmlld2VycyBvcGVuIG9uIHRoZSBzYW1lIG5hbWVkIHJlc291cmNl
|
||||||
Cg0KVUkgR3VpZGUNCg0KbGVmdCBtb3VzZSBzZXRzIGN1cnNvciBpbiB0ZXh0LCBpbiBtZW51IGJh
|
IGFuZCBlZGl0DQpvbmUgeW91J2xsIHNlZSB0aGUgb3RoZXIgdXBkYXRlIGFzIHlvdSB0eXBlLikN
|
||||||
ciByZXNpemVzIHZpZXdlciBpbnRlcmFjdGl2ZWx5DQoodGhpcyBpcyBhIGxpdHRsZSBidWdneSBp
|
Cg0KVUkgR3VpZGUNCg0KbGVmdCBtb3VzZSBzZXRzIGN1cnNvciBpbiB0ZXh0LCBpbiBtZW51IGJh
|
||||||
biB0aGF0IHlvdSBjYW4gbW92ZSB0aGUgbW91c2UgcXVpY2tseSBhbmQgZ2V0DQpvdXRzaWRlIHRo
|
ciByZXNpemVzIHZpZXdlciBpbnRlcmFjdGl2ZWx5DQoodGhpcyBpcyBhIGxpdHRsZSBidWdneSBp
|
||||||
ZSBtZW51LCBsZWF2aW5nIHRoZSB2aWV3ZXIgaW4gdGhlICJyZXNpemluZyIgc3RhdGUuIFVudGls
|
biB0aGF0IHlvdSBjYW4gbW92ZSB0aGUgbW91c2UgcXVpY2tseSBhbmQgZ2V0DQpvdXRzaWRlIHRo
|
||||||
IEkgZml4DQp0aGlzLCB0aGUgd29ya2Fyb3VuZCBpcyB0byBqdXN0IGdyYWIgdGhlIG1lbnUgYmFy
|
ZSBtZW51LCBsZWF2aW5nIHRoZSB2aWV3ZXIgaW4gdGhlICJyZXNpemluZyIgc3RhdGUuIFVudGls
|
||||||
IGFnYWluIGFuZCB3aWdnbGUgaXQgYQ0KZmV3IHBpeGVscyBhbmQgbGV0IGdvLiAgVGhpcyB3aWxs
|
IEkgZml4DQp0aGlzLCB0aGUgd29ya2Fyb3VuZCBpcyB0byBqdXN0IGdyYWIgdGhlIG1lbnUgYmFy
|
||||||
IHJlc2V0IHRoZSBtYWNoaW5lcnkuKQ0KDQpSaWdodCBtb3VzZSBleGVjdXRlcyBKb3kgY29tbWFu
|
IGFnYWluIGFuZCB3aWdnbGUgaXQgYQ0KZmV3IHBpeGVscyBhbmQgbGV0IGdvLiAgVGhpcyB3aWxs
|
||||||
ZCAoZnVuY3Rpb25zKSwgYW5kIHlvdSBjYW4gZHJhZyB3aXRoIHRoZQ0KcmlnaHQgYnV0dG9uIHRv
|
IHJlc2V0IHRoZSBtYWNoaW5lcnkuKQ0KDQpSaWdodCBtb3VzZSBleGVjdXRlcyBKb3kgY29tbWFu
|
||||||
IGhpZ2hsaWdodCAod2VsbCwgdW5kZXJsaW5lKSBjb21tYW5kcy4gIFdvcmRzIHRoYXQgYXJlbid0
|
ZCAoZnVuY3Rpb25zKSwgYW5kIHlvdSBjYW4gZHJhZyB3aXRoIHRoZQ0KcmlnaHQgYnV0dG9uIHRv
|
||||||
DQpuYW1lcyBvZiBKb3kgY29tbWFuZHMgd29uJ3QgYmUgdW5kZXJsaW5lZC4gIFJlbGVhc2UgdGhl
|
IGhpZ2hsaWdodCAod2VsbCwgdW5kZXJsaW5lKSBjb21tYW5kcy4gIFdvcmRzIHRoYXQgYXJlbid0
|
||||||
IGJ1dHRvbiB0byBleGVjdXRlDQp0aGUgY29tbWFuZC4NCg0KVGhlIG1pZGRsZSBtb3VzZSBidXR0
|
DQpuYW1lcyBvZiBKb3kgY29tbWFuZHMgd29uJ3QgYmUgdW5kZXJsaW5lZC4gIFJlbGVhc2UgdGhl
|
||||||
b24gKHVzdWFsbHkgYSB3aGVlbCB0aGVzZSBkYXlzKSBzY3JvbGxzIHRoZSB0ZXh0IGJ1dA0KeW91
|
IGJ1dHRvbiB0byBleGVjdXRlDQp0aGUgY29tbWFuZC4NCg0KVGhlIG1pZGRsZSBtb3VzZSBidXR0
|
||||||
IGNhbiBhbHNvIGNsaWNrIGFuZCBkcmFnIGFueSB2aWV3ZXIgd2l0aCBpdCB0byBtb3ZlIHRoYXQg
|
b24gKHVzdWFsbHkgYSB3aGVlbCB0aGVzZSBkYXlzKSBzY3JvbGxzIHRoZSB0ZXh0IGJ1dA0KeW91
|
||||||
dmlld2VyIHRvDQphbm90aGVyIHRyYWNrIG9yIHRvIGEgZGlmZmVyZW50IGxvY2F0aW9uIGluIHRo
|
IGNhbiBhbHNvIGNsaWNrIGFuZCBkcmFnIGFueSB2aWV3ZXIgd2l0aCBpdCB0byBtb3ZlIHRoYXQg
|
||||||
ZSBzYW1lIHRyYWNrLiAgVGhlcmUncyBubw0KZGlyZWN0IHZpc3VhbCBmZWVkYmFjayBmb3IgdGhp
|
dmlld2VyIHRvDQphbm90aGVyIHRyYWNrIG9yIHRvIGEgZGlmZmVyZW50IGxvY2F0aW9uIGluIHRo
|
||||||
cyAoeWV0KSBidXQgdGhhdCBkb3Nlbid0IHNlZW0gdG8gaW1wYWlyIGl0cw0KdXNlZnVsbmVzcy4N
|
ZSBzYW1lIHRyYWNrLiAgVGhlcmUncyBubw0KZGlyZWN0IHZpc3VhbCBmZWVkYmFjayBmb3IgdGhp
|
||||||
Cg0KRjEsIEYyIC0gc2V0IHNlbGVjdGlvbiBiZWdpbiBhbmQgZW5kIG1hcmtlcnMgKGNydWRlIGJ1
|
cyAoeWV0KSBidXQgdGhhdCBkb3Nlbid0IHNlZW0gdG8gaW1wYWlyIGl0cw0KdXNlZnVsbmVzcy4N
|
||||||
dCB1c2FibGUuKQ0KDQpGMyAtIGNvcHkgc2VsZWN0ZWQgdGV4dCB0byB0aGUgdG9wIG9mIHRoZSBz
|
Cg0KRjEsIEYyIC0gc2V0IHNlbGVjdGlvbiBiZWdpbiBhbmQgZW5kIG1hcmtlcnMgKGNydWRlIGJ1
|
||||||
dGFjay4NCg0KU2hpZnQtRjMgLSBhcyBjb3B5IHRoZW4gcnVuICJwYXJzZSIgY29tbWFuZCBvbiB0
|
dCB1c2FibGUuKQ0KDQpGMyAtIGNvcHkgc2VsZWN0ZWQgdGV4dCB0byB0aGUgdG9wIG9mIHRoZSBz
|
||||||
aGUgc3RyaW5nLg0KDQpGNCAtIGN1dCBzZWxlY3RlZCB0ZXh0IHRvIHRoZSB0b3Agb2YgdGhlIHN0
|
dGFjay4NCg0KU2hpZnQtRjMgLSBhcyBjb3B5IHRoZW4gcnVuICJwYXJzZSIgY29tbWFuZCBvbiB0
|
||||||
YWNrLg0KDQpTaGlmdC1GNCAtIGFzIGN1dCB0aGVuIHJ1biAicG9wIiAoZGVsZXRlIHNlbGVjdGlv
|
aGUgc3RyaW5nLg0KDQpGNCAtIGN1dCBzZWxlY3RlZCB0ZXh0IHRvIHRoZSB0b3Agb2YgdGhlIHN0
|
||||||
bi4pDQoNCkpveQ0KDQpQcmV0dHkgbXVjaCBhbGwgb2YgdGhlIHJlc3Qgb2YgdGhlIGZ1bmN0aW9u
|
YWNrLg0KDQpTaGlmdC1GNCAtIGFzIGN1dCB0aGVuIHJ1biAicG9wIiAoZGVsZXRlIHNlbGVjdGlv
|
||||||
YWxpdHkgb2YgdGhlIHN5c3RlbSBpcyBwcm92aWRlZA0KYnkgZXhlY3V0aW5nIEpveSBjb21tYW5k
|
bi4pDQoNCkpveQ0KDQpQcmV0dHkgbXVjaCBhbGwgb2YgdGhlIHJlc3Qgb2YgdGhlIGZ1bmN0aW9u
|
||||||
cyAoYWthIGZ1bmN0aW9ucywgYWthICJ3b3JkcyIgaW4gRm9ydGgpIGJ5IHJpZ2h0LQ0KY2xpY2tp
|
YWxpdHkgb2YgdGhlIHN5c3RlbSBpcyBwcm92aWRlZA0KYnkgZXhlY3V0aW5nIEpveSBjb21tYW5k
|
||||||
bmcgb24gdGhlaXIgbmFtZXMgaW4gYW55IHRleHQuDQoNClRvIGdldCBoZWxwIG9uIGEgSm95IGZ1
|
cyAoYWthIGZ1bmN0aW9ucywgYWthICJ3b3JkcyIgaW4gRm9ydGgpIGJ5IHJpZ2h0LQ0KY2xpY2tp
|
||||||
bmN0aW9uIHNlbGVjdCB0aGUgbmFtZSBvZiB0aGUgZnVuY3Rpb24gaW4gYQ0KVGV4dFZpZXdlciB1
|
bmcgb24gdGhlaXIgbmFtZXMgaW4gYW55IHRleHQuDQoNClRvIGdldCBoZWxwIG9uIGEgSm95IGZ1
|
||||||
c2luZyBGMSBhbmQgRjIsIHRoZW4gcHJlc3Mgc2hpZnQtRjMgdG8gcGFyc2UgdGhlIHNlbGVjdGlv
|
bmN0aW9uIHNlbGVjdCB0aGUgbmFtZSBvZiB0aGUgZnVuY3Rpb24gaW4gYQ0KVGV4dFZpZXdlciB1
|
||||||
bi4NClRoZSBmdW5jdGlvbiAocmVhbGx5IGl0cyBTeW1ib2wpIHdpbGwgYXBwZWFyIG9uIHRoZSBz
|
c2luZyBGMSBhbmQgRjIsIHRoZW4gcHJlc3Mgc2hpZnQtRjMgdG8gcGFyc2UgdGhlIHNlbGVjdGlv
|
||||||
dGFjayBpbiBicmFja2V0cyAoYQ0KInF1b3RlZCBwcm9ncmFtIiBzdWNoIGFzICJbcG9wXSIuKSAg
|
bi4NClRoZSBmdW5jdGlvbiAocmVhbGx5IGl0cyBTeW1ib2wpIHdpbGwgYXBwZWFyIG9uIHRoZSBz
|
||||||
VGhlbiByaWdodC1jbGljayBvbiB0aGUgd29yZCBoZWxwIGluDQphbnkgVGV4dFZpZXdlciAoaWYg
|
dGFjayBpbiBicmFja2V0cyAoYQ0KInF1b3RlZCBwcm9ncmFtIiBzdWNoIGFzICJbcG9wXSIuKSAg
|
||||||
aXQncyBub3QgYWxyZWFkeSB0aGVyZSwganVzdCB0eXBlIGl0IGluIHNvbWV3aGVyZS4pDQpUaGlz
|
VGhlbiByaWdodC1jbGljayBvbiB0aGUgd29yZCBoZWxwIGluDQphbnkgVGV4dFZpZXdlciAoaWYg
|
||||||
IHdpbGwgcHJpbnQgdGhlIGRvY3N0cmluZyBvciBkZWZpbml0aW9uIG9mIHRoZSB3b3JkIChmdW5j
|
aXQncyBub3QgYWxyZWFkeSB0aGVyZSwganVzdCB0eXBlIGl0IGluIHNvbWV3aGVyZS4pDQpUaGlz
|
||||||
dGlvbikgdG8NCnN0ZG91dC4gIEF0IHNvbWUgcG9pbnQgSSdsbCB3cml0ZSBhIHRoaW5nIHRvIHNl
|
IHdpbGwgcHJpbnQgdGhlIGRvY3N0cmluZyBvciBkZWZpbml0aW9uIG9mIHRoZSB3b3JkIChmdW5j
|
||||||
bmQgdGhhdCB0byB0aGUgbG9nLnR4dCBmaWxlDQppbnN0ZWFkLCBidXQgZm9yIG5vdyBsb29rIGZv
|
dGlvbikgdG8NCnN0ZG91dC4gIEF0IHNvbWUgcG9pbnQgSSdsbCB3cml0ZSBhIHRoaW5nIHRvIHNl
|
||||||
ciBvdXRwdXQgaW4gdGhlIHRlcm1pbmFsLg0KUEsDBBQAAAAAAORmeE53f5peAwAAAAMAAAAMAAAA
|
bmQgdGhhdCB0byB0aGUgbG9nLnR4dCBmaWxlDQppbnN0ZWFkLCBidXQgZm9yIG5vdyBsb29rIGZv
|
||||||
c3RhY2sucGlja2xlKHQuUEsBAhQAFAAAAAAA5GZ4Tv3gGVF+AwAAfgMAAA8AAAAAAAAAAAAAALaB
|
ciBvdXRwdXQgaW4gdGhlIHRlcm1pbmFsLg0KUEsDBBQAAAAAAORmeE53f5peAwAAAAMAAAAMAAAA
|
||||||
AAAAAGRlZmluaXRpb25zLnR4dFBLAQIUABQAAAAAACFrpk7/HHjxGBYAABgWAAAKAAAAAAAAAAAA
|
c3RhY2sucGlja2xlKHQuUEsBAhQAFAAAAAAA5GZ4Tv3gGVF+AwAAfgMAAA8AAAAAAAAAAAAAALaB
|
||||||
AAC2gasDAABsaWJyYXJ5LnB5UEsBAhQAFAAAAAAA5GZ4TkXs5NYLAAAACwAAAAcAAAAAAAAAAAAA
|
AAAAAGRlZmluaXRpb25zLnR4dFBLAQIUABQAAAAAACFrpk7/HHjxGBYAABgWAAAKAAAAAAAAAAAA
|
||||||
ALaB6xkAAGxvZy50eHRQSwECFAAUAAAAAADkZnhOZ/a7zQIFAAACBQAACAAAAAAAAAAAAAAAtoEb
|
AAC2gasDAABsaWJyYXJ5LnB5UEsBAhQAFAAAAAAA5GZ4TkXs5NYLAAAACwAAAAcAAAAAAAAAAAAA
|
||||||
GgAAbWVudS50eHRQSwECFAAUAAAAAADkZnhOAKs9xo4QAACOEAAACwAAAAAAAAAAAAAAtoFDHwAA
|
ALaB6xkAAGxvZy50eHRQSwECFAAUAAAAAADkZnhOZ/a7zQIFAAACBQAACAAAAAAAAAAAAAAAtoEb
|
||||||
c2NyYXRjaC50eHRQSwECFAAUAAAAAADkZnhOd3+aXgMAAAADAAAADAAAAAAAAAAAAAAAtoH6LwAA
|
GgAAbWVudS50eHRQSwECFAAUAAAAAADkZnhOAKs9xo4QAACOEAAACwAAAAAAAAAAAAAAtoFDHwAA
|
||||||
c3RhY2sucGlja2xlUEsFBgAAAAAGAAYAUwEAACcwAAAAAA==''')))
|
c2NyYXRjaC50eHRQSwECFAAUAAAAAADkZnhOd3+aXgMAAAADAAAADAAAAAAAAAAAAAAAtoH6LwAA
|
||||||
|
c3RhY2sucGlja2xlUEsFBgAAAAAGAAYAUwEAACcwAAAAAA==''')))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
print create_data()
|
if __name__ == '__main__':
|
||||||
|
print(create_data())
|
||||||
|
|
|
||||||
349
joy/vui/main.py
349
joy/vui/main.py
|
|
@ -1,174 +1,175 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright © 2019 Simon Forman
|
# Copyright © 2019 Simon Forman
|
||||||
#
|
#
|
||||||
# This file is part of Thun
|
# This file is part of Thun
|
||||||
#
|
#
|
||||||
# Thun is free software: you can redistribute it and/or modify
|
# Thun is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# Thun is distributed in the hope that it will be useful,
|
# Thun is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Thun. If not see <http://www.gnu.org/licenses/>.
|
# along with Thun. If not see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
'''
|
'''
|
||||||
|
|
||||||
Main Module
|
Main Module
|
||||||
======================================
|
======================================
|
||||||
|
|
||||||
Pulls everything together.
|
Pulls everything together.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
import os, sys, traceback
|
from __future__ import print_function
|
||||||
import pygame
|
import os, sys, traceback
|
||||||
from joy.library import initialize, DefinitionWrapper, SimpleFunctionWrapper
|
import pygame
|
||||||
from joy.vui import core, display, persist_task
|
from joy.library import initialize, DefinitionWrapper, SimpleFunctionWrapper
|
||||||
|
from joy.vui import core, display, persist_task
|
||||||
|
|
||||||
FULLSCREEN = '-f' in sys.argv
|
|
||||||
|
FULLSCREEN = '-f' in sys.argv
|
||||||
|
|
||||||
JOY_HOME = os.environ.get('JOY_HOME')
|
|
||||||
if JOY_HOME is None:
|
JOY_HOME = os.environ.get('JOY_HOME')
|
||||||
JOY_HOME = os.path.expanduser('~/.thun')
|
if JOY_HOME is None:
|
||||||
if not os.path.isabs(JOY_HOME):
|
JOY_HOME = os.path.expanduser('~/.thun')
|
||||||
raise ValueError('what directory?')
|
if not os.path.isabs(JOY_HOME):
|
||||||
|
raise ValueError('what directory?')
|
||||||
|
|
||||||
def load_definitions(pt, dictionary):
|
|
||||||
'''Load definitions from ``definitions.txt``.'''
|
def load_definitions(pt, dictionary):
|
||||||
lines = pt.open('definitions.txt')[1]
|
'''Load definitions from ``definitions.txt``.'''
|
||||||
for line in lines:
|
lines = pt.open('definitions.txt')[1]
|
||||||
if '==' in line:
|
for line in lines:
|
||||||
DefinitionWrapper.add_def(line, dictionary)
|
if '==' in line:
|
||||||
|
DefinitionWrapper.add_def(line, dictionary)
|
||||||
|
|
||||||
def load_primitives(home, name_space):
|
|
||||||
'''Load primitives from ``library.py``.'''
|
def load_primitives(home, name_space):
|
||||||
fn = os.path.join(home, 'library.py')
|
'''Load primitives from ``library.py``.'''
|
||||||
if os.path.exists(fn):
|
fn = os.path.join(home, 'library.py')
|
||||||
execfile(fn, name_space)
|
if os.path.exists(fn):
|
||||||
|
execfile(fn, name_space)
|
||||||
|
|
||||||
def init():
|
|
||||||
'''
|
def init():
|
||||||
Initialize the system.
|
'''
|
||||||
|
Initialize the system.
|
||||||
* Init PyGame
|
|
||||||
* Create main window
|
* Init PyGame
|
||||||
* Start the PyGame clock
|
* Create main window
|
||||||
* Set the event mask
|
* Start the PyGame clock
|
||||||
* Create the PersistTask
|
* Set the event mask
|
||||||
|
* Create the PersistTask
|
||||||
'''
|
|
||||||
print 'Initializing Pygame...'
|
'''
|
||||||
pygame.init()
|
print('Initializing Pygame...')
|
||||||
print 'Creating window...'
|
pygame.init()
|
||||||
if FULLSCREEN:
|
print('Creating window...')
|
||||||
screen = pygame.display.set_mode()
|
if FULLSCREEN:
|
||||||
else:
|
screen = pygame.display.set_mode()
|
||||||
screen = pygame.display.set_mode((1024, 768))
|
else:
|
||||||
clock = pygame.time.Clock()
|
screen = pygame.display.set_mode((1024, 768))
|
||||||
pygame.event.set_allowed(None)
|
clock = pygame.time.Clock()
|
||||||
pygame.event.set_allowed(core.ALLOWED_EVENTS)
|
pygame.event.set_allowed(None)
|
||||||
pt = persist_task.PersistTask(JOY_HOME)
|
pygame.event.set_allowed(core.ALLOWED_EVENTS)
|
||||||
return screen, clock, pt
|
pt = persist_task.PersistTask(JOY_HOME)
|
||||||
|
return screen, clock, pt
|
||||||
|
|
||||||
def init_context(screen, clock, pt):
|
|
||||||
'''
|
def init_context(screen, clock, pt):
|
||||||
More initialization
|
'''
|
||||||
|
More initialization
|
||||||
* Create the Joy dictionary
|
|
||||||
* Create the Display
|
* Create the Joy dictionary
|
||||||
* Open the log, menu, and scratch text viewers, and the stack pickle
|
* Create the Display
|
||||||
* Start the main loop
|
* Open the log, menu, and scratch text viewers, and the stack pickle
|
||||||
* Create the World object
|
* Start the main loop
|
||||||
* Register PersistTask and World message handlers with the Display
|
* Create the World object
|
||||||
* Load user function definitions.
|
* Register PersistTask and World message handlers with the Display
|
||||||
|
* Load user function definitions.
|
||||||
'''
|
|
||||||
D = initialize()
|
'''
|
||||||
d = display.Display(
|
D = initialize()
|
||||||
screen,
|
d = display.Display(
|
||||||
D.__contains__,
|
screen,
|
||||||
*((144 - 89, 144, 89) if FULLSCREEN else (89, 144))
|
D.__contains__,
|
||||||
)
|
*((144 - 89, 144, 89) if FULLSCREEN else (89, 144))
|
||||||
log = d.init_text(pt, 0, 0, 'log.txt')
|
)
|
||||||
tho = d.init_text(pt, 0, d.h / 3, 'menu.txt')
|
log = d.init_text(pt, 0, 0, 'log.txt')
|
||||||
t = d.init_text(pt, d.w / 2, 0, 'scratch.txt')
|
tho = d.init_text(pt, 0, d.h / 3, 'menu.txt')
|
||||||
loop = core.TheLoop(d, clock)
|
t = d.init_text(pt, d.w / 2, 0, 'scratch.txt')
|
||||||
stack_id, stack_holder = pt.open('stack.pickle')
|
loop = core.TheLoop(d, clock)
|
||||||
world = core.World(stack_id, stack_holder, D, d.broadcast, log)
|
stack_id, stack_holder = pt.open('stack.pickle')
|
||||||
loop.install_task(pt.task_run, 10000) # save files every ten seconds
|
world = core.World(stack_id, stack_holder, D, d.broadcast, log)
|
||||||
d.handlers.append(pt.handle)
|
loop.install_task(pt.task_run, 10000) # save files every ten seconds
|
||||||
d.handlers.append(world.handle)
|
d.handlers.append(pt.handle)
|
||||||
load_definitions(pt, D)
|
d.handlers.append(world.handle)
|
||||||
return locals()
|
load_definitions(pt, D)
|
||||||
|
return locals()
|
||||||
|
|
||||||
def error_guard(loop, n=10):
|
|
||||||
'''
|
def error_guard(loop, n=10):
|
||||||
Run a loop function, retry for ``n`` exceptions.
|
'''
|
||||||
Prints tracebacks on ``sys.stderr``.
|
Run a loop function, retry for ``n`` exceptions.
|
||||||
'''
|
Prints tracebacks on ``sys.stderr``.
|
||||||
error_count = 0
|
'''
|
||||||
while error_count < n:
|
error_count = 0
|
||||||
try:
|
while error_count < n:
|
||||||
loop()
|
try:
|
||||||
break
|
loop()
|
||||||
except:
|
break
|
||||||
traceback.print_exc(file=sys.stderr)
|
except:
|
||||||
error_count += 1
|
traceback.print_exc(file=sys.stderr)
|
||||||
|
error_count += 1
|
||||||
|
|
||||||
class FileFaker(object):
|
|
||||||
'''Pretends to be a file object but writes to log instead.'''
|
class FileFaker(object):
|
||||||
|
'''Pretends to be a file object but writes to log instead.'''
|
||||||
def __init__(self, log):
|
|
||||||
self.log = log
|
def __init__(self, log):
|
||||||
|
self.log = log
|
||||||
def write(self, text):
|
|
||||||
'''Write text to log.'''
|
def write(self, text):
|
||||||
self.log.append(text)
|
'''Write text to log.'''
|
||||||
|
self.log.append(text)
|
||||||
def flush(self):
|
|
||||||
pass
|
def flush(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def main(screen, clock, pt):
|
|
||||||
'''
|
def main(screen, clock, pt):
|
||||||
Main function.
|
'''
|
||||||
|
Main function.
|
||||||
* Call ``init_context()``
|
|
||||||
* Load primitives
|
* Call ``init_context()``
|
||||||
* Create an ``evaluate`` function that lets you just eval some Python code
|
* Load primitives
|
||||||
* Redirect ``stdout`` to the log using a ``FileFaker`` object, and...
|
* Create an ``evaluate`` function that lets you just eval some Python code
|
||||||
* Start the main loop.
|
* Redirect ``stdout`` to the log using a ``FileFaker`` object, and...
|
||||||
'''
|
* Start the main loop.
|
||||||
name_space = init_context(screen, clock, pt)
|
'''
|
||||||
load_primitives(pt.home, name_space.copy())
|
name_space = init_context(screen, clock, pt)
|
||||||
|
load_primitives(pt.home, name_space.copy())
|
||||||
@SimpleFunctionWrapper
|
|
||||||
def evaluate(stack):
|
@SimpleFunctionWrapper
|
||||||
'''Evaluate the Python code text on the top of the stack.'''
|
def evaluate(stack):
|
||||||
code, stack = stack
|
'''Evaluate the Python code text on the top of the stack.'''
|
||||||
exec code in name_space.copy()
|
code, stack = stack
|
||||||
return stack
|
exec(code, name_space.copy())
|
||||||
|
return stack
|
||||||
name_space['D']['evaluate'] = evaluate
|
|
||||||
|
name_space['D']['evaluate'] = evaluate
|
||||||
|
|
||||||
sys.stdout, old_stdout = FileFaker(name_space['log']), sys.stdout
|
|
||||||
try:
|
sys.stdout, old_stdout = FileFaker(name_space['log']), sys.stdout
|
||||||
error_guard(name_space['loop'].loop)
|
try:
|
||||||
finally:
|
error_guard(name_space['loop'].loop)
|
||||||
sys.stdout = old_stdout
|
finally:
|
||||||
|
sys.stdout = old_stdout
|
||||||
return name_space['d']
|
|
||||||
|
return name_space['d']
|
||||||
|
|
|
||||||
|
|
@ -1,272 +1,273 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright © 2019 Simon Forman
|
# Copyright © 2019 Simon Forman
|
||||||
#
|
#
|
||||||
# This file is part of Thun
|
# This file is part of Thun
|
||||||
#
|
#
|
||||||
# Thun is free software: you can redistribute it and/or modify
|
# Thun is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# Thun is distributed in the hope that it will be useful,
|
# Thun is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Thun. If not see <http://www.gnu.org/licenses/>.
|
# along with Thun. If not see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
'''
|
'''
|
||||||
|
|
||||||
Persist Task
|
Persist Task
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
This module deals with persisting the "resources" (text files and the
|
This module deals with persisting the "resources" (text files and the
|
||||||
stack) to the git repo in the ``JOY_HOME`` directory.
|
stack) to the git repo in the ``JOY_HOME`` directory.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
import os, pickle, traceback
|
from __future__ import print_function
|
||||||
from collections import Counter
|
import os, pickle, traceback
|
||||||
from dulwich.errors import NotGitRepository
|
from collections import Counter
|
||||||
from dulwich.repo import Repo
|
from dulwich.errors import NotGitRepository
|
||||||
from joy.vui import core, init_joy_home
|
from dulwich.repo import Repo
|
||||||
|
from joy.vui import core, init_joy_home
|
||||||
|
|
||||||
def open_repo(repo_dir=None, initialize=False):
|
|
||||||
'''
|
def open_repo(repo_dir=None, initialize=False):
|
||||||
Open, or create, and return a Dulwich git repo object for the given
|
'''
|
||||||
directory. If the dir path doesn't exist it will be created. If it
|
Open, or create, and return a Dulwich git repo object for the given
|
||||||
does exist but isn't a repo the result depends on the ``initialize``
|
directory. If the dir path doesn't exist it will be created. If it
|
||||||
argument. If it is ``False`` (the default) a ``NotGitRepository``
|
does exist but isn't a repo the result depends on the ``initialize``
|
||||||
exception is raised, otherwise ``git init`` is effected in the dir.
|
argument. If it is ``False`` (the default) a ``NotGitRepository``
|
||||||
'''
|
exception is raised, otherwise ``git init`` is effected in the dir.
|
||||||
if not os.path.exists(repo_dir):
|
'''
|
||||||
os.makedirs(repo_dir, 0700)
|
if not os.path.exists(repo_dir):
|
||||||
return init_repo(repo_dir)
|
os.makedirs(repo_dir, 0o700)
|
||||||
try:
|
return init_repo(repo_dir)
|
||||||
return Repo(repo_dir)
|
try:
|
||||||
except NotGitRepository:
|
return Repo(repo_dir)
|
||||||
if initialize:
|
except NotGitRepository:
|
||||||
return init_repo(repo_dir)
|
if initialize:
|
||||||
raise
|
return init_repo(repo_dir)
|
||||||
|
raise
|
||||||
|
|
||||||
def init_repo(repo_dir):
|
|
||||||
'''
|
def init_repo(repo_dir):
|
||||||
Initialize a git repository in the directory. Stage and commit all
|
'''
|
||||||
files (toplevel, not those in subdirectories if any) in the dir.
|
Initialize a git repository in the directory. Stage and commit all
|
||||||
'''
|
files (toplevel, not those in subdirectories if any) in the dir.
|
||||||
repo = Repo.init(repo_dir)
|
'''
|
||||||
init_joy_home.initialize(repo_dir)
|
repo = Repo.init(repo_dir)
|
||||||
repo.stage([
|
init_joy_home.initialize(repo_dir)
|
||||||
fn
|
repo.stage([
|
||||||
for fn in os.listdir(repo_dir)
|
fn
|
||||||
if os.path.isfile(os.path.join(repo_dir, fn))
|
for fn in os.listdir(repo_dir)
|
||||||
])
|
if os.path.isfile(os.path.join(repo_dir, fn))
|
||||||
repo.do_commit('Initial commit.', committer=core.COMMITTER)
|
])
|
||||||
return repo
|
repo.do_commit('Initial commit.', committer=core.COMMITTER)
|
||||||
|
return repo
|
||||||
|
|
||||||
def make_repo_relative_path_maker(repo):
|
|
||||||
'''
|
def make_repo_relative_path_maker(repo):
|
||||||
Helper function to return a function that returns a path given a path,
|
'''
|
||||||
that's relative to the repository.
|
Helper function to return a function that returns a path given a path,
|
||||||
'''
|
that's relative to the repository.
|
||||||
c = repo.controldir()
|
'''
|
||||||
def repo_relative_path(path):
|
c = repo.controldir()
|
||||||
return os.path.relpath(path, os.path.commonprefix((c, path)))
|
def repo_relative_path(path):
|
||||||
return repo_relative_path
|
return os.path.relpath(path, os.path.commonprefix((c, path)))
|
||||||
|
return repo_relative_path
|
||||||
|
|
||||||
class Resource(object):
|
|
||||||
'''
|
class Resource(object):
|
||||||
Handle the content of a text files as a list of lines, deal with
|
'''
|
||||||
saving it and staging the changes to a repo.
|
Handle the content of a text files as a list of lines, deal with
|
||||||
'''
|
saving it and staging the changes to a repo.
|
||||||
|
'''
|
||||||
def __init__(self, filename, repo_relative_filename, thing=None):
|
|
||||||
self.filename = filename
|
def __init__(self, filename, repo_relative_filename, thing=None):
|
||||||
self.repo_relative_filename = repo_relative_filename
|
self.filename = filename
|
||||||
self.thing = thing or self._from_file(open(filename))
|
self.repo_relative_filename = repo_relative_filename
|
||||||
|
self.thing = thing or self._from_file(open(filename))
|
||||||
def _from_file(self, f):
|
|
||||||
return f.read().splitlines()
|
def _from_file(self, f):
|
||||||
|
return f.read().splitlines()
|
||||||
def _to_file(self, f):
|
|
||||||
for line in self.thing:
|
def _to_file(self, f):
|
||||||
print >> f, line
|
for line in self.thing:
|
||||||
|
print(line, file=f)
|
||||||
def persist(self, repo):
|
|
||||||
'''
|
def persist(self, repo):
|
||||||
Save the lines to the file and stage the file in the repo.
|
'''
|
||||||
'''
|
Save the lines to the file and stage the file in the repo.
|
||||||
with open(self.filename, 'w') as f:
|
'''
|
||||||
os.chmod(self.filename, 0600)
|
with open(self.filename, 'w') as f:
|
||||||
self._to_file(f)
|
os.chmod(self.filename, 0o600)
|
||||||
f.flush()
|
self._to_file(f)
|
||||||
os.fsync(f.fileno())
|
f.flush()
|
||||||
# For goodness's sake, write it to the disk already!
|
os.fsync(f.fileno())
|
||||||
repo.stage([self.repo_relative_filename])
|
# For goodness's sake, write it to the disk already!
|
||||||
|
repo.stage([self.repo_relative_filename])
|
||||||
|
|
||||||
class PickledResource(Resource):
|
|
||||||
'''
|
class PickledResource(Resource):
|
||||||
A ``Resource`` subclass that uses ``pickle`` on its file/thing.
|
'''
|
||||||
'''
|
A ``Resource`` subclass that uses ``pickle`` on its file/thing.
|
||||||
|
'''
|
||||||
def _from_file(self, f):
|
|
||||||
return [pickle.load(f)]
|
def _from_file(self, f):
|
||||||
|
return [pickle.load(f)]
|
||||||
def _to_file(self, f):
|
|
||||||
pickle.dump(self.thing[0], f)
|
def _to_file(self, f):
|
||||||
|
pickle.dump(self.thing[0], f)
|
||||||
|
|
||||||
class PersistTask(object):
|
|
||||||
'''
|
class PersistTask(object):
|
||||||
This class deals with saving changes to the git repo.
|
'''
|
||||||
'''
|
This class deals with saving changes to the git repo.
|
||||||
|
'''
|
||||||
LIMIT = 10
|
|
||||||
MAX_SAVE = 10
|
LIMIT = 10
|
||||||
|
MAX_SAVE = 10
|
||||||
def __init__(self, home):
|
|
||||||
self.home = home
|
def __init__(self, home):
|
||||||
self.repo = open_repo(home)
|
self.home = home
|
||||||
self._r = make_repo_relative_path_maker(self.repo)
|
self.repo = open_repo(home)
|
||||||
self.counter = Counter()
|
self._r = make_repo_relative_path_maker(self.repo)
|
||||||
self.store = {}
|
self.counter = Counter()
|
||||||
|
self.store = {}
|
||||||
def open(self, name):
|
|
||||||
'''
|
def open(self, name):
|
||||||
Look up the named file in home and return its content_id and data.
|
'''
|
||||||
'''
|
Look up the named file in home and return its content_id and data.
|
||||||
fn = os.path.join(self.home, name)
|
'''
|
||||||
content_id = name # hash(fn)
|
fn = os.path.join(self.home, name)
|
||||||
try:
|
content_id = name # hash(fn)
|
||||||
resource = self.store[content_id]
|
try:
|
||||||
except KeyError:
|
resource = self.store[content_id]
|
||||||
R = PickledResource if name.endswith('.pickle') else Resource
|
except KeyError:
|
||||||
resource = self.store[content_id] = R(fn, self._r(fn))
|
R = PickledResource if name.endswith('.pickle') else Resource
|
||||||
return content_id, resource.thing
|
resource = self.store[content_id] = R(fn, self._r(fn))
|
||||||
|
return content_id, resource.thing
|
||||||
def handle(self, message):
|
|
||||||
'''
|
def handle(self, message):
|
||||||
Handle messages, dispatch to ``handle_FOO()`` methods.
|
'''
|
||||||
'''
|
Handle messages, dispatch to ``handle_FOO()`` methods.
|
||||||
if isinstance(message, core.OpenMessage):
|
'''
|
||||||
self.handle_open(message)
|
if isinstance(message, core.OpenMessage):
|
||||||
elif isinstance(message, core.ModifyMessage):
|
self.handle_open(message)
|
||||||
self.handle_modify(message)
|
elif isinstance(message, core.ModifyMessage):
|
||||||
elif isinstance(message, core.PersistMessage):
|
self.handle_modify(message)
|
||||||
self.handle_persist(message)
|
elif isinstance(message, core.PersistMessage):
|
||||||
elif isinstance(message, core.ShutdownMessage):
|
self.handle_persist(message)
|
||||||
for content_id in self.counter:
|
elif isinstance(message, core.ShutdownMessage):
|
||||||
self.store[content_id].persist(self.repo)
|
for content_id in self.counter:
|
||||||
self.commit('shutdown')
|
self.store[content_id].persist(self.repo)
|
||||||
|
self.commit('shutdown')
|
||||||
def handle_open(self, message):
|
|
||||||
'''
|
def handle_open(self, message):
|
||||||
Foo.
|
'''
|
||||||
'''
|
Foo.
|
||||||
try:
|
'''
|
||||||
message.content_id, message.thing = self.open(message.name)
|
try:
|
||||||
except:
|
message.content_id, message.thing = self.open(message.name)
|
||||||
message.traceback = traceback.format_exc()
|
except:
|
||||||
message.status = core.ERROR
|
message.traceback = traceback.format_exc()
|
||||||
else:
|
message.status = core.ERROR
|
||||||
message.status = core.SUCCESS
|
else:
|
||||||
|
message.status = core.SUCCESS
|
||||||
def handle_modify(self, message):
|
|
||||||
'''
|
def handle_modify(self, message):
|
||||||
Foo.
|
'''
|
||||||
'''
|
Foo.
|
||||||
try:
|
'''
|
||||||
content_id = message.details['content_id']
|
try:
|
||||||
except KeyError:
|
content_id = message.details['content_id']
|
||||||
return
|
except KeyError:
|
||||||
if not content_id:
|
return
|
||||||
return
|
if not content_id:
|
||||||
self.counter[content_id] += 1
|
return
|
||||||
if self.counter[content_id] > self.LIMIT:
|
self.counter[content_id] += 1
|
||||||
self.persist(content_id)
|
if self.counter[content_id] > self.LIMIT:
|
||||||
self.commit('due to activity')
|
self.persist(content_id)
|
||||||
|
self.commit('due to activity')
|
||||||
def handle_persist(self, message):
|
|
||||||
'''
|
def handle_persist(self, message):
|
||||||
Foo.
|
'''
|
||||||
'''
|
Foo.
|
||||||
try:
|
'''
|
||||||
resource = self.store[message.content_id]
|
try:
|
||||||
except KeyError:
|
resource = self.store[message.content_id]
|
||||||
resource = self.handle_persist_new(message)
|
except KeyError:
|
||||||
resource.persist(self.repo)
|
resource = self.handle_persist_new(message)
|
||||||
self.commit('by request from %r' % (message.sender,))
|
resource.persist(self.repo)
|
||||||
|
self.commit('by request from %r' % (message.sender,))
|
||||||
def handle_persist_new(self, message):
|
|
||||||
'''
|
def handle_persist_new(self, message):
|
||||||
Foo.
|
'''
|
||||||
'''
|
Foo.
|
||||||
name = message.content_id
|
'''
|
||||||
check_filename(name)
|
name = message.content_id
|
||||||
fn = os.path.join(self.home, name)
|
check_filename(name)
|
||||||
thing = message.details['thing']
|
fn = os.path.join(self.home, name)
|
||||||
R = PickledResource if name.endswith('.pickle') else Resource # !!! refactor!
|
thing = message.details['thing']
|
||||||
resource = self.store[name] = R(fn, self._r(fn), thing)
|
R = PickledResource if name.endswith('.pickle') else Resource # !!! refactor!
|
||||||
return resource
|
resource = self.store[name] = R(fn, self._r(fn), thing)
|
||||||
|
return resource
|
||||||
def persist(self, content_id):
|
|
||||||
'''
|
def persist(self, content_id):
|
||||||
Persist a resource.
|
'''
|
||||||
'''
|
Persist a resource.
|
||||||
del self.counter[content_id]
|
'''
|
||||||
self.store[content_id].persist(self.repo)
|
del self.counter[content_id]
|
||||||
|
self.store[content_id].persist(self.repo)
|
||||||
def task_run(self):
|
|
||||||
'''
|
def task_run(self):
|
||||||
Stage any outstanding changes.
|
'''
|
||||||
'''
|
Stage any outstanding changes.
|
||||||
if not self.counter:
|
'''
|
||||||
return
|
if not self.counter:
|
||||||
for content_id, _ in self.counter.most_common(self.MAX_SAVE):
|
return
|
||||||
self.persist(content_id)
|
for content_id, _ in self.counter.most_common(self.MAX_SAVE):
|
||||||
self.commit()
|
self.persist(content_id)
|
||||||
|
self.commit()
|
||||||
def commit(self, message='auto-commit'):
|
|
||||||
'''
|
def commit(self, message='auto-commit'):
|
||||||
Commit.
|
'''
|
||||||
'''
|
Commit.
|
||||||
return self.repo.do_commit(message, committer=core.COMMITTER)
|
'''
|
||||||
|
return self.repo.do_commit(message, committer=core.COMMITTER)
|
||||||
def scan(self):
|
|
||||||
'''
|
def scan(self):
|
||||||
Return a sorted list of all the files in the home dir.
|
'''
|
||||||
'''
|
Return a sorted list of all the files in the home dir.
|
||||||
return sorted([
|
'''
|
||||||
fn
|
return sorted([
|
||||||
for fn in os.listdir(self.home)
|
fn
|
||||||
if os.path.isfile(os.path.join(self.home, fn))
|
for fn in os.listdir(self.home)
|
||||||
])
|
if os.path.isfile(os.path.join(self.home, fn))
|
||||||
|
])
|
||||||
|
|
||||||
def check_filename(name):
|
|
||||||
'''
|
def check_filename(name):
|
||||||
Sanity checks for filename.
|
'''
|
||||||
'''
|
Sanity checks for filename.
|
||||||
# TODO: improve this...
|
'''
|
||||||
if len(name) > 64:
|
# TODO: improve this...
|
||||||
raise ValueError('bad name %r' % (name,))
|
if len(name) > 64:
|
||||||
left, dot, right = name.partition('.')
|
raise ValueError('bad name %r' % (name,))
|
||||||
if not left.isalnum() or dot and not right.isalnum():
|
left, dot, right = name.partition('.')
|
||||||
raise ValueError('bad name %r' % (name,))
|
if not left.isalnum() or dot and not right.isalnum():
|
||||||
|
raise ValueError('bad name %r' % (name,))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
JOY_HOME = os.path.expanduser('~/.thun')
|
if __name__ == '__main__':
|
||||||
pt = PersistTask(JOY_HOME)
|
JOY_HOME = os.path.expanduser('~/.thun')
|
||||||
content_id, thing = pt.open('stack.pickle')
|
pt = PersistTask(JOY_HOME)
|
||||||
pt.persist(content_id)
|
content_id, thing = pt.open('stack.pickle')
|
||||||
print pt.counter
|
pt.persist(content_id)
|
||||||
mm = core.ModifyMessage(None, None, content_id=content_id)
|
print(pt.counter)
|
||||||
pt.handle(mm)
|
mm = core.ModifyMessage(None, None, content_id=content_id)
|
||||||
print pt.counter
|
pt.handle(mm)
|
||||||
|
print(pt.counter)
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,245 +1,246 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright © 2019 Simon Forman
|
# Copyright © 2019 Simon Forman
|
||||||
#
|
#
|
||||||
# This file is part of joy.py
|
# This file is part of joy.py
|
||||||
#
|
#
|
||||||
# joy.py is free software: you can redistribute it and/or modify
|
# joy.py is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
#
|
||||||
# joy.py is distributed in the hope that it will be useful,
|
# joy.py is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with joy.py. If not see <http://www.gnu.org/licenses/>.
|
# along with joy.py. If not see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
'''
|
'''
|
||||||
|
|
||||||
Viewer
|
Viewer
|
||||||
=================
|
=================
|
||||||
|
|
||||||
'''
|
'''
|
||||||
import pygame
|
from __future__ import print_function
|
||||||
from joy.vui.core import BACKGROUND, FOREGROUND
|
import pygame
|
||||||
|
from joy.vui.core import BACKGROUND, FOREGROUND
|
||||||
|
|
||||||
class Viewer(object):
|
|
||||||
'''
|
class Viewer(object):
|
||||||
Base Viewer class
|
'''
|
||||||
'''
|
Base Viewer class
|
||||||
|
'''
|
||||||
MINIMUM_HEIGHT = 11
|
|
||||||
|
MINIMUM_HEIGHT = 11
|
||||||
def __init__(self, surface):
|
|
||||||
self.resurface(surface)
|
def __init__(self, surface):
|
||||||
self.last_touch = 0, 0
|
self.resurface(surface)
|
||||||
|
self.last_touch = 0, 0
|
||||||
def resurface(self, surface):
|
|
||||||
self.w, self.h = surface.get_width(), surface.get_height()
|
def resurface(self, surface):
|
||||||
self.surface = surface
|
self.w, self.h = surface.get_width(), surface.get_height()
|
||||||
|
self.surface = surface
|
||||||
def split(self, y):
|
|
||||||
'''
|
def split(self, y):
|
||||||
Split the viewer at the y coordinate (which is relative to the
|
'''
|
||||||
viewer's surface and must be inside it somewhere) and return the
|
Split the viewer at the y coordinate (which is relative to the
|
||||||
remaining height. The upper part of the viewer remains (and gets
|
viewer's surface and must be inside it somewhere) and return the
|
||||||
redrawn on a new surface) and the lower space is now available
|
remaining height. The upper part of the viewer remains (and gets
|
||||||
for e.g. a new viewer.
|
redrawn on a new surface) and the lower space is now available
|
||||||
'''
|
for e.g. a new viewer.
|
||||||
assert y >= self.MINIMUM_HEIGHT
|
'''
|
||||||
new_viewer_h = self.h - y
|
assert y >= self.MINIMUM_HEIGHT
|
||||||
self.resurface(self.surface.subsurface((0, 0, self.w, y)))
|
new_viewer_h = self.h - y
|
||||||
if y <= self.last_touch[1]: self.last_touch = 0, 0
|
self.resurface(self.surface.subsurface((0, 0, self.w, y)))
|
||||||
self.draw()
|
if y <= self.last_touch[1]: self.last_touch = 0, 0
|
||||||
return new_viewer_h
|
self.draw()
|
||||||
|
return new_viewer_h
|
||||||
def handle(self, message):
|
|
||||||
assert self is not message.sender
|
def handle(self, message):
|
||||||
pass
|
assert self is not message.sender
|
||||||
|
pass
|
||||||
def draw(self):
|
|
||||||
'''Draw the viewer onto its surface.'''
|
def draw(self):
|
||||||
self.surface.fill(BACKGROUND)
|
'''Draw the viewer onto its surface.'''
|
||||||
x, y, h = self.w - 1, self.MINIMUM_HEIGHT, self.h - 1
|
self.surface.fill(BACKGROUND)
|
||||||
# Right-hand side.
|
x, y, h = self.w - 1, self.MINIMUM_HEIGHT, self.h - 1
|
||||||
pygame.draw.line(self.surface, FOREGROUND, (x, 0), (x, h))
|
# Right-hand side.
|
||||||
# Between header and body.
|
pygame.draw.line(self.surface, FOREGROUND, (x, 0), (x, h))
|
||||||
pygame.draw.line(self.surface, FOREGROUND, (0, y), (x, y))
|
# Between header and body.
|
||||||
# Bottom.
|
pygame.draw.line(self.surface, FOREGROUND, (0, y), (x, y))
|
||||||
pygame.draw.line(self.surface, FOREGROUND, (0, h), (x, h))
|
# Bottom.
|
||||||
|
pygame.draw.line(self.surface, FOREGROUND, (0, h), (x, h))
|
||||||
def close(self):
|
|
||||||
'''Close the viewer and release any resources, etc...'''
|
def close(self):
|
||||||
|
'''Close the viewer and release any resources, etc...'''
|
||||||
def focus(self, display):
|
|
||||||
pass
|
def focus(self, display):
|
||||||
|
pass
|
||||||
def unfocus(self):
|
|
||||||
pass
|
def unfocus(self):
|
||||||
|
pass
|
||||||
# Event handling.
|
|
||||||
|
# Event handling.
|
||||||
def mouse_down(self, display, x, y, button):
|
|
||||||
self.last_touch = x, y
|
def mouse_down(self, display, x, y, button):
|
||||||
|
self.last_touch = x, y
|
||||||
def mouse_up(self, display, x, y, button):
|
|
||||||
pass
|
def mouse_up(self, display, x, y, button):
|
||||||
|
pass
|
||||||
def mouse_motion(self, display, x, y, dx, dy, button0, button1, button2):
|
|
||||||
pass
|
def mouse_motion(self, display, x, y, dx, dy, button0, button1, button2):
|
||||||
|
pass
|
||||||
def key_up(self, display, key, mod):
|
|
||||||
if key == pygame.K_q and mod & pygame.KMOD_CTRL: # Ctrl-q
|
def key_up(self, display, key, mod):
|
||||||
display.close_viewer(self)
|
if key == pygame.K_q and mod & pygame.KMOD_CTRL: # Ctrl-q
|
||||||
return True
|
display.close_viewer(self)
|
||||||
if key == pygame.K_g and mod & pygame.KMOD_CTRL: # Ctrl-g
|
return True
|
||||||
display.grow_viewer(self)
|
if key == pygame.K_g and mod & pygame.KMOD_CTRL: # Ctrl-g
|
||||||
return True
|
display.grow_viewer(self)
|
||||||
|
return True
|
||||||
def key_down(self, display, uch, key, mod):
|
|
||||||
pass
|
def key_down(self, display, uch, key, mod):
|
||||||
|
pass
|
||||||
|
|
||||||
class MenuViewer(Viewer):
|
|
||||||
|
class MenuViewer(Viewer):
|
||||||
'''
|
|
||||||
MenuViewer class
|
'''
|
||||||
'''
|
MenuViewer class
|
||||||
|
'''
|
||||||
MINIMUM_HEIGHT = 26
|
|
||||||
|
MINIMUM_HEIGHT = 26
|
||||||
def __init__(self, surface):
|
|
||||||
Viewer.__init__(self, surface)
|
def __init__(self, surface):
|
||||||
self.resizing = 0
|
Viewer.__init__(self, surface)
|
||||||
self.bg = 100, 150, 100
|
self.resizing = 0
|
||||||
|
self.bg = 100, 150, 100
|
||||||
def resurface(self, surface):
|
|
||||||
Viewer.resurface(self, surface)
|
def resurface(self, surface):
|
||||||
n = self.MINIMUM_HEIGHT - 2
|
Viewer.resurface(self, surface)
|
||||||
self.close_rect = pygame.rect.Rect(self.w - 2 - n, 1, n, n)
|
n = self.MINIMUM_HEIGHT - 2
|
||||||
self.grow_rect = pygame.rect.Rect(1, 1, n, n)
|
self.close_rect = pygame.rect.Rect(self.w - 2 - n, 1, n, n)
|
||||||
self.body_rect = pygame.rect.Rect(
|
self.grow_rect = pygame.rect.Rect(1, 1, n, n)
|
||||||
0, self.MINIMUM_HEIGHT + 1,
|
self.body_rect = pygame.rect.Rect(
|
||||||
self.w - 1, self.h - self.MINIMUM_HEIGHT - 2)
|
0, self.MINIMUM_HEIGHT + 1,
|
||||||
|
self.w - 1, self.h - self.MINIMUM_HEIGHT - 2)
|
||||||
def draw(self):
|
|
||||||
'''Draw the viewer onto its surface.'''
|
def draw(self):
|
||||||
Viewer.draw(self)
|
'''Draw the viewer onto its surface.'''
|
||||||
if not self.resizing:
|
Viewer.draw(self)
|
||||||
self.draw_menu()
|
if not self.resizing:
|
||||||
self.draw_body()
|
self.draw_menu()
|
||||||
|
self.draw_body()
|
||||||
def draw_menu(self):
|
|
||||||
# menu buttons
|
def draw_menu(self):
|
||||||
pygame.draw.rect(self.surface, FOREGROUND, self.close_rect, 1)
|
# menu buttons
|
||||||
pygame.draw.rect(self.surface, FOREGROUND, self.grow_rect, 1)
|
pygame.draw.rect(self.surface, FOREGROUND, self.close_rect, 1)
|
||||||
|
pygame.draw.rect(self.surface, FOREGROUND, self.grow_rect, 1)
|
||||||
def draw_body(self):
|
|
||||||
self.surface.fill(self.bg, self.body_rect)
|
def draw_body(self):
|
||||||
|
self.surface.fill(self.bg, self.body_rect)
|
||||||
def mouse_down(self, display, x, y, button):
|
|
||||||
Viewer.mouse_down(self, display, x, y, button)
|
def mouse_down(self, display, x, y, button):
|
||||||
if y <= self.MINIMUM_HEIGHT:
|
Viewer.mouse_down(self, display, x, y, button)
|
||||||
self.menu_click(display, x, y, button)
|
if y <= self.MINIMUM_HEIGHT:
|
||||||
else:
|
self.menu_click(display, x, y, button)
|
||||||
bx, by = self.body_rect.topleft
|
else:
|
||||||
self.body_click(display, x - bx, y - by, button)
|
bx, by = self.body_rect.topleft
|
||||||
|
self.body_click(display, x - bx, y - by, button)
|
||||||
def body_click(self, display, x, y, button):
|
|
||||||
if button == 1:
|
def body_click(self, display, x, y, button):
|
||||||
self.draw_an_a(x, y)
|
if button == 1:
|
||||||
|
self.draw_an_a(x, y)
|
||||||
def menu_click(self, display, x, y, button):
|
|
||||||
if button == 1:
|
def menu_click(self, display, x, y, button):
|
||||||
self.resizing = 1
|
if button == 1:
|
||||||
elif button == 3:
|
self.resizing = 1
|
||||||
if self.close_rect.collidepoint(x, y):
|
elif button == 3:
|
||||||
display.close_viewer(self)
|
if self.close_rect.collidepoint(x, y):
|
||||||
return True
|
display.close_viewer(self)
|
||||||
elif self.grow_rect.collidepoint(x, y):
|
return True
|
||||||
display.grow_viewer(self)
|
elif self.grow_rect.collidepoint(x, y):
|
||||||
return True
|
display.grow_viewer(self)
|
||||||
|
return True
|
||||||
def mouse_up(self, display, x, y, button):
|
|
||||||
|
def mouse_up(self, display, x, y, button):
|
||||||
if button == 1 and self.resizing:
|
|
||||||
if self.resizing == 2:
|
if button == 1 and self.resizing:
|
||||||
self.resizing = 0
|
if self.resizing == 2:
|
||||||
self.draw()
|
self.resizing = 0
|
||||||
display.done_resizing()
|
self.draw()
|
||||||
self.resizing = 0
|
display.done_resizing()
|
||||||
return True
|
self.resizing = 0
|
||||||
|
return True
|
||||||
def mouse_motion(self, display, x, y, rel_x, rel_y, button0, button1, button2):
|
|
||||||
if self.resizing and button0:
|
def mouse_motion(self, display, x, y, rel_x, rel_y, button0, button1, button2):
|
||||||
self.resizing = 2
|
if self.resizing and button0:
|
||||||
display.change_viewer(self, rel_y, relative=True)
|
self.resizing = 2
|
||||||
return True
|
display.change_viewer(self, rel_y, relative=True)
|
||||||
else:
|
return True
|
||||||
self.resizing = 0
|
else:
|
||||||
#self.draw_an_a(x, y)
|
self.resizing = 0
|
||||||
|
#self.draw_an_a(x, y)
|
||||||
def key_up(self, display, key, mod):
|
|
||||||
if Viewer.key_up(self, display, key, mod):
|
def key_up(self, display, key, mod):
|
||||||
return True
|
if Viewer.key_up(self, display, key, mod):
|
||||||
|
return True
|
||||||
def draw_an_a(self, x, y):
|
|
||||||
# Draw a crude letter A.
|
def draw_an_a(self, x, y):
|
||||||
lw, lh = 10, 14
|
# Draw a crude letter A.
|
||||||
try: surface = self.surface.subsurface((x - lw, y - lh, lw, lh))
|
lw, lh = 10, 14
|
||||||
except ValueError: return
|
try: surface = self.surface.subsurface((x - lw, y - lh, lw, lh))
|
||||||
draw_a(surface, blend=1)
|
except ValueError: return
|
||||||
|
draw_a(surface, blend=1)
|
||||||
|
|
||||||
class SomeViewer(MenuViewer):
|
|
||||||
|
class SomeViewer(MenuViewer):
|
||||||
def __init__(self, surface):
|
|
||||||
MenuViewer.__init__(self, surface)
|
def __init__(self, surface):
|
||||||
|
MenuViewer.__init__(self, surface)
|
||||||
def resurface(self, surface):
|
|
||||||
MenuViewer.resurface(self, surface)
|
def resurface(self, surface):
|
||||||
|
MenuViewer.resurface(self, surface)
|
||||||
def draw_menu(self):
|
|
||||||
MenuViewer.draw_menu(self)
|
def draw_menu(self):
|
||||||
|
MenuViewer.draw_menu(self)
|
||||||
def draw_body(self):
|
|
||||||
pass
|
def draw_body(self):
|
||||||
|
pass
|
||||||
def body_click(self, display, x, y, button):
|
|
||||||
pass
|
def body_click(self, display, x, y, button):
|
||||||
|
pass
|
||||||
def menu_click(self, display, x, y, button):
|
|
||||||
if MenuViewer.menu_click(self, display, x, y, button):
|
def menu_click(self, display, x, y, button):
|
||||||
return True
|
if MenuViewer.menu_click(self, display, x, y, button):
|
||||||
|
return True
|
||||||
def mouse_up(self, display, x, y, button):
|
|
||||||
if MenuViewer.mouse_up(self, display, x, y, button):
|
def mouse_up(self, display, x, y, button):
|
||||||
return True
|
if MenuViewer.mouse_up(self, display, x, y, button):
|
||||||
|
return True
|
||||||
def mouse_motion(self, display, x, y, rel_x, rel_y, button0, button1, button2):
|
|
||||||
if MenuViewer.mouse_motion(self, display, x, y, rel_x, rel_y,
|
def mouse_motion(self, display, x, y, rel_x, rel_y, button0, button1, button2):
|
||||||
button0, button1, button2):
|
if MenuViewer.mouse_motion(self, display, x, y, rel_x, rel_y,
|
||||||
return True
|
button0, button1, button2):
|
||||||
|
return True
|
||||||
def key_down(self, display, uch, key, mod):
|
|
||||||
try:
|
def key_down(self, display, uch, key, mod):
|
||||||
print chr(key),
|
try:
|
||||||
except ValueError:
|
print(chr(key), end=' ')
|
||||||
pass
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
# Note that Oberon book says that if you split at the exact top of a viewer
|
|
||||||
# it should close, and I think this implies the new viewer gets the old
|
# Note that Oberon book says that if you split at the exact top of a viewer
|
||||||
# viewer's whole height. I haven't implemented that yet, so the edge-case
|
# it should close, and I think this implies the new viewer gets the old
|
||||||
# in the code is broken by "intent" for now..
|
# viewer's whole height. I haven't implemented that yet, so the edge-case
|
||||||
|
# in the code is broken by "intent" for now..
|
||||||
|
|
||||||
def draw_a(surface, color=FOREGROUND, blend=False):
|
|
||||||
w, h = surface.get_width() - 2, surface.get_height() - 2
|
def draw_a(surface, color=FOREGROUND, blend=False):
|
||||||
pygame.draw.aalines(surface, color, False, (
|
w, h = surface.get_width() - 2, surface.get_height() - 2
|
||||||
(1, h), (w / 2, 1), (w, h), (1, h / 2)
|
pygame.draw.aalines(surface, color, False, (
|
||||||
), blend)
|
(1, h), (w / 2, 1), (w, h), (1, h / 2)
|
||||||
|
), blend)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue