Skip to content

Commit a885b53

Browse files
committed
CC:T improve window & term apis
1 parent 04d773a commit a885b53

12 files changed

Lines changed: 190 additions & 93 deletions

File tree

computercraft/back.lua

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ local _py = {
99
coparams = {},
1010
modules = {},
1111
mcache = {},
12+
temp = {},
1213
}
1314

1415
if type(getfenv) == 'function' then
@@ -20,8 +21,7 @@ elseif type(_G) == 'table' then
2021
else
2122
error('E001: Can\'t get environment')
2223
end
23-
-- TODO: rename temp to _pytemp
24-
_py.genv.temp = {}
24+
_py.genv.temp = _py.temp
2525
_py.genv._m = _py.modules
2626

2727
if type(loadstring) == 'function' then
@@ -183,6 +183,10 @@ function _py.deserialize(stream)
183183
local slen = tonumber(stream.tostop('>'))
184184
local fn = assert(_py.loadstring(stream.fixed(slen)))
185185
return fn()
186+
elseif tok == 'X' then
187+
local slen = tonumber(stream.tostop('>'))
188+
local key = stream.fixed(slen)
189+
return _py.temp[key]
186190
elseif tok == '{' then
187191
local r = {}
188192
while true do

computercraft/lua.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@
88
class LuaExpr:
99
def get_expr_code(self):
1010
raise NotImplementedError
11+
12+
13+
class TempObject:
14+
def __init__(self, fid: bytes):
15+
self._fid = fid

computercraft/oc/filesystem.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,18 +164,20 @@ def copy(fromPath: str, toPath: str) -> bool:
164164

165165

166166
class File(ContextObject):
167+
CALL_OP = b':'
168+
167169
def read(self, n: int) -> Optional[bytes]:
168-
r = self._call(b':read', n)
170+
r = self._call(b'read', n)
169171
r.check_nil_error(allow_nil_nil=True)
170172
return r.take_option_bytes()
171173

172174
def seek(self, whence: str, offset: int = 0) -> int:
173-
r = self._call(b':seek', whence, offset)
175+
r = self._call(b'seek', whence, offset)
174176
r.check_nil_error()
175177
return r.take_int()
176178

177179
def write(self, data: bytes) -> bool:
178-
r = self._call(b':write', data)
180+
r = self._call(b'write', data)
179181
r.check_nil_error()
180182
return r.take_bool()
181183

computercraft/ser.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ def serialize(v: Any, encoding: str) -> bytes:
5252
elif isinstance(v, lua.LuaExpr):
5353
code = v.get_expr_code()
5454
return 'E{}>'.format(len(code)).encode('ascii') + code
55+
elif isinstance(v, lua.TempObject):
56+
return 'X{}>'.format(len(v._fid)).encode('ascii') + v._fid
5557
else:
5658
raise ValueError('Value can\'t be serialized: {}'.format(repr(v)))
5759

computercraft/sess.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
from greenlet import greenlet, getcurrent as get_current_greenlet
1717

18-
from . import rproc, ser
18+
from . import rproc, ser, lua
1919

2020

