easycoder 250116.1__tar.gz → 250116.4__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.

Potentially problematic release.


This version of easycoder might be problematic. Click here for more details.

Files changed (171) hide show
  1. {easycoder-250116.1 → easycoder-250116.4}/PKG-INFO +28 -14
  2. {easycoder-250116.1 → easycoder-250116.4}/README.md +27 -13
  3. {easycoder-250116.1 → easycoder-250116.4}/easycoder/__init__.py +1 -1
  4. {easycoder-250116.1 → easycoder-250116.4}/easycoder/ec_compiler.py +2 -2
  5. {easycoder-250116.1 → easycoder-250116.4}/easycoder/ec_graphics.py +88 -141
  6. {easycoder-250116.1 → easycoder-250116.4}/easycoder/ec_gutils.py +6 -6
  7. easycoder-250116.4/scripts/testg.ecg +48 -0
  8. easycoder-250116.1/scripts/testg.ecg +0 -44
  9. {easycoder-250116.1 → easycoder-250116.4}/LICENSE +0 -0
  10. {easycoder-250116.1 → easycoder-250116.4}/doc/README.md +0 -0
  11. {easycoder-250116.1 → easycoder-250116.4}/doc/core/README.md +0 -0
  12. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/boolean.md +0 -0
  13. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/empty.md +0 -0
  14. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/ends.md +0 -0
  15. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/even.md +0 -0
  16. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/exists.md +0 -0
  17. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/greater.md +0 -0
  18. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/hasProperty.md +0 -0
  19. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/includes.md +0 -0
  20. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/is.md +0 -0
  21. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/less.md +0 -0
  22. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/list.md +0 -0
  23. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/none.md +0 -0
  24. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/not.md +0 -0
  25. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/numeric.md +0 -0
  26. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/object.md +0 -0
  27. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/odd.md +0 -0
  28. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/starts.md +0 -0
  29. {easycoder-250116.1 → easycoder-250116.4}/doc/core/conditions/string.md +0 -0
  30. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/add.md +0 -0
  31. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/append.md +0 -0
  32. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/assert.md +0 -0
  33. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/begin.md +0 -0
  34. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/clear.md +0 -0
  35. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/close.md +0 -0
  36. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/create.md +0 -0
  37. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/debug.md +0 -0
  38. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/decrement.md +0 -0
  39. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/delete.md +0 -0
  40. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/divide.md +0 -0
  41. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/exit.md +0 -0
  42. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/file.md +0 -0
  43. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/fork.md +0 -0
  44. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/get.md +0 -0
  45. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/go.md +0 -0
  46. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/gosub.md +0 -0
  47. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/if.md +0 -0
  48. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/import.md +0 -0
  49. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/increment.md +0 -0
  50. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/index.md +0 -0
  51. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/init.md +0 -0
  52. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/input.md +0 -0
  53. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/load.md +0 -0
  54. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/lock.md +0 -0
  55. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/module.md +0 -0
  56. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/multiply.md +0 -0
  57. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/negate.md +0 -0
  58. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/open.md +0 -0
  59. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/pop.md +0 -0
  60. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/post.md +0 -0
  61. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/print.md +0 -0
  62. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/push.md +0 -0
  63. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/put.md +0 -0
  64. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/read.md +0 -0
  65. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/release.md +0 -0
  66. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/replace.md +0 -0
  67. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/return.md +0 -0
  68. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/run.md +0 -0
  69. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/save.md +0 -0
  70. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/script.md +0 -0
  71. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/set.md +0 -0
  72. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/split.md +0 -0
  73. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/stack.md +0 -0
  74. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/stop.md +0 -0
  75. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/system.md +0 -0
  76. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/take.md +0 -0
  77. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/toggle.md +0 -0
  78. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/truncate.md +0 -0
  79. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/unlock.md +0 -0
  80. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/variable.md +0 -0
  81. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/wait.md +0 -0
  82. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/while.md +0 -0
  83. {easycoder-250116.1 → easycoder-250116.4}/doc/core/keywords/write.md +0 -0
  84. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/arg.md +0 -0
  85. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/args.md +0 -0
  86. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/cos.md +0 -0
  87. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/datime.md +0 -0
  88. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/decode.md +0 -0
  89. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/element.md +0 -0
  90. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/elements.md +0 -0
  91. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/empty.md +0 -0
  92. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/encode.md +0 -0
  93. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/error.md +0 -0
  94. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/files.md +0 -0
  95. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/float.md +0 -0
  96. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/from.md +0 -0
  97. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/hash.md +0 -0
  98. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/index.md +0 -0
  99. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/integer.md +0 -0
  100. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/json.md +0 -0
  101. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/keys.md +0 -0
  102. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/left.md +0 -0
  103. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/length.md +0 -0
  104. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/lowercase.md +0 -0
  105. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/memory.md +0 -0
  106. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/modification.md +0 -0
  107. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/modulo.md +0 -0
  108. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/newline.md +0 -0
  109. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/now.md +0 -0
  110. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/position.md +0 -0
  111. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/property.md +0 -0
  112. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/random.md +0 -0
  113. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/right.md +0 -0
  114. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/sin.md +0 -0
  115. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/stringify.md +0 -0
  116. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/tab.md +0 -0
  117. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/tan.md +0 -0
  118. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/timestamp.md +0 -0
  119. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/today.md +0 -0
  120. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/trim.md +0 -0
  121. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/type.md +0 -0
  122. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/uppercase.md +0 -0
  123. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/value.md +0 -0
  124. {easycoder-250116.1 → easycoder-250116.4}/doc/core/values/weekday.md +0 -0
  125. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/README.md +0 -0
  126. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/keywords/attach.md +0 -0
  127. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/keywords/close.md +0 -0
  128. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/keywords/create.md +0 -0
  129. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/keywords/ellipse.md +0 -0
  130. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/keywords/image.md +0 -0
  131. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/keywords/move.md +0 -0
  132. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/keywords/on.md +0 -0
  133. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/keywords/rectangle.md +0 -0
  134. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/keywords/render.md +0 -0
  135. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/keywords/run.md +0 -0
  136. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/keywords/set.md +0 -0
  137. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/keywords/text.md +0 -0
  138. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/values/attribute.md +0 -0
  139. {easycoder-250116.1 → easycoder-250116.4}/doc/graphics/values/window.md +0 -0
  140. {easycoder-250116.1 → easycoder-250116.4}/easycoder/README.md +0 -0
  141. {easycoder-250116.1 → easycoder-250116.4}/easycoder/ec_classes.py +0 -0
  142. {easycoder-250116.1 → easycoder-250116.4}/easycoder/ec_condition.py +0 -0
  143. {easycoder-250116.1 → easycoder-250116.4}/easycoder/ec_core.py +0 -0
  144. {easycoder-250116.1 → easycoder-250116.4}/easycoder/ec_handler.py +0 -0
  145. {easycoder-250116.1 → easycoder-250116.4}/easycoder/ec_program.py +0 -0
  146. {easycoder-250116.1 → easycoder-250116.4}/easycoder/ec_timestamp.py +0 -0
  147. {easycoder-250116.1 → easycoder-250116.4}/easycoder/ec_value.py +0 -0
  148. {easycoder-250116.1 → easycoder-250116.4}/images/Semoigo Dawn.jpg +0 -0
  149. {easycoder-250116.1 → easycoder-250116.4}/json/graphics-demo.json +0 -0
  150. {easycoder-250116.1 → easycoder-250116.4}/plugins/ec_keyboard.py +0 -0
  151. {easycoder-250116.1 → easycoder-250116.4}/plugins/ec_p100.py +0 -0
  152. {easycoder-250116.1 → easycoder-250116.4}/plugins/example.py +0 -0
  153. {easycoder-250116.1 → easycoder-250116.4}/plugins/keyboards/4-function.json +0 -0
  154. {easycoder-250116.1 → easycoder-250116.4}/plugins/keyboards/4-function.png +0 -0
  155. {easycoder-250116.1 → easycoder-250116.4}/plugins/keyboards/qwerty-0.json +0 -0
  156. {easycoder-250116.1 → easycoder-250116.4}/plugins/keyboards/qwerty-0.png +0 -0
  157. {easycoder-250116.1 → easycoder-250116.4}/plugins/keyboards/qwerty-1.json +0 -0
  158. {easycoder-250116.1 → easycoder-250116.4}/plugins/keyboards/qwerty-1.png +0 -0
  159. {easycoder-250116.1 → easycoder-250116.4}/plugins/keyboards/qwerty-2.json +0 -0
  160. {easycoder-250116.1 → easycoder-250116.4}/plugins/keyboards/qwerty-2.png +0 -0
  161. {easycoder-250116.1 → easycoder-250116.4}/plugins/keyboards/qwerty-3.json +0 -0
  162. {easycoder-250116.1 → easycoder-250116.4}/plugins/keyboards/qwerty-3.png +0 -0
  163. {easycoder-250116.1 → easycoder-250116.4}/pyproject.toml +0 -0
  164. {easycoder-250116.1 → easycoder-250116.4}/scripts/README.md +0 -0
  165. {easycoder-250116.1 → easycoder-250116.4}/scripts/benchmark.ecs +0 -0
  166. {easycoder-250116.1 → easycoder-250116.4}/scripts/ec_keyboard.py +0 -0
  167. {easycoder-250116.1 → easycoder-250116.4}/scripts/fizzbuzz.ecs +0 -0
  168. {easycoder-250116.1 → easycoder-250116.4}/scripts/hello.ecs +0 -0
  169. {easycoder-250116.1 → easycoder-250116.4}/scripts/points.ecs +0 -0
  170. {easycoder-250116.1 → easycoder-250116.4}/scripts/test.ecs +0 -0
  171. {easycoder-250116.1 → easycoder-250116.4}/scripts/tests.ecs +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: easycoder
