brittainscript 0.1.0__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {brittainscript-0.1.0 → brittainscript-0.2.0}/LICENSE +1 -1
- {brittainscript-0.1.0 → brittainscript-0.2.0}/PKG-INFO +2 -2
- {brittainscript-0.1.0 → brittainscript-0.2.0}/brittainscript.egg-info/PKG-INFO +2 -2
- {brittainscript-0.1.0 → brittainscript-0.2.0}/brittainscript.egg-info/SOURCES.txt +9 -1
- brittainscript-0.2.0/core/gui_backend.py +450 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/core/parser.py +143 -20
- {brittainscript-0.1.0 → brittainscript-0.2.0}/core/parsetab.py +43 -43
- brittainscript-0.2.0/libs/datetime.bs +50 -0
- brittainscript-0.2.0/libs/gui.bs +156 -0
- brittainscript-0.2.0/libs/io.bs +28 -0
- brittainscript-0.2.0/libs/terminal.bs +49 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/pyproject.toml +1 -1
- brittainscript-0.2.0/tests/test_datetime_builtin.py +54 -0
- brittainscript-0.2.0/tests/test_gui_builtins.py +43 -0
- brittainscript-0.2.0/tests/test_parser_builtins.py +39 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/Documentation/README.md +0 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/brittainscript.egg-info/dependency_links.txt +0 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/brittainscript.egg-info/entry_points.txt +0 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/brittainscript.egg-info/requires.txt +0 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/brittainscript.egg-info/top_level.txt +0 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/core/__init__.py +0 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/core/lexer.py +0 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/core/main.py +0 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/libs/__init__.py +0 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/libs/convert.bs +0 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/libs/math.bs +0 -0
- {brittainscript-0.1.0 → brittainscript-0.2.0}/setup.cfg +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: brittainscript
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: The BrittainScript programming language interpreter
|
|
5
5
|
Author-email: Luke Brittain <luke.brittain@gmail.com>
|
|
6
6
|
License: MIT License
|
|
7
7
|
|
|
8
|
-
Copyright (c)
|
|
8
|
+
Copyright (c) 2026 Luke Brittain
|
|
9
9
|
|
|
10
10
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
11
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: brittainscript
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: The BrittainScript programming language interpreter
|
|
5
5
|
Author-email: Luke Brittain <luke.brittain@gmail.com>
|
|
6
6
|
License: MIT License
|
|
7
7
|
|
|
8
|
-
Copyright (c)
|
|
8
|
+
Copyright (c) 2026 Luke Brittain
|
|
9
9
|
|
|
10
10
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
11
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -8,10 +8,18 @@ brittainscript.egg-info/entry_points.txt
|
|
|
8
8
|
brittainscript.egg-info/requires.txt
|
|
9
9
|
brittainscript.egg-info/top_level.txt
|
|
10
10
|
core/__init__.py
|
|
11
|
+
core/gui_backend.py
|
|
11
12
|
core/lexer.py
|
|
12
13
|
core/main.py
|
|
13
14
|
core/parser.py
|
|
14
15
|
core/parsetab.py
|
|
15
16
|
libs/__init__.py
|
|
16
17
|
libs/convert.bs
|
|
17
|
-
libs/
|
|
18
|
+
libs/datetime.bs
|
|
19
|
+
libs/gui.bs
|
|
20
|
+
libs/io.bs
|
|
21
|
+
libs/math.bs
|
|
22
|
+
libs/terminal.bs
|
|
23
|
+
tests/test_datetime_builtin.py
|
|
24
|
+
tests/test_gui_builtins.py
|
|
25
|
+
tests/test_parser_builtins.py
|
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
# gui_backend.py -- tkinter bridge for the BrittainScript gui library
|
|
2
|
+
#
|
|
3
|
+
# Widgets are handed to BrittainScript code as integer ids so scripts only
|
|
4
|
+
# ever hold plain numbers. Callbacks are BrittainScript function names passed
|
|
5
|
+
# as strings; when tkinter fires an event we call back into the interpreter
|
|
6
|
+
# through the invoker set by parser.py.
|
|
7
|
+
#
|
|
8
|
+
# tkinter is imported lazily so environments without a display can still run
|
|
9
|
+
# non-GUI scripts.
|
|
10
|
+
|
|
11
|
+
tk = None
|
|
12
|
+
messagebox = None
|
|
13
|
+
simpledialog = None
|
|
14
|
+
|
|
15
|
+
callback_invoker = None
|
|
16
|
+
|
|
17
|
+
widgets = {}
|
|
18
|
+
next_id = 1
|
|
19
|
+
root_window = None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def set_callback_invoker(invoker):
|
|
23
|
+
global callback_invoker
|
|
24
|
+
callback_invoker = invoker
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _load_tk():
|
|
28
|
+
global tk, messagebox, simpledialog
|
|
29
|
+
if tk is not None:
|
|
30
|
+
return True
|
|
31
|
+
try:
|
|
32
|
+
import tkinter as tk_module
|
|
33
|
+
from tkinter import messagebox as messagebox_module
|
|
34
|
+
from tkinter import simpledialog as simpledialog_module
|
|
35
|
+
except ImportError:
|
|
36
|
+
print("GUI error: tkinter is not available on this system")
|
|
37
|
+
return False
|
|
38
|
+
tk = tk_module
|
|
39
|
+
messagebox = messagebox_module
|
|
40
|
+
simpledialog = simpledialog_module
|
|
41
|
+
return True
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _register(widget):
|
|
45
|
+
global next_id
|
|
46
|
+
widget_id = next_id
|
|
47
|
+
next_id += 1
|
|
48
|
+
widgets[widget_id] = widget
|
|
49
|
+
return widget_id
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _lookup(widget_id, kinds=None):
|
|
53
|
+
widget = widgets.get(widget_id)
|
|
54
|
+
if widget is None:
|
|
55
|
+
print(f"GUI error: no widget with id {widget_id}")
|
|
56
|
+
return None
|
|
57
|
+
if kinds and not isinstance(widget, kinds):
|
|
58
|
+
print(f"GUI error: widget {widget_id} does not support this operation")
|
|
59
|
+
return None
|
|
60
|
+
return widget
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _run_callback(name, args):
|
|
64
|
+
if callback_invoker is None:
|
|
65
|
+
print("GUI error: no callback invoker set")
|
|
66
|
+
return
|
|
67
|
+
callback_invoker(name, list(args))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def gui_window(args):
|
|
71
|
+
if not _load_tk():
|
|
72
|
+
return None
|
|
73
|
+
global root_window
|
|
74
|
+
title, width, height = args
|
|
75
|
+
if root_window is None or not _window_alive(root_window):
|
|
76
|
+
window = tk.Tk()
|
|
77
|
+
root_window = window
|
|
78
|
+
else:
|
|
79
|
+
window = tk.Toplevel(root_window)
|
|
80
|
+
window.title(str(title))
|
|
81
|
+
window.geometry(f"{int(width)}x{int(height)}")
|
|
82
|
+
return _register(window)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _window_alive(window):
|
|
86
|
+
try:
|
|
87
|
+
return bool(window.winfo_exists())
|
|
88
|
+
except Exception:
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def gui_title(args):
|
|
93
|
+
window = _lookup(args[0])
|
|
94
|
+
if window is not None:
|
|
95
|
+
window.title(str(args[1]))
|
|
96
|
+
return None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def gui_close(args):
|
|
100
|
+
window = _lookup(args[0])
|
|
101
|
+
if window is not None:
|
|
102
|
+
window.destroy()
|
|
103
|
+
return None
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def gui_run(args):
|
|
107
|
+
if root_window is None or not _window_alive(root_window):
|
|
108
|
+
print("GUI error: create a window before calling run()")
|
|
109
|
+
return None
|
|
110
|
+
root_window.mainloop()
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def gui_frame(args):
|
|
115
|
+
parent = _lookup(args[0])
|
|
116
|
+
if parent is None:
|
|
117
|
+
return None
|
|
118
|
+
return _register(tk.Frame(parent))
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def gui_label(args):
|
|
122
|
+
parent = _lookup(args[0])
|
|
123
|
+
if parent is None:
|
|
124
|
+
return None
|
|
125
|
+
return _register(tk.Label(parent, text=str(args[1])))
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def gui_button(args):
|
|
129
|
+
parent = _lookup(args[0])
|
|
130
|
+
if parent is None:
|
|
131
|
+
return None
|
|
132
|
+
callback_name = str(args[2])
|
|
133
|
+
button = tk.Button(parent, text=str(args[1]),
|
|
134
|
+
command=lambda: _run_callback(callback_name, []))
|
|
135
|
+
return _register(button)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def gui_entry(args):
|
|
139
|
+
parent = _lookup(args[0])
|
|
140
|
+
if parent is None:
|
|
141
|
+
return None
|
|
142
|
+
return _register(tk.Entry(parent))
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def gui_textbox(args):
|
|
146
|
+
parent = _lookup(args[0])
|
|
147
|
+
if parent is None:
|
|
148
|
+
return None
|
|
149
|
+
return _register(tk.Text(parent, width=int(args[1]), height=int(args[2])))
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def gui_checkbox(args):
|
|
153
|
+
parent = _lookup(args[0])
|
|
154
|
+
if parent is None:
|
|
155
|
+
return None
|
|
156
|
+
variable = tk.BooleanVar(parent, value=False)
|
|
157
|
+
checkbox = tk.Checkbutton(parent, text=str(args[1]), variable=variable)
|
|
158
|
+
checkbox.bs_variable = variable
|
|
159
|
+
return _register(checkbox)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def gui_slider(args):
|
|
163
|
+
parent = _lookup(args[0])
|
|
164
|
+
if parent is None:
|
|
165
|
+
return None
|
|
166
|
+
slider = tk.Scale(parent, from_=args[1], to=args[2], orient='horizontal')
|
|
167
|
+
return _register(slider)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def gui_canvas(args):
|
|
171
|
+
parent = _lookup(args[0])
|
|
172
|
+
if parent is None:
|
|
173
|
+
return None
|
|
174
|
+
canvas = tk.Canvas(parent, width=int(args[1]), height=int(args[2]),
|
|
175
|
+
background='white', highlightthickness=0)
|
|
176
|
+
return _register(canvas)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def gui_pack(args):
|
|
180
|
+
widget = _lookup(args[0])
|
|
181
|
+
if widget is not None:
|
|
182
|
+
widget.pack(padx=4, pady=4)
|
|
183
|
+
return None
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def gui_place(args):
|
|
187
|
+
widget = _lookup(args[0])
|
|
188
|
+
if widget is not None:
|
|
189
|
+
widget.place(x=int(args[1]), y=int(args[2]))
|
|
190
|
+
return None
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def gui_grid(args):
|
|
194
|
+
widget = _lookup(args[0])
|
|
195
|
+
if widget is not None:
|
|
196
|
+
widget.grid(row=int(args[1]), column=int(args[2]), padx=4, pady=4)
|
|
197
|
+
return None
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def gui_gettext(args):
|
|
201
|
+
widget = _lookup(args[0])
|
|
202
|
+
if widget is None:
|
|
203
|
+
return None
|
|
204
|
+
if isinstance(widget, tk.Entry):
|
|
205
|
+
return widget.get()
|
|
206
|
+
if isinstance(widget, tk.Text):
|
|
207
|
+
return widget.get('1.0', 'end-1c')
|
|
208
|
+
try:
|
|
209
|
+
return widget.cget('text')
|
|
210
|
+
except Exception:
|
|
211
|
+
print(f"GUI error: widget {args[0]} has no text")
|
|
212
|
+
return None
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def gui_settext(args):
|
|
216
|
+
widget = _lookup(args[0])
|
|
217
|
+
if widget is None:
|
|
218
|
+
return None
|
|
219
|
+
text = str(args[1])
|
|
220
|
+
if isinstance(widget, tk.Entry):
|
|
221
|
+
widget.delete(0, 'end')
|
|
222
|
+
widget.insert(0, text)
|
|
223
|
+
elif isinstance(widget, tk.Text):
|
|
224
|
+
widget.delete('1.0', 'end')
|
|
225
|
+
widget.insert('1.0', text)
|
|
226
|
+
else:
|
|
227
|
+
try:
|
|
228
|
+
widget.config(text=text)
|
|
229
|
+
except Exception:
|
|
230
|
+
print(f"GUI error: widget {args[0]} has no text")
|
|
231
|
+
return None
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def gui_setcolor(args):
|
|
235
|
+
widget = _lookup(args[0])
|
|
236
|
+
if widget is None:
|
|
237
|
+
return None
|
|
238
|
+
try:
|
|
239
|
+
widget.config(background=str(args[1]), foreground=str(args[2]))
|
|
240
|
+
except Exception:
|
|
241
|
+
try:
|
|
242
|
+
widget.config(background=str(args[1]))
|
|
243
|
+
except Exception as error:
|
|
244
|
+
print(f"GUI error: could not set color: {error}")
|
|
245
|
+
return None
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def gui_setfont(args):
|
|
249
|
+
widget = _lookup(args[0])
|
|
250
|
+
if widget is None:
|
|
251
|
+
return None
|
|
252
|
+
try:
|
|
253
|
+
widget.config(font=(str(args[1]), int(args[2])))
|
|
254
|
+
except Exception as error:
|
|
255
|
+
print(f"GUI error: could not set font: {error}")
|
|
256
|
+
return None
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def gui_ischecked(args):
|
|
260
|
+
widget = _lookup(args[0])
|
|
261
|
+
if widget is None:
|
|
262
|
+
return None
|
|
263
|
+
variable = getattr(widget, 'bs_variable', None)
|
|
264
|
+
if variable is None:
|
|
265
|
+
print(f"GUI error: widget {args[0]} is not a checkbox")
|
|
266
|
+
return None
|
|
267
|
+
return bool(variable.get())
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def gui_getvalue(args):
|
|
271
|
+
widget = _lookup(args[0])
|
|
272
|
+
if widget is None:
|
|
273
|
+
return None
|
|
274
|
+
try:
|
|
275
|
+
return widget.get()
|
|
276
|
+
except Exception:
|
|
277
|
+
print(f"GUI error: widget {args[0]} has no value")
|
|
278
|
+
return None
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def gui_setvalue(args):
|
|
282
|
+
widget = _lookup(args[0])
|
|
283
|
+
if widget is None:
|
|
284
|
+
return None
|
|
285
|
+
try:
|
|
286
|
+
widget.set(args[1])
|
|
287
|
+
except Exception:
|
|
288
|
+
print(f"GUI error: widget {args[0]} has no value")
|
|
289
|
+
return None
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def _canvas(args):
|
|
293
|
+
return _lookup(args[0], (tk.Canvas,)) if _load_tk() else None
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def gui_drawline(args):
|
|
297
|
+
canvas = _canvas(args)
|
|
298
|
+
if canvas is None:
|
|
299
|
+
return None
|
|
300
|
+
return canvas.create_line(args[1], args[2], args[3], args[4],
|
|
301
|
+
fill=str(args[5]), width=2)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def gui_drawrect(args):
|
|
305
|
+
canvas = _canvas(args)
|
|
306
|
+
if canvas is None:
|
|
307
|
+
return None
|
|
308
|
+
return canvas.create_rectangle(args[1], args[2], args[3], args[4],
|
|
309
|
+
fill=str(args[5]), outline=str(args[5]))
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def gui_drawoval(args):
|
|
313
|
+
canvas = _canvas(args)
|
|
314
|
+
if canvas is None:
|
|
315
|
+
return None
|
|
316
|
+
return canvas.create_oval(args[1], args[2], args[3], args[4],
|
|
317
|
+
fill=str(args[5]), outline=str(args[5]))
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def gui_drawtext(args):
|
|
321
|
+
canvas = _canvas(args)
|
|
322
|
+
if canvas is None:
|
|
323
|
+
return None
|
|
324
|
+
return canvas.create_text(args[1], args[2], text=str(args[3]),
|
|
325
|
+
fill=str(args[4]))
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def gui_move(args):
|
|
329
|
+
canvas = _canvas(args)
|
|
330
|
+
if canvas is not None:
|
|
331
|
+
canvas.move(args[1], args[2], args[3])
|
|
332
|
+
return None
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def gui_erase(args):
|
|
336
|
+
canvas = _canvas(args)
|
|
337
|
+
if canvas is not None:
|
|
338
|
+
canvas.delete(args[1])
|
|
339
|
+
return None
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def gui_clearcanvas(args):
|
|
343
|
+
canvas = _canvas(args)
|
|
344
|
+
if canvas is not None:
|
|
345
|
+
canvas.delete('all')
|
|
346
|
+
return None
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def gui_onkey(args):
|
|
350
|
+
window = _lookup(args[0])
|
|
351
|
+
if window is None:
|
|
352
|
+
return None
|
|
353
|
+
callback_name = str(args[1])
|
|
354
|
+
window.bind('<Key>',
|
|
355
|
+
lambda event: _run_callback(callback_name, [event.keysym]))
|
|
356
|
+
return None
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def gui_onclick(args):
|
|
360
|
+
widget = _lookup(args[0])
|
|
361
|
+
if widget is None:
|
|
362
|
+
return None
|
|
363
|
+
callback_name = str(args[1])
|
|
364
|
+
widget.bind('<Button-1>',
|
|
365
|
+
lambda event: _run_callback(callback_name, [event.x, event.y]))
|
|
366
|
+
return None
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def gui_after(args):
|
|
370
|
+
if root_window is None or not _window_alive(root_window):
|
|
371
|
+
print("GUI error: create a window before calling after()")
|
|
372
|
+
return None
|
|
373
|
+
callback_name = str(args[1])
|
|
374
|
+
root_window.after(int(args[0]), lambda: _run_callback(callback_name, []))
|
|
375
|
+
return None
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def gui_alert(args):
|
|
379
|
+
if not _load_tk():
|
|
380
|
+
return None
|
|
381
|
+
messagebox.showinfo(str(args[0]), str(args[1]))
|
|
382
|
+
return None
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def gui_confirm(args):
|
|
386
|
+
if not _load_tk():
|
|
387
|
+
return None
|
|
388
|
+
return bool(messagebox.askyesno(str(args[0]), str(args[1])))
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
def gui_prompt(args):
|
|
392
|
+
if not _load_tk():
|
|
393
|
+
return None
|
|
394
|
+
answer = simpledialog.askstring(str(args[0]), str(args[1]))
|
|
395
|
+
return answer if answer is not None else ""
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
BUILTINS = {
|
|
399
|
+
'guiwindow': (gui_window, 3),
|
|
400
|
+
'guititle': (gui_title, 2),
|
|
401
|
+
'guiclose': (gui_close, 1),
|
|
402
|
+
'guirun': (gui_run, 0),
|
|
403
|
+
'guiframe': (gui_frame, 1),
|
|
404
|
+
'guilabel': (gui_label, 2),
|
|
405
|
+
'guibutton': (gui_button, 3),
|
|
406
|
+
'guientry': (gui_entry, 1),
|
|
407
|
+
'guitextbox': (gui_textbox, 3),
|
|
408
|
+
'guicheckbox': (gui_checkbox, 2),
|
|
409
|
+
'guislider': (gui_slider, 3),
|
|
410
|
+
'guicanvas': (gui_canvas, 3),
|
|
411
|
+
'guipack': (gui_pack, 1),
|
|
412
|
+
'guiplace': (gui_place, 3),
|
|
413
|
+
'guigrid': (gui_grid, 3),
|
|
414
|
+
'guigettext': (gui_gettext, 1),
|
|
415
|
+
'guisettext': (gui_settext, 2),
|
|
416
|
+
'guisetcolor': (gui_setcolor, 3),
|
|
417
|
+
'guisetfont': (gui_setfont, 3),
|
|
418
|
+
'guiischecked': (gui_ischecked, 1),
|
|
419
|
+
'guigetvalue': (gui_getvalue, 1),
|
|
420
|
+
'guisetvalue': (gui_setvalue, 2),
|
|
421
|
+
'guidrawline': (gui_drawline, 6),
|
|
422
|
+
'guidrawrect': (gui_drawrect, 6),
|
|
423
|
+
'guidrawoval': (gui_drawoval, 6),
|
|
424
|
+
'guidrawtext': (gui_drawtext, 5),
|
|
425
|
+
'guimove': (gui_move, 4),
|
|
426
|
+
'guierase': (gui_erase, 2),
|
|
427
|
+
'guiclearcanvas': (gui_clearcanvas, 1),
|
|
428
|
+
'guionkey': (gui_onkey, 2),
|
|
429
|
+
'guionclick': (gui_onclick, 2),
|
|
430
|
+
'guiafter': (gui_after, 2),
|
|
431
|
+
'guialert': (gui_alert, 2),
|
|
432
|
+
'guiconfirm': (gui_confirm, 2),
|
|
433
|
+
'guiprompt': (gui_prompt, 2),
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def is_gui_builtin(name):
|
|
438
|
+
return name in BUILTINS
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
def call_builtin(name, args):
|
|
442
|
+
handler, arity = BUILTINS[name]
|
|
443
|
+
if len(args) != arity:
|
|
444
|
+
print(f"Error: {name}() expects {arity} argument{'s' if arity != 1 else ''}")
|
|
445
|
+
return None
|
|
446
|
+
try:
|
|
447
|
+
return handler(args)
|
|
448
|
+
except Exception as error:
|
|
449
|
+
print(f"GUI error: {error}")
|
|
450
|
+
return None
|