2121
__all__ = (
@@ -211,32 +211,32 @@ def lua_context_object(
211211
try:
212212
yield fid
213213
finally:
214+
f = finalizer_template.replace(b'{e}', b'temp[n]')
215+
if f:
216+
f += b';' # important to not have ;;
214217
eval_lua(
215-
b'local n=...;'
216-
+ finalizer_template.replace(b'{e}', b'temp[n]')
217-
+ b';temp[n]=nil', fid)
218+
b'local n=...;' + f + b'temp[n]=nil', fid)
218219

219220

220-
class ContextObject:
221-
# TODO: support serializing this object
222-
223-
def __init__(self, fid):
224-
self._fid = fid
221+
class _TempObjectExt:
222+
CALL_OP = b'.'
225223

226224
def _call(self, method: bytes, *args):
227225
return eval_lua(
228226
b'return(function(n,...)return temp[n]'
227+
+ self.CALL_OP
229228
+ method
230229
+ b'(...);end)(...)', self._fid, *args)
231230

232231

233-
def eval_lua_method_factory(obj):
234-
# TODO: remove this
235-
# eval strings must be cacheable
236-
def method(name, *params):
237-
code = 'return ' + obj + name + '(...)'
238-
return eval_lua(code, *params)
239-
return method
232+
class ContextObject(_TempObjectExt, lua.TempObject):
233+
pass
234+
235+
236+
class ReferenceObject(_TempObjectExt, lua.TempObject):
237+
def __init__(self, lua_context_gen):
238+
self._g = lua_context_gen # keep the reference
239+
self._fid = self._g.__enter__()
240240

241241

242242
class CCGreenlet:

computercraft/subapis/fs.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
class SeekMixin:
3232
def seek(self, whence: str = None, offset: int = None) -> int:
3333
# whence: set, cur, end
34-
rp = self._call(b'.seek', whence, offset)
34+
rp = self._call(b'seek', whence, offset)
3535
rp.check_nil_error()
3636
return rp.take_int()
3737

@@ -41,13 +41,13 @@ def _take(self, rp):
4141
raise NotImplementedError
4242

4343
def read(self, count: int = 1) -> Optional[str]:
44-
return self._take(self._call(b'.read', count))
44+
return self._take(self._call(b'read', count))
4545

4646
def readLine(self, withTrailing: bool = False) -> Optional[str]:
47-
return self._take(self._call(b'.readLine', withTrailing))
47+
return self._take(self._call(b'readLine', withTrailing))
4848

4949
def readAll(self) -> Optional[str]:
50-
return self._take(self._call(b'.readAll'))
50+
return self._take(self._call(b'readAll'))
5151

5252
def __iter__(self):
5353
return self
@@ -64,10 +64,10 @@ def _put(self, t):
6464
raise NotImplementedError
6565

6666
def write(self, text: str) -> None:
67-
return self._call(b'.write', self._put(text)).take_none()
67+
return self._call(b'write', self._put(text)).take_none()
6868

6969
def flush(self) -> None:
70-
return self._call(b'.flush').take_none()
70+
return self._call(b'flush').take_none()
7171

7272

7373
class ReadHandle(ReadMixin, ContextObject):

computercraft/subapis/term.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from typing import Tuple
33

44
from .. import ser
5-
from ..sess import eval_lua, lua_context_object, ContextObject
5+
from ..sess import eval_lua, lua_context_object, ReferenceObject
66

77

88
__all__ = (
@@ -25,8 +25,10 @@
2525
'setPaletteColor',
2626
'nativePaletteColor',
2727
'redirect',
28-
# 'get_current_target',
29-
# 'get_native_target',
28+
'current',
29+
'native',
30+
'get_current_target',
31+
'get_native_target',
3032
)
3133

3234

@@ -86,10 +88,6 @@ def setPaletteColor(self, colorID: int, r: float, g: float, b: float) -> None:
8688
return self._call(b'setPaletteColor', colorID, r, g, b).take_none()
8789

8890

89-
class TermTarget(ContextObject, TermMixin):
90-
pass
91-
92-
9391
class _Proxy(TermMixin):
9492
def _call(self, method, *args):
9593
return eval_lua(b'G:term:M:' + method, *args)
@@ -122,6 +120,10 @@ def nativePaletteColor(colorID: int) -> Tuple[float, float, float]:
122120
return tuple(rp.take_number() for _ in range(3))
123121

124122

123+
class TermTarget(ReferenceObject, TermMixin):
124+
pass
125+
126+
125127
@contextmanager
126128
def redirect(target: TermTarget):
127129
with lua_context_object(
@@ -132,11 +134,14 @@ def redirect(target: TermTarget):
132134
yield
133135

134136

135-
# TODO: implement
137+
def current() -> TermTarget:
138+
return TermTarget(lua_context_object(b'term.current()', ()))
139+
136140

137-
# def get_current_target() -> TermTarget:
138-
# return TermTarget('term.current()')
141+
def native() -> TermTarget:
142+
return TermTarget(lua_context_object(b'term.native()', ()))
139143

140144

141-
# def get_native_target() -> TermTarget:
142-
# return TermTarget('term.native()')
145+
# compat
146+
get_current_target = current
147+
get_native_target = native

computercraft/subapis/window.py

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,37 @@
1-
from contextlib import contextmanager
21
from typing import Tuple
32

4-
from ..sess import lua_context_object, ContextObject
3+
from ..sess import lua_context_object, ReferenceObject
54
from .term import TermMixin, TermTarget
65

76

8-
__all__ = (
9-
'create',
10-
)
7+
__all__ = ('create', )
118

129

13-
class TermWindow(ContextObject, TermMixin):
10+
class TermWindow(ReferenceObject, TermMixin):
1411
def setVisible(self, visibility: bool) -> None:
15-
return self._call(b'.setVisible', visibility).take_none()
12+
return self._call(b'setVisible', visibility).take_none()
1613

1714
def redraw(self) -> None:
18-
return self._call(b'.redraw').take_none()
15+
return self._call(b'redraw').take_none()
1916

2017
def restoreCursor(self) -> None:
21-
return self._call(b'.restoreCursor').take_none()
18+
return self._call(b'restoreCursor').take_none()
2219

2320
def getPosition(self) -> Tuple[int, int]:
24-
rp = self._call(b'.getPosition')
21+
rp = self._call(b'getPosition')
2522
return tuple(rp.take_int() for _ in range(2))
2623

2724
def reposition(self, x: int, y: int, width: int = None, height: int = None, parent: TermTarget = None) -> None:
28-
return self._call('.reposition', x, y, width, height, parent).take_none()
25+
return self._call(b'reposition', x, y, width, height, parent).take_none()
2926

3027
def getLine(self, y: int) -> Tuple[str, bytes, bytes]:
31-
rp = self._call(b'.getLine', y)
28+
rp = self._call(b'getLine', y)
3229
return rp.take_string(), rp.take_bytes(), rp.take_bytes()
3330

3431

35-
@contextmanager
3632
def create(
3733
parentTerm: TermTarget, x: int, y: int, width: int, height: int, visible: bool = None,
3834
) -> TermWindow:
39-
with lua_context_object(
35+
return TermWindow(lua_context_object(
4036
b'window.create(...)',
41-
(parentTerm, x, y, width, height, visible),
42-
) as fid:
43-
yield TermWindow(fid)
37+
(parentTerm, x, y, width, height, visible)))

examples/test_window.py

Lines changed: 0 additions & 36 deletions
This file was deleted.

tests/cc_programs/window.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from cc import colors, term, os, window
2+
3+
4+
win = window.create(term.current(), 15, 5, 5, 5, False)
5+
assert win.getPosition() == (15, 5)
6+
assert win.getSize() == (5, 5)
7+
8+
win.setBackgroundColor(colors.red)
9+
win.clear()
10+
win.setVisible(True)
11+
12+
os.sleep(1)
13+
14+
win.setVisible(False)
15+
win.setCursorPos(1, 1)
16+
win.setTextColor(colors.yellow)
17+
win.write('*********')
18+
win.setVisible(True)
19+
20+
os.sleep(1)
21+
22+
term.clear()
23+
24+
os.sleep(1)
25+
26+
win.redraw()
27+
assert win.getLine(1) == ('*****', b'44444', b'eeeee')
28+
29+
# draws immediately
30+
win.reposition(21, 5)
31+
win.reposition(27, 5)
32+
33+
print('Test finished successfully')

0 commit comments

Comments
 (0)