3
- Version: 250116.1
3
+ Version: 250116.4
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>
@@ -22,15 +22,30 @@ Website: [https://easycoder.github.io](https://easycoder.github.io)
22
22
  ## Quick Start
23
23
  Install **_EasyCoder_** in your Python environment:
24
24
  ```
25
- pip install easycoder
25
+ pip install requests pytz easycoder
26
26
  ```
27
- You may also need to install `pytz`, as some commands need it.
28
27
 
29
- Write a test script, 'hello.ecs', containing the following:
28
+ Test the install by typing the command `easycoder`.
29
+ <hr>
30
+ On Linux, this will probably fail as the installer places the executable file in the `$HOME/.local/bin` directory. So give the command
31
+ ```
32
+ export PATH=$HOME/.local/bin:$PATH
33
+ ```
34
+
35
+ To make this change permanent, edit your `.profile` file, adding the following:
36
+ ```
37
+ # set PATH so it includes user's private .local/bin if it exists
38
+ if [ -d "$HOME/.local/bin" ] ; then
39
+ PATH="$HOME/.local/bin:$PATH"
40
+ fi
41
+ ```
42
+ <hr>
43
+
44
+ Now write a test script, 'hello.ecs', containing the following:
30
45
  ```
31
46
  print `Hello, world!`
32
47
  ```
33
- This is traditionally the first program to be written in virtually any language. To run it, use `easycoder hello.ecs`.
48
+ (Note the backticks.) This is traditionally the first program to be written in virtually any language. To run it, use `easycoder hello.ecs`.
34
49
 
35
50
  The output will look like this (the version number will differ):
36
51
  ```
@@ -63,19 +78,18 @@ Here in the repository is a folder called `scripts` containing some sample scrip
63
78
  `benchmark.ecs` allows the performance of **_EasyCoder_** to be compared to other languages if a similar script is written for each one.
64
79
 
65
80
  ## Graphical programmming
66
- **_EasyCoder_** includes a graphical programming environment that is in the early stages of development. A couple of demo scripts are included in the `scripts` directory. To run them, first install the Python `kivy` graphics library if it's not already present on your system. This is done with `pip install kivy`. Then run your **_EasyCoder_** script using `easycoder {scriptname}.ecg`.
67
-
68
- Graphical scripts look much like any other script but their file names must use the extension `.ecg` to signal to **_EasyCoder_** that it needs to load the graphics module. Non-graphical applications can use any extension but `.ecs` is recommended. This allows the **_EasyCoder_** application to be used wherever Python is installed, in either a command-line or a graphical environment, but graphics will of course not be available in the former.
69
-
70
- Some demo graphical scripts are included in the `scripts` directory:
81
+ **_EasyCoder_** includes a graphical programming environment that is in the early stages of development. Some demo scripts will be included in the `scripts` directory; these can be recognised by the extension`.ecg`. To run them, first install `tkinter`. On Linux this is done with
82
+ ```
83
+ sudo apt install python3-tk
84
+ ```
71
85
 
72
- `graphics-demo.ecg` shows some of the elements that can be created, and demonstrates a variety of the graphical features of the language such as detecting when elements are clicked.
86
+ Next, install the Python `pySimpleGUI` graphics library; this is done with `pip install pysimplegui`. Then run your **_EasyCoder_** script using `easycoder {scriptname}.ecg`.
73
87
 
74
- `wave.ecg` is a "Mexican Wave" simulation.
88
+ Graphical scripts look much like any other script but their file names must use the extension `.ecg` to signal to **_EasyCoder_** that it needs to load the graphics module. Non-graphical applications can use any extension but `.ecs` is recommended. This allows the **_EasyCoder_** application to be used wherever Python is installed, in either a command-line or a graphical environment, but graphics will of course not be available in the former.
75
89
 
76
- `keyboard.ecg` creates an on-screen keyboard (currently a 4-function calculator keypad) that responds to clicks on its keys. It uses a plugin module (see below) to add extra vocabulary and syntax to the language. This is currently under development so its features are likely to change. The intention is to support a wide range of keyboard styles with the minimum mount of coding. The plugin (`ec_keyword.py`) can be downloaded from the repository.
90
+ Some demo graphical scripts will included in the `scripts` directory as development proceeds.
77
91
 
78
- **_EasyCoder_** graphics are handled by a library module, `ec_renderer` that can be used outside of the **_EasyCoder_** environment, in other Python programs. The renderer works with JSON-formatted specifications of the itens to be displayed.
92
+ `gtest.ecg` contains sample code to demonstrate and test basic features.
79
93
 
80
94
  ## Significant features
81
95
 
@@ -11,15 +11,30 @@ Website: [https://easycoder.github.io](https://easycoder.github.io)
11
11
  ## Quick Start
12
12
  Install **_EasyCoder_** in your Python environment:
13
13
  ```
14
- pip install easycoder
14
+ pip install requests pytz easycoder
15
15
  ```
16
- You may also need to install `pytz`, as some commands need it.
17
16
 
18
- Write a test script, 'hello.ecs', containing the following:
17
+ Test the install by typing the command `easycoder`.
18
+ <hr>
19
+ On Linux, this will probably fail as the installer places the executable file in the `$HOME/.local/bin` directory. So give the command
20
+ ```
21
+ export PATH=$HOME/.local/bin:$PATH
22
+ ```
23
+
24
+ To make this change permanent, edit your `.profile` file, adding the following:
25
+ ```
26
+ # set PATH so it includes user's private .local/bin if it exists
27
+ if [ -d "$HOME/.local/bin" ] ; then
28
+ PATH="$HOME/.local/bin:$PATH"
29
+ fi
30
+ ```
31
+ <hr>
32
+
33
+ Now write a test script, 'hello.ecs', containing the following:
19
34
  ```
20
35
  print `Hello, world!`
21
36
  ```
22
- This is traditionally the first program to be written in virtually any language. To run it, use `easycoder hello.ecs`.
37
+ (Note the backticks.) This is traditionally the first program to be written in virtually any language. To run it, use `easycoder hello.ecs`.
23
38
 
24
39
  The output will look like this (the version number will differ):
25
40
  ```
@@ -52,19 +67,18 @@ Here in the repository is a folder called `scripts` containing some sample scrip
52
67
  `benchmark.ecs` allows the performance of **_EasyCoder_** to be compared to other languages if a similar script is written for each one.
53
68
 
54
69
  ## Graphical programmming
55
- **_EasyCoder_** includes a graphical programming environment that is in the early stages of development. A couple of demo scripts are included in the `scripts` directory. To run them, first install the Python `kivy` graphics library if it's not already present on your system. This is done with `pip install kivy`. Then run your **_EasyCoder_** script using `easycoder {scriptname}.ecg`.
56
-
57
- Graphical scripts look much like any other script but their file names must use the extension `.ecg` to signal to **_EasyCoder_** that it needs to load the graphics module. Non-graphical applications can use any extension but `.ecs` is recommended. This allows the **_EasyCoder_** application to be used wherever Python is installed, in either a command-line or a graphical environment, but graphics will of course not be available in the former.
58
-
59
- Some demo graphical scripts are included in the `scripts` directory:
70
+ **_EasyCoder_** includes a graphical programming environment that is in the early stages of development. Some demo scripts will be included in the `scripts` directory; these can be recognised by the extension`.ecg`. To run them, first install `tkinter`. On Linux this is done with
71
+ ```
72
+ sudo apt install python3-tk
73
+ ```
60
74
 
61
- `graphics-demo.ecg` shows some of the elements that can be created, and demonstrates a variety of the graphical features of the language such as detecting when elements are clicked.
75
+ Next, install the Python `pySimpleGUI` graphics library; this is done with `pip install pysimplegui`. Then run your **_EasyCoder_** script using `easycoder {scriptname}.ecg`.
62
76
 
63
- `wave.ecg` is a "Mexican Wave" simulation.
77
+ Graphical scripts look much like any other script but their file names must use the extension `.ecg` to signal to **_EasyCoder_** that it needs to load the graphics module. Non-graphical applications can use any extension but `.ecs` is recommended. This allows the **_EasyCoder_** application to be used wherever Python is installed, in either a command-line or a graphical environment, but graphics will of course not be available in the former.
64
78
 
65
- `keyboard.ecg` creates an on-screen keyboard (currently a 4-function calculator keypad) that responds to clicks on its keys. It uses a plugin module (see below) to add extra vocabulary and syntax to the language. This is currently under development so its features are likely to change. The intention is to support a wide range of keyboard styles with the minimum mount of coding. The plugin (`ec_keyword.py`) can be downloaded from the repository.
79
+ Some demo graphical scripts will included in the `scripts` directory as development proceeds.
66
80
 
67
- **_EasyCoder_** graphics are handled by a library module, `ec_renderer` that can be used outside of the **_EasyCoder_** environment, in other Python programs. The renderer works with JSON-formatted specifications of the itens to be displayed.
81
+ `gtest.ecg` contains sample code to demonstrate and test basic features.
68
82
 
69
83
  ## Significant features
70
84
 
@@ -9,4 +9,4 @@ from .ec_program import *
9
9
  from .ec_timestamp import *
10
10
  from .ec_value import *
11
11
 
12
- __version__ = "250116.1"
12
+ __version__ = "250116.4"
@@ -98,11 +98,11 @@ class Compiler:
98
98
  return self.tokens[self.index].lino
99
99
 
100
100
  def warning(self, message):
101
- self.warnings.append(message)
101
+ self.warnings.append(f'Warning at line {self.getLino() + 1} of {self.program.name}: {message}')
102
102
 
103
103
  def showWarnings(self):
104
104
  for warning in self.warnings:
105
- print(f'Warning at line {self.getLino() + 1} of {self.program.name}: {warning}')
105
+ print(warning)
106
106
 
107
107
  def getSymbolRecord(self):
108
108
  token = self.getToken()
@@ -9,6 +9,7 @@ class Graphics(Handler):
9
9
  def __init__(self, compiler):
10
10
  Handler.__init__(self, compiler)
11
11
  self.utils = GUtils()
12
+ self.eventHandlers = {}
12
13
 
13
14
  def getName(self):
14
15
  return 'graphics'
@@ -18,17 +19,17 @@ class Graphics(Handler):
18
19
 
19
20
  def k_add(self, command):
20
21
  elements = []
21
- while True:
22
- if self.nextIsSymbol():
23
- symbolRecord = self.getSymbolRecord()
24
- name = symbolRecord['name']
25
- if 'iselement' in symbolRecord:
26
- elements.append(name)
27
- if self.peek() != 'and': break
28
- else: FatalError(self.program.compiler, f'"{name}" is not a graphic element')
29
- else: FatalError(self.program.compiler, f'Element expected; got "{self.getToken()}"')
30
- self.nextToken()
31
- command['elements'] = json.dumps(elements)
22
+ token = self.nextToken()
23
+ if self.isSymbol():
24
+ symbolRecord = self.getSymbolRecord()
25
+ name = symbolRecord['name']
26
+ if symbolRecord['keyword'] == 'layout':
27
+ elements.append(name)
28
+ command['args'] = name
29
+ else: FatalError(self.compiler.program, f'\'{name}\' is not a layout')
30
+ else:
31
+ command['type'] = token
32
+ command['args'] = self.utils.getArgs(self)
32
33
  if self.nextIs('to'):
33
34
  if self.nextIsSymbol():
34
35
  symbolRecord = self.getSymbolRecord()
@@ -40,14 +41,36 @@ class Graphics(Handler):
40
41
 
41
42
  def r_add(self, command):
42
43
  target = self.getVariable(command['target'])
43
- elements = json.loads(command['elements'])
44
+ type = command['type']
45
+ args = command['args']
44
46
  if not 'layout' in target:
45
47
  target['layout'] = []
46
- for element in elements:
47
- v = self.getVariable(element)
48
+ if args[0] == '{':
49
+ layout = json.loads(self.getRuntimeValue(json.loads(args)))
50
+ default = self.utils.getDefaultArgs(type)
51
+ for n in range(0, len(layout)):
52
+ args = self.utils.decode(default, layout[n])
53
+ target['layout'].append(self.utils.createElement(type, args))
54
+ else:
55
+ v = self.getVariable(args)
48
56
  target['layout'].append(v['layout'])
49
57
  return self.nextPC()
50
58
 
59
+ def k_capture(self, command):
60
+ if self.nextIs('event'):
61
+ if self.nextIs('as'):
62
+ if self.nextIsSymbol():
63
+ record = self.getSymbolRecord()
64
+ command['target'] = record['name']
65
+ self.addCommand(command)
66
+ return True
67
+ return False
68
+
69
+ def r_capture(self, command):
70
+ target = self.getVariable(command['target'])
71
+ self.putSymbolValue(target, self.getConstant(self.eventValues))
72
+ return self.nextPC()
73
+
51
74
  def k_close(self, command):
52
75
  if self.nextIsSymbol():
53
76
  symbolRecord = self.getSymbolRecord()
@@ -79,10 +102,6 @@ class Graphics(Handler):
79
102
  command['layout'] = symbolRecord['name']
80
103
  self.addCommand(command)
81
104
  return True
82
- elif type[0:2] == 'g_':
83
- command['args'] = self.compileConstant(self.utils.getArgs(self))
84
- self.addCommand(command)
85
- return True
86
105
  return False
87
106
 
88
107
  def r_create(self, command):
@@ -96,79 +115,10 @@ class Graphics(Handler):
96
115
  self.mainLoop()
97
116
  self.program.kill()
98
117
  return 0
99
- elif 'iselement' in record:
100
- layout = json.loads(self.getRuntimeValue(command['args']))
101
- args = self.utils.getDefaultArgs(type)
102
- content = json.loads(layout['content'])
103
- for n in range(0, len(content)):
104
- args = self.utils.decode(args, content[n])
105
- element = self.utils.createElement(type, args)
106
- record['layout'] = element
107
- return self.nextPC()
108
118
  else:
109
119
  RuntimeError(self.program, 'Variable is not a window or an element')
110
120
 
111
- def k_g_button(self, command):
112
- command['iselement'] = True
113
- return self.compileVariable(command)
114
-
115
- def r_g_button(self, command):
116
- return self.nextPC()
117
-
118
- def k_g_input(self, command):
119
- command['iselement'] = True
120
- return self.compileVariable(command)
121
-
122
- def r_g_input(self, command):
123
- return self.nextPC()
124
-
125
- def k_g_text(self, command):
126
- command['iselement'] = True
127
- return self.compileVariable(command)
128
-
129
- def r_g_text(self, command):
130
- return self.nextPC()
131
-
132
- def k_init(self, command):
133
- if self.nextIsSymbol():
134
- record = self.getSymbolRecord()
135
- if record['keyword'] == 'layout':
136
- command['target'] = record['name']
137
- if self.peek() == 'with':
138
- self.nextToken()
139
- if self.nextIsSymbol():
140
- record = self.getSymbolRecord()
141
- name = record['name']
142
- if record['iselement']:
143
- command['args'] = name
144
- else: FatalError(self.program.compiler, f'\'{name}\' is not a graphic element')
145
- else:
146
- command['type'] = self.getToken()
147
- command['args'] = self.utils.getArgs(self)
148
- else: command['args'] = None
149
- self.addCommand(command)
150
- return True
151
- return False
152
-
153
- def r_init(self, command):
154
- record = self.getVariable(command['target'])
155
- record['layout'] = []
156
- type = command['type']
157
- args = command['args']
158
- if args != None:
159
- if args[0] == '{':
160
- layout = json.loads(self.getRuntimeValue(json.loads(args)))
161
- args = self.utils.getDefaultArgs(type)
162
- for n in range(0, len(layout)):
163
- args = self.utils.decode(args, layout[n])
164
- record['layout'].append(self.utils.createElement(type, args))
165
- else:
166
- v = self.getVariable(args)
167
- record['layout'].append(v['layout'])
168
- return self.nextPC()
169
-
170
121
  def k_layout(self, command):
171
- command['iselement'] = True
172
122
  return self.compileVariable(command)
173
123
 
174
124
  def r_layout(self, command):
@@ -176,42 +126,8 @@ class Graphics(Handler):
176
126
 
177
127
  def k_on(self, command):
178
128
  token = self.nextToken()
179
- command['type'] = token
180
- if token == 'click':
181
- command['event'] = token
182
- if self.peek() == 'in':
183
- self.nextToken()
184
- if self.nextIs('screen'):
185
- command['target'] = None
186
- elif self.isSymbol():
187
- target = self.getSymbolRecord()
188
- command['target'] = target['name']
189
- else:
190
- FatalError(self.program.compiler, f'{self.getToken()} is not a screen element')
191
- return False
192
- command['goto'] = self.getPC() + 2
193
- self.add(command)
194
- self.nextToken()
195
- pcNext = self.getPC()
196
- cmd = {}
197
- cmd['domain'] = 'core'
198
- cmd['lino'] = command['lino']
199
- cmd['keyword'] = 'gotoPC'
200
- cmd['goto'] = 0
201
- cmd['debug'] = False
202
- self.addCommand(cmd)
203
- self.compileOne()
204
- cmd = {}
205
- cmd['domain'] = 'core'
206
- cmd['lino'] = command['lino']
207
- cmd['keyword'] = 'stop'
208
- cmd['debug'] = False
209
- self.addCommand(cmd)
210
- # Fixup the link
211
- self.getCommandAt(pcNext)['goto'] = self.getPC()
212
- return True
213
- elif token == 'tick':
214
- command['event'] = token
129
+ if token == 'event':
130
+ command['key'] = self.nextValue()
215
131
  command['goto'] = self.getPC() + 2
216
132
  self.add(command)
217
133
  self.nextToken()
@@ -236,17 +152,9 @@ class Graphics(Handler):
236
152
  return False
237
153
 
238
154
  def r_on(self, command):
155
+ key = self.getRuntimeValue(command['key'])
239
156
  pc = command['goto']
240
- if command['type'] == 'click':
241
- event = command['event']
242
- if event == 'click':
243
- target = command['target']
244
- if target == None:
245
- value = 'screen'
246
- else:
247
- widget = self.getVariable(target)
248
- value = widget['value'][widget['index']]
249
- self.renderer.setOnClick(value['content'], lambda: self.run(pc))
157
+ self.eventHandlers[key] = lambda: self.run(pc)
250
158
  return self.nextPC()
251
159
 
252
160
  def k_popup(self, command):
@@ -259,9 +167,37 @@ class Graphics(Handler):
259
167
  return self.nextPC()
260
168
 
261
169
  def k_set(self, command):
262
- return True
170
+ if self.nextIsSymbol():
171
+ record = self.getSymbolRecord()
172
+ keyword = record['keyword']
173
+ if keyword == 'layout':
174
+ command['target'] = record['name']
175
+ if self.peek() == 'to':
176
+ self.nextToken()
177
+ command['type'] = self.nextToken()
178
+ command['args'] = self.utils.getArgs(self)
179
+ else: command['args'] = None
180
+ self.addCommand(command)
181
+ return True
182
+ elif keyword == 'event':
183
+ pass
184
+ return False
263
185
 
264
186
  def r_set(self, command):
187
+ target = self.getVariable(command['target'])
188
+ target['layout'] = []
189
+ type = command['type']
190
+ args = command['args']
191
+ if args != None:
192
+ if args[0] == '{':
193
+ layout = json.loads(self.getRuntimeValue(json.loads(args)))
194
+ default = self.utils.getDefaultArgs(type)
195
+ for n in range(0, len(layout)):
196
+ args = self.utils.decode(default, layout[n])
197
+ target['layout'].append(self.utils.createElement(type, args))
198
+ else:
199
+ v = self.getVariable(args)
200
+ target['layout'].append(v['layout'])
265
201
  return self.nextPC()
266
202
 
267
203
  def k_window(self, command):
@@ -274,19 +210,20 @@ class Graphics(Handler):
274
210
  # Compile a value in this domain
275
211
  def compileValue(self):
276
212
  value = {}
277
- value['domain'] = 'graphics'
213
+ value['domain'] = self.getName()
278
214
  token = self.getToken()
279
215
  if self.isSymbol():
216
+ value['name'] = token
217
+ symbolRecord = self.getSymbolRecord()
218
+ keyword = symbolRecord['keyword']
219
+ if keyword == 'event':
220
+ value['type'] = 'symbol'
221
+ return value
280
222
  return None
281
223
 
282
- if self.tokenIs('the'):
283
- self.nextToken()
284
- token = self.getToken()
285
-
286
224
  value['type'] = token
287
225
 
288
226
  if token == 'test':
289
- name = self.nextToken()
290
227
  value = {}
291
228
  value['type'] = 'text'
292
229
  value['content'] = 'test'
@@ -302,6 +239,13 @@ class Graphics(Handler):
302
239
  #############################################################################
303
240
  # Value handlers
304
241
 
242
+ # This is used by the expression evaluator to get the value of a symbol
243
+ def v_symbol(self, symbolRecord):
244
+ if symbolRecord['keyword'] == 'event':
245
+ return self.getSymbolValue(symbolRecord)
246
+ else:
247
+ return None
248
+
305
249
  def v_test(self, v):
306
250
  return v
307
251
 
@@ -323,4 +267,7 @@ class Graphics(Handler):
323
267
  break
324
268
  if event == '__TIMEOUT__': self.program.flushCB()
325
269
  else:
326
- print(event, values)
270
+ if event in self.eventHandlers:
271
+ self.eventValues = values
272
+ self.eventHandlers[event]()
273
+
@@ -21,13 +21,13 @@ class GUtils:
21
21
  # Get the default args for a graphic element
22
22
  def getDefaultArgs(self, type):
23
23
  args = {}
24
- if type == 'g_text':
24
+ if type == 'Text':
25
25
  args['text'] = '(empty)'
26
26
  args['expand_x'] = False
27
- elif type == 'g_input':
27
+ elif type == 'Input':
28
28
  args['key'] = None
29
29
  args['size'] = (None, None)
30
- elif type == 'g_button':
30
+ elif type == 'Button':
31
31
  args['button_text'] = '(empty)'
32
32
  return args
33
33
 
@@ -43,10 +43,10 @@ class GUtils:
43
43
 
44
44
  # Create an element
45
45
  def createElement(self, type, args):
46
- if type == 'g_text': return psg.Text(text=args['text'], expand_x=args['expand_x'])
47
- elif type == 'g_input':
46
+ if type == 'Text': return psg.Text(text=args['text'], expand_x=args['expand_x'])
47
+ elif type == 'Input':
48
48
  size = args['size'].split()
49
49
  size = (size[0], size[1])
50
50
  return psg.Input(key=args['key'], size=size)
51
- elif type == 'g_button': return psg.Button(button_text=args['button_text'])
51
+ elif type == 'Button': return psg.Button(button_text=args['button_text'])
52
52
  else: return None
@@ -0,0 +1,48 @@
1
+ ! A test script
2
+
3
+ script Test
4
+
5
+ layout Row
6
+ layout Layout
7
+ window Window
8
+ variable Event
9
+ variable N
10
+
11
+ popup `Hello!`
12
+ ! debug step
13
+
14
+ set Row to Text text `Date (YYYY-MM-DD):` and expand_x true
15
+ add Input key `-DATE-` and size `20 1` to Row
16
+ add Row to Layout
17
+
18
+ set Row to Text text `Time (HH:MM):` and expand_x true
19
+ add Input key `-TIME-` and size `20 1` to Row
20
+ add Row to Layout
21
+
22
+ set Row to Text text `Your name:` and expand_x true
23
+ add Input key `-NAME-` and size `20 1` to Row
24
+ add Row to Layout
25
+
26
+ set Row to Button button_text `Click me`
27
+ add Row to Layout
28
+
29
+ create Window `Graphics Test`
30
+ layout Layout
31
+
32
+ on event `Click me`
33
+ begin
34
+ capture event as Event
35
+ print `Date: ` cat property `-DATE-` of Event
36
+ print `Time: ` cat property `-TIME-` of Event
37
+ print `Name: ` cat property `-NAME-` of Event
38
+ end
39
+
40
+ put 0 into N
41
+ while true
42
+ begin
43
+ if N modulo 1000 is 0 print `Running ` cat N
44
+ increment N
45
+ wait 10 ticks
46
+ end
47
+
48
+ stop
@@ -1,44 +0,0 @@
1
- ! A test script
2
-
3
- script Test
4
-
5
- layout Row
6
- layout Layout
7
- window Window
8
- g_input Input
9
- g_button Button
10
- variable N
11
-
12
- init Layout
13
-
14
- ! popup `Hello!`
15
- ! debug step
16
-
17
- init Row with g_text text `Date (YYYY-MM-DD):` and expand_x true
18
- create Input key `-DATE-` and size `20 1`
19
- add Input to Row
20
- add Row to Layout
21
- init Row with g_text text `Time (HH:MM):` and expand_x true
22
- create Input key `-TIME-` and size `20 1`
23
- add Input to Row
24
- add Row to Layout
25
- init Row with g_text text `Your name:` and expand_x true
26
- create Input key `-NAME-` and size `20 1`
27
- add Input to Row
28
- add Row to Layout
29
- create Button button_text `Click me`
30
- init Row with Button
31
- add Row to Layout
32
-
33
- create Window `Graphics Test`
34
- layout Layout
35
-
36
- put 0 into N
37
- while true
38
- begin
39
- if N modulo 1000 is 0 print `Running ` cat N
40
- increment N
41
- wait 10 ticks
42
- end
43
-
44
- stop
File without changes
File without changes