Thun/joy/vui/default_joy_home/library.py

207 lines
5.5 KiB
Python

'''
This file is execfile()'d with a namespace containing:
D - the Joy dictionary
d - the Display object
pt - the PersistTask object
log - the log.txt viewer
loop - the TheLoop main loop object
stack_holder - the Python list object that holds the Joy stack tuple
world - the Joy environment
'''
from joy.library import (
DefinitionWrapper,
FunctionWrapper,
SimpleFunctionWrapper,
)
from joy.utils.stack import list_to_stack, concat
from joy.vui import core, text_viewer, stack_viewer
def install(command): D[command.name] = command
@install
@SimpleFunctionWrapper
def list_resources(stack):
'''
Put a string on the stack with the names of all the known resources
one-per-line.
'''
return '\n'.join(pt.scan()), stack
@install
@SimpleFunctionWrapper
def open_stack(stack):
'''
Given a coordinate pair [x y] (in pixels) open a StackViewer there.
'''
(x, (y, _)), stack = stack
V = d.open_viewer(x, y, stack_viewer.StackViewer)
V.draw()
return stack
@install
@SimpleFunctionWrapper
def open_resource(stack):
'''
Given a coordinate pair [x y] (in pixels) and the name of a resource
(from list_resources command) open a viewer on that resource at that
location.
'''
((x, (y, _)), (name, stack)) = stack
om = core.OpenMessage(world, name)
d.broadcast(om)
if om.status == core.SUCCESS:
V = d.open_viewer(x, y, text_viewer.TextViewer)
V.content_id, V.lines = om.content_id, om.thing
V.draw()
return stack
@install
@SimpleFunctionWrapper
def name_viewer(stack):
'''
Given a string name on the stack, if the currently focused viewer is
anonymous, name the viewer and persist it in the resource store under
that name.
'''
name, stack = stack
assert isinstance(name, str), repr(name)
if d.focused_viewer and not d.focused_viewer.content_id:
d.focused_viewer.content_id = name
pm = core.PersistMessage(world, name, thing=d.focused_viewer.lines)
d.broadcast(pm)
d.focused_viewer.draw_menu()
return stack
##@install
##@SimpleFunctionWrapper
##def persist_viewer(stack):
## if self.focused_viewer:
##
## self.focused_viewer.content_id = name
## self.focused_viewer.draw_menu()
## return stack
@install
@SimpleFunctionWrapper
def inscribe(stack):
'''
Create a new Joy function definition in the Joy dictionary. A
definition is given as a string with a name followed by a double
equal sign then one or more Joy functions, the body. for example:
sqr == dup mul
If you want the definition to persist over restarts, enter it into
the definitions.txt resource.
'''
definition, stack = stack
DefinitionWrapper.add_def(definition, D)
return stack
@install
@SimpleFunctionWrapper
def open_viewer(stack):
'''
Given a coordinate pair [x y] (in pixels) and a string, open a new
unnamed viewer on that string at that location.
'''
((x, (y, _)), (content, stack)) = stack
V = d.open_viewer(x, y, text_viewer.TextViewer)
V.lines = content.splitlines()
V.draw()
return stack
@install
@SimpleFunctionWrapper
def good_viewer_location(stack):
'''
Leave a coordinate pair [x y] (in pixels) on the stack that would
be a good location at which to open a new viewer. (The heuristic
employed is to take up the bottom half of the currently open viewer
with the greatest area.)
'''
viewers = list(d.iter_viewers())
if viewers:
viewers.sort(key=lambda (V, x, y): V.w * V.h)
V, x, y = viewers[-1]
coords = (x + 1, (y + V.h / 2, ()))
else:
coords = (0, (0, ()))
return coords, stack
@install
@FunctionWrapper
def cmp_(stack, expression, dictionary):
'''
The cmp combinator takes two values and three quoted programs on the
stack and runs one of the three depending on the results of comparing
the two values:
a b [G] [E] [L] cmp
------------------------- a > b
G
a b [G] [E] [L] cmp
------------------------- a = b
E
a b [G] [E] [L] cmp
------------------------- a < b
L
'''
L, (E, (G, (b, (a, stack)))) = stack
expression = concat(G if a > b else L if a < b else E, expression)
return stack, expression, dictionary
@install
@SimpleFunctionWrapper
def list_viewers(stack):
'''
Put a string on the stack with some information about the currently
open viewers, one-per-line. This is kind of a demo function, rather
than something really useful.
'''
lines = []
for x, T in d.tracks:
#lines.append('x: %i, w: %i, %r' % (x, T.w, T))
for y, V in T.viewers:
lines.append('x: %i y: %i h: %i %r %r' % (x, y, V.h, V.content_id, V))
return '\n'.join(lines), stack
@install
@SimpleFunctionWrapper
def splitlines(stack):
'''
Given a string on the stack replace it with a list of the lines in
the string.
'''
text, stack = stack
assert isinstance(text, str), repr(text)
return list_to_stack(text.splitlines()), stack
@install
@SimpleFunctionWrapper
def hiya(stack):
'''
Demo function to insert "Hi World!" into the current viewer, if any.
'''
if d.focused_viewer:
d.focused_viewer.insert('Hi World!')
return stack