easycoder 250423.2__py2.py3-none-any.whl → 250503.1__py2.py3-none-any.whl
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.
Potentially problematic release.
This version of easycoder might be problematic. Click here for more details.
- easycoder/__init__.py +1 -1
- easycoder/ec_compiler.py +14 -4
- easycoder/ec_core.py +49 -32
- easycoder/ec_handler.py +1 -0
- easycoder/ec_program.py +1 -1
- easycoder/{ec_pyside6.py → ec_pyside.py} +419 -171
- {easycoder-250423.2.dist-info → easycoder-250503.1.dist-info}/METADATA +10 -9
- easycoder-250503.1.dist-info/RECORD +18 -0
- easycoder-250423.2.dist-info/RECORD +0 -18
- {easycoder-250423.2.dist-info → easycoder-250503.1.dist-info}/LICENSE +0 -0
- {easycoder-250423.2.dist-info → easycoder-250503.1.dist-info}/WHEEL +0 -0
- {easycoder-250423.2.dist-info → easycoder-250503.1.dist-info}/entry_points.txt +0 -0
easycoder/__init__.py
CHANGED
easycoder/ec_compiler.py
CHANGED
|
@@ -87,6 +87,15 @@ class Compiler:
|
|
|
87
87
|
def nextIsSymbol(self):
|
|
88
88
|
self.next()
|
|
89
89
|
return self.isSymbol()
|
|
90
|
+
|
|
91
|
+
def skip(self, token):
|
|
92
|
+
next = self.peek()
|
|
93
|
+
if type(token) == list:
|
|
94
|
+
for item in token:
|
|
95
|
+
if next == item:
|
|
96
|
+
self.nextToken()
|
|
97
|
+
return
|
|
98
|
+
elif next == token: self.nextToken()
|
|
90
99
|
|
|
91
100
|
def rewindTo(self, index):
|
|
92
101
|
self.index = index
|
|
@@ -114,10 +123,10 @@ class Compiler:
|
|
|
114
123
|
def compileLabel(self, command):
|
|
115
124
|
return self.compileSymbol(command, self.getToken(), False)
|
|
116
125
|
|
|
117
|
-
def compileVariable(self, command, hasValue = False):
|
|
118
|
-
return self.compileSymbol(command, self.nextToken(), hasValue)
|
|
126
|
+
def compileVariable(self, command, hasValue = False, extra=None):
|
|
127
|
+
return self.compileSymbol(command, self.nextToken(), hasValue, extra)
|
|
119
128
|
|
|
120
|
-
def compileSymbol(self, command, name, hasValue):
|
|
129
|
+
def compileSymbol(self, command, name, hasValue, extra=None):
|
|
121
130
|
try:
|
|
122
131
|
v = self.symbols[name]
|
|
123
132
|
except:
|
|
@@ -137,6 +146,7 @@ class Compiler:
|
|
|
137
146
|
command['debug'] = False
|
|
138
147
|
command['import'] = None
|
|
139
148
|
command['locked'] = False
|
|
149
|
+
command['extra'] = extra
|
|
140
150
|
self.addCommand(command)
|
|
141
151
|
return True
|
|
142
152
|
|
|
@@ -164,7 +174,7 @@ class Compiler:
|
|
|
164
174
|
self.rewindTo(mark)
|
|
165
175
|
else:
|
|
166
176
|
self.rewindTo(mark)
|
|
167
|
-
FatalError(self, f'
|
|
177
|
+
FatalError(self, f'Unable to compile this "{token}" command. Perhaps a syntax error?')
|
|
168
178
|
|
|
169
179
|
# Compile a single command
|
|
170
180
|
def compileOne(self):
|
easycoder/ec_core.py
CHANGED
|
@@ -14,6 +14,9 @@ class Core(Handler):
|
|
|
14
14
|
|
|
15
15
|
def getName(self):
|
|
16
16
|
return 'core'
|
|
17
|
+
|
|
18
|
+
def noSymbolWarning(self):
|
|
19
|
+
self.warning(f'Symbol "{self.getToken()}" not found')
|
|
17
20
|
|
|
18
21
|
#############################################################################
|
|
19
22
|
# Keyword handlers
|
|
@@ -161,7 +164,6 @@ class Core(Handler):
|
|
|
161
164
|
val['type'] = 'boolean'
|
|
162
165
|
val['content'] = False
|
|
163
166
|
self.putSymbolValue(target, val)
|
|
164
|
-
# self.add(command)
|
|
165
167
|
return self.nextPC()
|
|
166
168
|
|
|
167
169
|
# Close a file
|
|
@@ -367,6 +369,8 @@ class Core(Handler):
|
|
|
367
369
|
return True
|
|
368
370
|
|
|
369
371
|
def r_exit(self, command):
|
|
372
|
+
if self.program.graphics != None:
|
|
373
|
+
self.program.graphics.force_exit()
|
|
370
374
|
return -1
|
|
371
375
|
|
|
372
376
|
# Declare a file variable
|
|
@@ -717,7 +721,7 @@ class Core(Handler):
|
|
|
717
721
|
try:
|
|
718
722
|
with open(filename) as f: content = f.read()
|
|
719
723
|
except:
|
|
720
|
-
|
|
724
|
+
content = ''
|
|
721
725
|
try:
|
|
722
726
|
if filename.endswith('.json'): content = json.loads(content)
|
|
723
727
|
except:
|
|
@@ -1295,7 +1299,10 @@ class Core(Handler):
|
|
|
1295
1299
|
if self.nextIsSymbol():
|
|
1296
1300
|
command['target'] = self.getSymbolRecord()['name']
|
|
1297
1301
|
if self.nextIs('to'):
|
|
1298
|
-
|
|
1302
|
+
value = self.nextValue()
|
|
1303
|
+
if value == None:
|
|
1304
|
+
FatalError(self.compiler, 'Unable to get a value')
|
|
1305
|
+
command['value'] = value
|
|
1299
1306
|
self.add(command)
|
|
1300
1307
|
return True
|
|
1301
1308
|
|
|
@@ -1379,6 +1386,33 @@ class Core(Handler):
|
|
|
1379
1386
|
self.putSymbolValue(targetVariable, val)
|
|
1380
1387
|
return self.nextPC()
|
|
1381
1388
|
|
|
1389
|
+
# Shuffle a list
|
|
1390
|
+
def k_shuffle(self, command):
|
|
1391
|
+
if self.nextIsSymbol():
|
|
1392
|
+
symbolRecord = self.getSymbolRecord()
|
|
1393
|
+
if symbolRecord['hasValue']:
|
|
1394
|
+
command['target'] = self.getToken()
|
|
1395
|
+
self.add(command)
|
|
1396
|
+
return True
|
|
1397
|
+
self.warning(f'Core.negate: Variable "{symbolRecord["name"]}" does not hold a value')
|
|
1398
|
+
return False
|
|
1399
|
+
|
|
1400
|
+
def r_shuffle(self, command):
|
|
1401
|
+
symbolRecord = self.getVariable(command['target'])
|
|
1402
|
+
if not symbolRecord['hasValue']:
|
|
1403
|
+
RuntimeError(self.program, f'{symbolRecord["name"]} does not hold a value')
|
|
1404
|
+
return None
|
|
1405
|
+
value = self.getSymbolValue(symbolRecord)
|
|
1406
|
+
if value == None:
|
|
1407
|
+
RuntimeError(self.program, f'{symbolRecord["name"]} has not been initialised')
|
|
1408
|
+
content = value['content']
|
|
1409
|
+
if isinstance(content, list):
|
|
1410
|
+
random.shuffle(content)
|
|
1411
|
+
value['content'] = content
|
|
1412
|
+
self.putSymbolValue(symbolRecord, value)
|
|
1413
|
+
return self.nextPC()
|
|
1414
|
+
RuntimeError(self.program, f'{symbolRecord["name"]} is not a list')
|
|
1415
|
+
|
|
1382
1416
|
# Split a string into a variable with several elements
|
|
1383
1417
|
# split {variable} on {value}
|
|
1384
1418
|
def k_split(self, command):
|
|
@@ -1400,6 +1434,7 @@ class Core(Handler):
|
|
|
1400
1434
|
command['on'] = self.nextValue()
|
|
1401
1435
|
self.add(command)
|
|
1402
1436
|
return True
|
|
1437
|
+
else: self.noSymbolWarning()
|
|
1403
1438
|
return False
|
|
1404
1439
|
|
|
1405
1440
|
def r_split(self, command):
|
|
@@ -1419,33 +1454,6 @@ class Core(Handler):
|
|
|
1419
1454
|
|
|
1420
1455
|
return self.nextPC()
|
|
1421
1456
|
|
|
1422
|
-
# Shuffle a list
|
|
1423
|
-
def k_shuffle(self, command):
|
|
1424
|
-
if self.nextIsSymbol():
|
|
1425
|
-
symbolRecord = self.getSymbolRecord()
|
|
1426
|
-
if symbolRecord['hasValue']:
|
|
1427
|
-
command['target'] = self.getToken()
|
|
1428
|
-
self.add(command)
|
|
1429
|
-
return True
|
|
1430
|
-
self.warning(f'Core.negate: Variable "{symbolRecord["name"]}" does not hold a value')
|
|
1431
|
-
return False
|
|
1432
|
-
|
|
1433
|
-
def r_shuffle(self, command):
|
|
1434
|
-
symbolRecord = self.getVariable(command['target'])
|
|
1435
|
-
if not symbolRecord['hasValue']:
|
|
1436
|
-
RuntimeError(self.program, f'{symbolRecord["name"]} does not hold a value')
|
|
1437
|
-
return None
|
|
1438
|
-
value = self.getSymbolValue(symbolRecord)
|
|
1439
|
-
if value == None:
|
|
1440
|
-
RuntimeError(self.program, f'{symbolRecord["name"]} has not been initialised')
|
|
1441
|
-
content = value['content']
|
|
1442
|
-
if isinstance(content, list):
|
|
1443
|
-
random.shuffle(content)
|
|
1444
|
-
value['content'] = content
|
|
1445
|
-
self.putSymbolValue(symbolRecord, value)
|
|
1446
|
-
return self.nextPC()
|
|
1447
|
-
RuntimeError(self.program, f'{symbolRecord["name"]} is not a list')
|
|
1448
|
-
|
|
1449
1457
|
# Declare a stack variable
|
|
1450
1458
|
def k_stack(self, command):
|
|
1451
1459
|
return self.compileVariable(command)
|
|
@@ -1599,7 +1607,9 @@ class Core(Handler):
|
|
|
1599
1607
|
|
|
1600
1608
|
def k_use(self, command):
|
|
1601
1609
|
if self.nextIs('graphics'):
|
|
1602
|
-
|
|
1610
|
+
print('Loading graphics module')
|
|
1611
|
+
from .ec_pyside import Graphics
|
|
1612
|
+
self.program.graphics = Graphics
|
|
1603
1613
|
self.program.classes.append(Graphics)
|
|
1604
1614
|
self.program.processClasses()
|
|
1605
1615
|
return True
|
|
@@ -1762,7 +1772,7 @@ class Core(Handler):
|
|
|
1762
1772
|
if token in ['now', 'today', 'newline', 'tab', 'empty']:
|
|
1763
1773
|
return value
|
|
1764
1774
|
|
|
1765
|
-
if token in ['stringify', 'json', 'lowercase', 'uppercase', 'hash', 'random', 'float', 'integer', 'encode', 'decode']:
|
|
1775
|
+
if token in ['stringify', 'prettify', 'json', 'lowercase', 'uppercase', 'hash', 'random', 'float', 'integer', 'encode', 'decode']:
|
|
1766
1776
|
value['content'] = self.nextValue()
|
|
1767
1777
|
return value
|
|
1768
1778
|
|
|
@@ -2272,6 +2282,13 @@ class Core(Handler):
|
|
|
2272
2282
|
value['content'] = haystack.rfind(needle) if last else haystack.find(needle)
|
|
2273
2283
|
return value
|
|
2274
2284
|
|
|
2285
|
+
def v_prettify(self, v):
|
|
2286
|
+
item = self.getRuntimeValue(v['content'])
|
|
2287
|
+
value = {}
|
|
2288
|
+
value['type'] = 'text'
|
|
2289
|
+
value['content'] = json.dumps(item, indent=4)
|
|
2290
|
+
return value
|
|
2291
|
+
|
|
2275
2292
|
def v_property(self, v):
|
|
2276
2293
|
propertyValue = self.getRuntimeValue(v['name'])
|
|
2277
2294
|
if 'target' in v:
|
easycoder/ec_handler.py
CHANGED
easycoder/ec_program.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
from easycoder import Handler, FatalError, RuntimeError
|
|
3
3
|
from PySide6.QtCore import Qt, QTimer
|
|
4
|
+
from PySide6.QtGui import QPixmap
|
|
4
5
|
from PySide6.QtWidgets import (
|
|
5
6
|
QApplication,
|
|
6
7
|
QCheckBox,
|
|
@@ -30,7 +31,8 @@ from PySide6.QtWidgets import (
|
|
|
30
31
|
QSpacerItem,
|
|
31
32
|
QSizePolicy,
|
|
32
33
|
QDialog,
|
|
33
|
-
QMessageBox
|
|
34
|
+
QMessageBox,
|
|
35
|
+
QDialogButtonBox
|
|
34
36
|
)
|
|
35
37
|
|
|
36
38
|
class Graphics(Handler):
|
|
@@ -84,28 +86,30 @@ class Graphics(Handler):
|
|
|
84
86
|
|
|
85
87
|
# Here it's either (1) or (2)
|
|
86
88
|
elif self.isSymbol():
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
self.nextToken()
|
|
92
|
-
return addToLayout()
|
|
93
|
-
else:
|
|
94
|
-
# (1)
|
|
95
|
-
command['value'] = self.getValue()
|
|
96
|
-
if self.nextIs('to'):
|
|
97
|
-
if self.nextIsSymbol():
|
|
89
|
+
record = self.getSymbolRecord()
|
|
90
|
+
if record['extra'] == 'gui':
|
|
91
|
+
if self.peek() == 'to':
|
|
92
|
+
# (2)
|
|
98
93
|
record = self.getSymbolRecord()
|
|
99
94
|
command['widget'] = record['name']
|
|
100
|
-
self.
|
|
101
|
-
return
|
|
95
|
+
self.nextToken()
|
|
96
|
+
return addToLayout()
|
|
97
|
+
return False
|
|
98
|
+
# (1)
|
|
99
|
+
command['value'] = self.getValue()
|
|
100
|
+
self.skip('to')
|
|
101
|
+
if self.nextIsSymbol():
|
|
102
|
+
record = self.getSymbolRecord()
|
|
103
|
+
command['widget'] = record['name']
|
|
104
|
+
self.add(command)
|
|
105
|
+
return True
|
|
102
106
|
return False
|
|
103
107
|
|
|
104
108
|
def r_add(self, command):
|
|
105
109
|
if 'value' in command:
|
|
106
110
|
value = self.getRuntimeValue(command['value'])
|
|
107
111
|
widget = self.getVariable(command['widget'])
|
|
108
|
-
if widget['keyword']
|
|
112
|
+
if widget['keyword'] in ['listbox', 'combobox']:
|
|
109
113
|
widget['widget'].addItem(value)
|
|
110
114
|
else:
|
|
111
115
|
layoutRecord = self.getVariable(command['layout'])
|
|
@@ -132,14 +136,51 @@ class Graphics(Handler):
|
|
|
132
136
|
else: layout.addWidget(widget)
|
|
133
137
|
return self.nextPC()
|
|
134
138
|
|
|
139
|
+
# Center one window on another
|
|
140
|
+
# center {window2} on {window1}
|
|
141
|
+
def k_center(self, command):
|
|
142
|
+
if self.nextIsSymbol():
|
|
143
|
+
record = self.getSymbolRecord()
|
|
144
|
+
if record['keyword'] == 'window':
|
|
145
|
+
command['window2'] = record['name']
|
|
146
|
+
self.skip('on')
|
|
147
|
+
if self.nextIsSymbol():
|
|
148
|
+
record = self.getSymbolRecord()
|
|
149
|
+
if record['keyword'] == 'window':
|
|
150
|
+
command['window1'] = record['name']
|
|
151
|
+
self.add(command)
|
|
152
|
+
return True
|
|
153
|
+
return False
|
|
154
|
+
|
|
155
|
+
def r_center(self, command):
|
|
156
|
+
window1 = self.getVariable(command['window1'])['window']
|
|
157
|
+
window2 = self.getVariable(command['window2'])['window']
|
|
158
|
+
geo1 = window1.geometry()
|
|
159
|
+
geo2 = window2.geometry()
|
|
160
|
+
geo2.moveCenter(geo1.center())
|
|
161
|
+
window2.setGeometry(geo2)
|
|
162
|
+
return self.nextPC()
|
|
163
|
+
|
|
135
164
|
# Declare a checkbox variable
|
|
136
165
|
def k_checkbox(self, command):
|
|
137
|
-
return self.compileVariable(command, False)
|
|
166
|
+
return self.compileVariable(command, False, 'gui')
|
|
138
167
|
|
|
139
168
|
def r_checkbox(self, command):
|
|
140
169
|
return self.nextPC()
|
|
141
170
|
|
|
142
|
-
#
|
|
171
|
+
# clear {widget}
|
|
172
|
+
def k_clear(self, command):
|
|
173
|
+
if self.nextIsSymbol():
|
|
174
|
+
command['name'] = self.getSymbolRecord()['name']
|
|
175
|
+
self.add(command)
|
|
176
|
+
return True
|
|
177
|
+
return False
|
|
178
|
+
|
|
179
|
+
def r_clear(self, command):
|
|
180
|
+
self.getVariable(command['name'])['widget'].clear()
|
|
181
|
+
return self.nextPC()
|
|
182
|
+
|
|
183
|
+
# close {window}
|
|
143
184
|
def k_close(self, command):
|
|
144
185
|
if self.nextIsSymbol():
|
|
145
186
|
record = self.getSymbolRecord()
|
|
@@ -155,7 +196,7 @@ class Graphics(Handler):
|
|
|
155
196
|
|
|
156
197
|
# Declare a combobox variable
|
|
157
198
|
def k_combobox(self, command):
|
|
158
|
-
return self.compileVariable(command, False)
|
|
199
|
+
return self.compileVariable(command, False, 'gui')
|
|
159
200
|
|
|
160
201
|
def r_combobox(self, command):
|
|
161
202
|
return self.nextPC()
|
|
@@ -165,34 +206,39 @@ class Graphics(Handler):
|
|
|
165
206
|
command['title'] = 'Default'
|
|
166
207
|
x = None
|
|
167
208
|
y = None
|
|
168
|
-
w = 640
|
|
169
|
-
h = 480
|
|
209
|
+
w = self.compileConstant(640)
|
|
210
|
+
h = self.compileConstant(480)
|
|
170
211
|
while True:
|
|
171
212
|
token = self.peek()
|
|
172
|
-
if token in ['title', 'at', 'size']:
|
|
213
|
+
if token in ['title', 'at', 'size', 'layout']:
|
|
173
214
|
self.nextToken()
|
|
174
215
|
if token == 'title': command['title'] = self.nextValue()
|
|
175
216
|
elif token == 'at':
|
|
176
217
|
x = self.nextValue()
|
|
177
218
|
y = self.nextValue()
|
|
178
219
|
elif token == 'size':
|
|
179
|
-
|
|
180
|
-
|
|
220
|
+
w = self.nextValue()
|
|
221
|
+
h = self.nextValue()
|
|
222
|
+
elif token == 'layout':
|
|
223
|
+
if self.nextIsSymbol():
|
|
224
|
+
record = self.getSymbolRecord()
|
|
225
|
+
if record['keyword'] == 'layout':
|
|
226
|
+
command['layout'] = record['name']
|
|
227
|
+
else: return False
|
|
181
228
|
else: break
|
|
182
|
-
command['w'] = self.compileConstant(w)
|
|
183
|
-
command['h'] = self.compileConstant(h)
|
|
184
229
|
command['x'] = x
|
|
185
230
|
command['y'] = y
|
|
231
|
+
command['w'] = w
|
|
232
|
+
command['h'] = h
|
|
186
233
|
self.add(command)
|
|
187
234
|
return True
|
|
188
235
|
|
|
189
236
|
# Create a widget
|
|
190
237
|
def k_createLayout(self, command):
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return False
|
|
238
|
+
self.skip('type')
|
|
239
|
+
command['type'] = self.nextToken()
|
|
240
|
+
self.add(command)
|
|
241
|
+
return True
|
|
196
242
|
|
|
197
243
|
def k_createGroupBox(self, command):
|
|
198
244
|
if self.peek() == 'title':
|
|
@@ -204,7 +250,7 @@ class Graphics(Handler):
|
|
|
204
250
|
return True
|
|
205
251
|
|
|
206
252
|
def k_createLabel(self, command):
|
|
207
|
-
text = ''
|
|
253
|
+
text = self.compileConstant('')
|
|
208
254
|
while True:
|
|
209
255
|
token = self.peek()
|
|
210
256
|
if token == 'text':
|
|
@@ -213,6 +259,11 @@ class Graphics(Handler):
|
|
|
213
259
|
elif token == 'size':
|
|
214
260
|
self.nextToken()
|
|
215
261
|
command['size'] = self.nextValue()
|
|
262
|
+
elif token == 'align':
|
|
263
|
+
self.nextToken()
|
|
264
|
+
token = self.nextToken()
|
|
265
|
+
if token in ['left', 'right', 'center', 'centre', 'justify']:
|
|
266
|
+
command['align'] = token
|
|
216
267
|
else: break
|
|
217
268
|
command['text'] = text
|
|
218
269
|
self.add(command)
|
|
@@ -260,38 +311,50 @@ class Graphics(Handler):
|
|
|
260
311
|
return True
|
|
261
312
|
|
|
262
313
|
def k_createDialog(self, command):
|
|
263
|
-
if self.peek() == '
|
|
314
|
+
if self.peek() == 'on':
|
|
264
315
|
self.nextToken()
|
|
265
|
-
|
|
266
|
-
|
|
316
|
+
if self.nextIsSymbol():
|
|
317
|
+
command['window'] = self.getSymbolRecord()['name']
|
|
318
|
+
else: command['window'] = None
|
|
319
|
+
title = ''
|
|
320
|
+
while True:
|
|
321
|
+
if self.peek() == 'title':
|
|
322
|
+
self.nextToken()
|
|
323
|
+
title = self.nextValue()
|
|
324
|
+
elif self.peek() == 'layout':
|
|
325
|
+
self.nextToken()
|
|
326
|
+
if self.nextIsSymbol():
|
|
327
|
+
command['layout'] = self.getSymbolRecord()['name']
|
|
328
|
+
else: break
|
|
267
329
|
command['title'] = title
|
|
268
330
|
self.add(command)
|
|
269
331
|
return True
|
|
270
332
|
|
|
271
333
|
def k_createMessageBox(self, command):
|
|
272
|
-
if self.
|
|
334
|
+
if self.peek() == 'on':
|
|
335
|
+
self.nextToken()
|
|
273
336
|
if self.nextIsSymbol():
|
|
274
337
|
command['window'] = self.getSymbolRecord()['name']
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
return
|
|
338
|
+
else: command['window'] = None
|
|
339
|
+
style = 'question'
|
|
340
|
+
title = ''
|
|
341
|
+
message = ''
|
|
342
|
+
while True:
|
|
343
|
+
if self.peek() == 'style':
|
|
344
|
+
self.nextToken()
|
|
345
|
+
style = self.nextToken()
|
|
346
|
+
elif self.peek() == 'title':
|
|
347
|
+
self.nextToken()
|
|
348
|
+
title = self.nextValue()
|
|
349
|
+
elif self.peek() == 'message':
|
|
350
|
+
self.nextToken()
|
|
351
|
+
message = self.nextValue()
|
|
352
|
+
else: break
|
|
353
|
+
command['style'] = style
|
|
354
|
+
command['title'] = title
|
|
355
|
+
command['message'] = message
|
|
356
|
+
self.add(command)
|
|
357
|
+
return True
|
|
295
358
|
|
|
296
359
|
def k_create(self, command):
|
|
297
360
|
if self.nextIsSymbol():
|
|
@@ -323,6 +386,9 @@ class Graphics(Handler):
|
|
|
323
386
|
if y == None: y = (self.screenHeight - h) / 2
|
|
324
387
|
else: y = self.getRuntimeValue(x)
|
|
325
388
|
window.setGeometry(x, y, w, h)
|
|
389
|
+
container = QWidget()
|
|
390
|
+
container.setLayout(self.getVariable(command['layout'])['widget'])
|
|
391
|
+
window.setCentralWidget(container)
|
|
326
392
|
record['window'] = window
|
|
327
393
|
return self.nextPC()
|
|
328
394
|
|
|
@@ -347,17 +413,25 @@ class Graphics(Handler):
|
|
|
347
413
|
if 'size' in command:
|
|
348
414
|
fm = label.fontMetrics()
|
|
349
415
|
c = label.contentsMargins()
|
|
350
|
-
w = fm.horizontalAdvance('
|
|
416
|
+
w = fm.horizontalAdvance('m') * self.getRuntimeValue(command['size']) +c.left()+c.right()
|
|
351
417
|
label.setMaximumWidth(w)
|
|
418
|
+
if 'align' in command:
|
|
419
|
+
alignment = command['align']
|
|
420
|
+
if alignment == 'left': label.setAlignment(Qt.AlignLeft)
|
|
421
|
+
elif alignment == 'right': label.setAlignment(Qt.AlignRight)
|
|
422
|
+
elif alignment in ['center', 'centre']: label.setAlignment(Qt.AlignHCenter)
|
|
423
|
+
elif alignment == 'justify': label.setAlignment(Qt.AlignJustify)
|
|
352
424
|
record['widget'] = label
|
|
353
425
|
return self.nextPC()
|
|
354
426
|
|
|
355
427
|
def r_createPushbutton(self, command, record):
|
|
356
|
-
|
|
428
|
+
text = self.getRuntimeValue(command['text'])
|
|
429
|
+
pushbutton = QPushButton(text)
|
|
430
|
+
pushbutton.setAccessibleName(text)
|
|
357
431
|
if 'size' in command:
|
|
358
432
|
fm = pushbutton.fontMetrics()
|
|
359
433
|
c = pushbutton.contentsMargins()
|
|
360
|
-
w = fm.horizontalAdvance('
|
|
434
|
+
w = fm.horizontalAdvance('m') * self.getRuntimeValue(command['size']) +c.left()+c.right()
|
|
361
435
|
pushbutton.setMaximumWidth(w)
|
|
362
436
|
record['widget'] = pushbutton
|
|
363
437
|
return self.nextPC()
|
|
@@ -386,8 +460,14 @@ class Graphics(Handler):
|
|
|
386
460
|
return self.nextPC()
|
|
387
461
|
|
|
388
462
|
def r_createDialog(self, command, record):
|
|
463
|
+
layout = self.getVariable(command['layout'])['widget']
|
|
389
464
|
dialog = QDialog()
|
|
390
465
|
dialog.setWindowTitle(self.getRuntimeValue(command['title']))
|
|
466
|
+
dialog.buttonBox = QDialogButtonBox((QDialogButtonBox.Ok | QDialogButtonBox.Cancel))
|
|
467
|
+
dialog.buttonBox.accepted.connect(dialog.accept)
|
|
468
|
+
dialog.buttonBox.rejected.connect(dialog.reject)
|
|
469
|
+
layout.addWidget(dialog.buttonBox)
|
|
470
|
+
dialog.setLayout(layout)
|
|
391
471
|
record['dialog'] = dialog
|
|
392
472
|
return self.nextPC()
|
|
393
473
|
|
|
@@ -450,7 +530,7 @@ class Graphics(Handler):
|
|
|
450
530
|
|
|
451
531
|
# Create a group box
|
|
452
532
|
def k_groupbox(self, command):
|
|
453
|
-
return self.compileVariable(command, False)
|
|
533
|
+
return self.compileVariable(command, False, 'gui')
|
|
454
534
|
|
|
455
535
|
def r_groupbox(self, command):
|
|
456
536
|
return self.nextPC()
|
|
@@ -472,28 +552,28 @@ class Graphics(Handler):
|
|
|
472
552
|
|
|
473
553
|
# Declare a label variable
|
|
474
554
|
def k_label(self, command):
|
|
475
|
-
return self.compileVariable(command, False)
|
|
555
|
+
return self.compileVariable(command, False, 'gui')
|
|
476
556
|
|
|
477
557
|
def r_label(self, command):
|
|
478
558
|
return self.nextPC()
|
|
479
559
|
|
|
480
560
|
# Declare a layout variable
|
|
481
561
|
def k_layout(self, command):
|
|
482
|
-
return self.compileVariable(command, False)
|
|
562
|
+
return self.compileVariable(command, False, 'gui')
|
|
483
563
|
|
|
484
564
|
def r_layout(self, command):
|
|
485
565
|
return self.nextPC()
|
|
486
566
|
|
|
487
567
|
# Declare a line input variable
|
|
488
568
|
def k_lineinput(self, command):
|
|
489
|
-
return self.compileVariable(command, False)
|
|
569
|
+
return self.compileVariable(command, False, 'gui')
|
|
490
570
|
|
|
491
571
|
def r_lineinput(self, command):
|
|
492
572
|
return self.nextPC()
|
|
493
573
|
|
|
494
574
|
# Declare a listbox input variable
|
|
495
575
|
def k_listbox(self, command):
|
|
496
|
-
return self.compileVariable(command, False)
|
|
576
|
+
return self.compileVariable(command, False, 'gui')
|
|
497
577
|
|
|
498
578
|
def r_listbox(self, command):
|
|
499
579
|
return self.nextPC()
|
|
@@ -505,139 +585,247 @@ class Graphics(Handler):
|
|
|
505
585
|
def r_messagebox(self, command):
|
|
506
586
|
return self.nextPC()
|
|
507
587
|
|
|
508
|
-
#
|
|
588
|
+
# on click {pushbutton}
|
|
589
|
+
# on select {combobox}/{listbox}
|
|
509
590
|
def k_on(self, command):
|
|
510
|
-
|
|
591
|
+
def setupOn():
|
|
592
|
+
command['name'] = record['name']
|
|
593
|
+
command['goto'] = self.getPC() + 2
|
|
594
|
+
self.add(command)
|
|
595
|
+
self.nextToken()
|
|
596
|
+
# Step over the click handler
|
|
597
|
+
pcNext = self.getPC()
|
|
598
|
+
cmd = {}
|
|
599
|
+
cmd['domain'] = 'core'
|
|
600
|
+
cmd['lino'] = command['lino']
|
|
601
|
+
cmd['keyword'] = 'gotoPC'
|
|
602
|
+
cmd['goto'] = 0
|
|
603
|
+
cmd['debug'] = False
|
|
604
|
+
self.addCommand(cmd)
|
|
605
|
+
# This is the click handler
|
|
606
|
+
self.compileOne()
|
|
607
|
+
cmd = {}
|
|
608
|
+
cmd['domain'] = 'core'
|
|
609
|
+
cmd['lino'] = command['lino']
|
|
610
|
+
cmd['keyword'] = 'stop'
|
|
611
|
+
cmd['debug'] = False
|
|
612
|
+
self.addCommand(cmd)
|
|
613
|
+
# Fixup the link
|
|
614
|
+
self.getCommandAt(pcNext)['goto'] = self.getPC()
|
|
615
|
+
|
|
616
|
+
token = self.nextToken()
|
|
617
|
+
if token == 'click':
|
|
511
618
|
if self.nextIsSymbol():
|
|
512
619
|
record = self.getSymbolRecord()
|
|
513
620
|
if record['keyword'] == 'pushbutton':
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
cmd['domain'] = 'core'
|
|
522
|
-
cmd['lino'] = command['lino']
|
|
523
|
-
cmd['keyword'] = 'gotoPC'
|
|
524
|
-
cmd['goto'] = 0
|
|
525
|
-
cmd['debug'] = False
|
|
526
|
-
self.addCommand(cmd)
|
|
527
|
-
# This is the click handler
|
|
528
|
-
self.compileOne()
|
|
529
|
-
cmd = {}
|
|
530
|
-
cmd['domain'] = 'core'
|
|
531
|
-
cmd['lino'] = command['lino']
|
|
532
|
-
cmd['keyword'] = 'stop'
|
|
533
|
-
cmd['debug'] = False
|
|
534
|
-
self.addCommand(cmd)
|
|
535
|
-
# Fixup the link
|
|
536
|
-
self.getCommandAt(pcNext)['goto'] = self.getPC()
|
|
621
|
+
setupOn()
|
|
622
|
+
return True
|
|
623
|
+
elif token == 'select':
|
|
624
|
+
if self.nextIsSymbol():
|
|
625
|
+
record = self.getSymbolRecord()
|
|
626
|
+
if record['keyword'] in ['combobox', 'listbox']:
|
|
627
|
+
setupOn()
|
|
537
628
|
return True
|
|
538
629
|
return False
|
|
539
630
|
|
|
540
631
|
def r_on(self, command):
|
|
541
|
-
|
|
542
|
-
|
|
632
|
+
record = self.getVariable(command['name'])
|
|
633
|
+
widget = record['widget']
|
|
634
|
+
keyword = record['keyword']
|
|
635
|
+
if keyword == 'pushbutton':
|
|
636
|
+
widget.clicked.connect(lambda: self.run(command['goto']))
|
|
637
|
+
elif keyword == 'combobox':
|
|
638
|
+
widget.currentIndexChanged.connect(lambda: self.run(command['goto']))
|
|
639
|
+
elif keyword == 'listbox':
|
|
640
|
+
widget.itemClicked.connect(lambda: self.run(command['goto']))
|
|
543
641
|
return self.nextPC()
|
|
544
642
|
|
|
545
643
|
# Declare a pushbutton variable
|
|
546
644
|
def k_pushbutton(self, command):
|
|
547
|
-
return self.compileVariable(command, False)
|
|
645
|
+
return self.compileVariable(command, False, 'gui')
|
|
548
646
|
|
|
549
647
|
def r_pushbutton(self, command):
|
|
550
648
|
return self.nextPC()
|
|
551
649
|
|
|
552
|
-
# remove current item from {combobox}
|
|
650
|
+
# remove [the] [current/selected] [item] [from/in] {combobox}/{listbox}
|
|
553
651
|
def k_remove(self, command):
|
|
554
652
|
command['variant'] = None
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
653
|
+
self.skip('the')
|
|
654
|
+
self.skip(['current', 'selected'])
|
|
655
|
+
self.skip('item')
|
|
656
|
+
self.skip(['from', 'in'])
|
|
657
|
+
if self.nextIsSymbol():
|
|
658
|
+
record = self.getSymbolRecord()
|
|
659
|
+
if record['keyword'] == 'combobox':
|
|
660
|
+
command['variant'] = 'current'
|
|
661
|
+
command['name'] = record['name']
|
|
662
|
+
self.addCommand(command)
|
|
663
|
+
return True
|
|
664
|
+
elif record['keyword'] == 'listbox':
|
|
665
|
+
command['variant'] = 'current'
|
|
666
|
+
command['name'] = record['name']
|
|
667
|
+
self.addCommand(command)
|
|
668
|
+
return True
|
|
565
669
|
return False
|
|
566
670
|
|
|
567
671
|
def r_remove(self, command):
|
|
568
672
|
variant = command['variant']
|
|
569
673
|
record = self.getVariable(command['name'])
|
|
570
|
-
if
|
|
571
|
-
|
|
572
|
-
|
|
674
|
+
if variant == 'current':
|
|
675
|
+
if record['keyword'] == 'combobox':
|
|
676
|
+
widget = record['widget']
|
|
677
|
+
widget.removeItem(widget.currentIndex())
|
|
678
|
+
if record['keyword'] == 'listbox':
|
|
679
|
+
widget = record['widget']
|
|
680
|
+
selectedItem = widget.currentItem()
|
|
681
|
+
if selectedItem:
|
|
682
|
+
row = widget.row(selectedItem)
|
|
683
|
+
widget.takeItem(row)
|
|
573
684
|
return self.nextPC()
|
|
574
685
|
|
|
575
|
-
#
|
|
576
|
-
|
|
577
|
-
|
|
686
|
+
# select index {n} [of] {combobox]}
|
|
687
|
+
# select {name} [in] {combobox}
|
|
688
|
+
def k_select(self, command):
|
|
689
|
+
if self.nextIs('index'):
|
|
690
|
+
command['index'] = self.nextValue()
|
|
691
|
+
self.skip('of')
|
|
692
|
+
else:
|
|
693
|
+
command['name'] = self.nextValue()
|
|
694
|
+
self.skip('in')
|
|
695
|
+
if self.nextIsSymbol():
|
|
696
|
+
record = self.getSymbolRecord()
|
|
697
|
+
if record['keyword'] == 'combobox':
|
|
698
|
+
command['widget'] = record['name']
|
|
699
|
+
self.add(command)
|
|
700
|
+
return True
|
|
701
|
+
return False
|
|
702
|
+
|
|
703
|
+
def r_select(self, command):
|
|
704
|
+
widget = self.getVariable(command['widget'])['widget']
|
|
705
|
+
if 'index' in command:
|
|
706
|
+
index = self.getRuntimeValue(command['index'])
|
|
707
|
+
else:
|
|
708
|
+
name = self.getRuntimeValue(command['name'])
|
|
709
|
+
index = widget.findText(name, Qt.MatchFixedString)
|
|
710
|
+
if index >= 0:
|
|
711
|
+
widget.setCurrentIndex(index)
|
|
712
|
+
return self.nextPC()
|
|
578
713
|
|
|
579
|
-
#
|
|
714
|
+
# set [the] width/height [of] {widget} [to] {value}
|
|
715
|
+
# set [the] text [of] {label}/{button}/{lineinput} [to] {text}
|
|
716
|
+
# set [the] color [of] {label}/{button}/{lineinput} [to] {color}
|
|
717
|
+
# set {listbox} to {list}
|
|
580
718
|
def k_set(self, command):
|
|
719
|
+
self.skip('the')
|
|
581
720
|
token = self.nextToken()
|
|
582
|
-
|
|
583
|
-
if token
|
|
584
|
-
|
|
585
|
-
if self.
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
721
|
+
command['what'] = token
|
|
722
|
+
if token in ['width', 'height']:
|
|
723
|
+
self.skip('of')
|
|
724
|
+
if self.nextIsSymbol():
|
|
725
|
+
record = self.getSymbolRecord()
|
|
726
|
+
if record['extra'] == 'gui':
|
|
727
|
+
command['name'] = record['name']
|
|
728
|
+
self.skip('to')
|
|
729
|
+
command['value'] = self.nextValue()
|
|
730
|
+
self.add(command)
|
|
731
|
+
return True
|
|
732
|
+
elif token == 'text':
|
|
733
|
+
self.skip('of')
|
|
734
|
+
if self.nextIsSymbol():
|
|
735
|
+
record = self.getSymbolRecord()
|
|
736
|
+
if record['keyword'] in ['label', 'pushbutton', 'lineinput']:
|
|
737
|
+
command['name'] = record['name']
|
|
738
|
+
self.skip('to')
|
|
739
|
+
command['value'] = self.nextValue()
|
|
740
|
+
self.add(command)
|
|
741
|
+
return True
|
|
742
|
+
elif token == 'color':
|
|
743
|
+
self.skip('of')
|
|
744
|
+
if self.nextIsSymbol():
|
|
745
|
+
record = self.getSymbolRecord()
|
|
746
|
+
if record['keyword'] == 'label':
|
|
747
|
+
command['name'] = record['name']
|
|
748
|
+
self.skip('to')
|
|
749
|
+
command['value'] = self.nextValue()
|
|
750
|
+
self.add(command)
|
|
751
|
+
return True
|
|
752
|
+
elif token == 'background':
|
|
753
|
+
self.skip('color')
|
|
754
|
+
self.skip('of')
|
|
755
|
+
if self.nextIsSymbol():
|
|
756
|
+
record = self.getSymbolRecord()
|
|
757
|
+
if record['keyword'] in ['label', 'pushbutton', 'lineinput']:
|
|
758
|
+
command['name'] = record['name']
|
|
759
|
+
self.skip('to')
|
|
760
|
+
command['value'] = self.nextValue()
|
|
761
|
+
self.add(command)
|
|
762
|
+
return True
|
|
763
|
+
elif self.isSymbol():
|
|
764
|
+
record = self.getSymbolRecord()
|
|
765
|
+
if record['keyword'] == 'listbox':
|
|
766
|
+
command['what'] = 'listbox'
|
|
767
|
+
command['name'] = record['name']
|
|
768
|
+
self.skip('to')
|
|
769
|
+
command['value'] = self.nextValue()
|
|
770
|
+
self.add(command)
|
|
771
|
+
return True
|
|
595
772
|
return False
|
|
596
773
|
|
|
597
774
|
def r_set(self, command):
|
|
598
|
-
|
|
599
|
-
if
|
|
600
|
-
|
|
601
|
-
|
|
775
|
+
what = command['what']
|
|
776
|
+
if what == 'height':
|
|
777
|
+
widget = self.getVariable(command['name'])['widget']
|
|
778
|
+
widget.setFixedHeight(self.getRuntimeValue(command['value']))
|
|
779
|
+
elif what == 'width':
|
|
780
|
+
widget = self.getVariable(command['name'])['widget']
|
|
781
|
+
widget.setFixedWidth(self.getRuntimeValue(command['value']))
|
|
782
|
+
elif what == 'text':
|
|
783
|
+
record = self.getVariable(command['name'])
|
|
784
|
+
widget = self.getVariable(command['name'])['widget']
|
|
785
|
+
text = self.getRuntimeValue(command['value'])
|
|
786
|
+
widget.setText(text)
|
|
787
|
+
if record['keyword'] == 'pushbutton':
|
|
788
|
+
widget.setAccessibleName(text)
|
|
789
|
+
elif what == 'color':
|
|
790
|
+
widget = self.getVariable(command['name'])['widget']
|
|
791
|
+
color = self.getRuntimeValue(command['value'])
|
|
792
|
+
widget.setStyleSheet(f"color: {color};")
|
|
793
|
+
elif what == 'background-color':
|
|
794
|
+
widget = self.getVariable(command['name'])['widget']
|
|
795
|
+
bg_color = self.getRuntimeValue(command['value'])
|
|
796
|
+
widget.setStyleSheet(f"background-color: {bg_color};")
|
|
797
|
+
elif what == 'listbox':
|
|
798
|
+
widget = self.getVariable(command['name'])['widget']
|
|
799
|
+
value = self.getRuntimeValue(command['value'])
|
|
800
|
+
widget.addItems(value)
|
|
602
801
|
return self.nextPC()
|
|
603
802
|
|
|
604
|
-
#
|
|
605
|
-
# show {
|
|
606
|
-
# show {
|
|
803
|
+
# show {window}
|
|
804
|
+
# show {dialog}
|
|
805
|
+
# show {messagebox} giving {result}}
|
|
607
806
|
def k_show(self, command):
|
|
608
807
|
if self.nextIsSymbol():
|
|
609
808
|
record = self.getSymbolRecord()
|
|
610
809
|
keyword = record['keyword']
|
|
611
|
-
if keyword == '
|
|
612
|
-
command['
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
record = self.getSymbolRecord()
|
|
616
|
-
if record['keyword'] == 'window':
|
|
617
|
-
command['window'] = record['name']
|
|
618
|
-
self.add(command)
|
|
619
|
-
return True
|
|
810
|
+
if keyword == 'window':
|
|
811
|
+
command['window'] = record['name']
|
|
812
|
+
self.add(command)
|
|
813
|
+
return True
|
|
620
814
|
elif keyword == 'dialog':
|
|
621
815
|
command['dialog'] = record['name']
|
|
622
816
|
self.add(command)
|
|
623
817
|
return True
|
|
624
818
|
elif keyword == 'messagebox':
|
|
625
819
|
command['messagebox'] = record['name']
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
820
|
+
self.skip('giving')
|
|
821
|
+
if self.nextIsSymbol():
|
|
822
|
+
command['result'] = self.getSymbolRecord()['name']
|
|
823
|
+
self.add(command)
|
|
824
|
+
return True
|
|
631
825
|
return False
|
|
632
826
|
|
|
633
827
|
def r_show(self, command):
|
|
634
|
-
if '
|
|
635
|
-
dialog = self.getVariable(command['dialog'])['dialog']
|
|
636
|
-
b1 = QPushButton("ok",dialog)
|
|
637
|
-
b1.move(50,50)
|
|
638
|
-
dialog.setWindowModality(Qt.ApplicationModal)
|
|
639
|
-
dialog.exec_()
|
|
640
|
-
elif 'messagebox' in command:
|
|
828
|
+
if 'messagebox' in command:
|
|
641
829
|
data = self.getVariable(command['messagebox'])['data']
|
|
642
830
|
symbolRecord = self.getVariable(command['result'])
|
|
643
831
|
window = self.getVariable(data['window'])['window']
|
|
@@ -657,14 +845,12 @@ class Graphics(Handler):
|
|
|
657
845
|
v['type'] = 'text'
|
|
658
846
|
v['content'] = result
|
|
659
847
|
self.putSymbolValue(symbolRecord, v)
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
windowRecord = self.getVariable(command['window'])
|
|
663
|
-
window = windowRecord['window']
|
|
664
|
-
container = QWidget()
|
|
665
|
-
container.setLayout(layoutRecord['widget'])
|
|
666
|
-
window.setCentralWidget(container)
|
|
848
|
+
elif 'window' in command:
|
|
849
|
+
window = self.getVariable(command['window'])['window']
|
|
667
850
|
window.show()
|
|
851
|
+
elif 'dialog' in command:
|
|
852
|
+
dialog = self.getVariable(command['dialog'])['dialog']
|
|
853
|
+
dialog.exec()
|
|
668
854
|
return self.nextPC()
|
|
669
855
|
|
|
670
856
|
# Start the graphics
|
|
@@ -676,12 +862,14 @@ class Graphics(Handler):
|
|
|
676
862
|
|
|
677
863
|
def r_start(self, command):
|
|
678
864
|
def on_last_window_closed():
|
|
679
|
-
print("
|
|
865
|
+
print("Kill the appication...")
|
|
680
866
|
self.program.kill()
|
|
681
867
|
def resume():
|
|
682
868
|
self.program.flush(self.nextPC())
|
|
869
|
+
def flush():
|
|
870
|
+
self.program.flushCB()
|
|
683
871
|
timer = QTimer()
|
|
684
|
-
timer.timeout.connect(
|
|
872
|
+
timer.timeout.connect(flush)
|
|
685
873
|
timer.start(10)
|
|
686
874
|
QTimer.singleShot(500, resume)
|
|
687
875
|
self.app.lastWindowClosed.connect(on_last_window_closed)
|
|
@@ -693,7 +881,7 @@ class Graphics(Handler):
|
|
|
693
881
|
|
|
694
882
|
def r_window(self, command):
|
|
695
883
|
return self.nextPC()
|
|
696
|
-
|
|
884
|
+
|
|
697
885
|
#############################################################################
|
|
698
886
|
# Compile a value in this domain
|
|
699
887
|
def compileValue(self):
|
|
@@ -710,15 +898,27 @@ class Graphics(Handler):
|
|
|
710
898
|
token = self.getToken()
|
|
711
899
|
|
|
712
900
|
if token == 'count':
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
901
|
+
self.skip('of')
|
|
902
|
+
if self.nextIsSymbol():
|
|
903
|
+
value['type'] = 'symbol'
|
|
904
|
+
record = self.getSymbolRecord()
|
|
905
|
+
keyword = record['keyword']
|
|
906
|
+
if keyword in ['combobox', 'listbox']:
|
|
907
|
+
value['type'] = 'count'
|
|
908
|
+
value['name'] = record['name']
|
|
909
|
+
return value
|
|
910
|
+
|
|
911
|
+
if token == 'current':
|
|
912
|
+
self.skip('item')
|
|
913
|
+
self.skip('in')
|
|
914
|
+
if self.nextIsSymbol():
|
|
915
|
+
value['type'] = 'symbol'
|
|
916
|
+
record = self.getSymbolRecord()
|
|
917
|
+
keyword = record['keyword']
|
|
918
|
+
if keyword == 'listbox':
|
|
919
|
+
value['type'] = 'current'
|
|
920
|
+
value['name'] = record['name']
|
|
921
|
+
return value
|
|
722
922
|
|
|
723
923
|
return None
|
|
724
924
|
|
|
@@ -734,24 +934,53 @@ class Graphics(Handler):
|
|
|
734
934
|
def v_symbol(self, symbolRecord):
|
|
735
935
|
symbolRecord = self.getVariable(symbolRecord['name'])
|
|
736
936
|
keyword = symbolRecord['keyword']
|
|
737
|
-
if keyword == '
|
|
937
|
+
if keyword == 'pushbutton':
|
|
938
|
+
pushbutton = symbolRecord['widget']
|
|
939
|
+
v = {}
|
|
940
|
+
v['type'] = 'text'
|
|
941
|
+
v['content'] = pushbutton.accessibleName()
|
|
942
|
+
return v
|
|
943
|
+
elif keyword == 'lineinput':
|
|
944
|
+
lineinput = symbolRecord['widget']
|
|
945
|
+
v = {}
|
|
946
|
+
v['type'] = 'text'
|
|
947
|
+
v['content'] = lineinput.displayText()
|
|
948
|
+
return v
|
|
949
|
+
elif keyword == 'combobox':
|
|
738
950
|
combobox = symbolRecord['widget']
|
|
739
951
|
v = {}
|
|
740
952
|
v['type'] = 'text'
|
|
741
953
|
v['content'] = combobox.currentText()
|
|
742
954
|
return v
|
|
955
|
+
elif keyword == 'listbox':
|
|
956
|
+
listbox = symbolRecord['widget']
|
|
957
|
+
content = listbox.currentItem().text()
|
|
958
|
+
v = {}
|
|
959
|
+
v['type'] = 'text'
|
|
960
|
+
v['content'] = content
|
|
961
|
+
return v
|
|
743
962
|
return None
|
|
744
963
|
|
|
745
964
|
def v_count(self, v):
|
|
746
965
|
record = self.getVariable(v['name'])
|
|
747
966
|
keyword = record['keyword']
|
|
748
967
|
widget = record['widget']
|
|
749
|
-
if keyword
|
|
968
|
+
if keyword in ['combobox', 'listbox']: content = widget.count()
|
|
750
969
|
value = {}
|
|
751
970
|
value['type'] = 'int'
|
|
752
971
|
value['content'] = content
|
|
753
972
|
return value
|
|
754
973
|
|
|
974
|
+
def v_current(self, v):
|
|
975
|
+
record = self.getVariable(v['name'])
|
|
976
|
+
keyword = record['keyword']
|
|
977
|
+
widget = record['widget']
|
|
978
|
+
if keyword == 'listbox': content = widget.currentItem().text()
|
|
979
|
+
value = {}
|
|
980
|
+
value['type'] = 'text'
|
|
981
|
+
value['content'] = content
|
|
982
|
+
return value
|
|
983
|
+
|
|
755
984
|
#############################################################################
|
|
756
985
|
# Compile a condition
|
|
757
986
|
def compileCondition(self):
|
|
@@ -760,3 +989,22 @@ class Graphics(Handler):
|
|
|
760
989
|
|
|
761
990
|
#############################################################################
|
|
762
991
|
# Condition handlers
|
|
992
|
+
|
|
993
|
+
#############################################################################
|
|
994
|
+
# Force the application to exit
|
|
995
|
+
def force_exit(self):
|
|
996
|
+
QApplication.quit() # Gracefully close the application
|
|
997
|
+
sys.exit(0) # Force a complete system exit
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
def addIconToLayout(layout, icon_path):
|
|
1001
|
+
"""
|
|
1002
|
+
Adds an icon to the specified layout.
|
|
1003
|
+
|
|
1004
|
+
:param layout: The layout to which the icon will be added.
|
|
1005
|
+
:param icon_path: The file path of the icon image.
|
|
1006
|
+
"""
|
|
1007
|
+
icon_label = QLabel()
|
|
1008
|
+
pixmap = QPixmap(icon_path)
|
|
1009
|
+
icon_label.setPixmap(pixmap)
|
|
1010
|
+
layout.addWidget(icon_label)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: easycoder
|
|
3
|
-
Version:
|
|
3
|
+
Version: 250503.1
|
|
4
4
|
Summary: Rapid scripting in English
|
|
5
5
|
Keywords: compiler,scripting,prototyping,programming,coding,python,low code,hypertalk,computer language,learn to code
|
|
6
6
|
Author-email: Graham Trott <gtanyware@gmail.com>
|
|
@@ -11,7 +11,11 @@ Requires-Dist: pyside6
|
|
|
11
11
|
Project-URL: Home, https://github.com/easycoder/easycoder-py
|
|
12
12
|
|
|
13
13
|
# Introduction
|
|
14
|
-
**_EasyCoder_** is a high-level English-like scripting language suited for prototyping and rapid testing of ideas. It operates on the command line and a graphics module is under construction. The language is written in Python and it acts as a fairly thin wrapper around standard Python functions, giving fast compilation and good runtime performance for general applications.
|
|
14
|
+
**_EasyCoder_** is a high-level English-like domain-specific scripting language (DSL) suited for prototyping and rapid testing of ideas. It operates on the command line and a graphics module is under construction. The language is written in Python and it acts as a fairly thin wrapper around standard Python functions, giving fast compilation and good runtime performance for general applications.
|
|
15
|
+
|
|
16
|
+
**_EasyCoder_** is well suited to building command-line or graphical applications for expressing random logic such as operating procedures and rules, or controlling physical systems, primarily wifi devices. It is particularly easy to construct and issue REST commands to local or remote web servers.
|
|
17
|
+
|
|
18
|
+
For more advanced applications, **_EasyCoder_** is designed to be extensible, by enabling extra language syntax to be added via plugin-in modules. Once these are installed they act as seamless extensions to the basic syntax provided. **_EasyCoder_** derives its power from the use of rich and comprehensive language rather than a complex system of frameworks such as those commonly used in modern programming. This makes it very easy to learn as our brains are wired to operate that way. Having said that, the needs of most control systems are usually served by a fairly modest number of keywords and syntactic variants.
|
|
15
19
|
<hr>
|
|
16
20
|
|
|
17
21
|
There is also a JavaScript version of **_EasyCoder_**, which provides a full set of graphical features to run in a browser. For this, please visit
|
|
@@ -23,15 +27,12 @@ Website: [https://easycoder.github.io](https://easycoder.github.io)
|
|
|
23
27
|
## Quick Start
|
|
24
28
|
Install **_EasyCoder_** in your Python environment:
|
|
25
29
|
```
|
|
26
|
-
pip install requests
|
|
30
|
+
pip install requests easycoder
|
|
27
31
|
```
|
|
28
32
|
|
|
29
33
|
Test the install by typing the command `easycoder`.
|
|
30
34
|
<hr>
|
|
31
|
-
On Linux, this will probably fail as the installer places the executable file in the `$HOME/.local/bin` directory. So give the command
|
|
32
|
-
```
|
|
33
|
-
export PATH=$HOME/.local/bin:$PATH
|
|
34
|
-
```
|
|
35
|
+
On Linux, this will probably fail as the installer places the executable file in the `$HOME/.local/bin` directory. So give the command `export PATH=$HOME/.local/bin:$PATH`.
|
|
35
36
|
|
|
36
37
|
To make this change permanent, edit your `.profile` file, adding the following:
|
|
37
38
|
```
|
|
@@ -42,7 +43,7 @@ fi
|
|
|
42
43
|
```
|
|
43
44
|
<hr>
|
|
44
45
|
|
|
45
|
-
Now write a test script,
|
|
46
|
+
Now write a test script, `hello.ecs`, containing the following:
|
|
46
47
|
```
|
|
47
48
|
print `Hello, world!`
|
|
48
49
|
exit
|
|
@@ -84,7 +85,7 @@ Here in the repository is a folder called `scripts` containing some sample scrip
|
|
|
84
85
|
`benchmark.ecs` allows the performance of **_EasyCoder_** to be compared to other languages if a similar script is written for each one.
|
|
85
86
|
|
|
86
87
|
## Graphical programming
|
|
87
|
-
**_EasyCoder_** includes a graphical programming environment based on PySide6, that is in
|
|
88
|
+
**_EasyCoder_** includes a graphical programming environment based on PySide6, that is in under development. Some demo scripts will be included in the `scripts` directory as development proceeds. Anyone wishing to track progress can do so via this repository. At the time of writing we are transitioning from an early version based on PySimpleGUI to one based on PySide, the latter being an open product that matches the needs of a DSL better than does the former.
|
|
88
89
|
|
|
89
90
|
## Significant features
|
|
90
91
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
easycoder/README.md,sha256=BVXmYphcTJ6q6RN_9L6HtQukgCnOjSLVIsTM3lk-9aM,587
|
|
2
|
+
easycoder/__init__.py,sha256=nOSldJ2q0EIA4NLCRkG8vCCgqAc64CpgzIgBYq9yO78,262
|
|
3
|
+
easycoder/ec_classes.py,sha256=xnWBNak8oKydkFoxHLlq9wo3lIsB3aMnTDrqbtCfoWo,1512
|
|
4
|
+
easycoder/ec_compiler.py,sha256=vNOAKIK2pX_cW4mcxwCe0OR16iqeZqvZQ6JCgQ5MqtU,5062
|
|
5
|
+
easycoder/ec_condition.py,sha256=YXvSBQKEzKGCcgUGo3Qp8iHolXmm2BpEm0NimSDszIM,785
|
|
6
|
+
easycoder/ec_core.py,sha256=hmMHQ5UxJ8JS6gMmcttzmZGGHc6bXR624A5g8VCH3JY,91224
|
|
7
|
+
easycoder/ec_graphics.py,sha256=WXxKMB4GJSmxvk-FVbOTyufiUx4TYIzyDoB1PCAO3JY,16067
|
|
8
|
+
easycoder/ec_gutils.py,sha256=yqu4RRQ6VdRkC5B2ADBYsXzgNu76dLnekd9aUjdEgPw,6399
|
|
9
|
+
easycoder/ec_handler.py,sha256=zPDZ_hqdgNnkCd8B5HmSLkqsGgf4aDmqcUBOPHgo47U,2305
|
|
10
|
+
easycoder/ec_program.py,sha256=CxGYl1slYXNOYFxiSMc-BuXL_QztYuBfCXltPCtw1U4,10011
|
|
11
|
+
easycoder/ec_pyside.py,sha256=6GIZpnmIj9LissJopfqcSvc1i1qbl4h56PQsJXOu9XU,36005
|
|
12
|
+
easycoder/ec_timestamp.py,sha256=_3QFJPzIWZ9Rzk3SQOQJ-gwmvB07pg78k23SPntoZtY,288
|
|
13
|
+
easycoder/ec_value.py,sha256=zgDJTJhIg3yOvmnnKIfccIizmIhGbtvL_ghLTL1T5fg,2516
|
|
14
|
+
easycoder-250503.1.dist-info/entry_points.txt,sha256=JXAZbenl0TnsIft2FcGJbJ-4qoztVu2FuT8PFmWFexM,44
|
|
15
|
+
easycoder-250503.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
16
|
+
easycoder-250503.1.dist-info/WHEEL,sha256=ssQ84EZ5gH1pCOujd3iW7HClo_O_aDaClUbX4B8bjKY,100
|
|
17
|
+
easycoder-250503.1.dist-info/METADATA,sha256=S-ZJU8J3jqERA2fkdZ1SHwRhJ_Xdp-QR1ByCOwStNHU,6803
|
|
18
|
+
easycoder-250503.1.dist-info/RECORD,,
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
easycoder/README.md,sha256=BVXmYphcTJ6q6RN_9L6HtQukgCnOjSLVIsTM3lk-9aM,587
|
|
2
|
-
easycoder/__init__.py,sha256=rXpc2iuRmzM8KsgUZWefLoHMii_uABr61154GK0iZ_0,262
|
|
3
|
-
easycoder/ec_classes.py,sha256=xnWBNak8oKydkFoxHLlq9wo3lIsB3aMnTDrqbtCfoWo,1512
|
|
4
|
-
easycoder/ec_compiler.py,sha256=WN4DMTU66kzOAwOGJe3KDoXj2nPvq19ACegQ-RSMglo,4780
|
|
5
|
-
easycoder/ec_condition.py,sha256=YXvSBQKEzKGCcgUGo3Qp8iHolXmm2BpEm0NimSDszIM,785
|
|
6
|
-
easycoder/ec_core.py,sha256=X66TBECPnp-82lEcCpaiJuXSy4Ex519iBK2BM-wGHaQ,90611
|
|
7
|
-
easycoder/ec_graphics.py,sha256=WXxKMB4GJSmxvk-FVbOTyufiUx4TYIzyDoB1PCAO3JY,16067
|
|
8
|
-
easycoder/ec_gutils.py,sha256=yqu4RRQ6VdRkC5B2ADBYsXzgNu76dLnekd9aUjdEgPw,6399
|
|
9
|
-
easycoder/ec_handler.py,sha256=K7nBuQTH8l0k8hX1o2b4KhTnhZHGdf2fkEuX4FJXJs8,2277
|
|
10
|
-
easycoder/ec_program.py,sha256=ZCcvI36iq9HG4o8rFwFxzVElzZ7PEeNOPMr8eqwz8ns,10010
|
|
11
|
-
easycoder/ec_pyside6.py,sha256=0Z-uWrCq7Uz_C6WjN-9E0TDI-IHny14-j5sTc1a3LLg,26627
|
|
12
|
-
easycoder/ec_timestamp.py,sha256=_3QFJPzIWZ9Rzk3SQOQJ-gwmvB07pg78k23SPntoZtY,288
|
|
13
|
-
easycoder/ec_value.py,sha256=zgDJTJhIg3yOvmnnKIfccIizmIhGbtvL_ghLTL1T5fg,2516
|
|
14
|
-
easycoder-250423.2.dist-info/entry_points.txt,sha256=JXAZbenl0TnsIft2FcGJbJ-4qoztVu2FuT8PFmWFexM,44
|
|
15
|
-
easycoder-250423.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
16
|
-
easycoder-250423.2.dist-info/WHEEL,sha256=ssQ84EZ5gH1pCOujd3iW7HClo_O_aDaClUbX4B8bjKY,100
|
|
17
|
-
easycoder-250423.2.dist-info/METADATA,sha256=XZhRQ-0z-KpgImt8Nvyk46I6V_lZ1M2aet5VoR8hHYs,5617
|
|
18
|
-
easycoder-250423.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|