termgui 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +14 -0
  3. data/LICENSE +19 -0
  4. data/README.md +321 -0
  5. data/TODO.md +259 -0
  6. data/src/action.rb +58 -0
  7. data/src/box.rb +90 -0
  8. data/src/color.rb +174 -0
  9. data/src/cursor.rb +69 -0
  10. data/src/editor/editor_base.rb +152 -0
  11. data/src/editor/editor_base_handlers.rb +116 -0
  12. data/src/element.rb +61 -0
  13. data/src/element_bounds.rb +111 -0
  14. data/src/element_box.rb +64 -0
  15. data/src/element_render.rb +102 -0
  16. data/src/element_style.rb +51 -0
  17. data/src/emitter.rb +102 -0
  18. data/src/emitter_state.rb +19 -0
  19. data/src/enterable.rb +93 -0
  20. data/src/event.rb +92 -0
  21. data/src/focus.rb +102 -0
  22. data/src/geometry.rb +53 -0
  23. data/src/image.rb +60 -0
  24. data/src/input.rb +85 -0
  25. data/src/input_grab.rb +17 -0
  26. data/src/input_time.rb +97 -0
  27. data/src/key.rb +114 -0
  28. data/src/log.rb +24 -0
  29. data/src/node.rb +117 -0
  30. data/src/node_attributes.rb +27 -0
  31. data/src/node_visit.rb +52 -0
  32. data/src/renderer.rb +119 -0
  33. data/src/renderer_cursor.rb +18 -0
  34. data/src/renderer_draw.rb +28 -0
  35. data/src/renderer_image.rb +31 -0
  36. data/src/renderer_print.rb +40 -0
  37. data/src/screen.rb +96 -0
  38. data/src/screen_element.rb +59 -0
  39. data/src/screen_input.rb +43 -0
  40. data/src/screen_renderer.rb +53 -0
  41. data/src/style.rb +149 -0
  42. data/src/tco/colouring.rb +248 -0
  43. data/src/tco/config.rb +57 -0
  44. data/src/tco/palette.rb +603 -0
  45. data/src/tco/tco_termgui.rb +30 -0
  46. data/src/termgui.rb +29 -0
  47. data/src/util.rb +110 -0
  48. data/src/util/css.rb +98 -0
  49. data/src/util/css_query.rb +23 -0
  50. data/src/util/easing.rb +364 -0
  51. data/src/util/hash_object.rb +131 -0
  52. data/src/util/imagemagick.rb +27 -0
  53. data/src/util/justify.rb +20 -0
  54. data/src/util/unicode-categories.rb +572 -0
  55. data/src/util/wrap.rb +102 -0
  56. data/src/widget/button.rb +33 -0
  57. data/src/widget/checkbox.rb +47 -0
  58. data/src/widget/col.rb +30 -0
  59. data/src/widget/image.rb +106 -0
  60. data/src/widget/inline.rb +40 -0
  61. data/src/widget/input_number.rb +73 -0
  62. data/src/widget/inputbox.rb +85 -0
  63. data/src/widget/label.rb +33 -0
  64. data/src/widget/modal.rb +69 -0
  65. data/src/widget/row.rb +26 -0
  66. data/src/widget/selectbox.rb +100 -0
  67. data/src/widget/textarea.rb +54 -0
  68. data/src/xml/xml.rb +80 -0
  69. data/test/action_test.rb +34 -0
  70. data/test/box_test.rb +15 -0
  71. data/test/css_test.rb +39 -0
  72. data/test/editor/editor_base_test.rb +201 -0
  73. data/test/element_bounds_test.rb +77 -0
  74. data/test/element_box_test.rb +8 -0
  75. data/test/element_render_test.rb +124 -0
  76. data/test/element_style_test.rb +85 -0
  77. data/test/element_test.rb +10 -0
  78. data/test/emitter_test.rb +108 -0
  79. data/test/event_test.rb +19 -0
  80. data/test/focus_test.rb +37 -0
  81. data/test/geometry_test.rb +12 -0
  82. data/test/input_test.rb +47 -0
  83. data/test/key_test.rb +14 -0
  84. data/test/log_test.rb +21 -0
  85. data/test/node_test.rb +105 -0
  86. data/test/performance/performance1.rb +48 -0
  87. data/test/renderer_test.rb +74 -0
  88. data/test/renderer_test_rect.rb +4 -0
  89. data/test/screen_test.rb +58 -0
  90. data/test/style_test.rb +18 -0
  91. data/test/termgui_test.rb +10 -0
  92. data/test/test_all.rb +30 -0
  93. data/test/util_hash_object_test.rb +93 -0
  94. data/test/util_test.rb +26 -0
  95. data/test/widget/checkbox_test.rb +99 -0
  96. data/test/widget/col_test.rb +87 -0
  97. data/test/widget/inline_test.rb +40 -0
  98. data/test/widget/label_test.rb +94 -0
  99. data/test/widget/row_test.rb +40 -0
  100. data/test/wrap_test.rb +11 -0
  101. data/test/xml_test.rb +77 -0
  102. metadata +101 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af01d169693ceefa3a955883a770af3768f7a902e526ce00cd4aa11b09afa73d
4
- data.tar.gz: 4360e7b85f248e64074ae8371d3725d92518a1d9571ce0005884c5af3081226f
3
+ metadata.gz: de4eb3e84f29fd18258803d8e4e7b9d34bdecdc6d7831cca3471c5116f43a2ff
4
+ data.tar.gz: 8b7d86b1debb3a37e2e7a31223effaee8da41f6053978e2a6b172059a0f656f0
5
5
  SHA512:
6
- metadata.gz: 2e929dcad6d63589630c51c62ffd1638e3409a613b00acdac8d661e2b16ae9a93070e90b479259518b637b14d66729a5e404a4f657fcbf7fc3e943cdbe1f1111
7
- data.tar.gz: 34ab0ae4d6c7754b6e0b0806367c5f05584182c7d787d16c73abfeb058f2a5407da1e4bab8d666075af06399cb2fdc2ced757568858580c7a5f30f29bfd41319
6
+ metadata.gz: 12587d24d2e4b714101bbdea5f39d0a99df91e8d3b73fa155efdffdba7060323a4cb0d1d45edc7e59ed819d86639f39919e788cd19b1e32f582abde746493c1e
7
+ data.tar.gz: b6ada34e0e93522f29e71658ca587cb0c13c25ec11180107a7c211f96f9d6981e2ea153a2d966359138abcc6e1a1b5c77d89e9a3e8f23ff7a1fc207c459539ce
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ gem 'chunky_png'
6
+ # gem 'justify'
7
+ gem 'rexml'
8
+ # gem 'strings'
9
+
10
+ gem 'filewatcher', group: :development
11
+ gem 'rubocop', require: false, group: :development
12
+ gem 'solargraph', require: false, group: :development
13
+ gem 'test-unit', group: :development
14
+ # gem 'yarn', require: false, group: :development
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2020 Sebastián Gurin
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,321 @@
1
+ # termgui
2
+
3
+ Repository: https://github.com/cancerberoSgx/termgui
4
+
5
+ * Command line graphical user interface Ruby toolkit.
6
+ * Create desktop-like interfaces in the command line.
7
+ * Personal ruby-learning project at the beginning
8
+ * 100% ruby, no binaries, no dependencies
9
+ * some ideas taken from npm.org/blessed and my own npm.org/accursed
10
+ * HTML DOM like high level API with styles, layouts, box-model, cascade styles
11
+ * xml / edb support for declaring components in XML syntax
12
+ * rendered optionally supporting a buffer to print out the current screen for testing
13
+ * very well tested
14
+ * flexible managers for focus, actions, scroll, keys, input grab, input grab, cursor
15
+ * event loop supporting set_timeout, wait_for, set_interval
16
+ * text-area / editor support
17
+ * all colors and attributes
18
+ * some basic high level widgets: Button, Label, InputBox, TextArea, Editor, Select,
19
+ * independent low level APIs can be used without the high level overhead for listening stdin, drawing, etc
20
+ * box drawing, easing, css parser and dom selector
21
+
22
+
23
+ ## TODO / Status
24
+
25
+ See [TODO](TODO.md)
26
+
27
+
28
+ ## Motivation
29
+
30
+ * I don't want to use ncurses based dependencies since is binary
31
+ * I know there are a couple of initiatives 100% in ruby now, but I didn't knew them when I started this project
32
+ * I'm the author of npm.org/accursed which is a similar library so I can of already implemented this in JavaScript
33
+ * Initially a pet project to learn Ruby
34
+
35
+ ## Usage
36
+
37
+ ```
38
+ gem install termgui
39
+ ```
40
+
41
+ ### Example
42
+
43
+ ```rb
44
+ require 'termgui'
45
+ screen = Screen.new
46
+ left = screen.append_child Col.new(width: 0.4, height: 0.99, style: { bg: 'red' })
47
+ (0..8).map { |i| left.append_child Label.new(text: "Label_#{i}") }
48
+ right = screen.append_child Col.new(width: 0.6, height: 0.99, x: 0.4, style: {bg: 'blue'))
49
+ (0..4).map do |i|
50
+ right.append_child Button.new(
51
+ text: "Button_#{i}", x: 0.5,
52
+ style: {focus: {fg: '#ed5525'}},
53
+ action: proc { open_modal(screen: screen, title: "Button_#{i}") }
54
+ )
55
+ end
56
+ screen.start
57
+ ```
58
+
59
+ Result:
60
+
61
+ ![readme_screenshot01](readme_screenshot01.jpg)
62
+
63
+ ## Development commands
64
+
65
+ ```sh
66
+ cd termui
67
+ bundler install
68
+ sh bin/test
69
+ sh bin/doc
70
+ sh bin/dev # rails server
71
+ sh bin/watch # tests in watch mode
72
+ ```
73
+
74
+ ## API Reference
75
+
76
+ TODO
77
+
78
+ ### low level (working) examples
79
+
80
+ TODO
81
+
82
+ #### No DOM - just draw
83
+
84
+ TODO
85
+
86
+ #### Only Input
87
+
88
+ TODO
89
+
90
+ #### Only Renderer
91
+
92
+ TODO
93
+
94
+
95
+
96
+
97
+ ## Element attributes
98
+
99
+ Some high level element attributes implemented:
100
+
101
+ ### style-cascade
102
+
103
+ By default, children inherit parent style. If `element.get_attribute('style-cascade') == 'prevent'` it won't happen - this is the children won't be affected by its parent style and only its own is rendered.
104
+
105
+ ### focusable, focused and screen.focus.keys, focus, blur
106
+
107
+ elements with focusable attribute will be able to be focused when user press focus keys (configurable in screen.focus.keys ). By default screen.focus.keys == { next: ['tab'], prev: ['S-tab'] }.
108
+
109
+ focusable elements will emit "focus" and "blur" events
110
+
111
+ When focused, the attribute focused will be true and the element is able to receive "action" event (see actionable, action-keys below)
112
+
113
+ ### actionable, action-keys, action
114
+
115
+ this is useful to implement actionable widgets like buttons that, when focused, can emit "action" events when certain keys are pressed (by default ENTER)
116
+
117
+ focused elements with attribute "actionable" will emit "action" events if user press action-keys (enter by default) when they are focused. Action keys can be configured globally using screen.action.keys or by element with attribute action-keys. Both could be a string or array.
118
+
119
+
120
+ ### action-on-focus
121
+
122
+ automatically trigger an action event wneh an element is focused. helpful for selectbox so no enter is needed for working
123
+
124
+ ### escape-on-blur
125
+
126
+ automatically escapes an entered element on blur. helpful for selectbox so no escape is needed for switching focus - so it behaves like buttons
127
+
128
+
129
+ ### enterable, entered, change, input, escape, escape-keys
130
+
131
+ This is useful to implement textarea / textinput widgets for which we don't want to trigger focus or action events when user is writing text. When an enterable element (that also should be focusable) receives "action" it is set to "entered" mode. (whey you are writing text, you want TAB S-tab, enter, etc to actually insert characters and don't emit "focus" "action", etc events...)
132
+
133
+ When an element is on this mode (only one at a time) the rest of the elements will stop receiving common events like focus or action until it leaves the entered mode. . This could happen programmatically or by receiving "escape" event, by default pressing ESC will provoke "escape" event which will set entered = false and enable normal events again (like focus, action, etc). When entered==true, the entered element will listen for input independently and emit "input" events.
134
+
135
+ the enter event by default is provoked by "action" (enter) so it can be configured individually using action-keys.
136
+
137
+ the escape event by default pressing "escape" can be configurable per element using attribute escape-keys (just like action-keys)
138
+
139
+ TODO: configure to better play with focus: enter-on-focus to automatically "entered" without "action" and automatically "escape" on "blur" (focus will keep working on this case). Also is not clear how escape plays with change
140
+
141
+
142
+
143
+
144
+ ## Performance notes
145
+
146
+ * disabling renderer buffer speeds up rendering about 30%: `screen.renderer.no_buffer = true`. Genereally don't needed in production.
147
+
148
+
149
+ ## API example prototypes (WIP)
150
+
151
+ ** initial design stories**
152
+
153
+ ### layout
154
+
155
+ TODO / proposal
156
+
157
+ ```
158
+ require 'termgui'
159
+ class AppExplorer < Column
160
+ def initialize(model)
161
+ super
162
+ @model=model
163
+ @text = append_child(text: Textarea.new model.text, onChange: {|e| print e.key})
164
+ @text.onChange {|e| print e.key}
165
+ end
166
+ end
167
+ screen = Screen.new
168
+ main = Row.new
169
+ left = main.append_child(Column.new 0.3)
170
+ right = main.append_child(Column.new 0.7)
171
+ explorer = left.append_child(AppExplorer.new model)
172
+ editor = right.append_child(AppEditor.new model)
173
+ screen start
174
+ ```
175
+
176
+ ### structure
177
+
178
+ TODO / proposal
179
+
180
+ ```
181
+ class MyWidget < Column
182
+ def initialize
183
+ super 0.5
184
+ append_children [
185
+ {type: Row, height: 0.6, children: [
186
+ {type: Input, value: 'edit me', width: 0.5, onChange: {|e|print e} },
187
+ {type: Label, text: 'edit me'},
188
+ ]}
189
+ {type: Button, text: 'click me', onClick: {|e|print e}},
190
+ ]
191
+ end
192
+ end
193
+ ```
194
+
195
+ #### aside
196
+
197
+ ```
198
+ {type: Button, text: 'click me', onclick: {|e|print e}},
199
+ vs
200
+ Button.new text: 'click me', onclick: {|e|print e}},
201
+
202
+ {type: Row, height: 0.6, children: [
203
+ {type: Input, value: 'edit me', width: 0.5, onChange: {|e|print e} },
204
+ {type: Label, text: 'hello'},
205
+ ]}
206
+ vs
207
+ Row.new height: 0.6, children: [
208
+ Input.new value: 'edit me', width: 0.5, onChange: {|e|print e},
209
+ Label new: label: 'hello'
210
+ ]
211
+ ```
212
+
213
+ ### style
214
+
215
+ style = {
216
+ '.primary': {
217
+ bg: 'red',
218
+ fg: 'black'
219
+ bold: true
220
+ }
221
+ }
222
+ screen.append_child(Column.new children: [
223
+ Label.new text: 'are you sure?',
224
+ Button.new
225
+ ])
226
+
227
+
228
+ ### high level no layout
229
+
230
+ TODO / proposal
231
+
232
+ ```
233
+ s=Screen.new
234
+ b=Button.new(parent: s.document, width: 0.3, height: 0.3, left: 0, top: 0, label: 'click me', onClick: { |e| alert "#{e.target.label} clicked!" })
235
+ s.start
236
+ ```
237
+
238
+ ### example low level
239
+
240
+ (no HTML DOM at all, just drawing)
241
+ ```
242
+ screen = Screen.new
243
+ screen.renderer.rect(2,3,9,3,'-', {fg: 'yellow', bg: 'gray'})
244
+ screen.renderer.text(x: 3, y: 4,text; 'click me', style: Style.new(fg: '#ffee11', bg: 'black', bold: true))
245
+ ```
246
+
247
+ ### events
248
+
249
+ ```
250
+ screen=Screen.new
251
+ screen.event.add_listener('key', {|e| exit 0 if e.key=='q'})
252
+ renderer.text(text: 'press q to exit')
253
+ ```
254
+
255
+
256
+
257
+ ## Design
258
+
259
+ ### concepts
260
+
261
+ Screen: contains document, renderer, buffer, Input
262
+
263
+ Renderer: responsible of drawing given pixels to the terminal
264
+
265
+ Buffer: maintains screen as bitmap structure (so users can read the current screen contents like a bitmap)
266
+
267
+ Document: Node subclass analog to html's (access to parent screen)
268
+
269
+ Node: DOM like representation analog to html's (children, attributes)
270
+
271
+ Element: Node subclass analog to html's (border, margin, padding)
272
+
273
+ Input: responsible of user input - notifies screen - emitter
274
+
275
+ ## Summary
276
+
277
+ I'm author of npm.org/flor that although has superior terminal support (tput) I would like to re implement a similar library for ruby, writing it from scratch (currently learning ruby).
278
+
279
+ * low level html-canvas like to set attributes and write strings
280
+ * try to stick to html canvas api for Renderer
281
+ * user is responsible of setting the 'active style' like canvas' stroke-width - this simplifies renderer
282
+ * renderer of styled strings supporting cursor management,
283
+ * responsible of translating user's `{bg: 'red', s: 'hello'}` into a string with ansi codes
284
+ * screen maintains a virtual Buffer so current drawn screen can be accessed like a bitmap
285
+ * a DOM like API for children, attributes, box model, style
286
+ * supports user input events also like html dom EventSource (element.add_listener('key', ...))
287
+ * basic widget implementations: button,input,textarea
288
+ * style: fg, bg, ch, bold, etc.
289
+ * focus management: focused/focusable - element.style.focus
290
+ * input event loop : set_timeout
291
+ * easy keyboard event representation and API
292
+
293
+ ## Future
294
+
295
+ add features from npm.org/flor:
296
+
297
+ * scroll (element.scrollX=0.2) - dom support
298
+ * a xmlish syntax for defining GUI.
299
+ * support function attributes for event handlers as ruby fragments
300
+
301
+ ## Side projects
302
+
303
+ * cli/driver for ruby : for properly testing termgui we need cli-driver for ruby. see probes/stdin.rb for working exec and writing to process stdin async
304
+
305
+
306
+ ## Design notes
307
+
308
+ TODO
309
+
310
+ Screen, renderer, input are responsible of basic terminal styles like bg, fg, bold, etc.
311
+
312
+ On top of the screen, renderer and input a document object model like HTML DOM is supported. See Node, Element, Style, etc. Some features based on HTML supported are:
313
+
314
+ * box model similar
315
+ * children rendering
316
+ * text
317
+ * element query
318
+ * border
319
+ * padding
320
+
321
+ Some high level utilities, like the focus/action management, work on top of this DOM so probably 99% of users will want to go that way for building their GUIs.
data/TODO.md ADDED
@@ -0,0 +1,259 @@
1
+ ## TODO
2
+
3
+ - [ ] issues with bounds andborders is probably solvable by fixing box() by allowing not to print the content and only the border - so can be run after render_self without affecting the content
4
+ - [ ] this doesn't work: ` style: { padding: Bounds.new(top: 11, left: 11)` nor this: ``this does `style: Style.new(padding: Bounds.new(top: 11, left: 11)`
5
+ - [ ] advance focus
6
+ - [ ] how to support focus hierarchies ?
7
+ - [ ] alternative 1: use tabs to focus primary panels and arrows to focus internal widgets of current first level focused panel
8
+ - [ ] alternative 2: make a focusable & enterable - when entered focus-keys will only work inside it (focusing focusable children)
9
+
10
+ - [w] editor - generic text area like (see section "editor" below). See src/editor
11
+
12
+ - [ ] investigate similar target projects
13
+ - [ ] https://github.com/Shopify/cli-ui
14
+ - [ ] https://github.com/gavinlaking/vedeu
15
+ - [ ] input - check this - https://github.com/piotrmurach/tty-reader supports raw mode for multi line - "https://github.com/piotrmurach/tty-reader#22-read_line" - has the key map implemented. -
16
+ - [ ] keys - full map verify https://rubydoc.info/gems/vedeu/Vedeu
17
+ - [ ] check this out - terminal toolkit - many things needed here - research if it targets the same use cases https://ttytoolkit.org/components/
18
+
19
+ - [ ] scroll
20
+ - [x] Element#offset
21
+ - [ ] ScrollManager : define "scrollable" and define keys for scroll up, down, left right if current focused el is scrollable ? (manager?)
22
+ - [ ] scroll events
23
+ - [ ] need overflow: hidden to make sense - see probes/fileProbe.rb
24
+ - [ ] renderer should prevent children content outside overflow:hidden ancestors (expensive render)
25
+ - [ ] configurable scroll keys, offset amounts and easing, globally and per element.
26
+ - [ ] inspiration perhaps : https://github.com/xunker/peter_pan/blob/master/lib/peter_pan.rb
27
+
28
+ - [ ] test coverage : https://github.com/colszowka/simplecov
29
+
30
+ - [ ] notify / responsive when terminal is resized dynamically
31
+
32
+ - [ ] widgets
33
+ - [x] col
34
+ - [x] row
35
+ - [x] label
36
+ - [x] inputbox
37
+ - [ ] not grabing input - need a way of preventing other global listeners to listen while entered
38
+ - [x] checkbox
39
+ - [x] InputNumber
40
+ - [x] SelectBox
41
+ - [ ] trigger changeValue event
42
+ - [ ] trigger option-focus event
43
+ - [ ] call change, input and option_focus props
44
+ - [w] textarea- see editorbase
45
+
46
+
47
+ - [x] colors:
48
+ - [x] verify character attributes work in style (see color.rb ATTRIBUTES Update - removed ). -
49
+ - [x] test in a realProbe
50
+ - [x] fix src/tco to support all attributes - checkout https://github.com/sickill/rainbow and https://github.com/fazibear/colorize and https://github.com/piotrmurach/pastel - update - tco fixed
51
+ - [ ] TODO: tco pull request (blink, underline, etc)
52
+ - [x] tco [r,g,b] colouring is slow when using many colors (imgs, random_color)
53
+ - (WONT) this could be improved by auto generating a rgb->colour mapping table loaded in memory
54
+ - [ ] tco PR palette.rb #569 just using a simpler hash than to_s for cache key doubles speed
55
+ - [x] make a fast mode with simpler diff algorithm - see TermGui::fast_colouring(true) (tco PR?)
56
+
57
+ - [ ] how to debug ? check if this could help debugging
58
+
59
+ - [ ] DOM stuff
60
+ - [ ] bounds/layout cascade ?
61
+ - [x] border_final_style
62
+ - [x] attribute action-on-focus automatically trigger an action event wneh an element is focused. helpful for selectbox so no enter is needed for working
63
+ - [x] attribute escape-on-blur
64
+ - [ ] final_style performance - always cloning/merging even if elements don't have any focus or border style...
65
+ - [x] fix HashObject#assign so it won't merge nil valued properties. see element_style#merge_style
66
+ - [x] support hash style declarations: `Element.new(x: 0.1, y: 0.2, style: {fg: 'magenta', border: {style: :double}})`
67
+ - [x] CSS cascade style: children should inherit parent style if explicit and child has no value. (make it optional/configurable) (see `element.get_attribute('style-cascade') == 'prevent'`)
68
+ - [ ] store and formalize Element options (initialize arguments). store it so implementations can look at original values given by user (props)
69
+ - [ ] overflow: hidden
70
+ - [ ] overflow: scroll
71
+ - [x] Element#layout()
72
+ - [x] widgets Col and Row not working correctly - formalize them and test
73
+ - [x] an inline layout - similar to HTML display: inline - so I can add arbitrary elements. it will break when there is no more space and resize itself. See widget/Inline
74
+ - [ ] GridLayout and GridWidget
75
+ - [ ] check https://rubydoc.info/gems/terminal-layout
76
+ - [ ] element's margin
77
+ - [ ] introduce yoga-layout ? (binary)
78
+
79
+ - [x] Elements / renderer dirty / fast-re-render
80
+ - [x] expensive elements (like images) should have the chance to support render_cache and dirty flags-
81
+ - [x] if render_cache==true - Element.render only will be executed if dirty=true - otherwise Element.render output should cached
82
+
83
+ - [ ] mouse ? minimal mouse support possible ?
84
+
85
+ - [ ] gem
86
+ - [ ] minimally test gem pack from probe project
87
+ - [ ] publish
88
+ - [ ] check this helper: https://github.com/technicalpickles/jeweler
89
+
90
+ - [ ] cursor
91
+ - [x] simple cursor artificial class set_interval see src/cursor.rb
92
+ - [ ] use ansi escapes - https://github.com/piotrmurach/tty-cursor for cursor_current state
93
+ - [x] hide when screen.start
94
+ - [ ] widgets responsible of showing/hiding ? or should it be a cursor manager - enterable - cursorable attributes ? currently in inputbox, editor_base managing artificial cursor manually
95
+
96
+ - [ ] data table widget https://www.google.com/search?q=ruby+gem+terminal&oq=ruby+gem+terminal&aqs=chrome..69i57j69i64.3455j0j4&sourceid=chrome&ie=UTF-8#
97
+
98
+ - [ ] documentation
99
+ - [x] generate API documentation (using yard)
100
+ - [ ] publish docs/termgui to github pages
101
+ - [ ] add links to important APIs in README
102
+ - [ ] document important APIs - how to document events and DOM attributes as part of the API docs?
103
+ - [ ] screencasts, screenshots (check http://buildkite.github.io/terminal-to-html/) - asciicam-thing
104
+ - [ ] tutorials
105
+ - [ ] examples using only low level apis (Input, Renderer) without DOM
106
+ - [ ] announce in stack overflow, medium articles like https://medium.com/@bryantteng/outputting-to-the-terminal-in-style-f489bc2fa52c -
107
+
108
+ - [x] erb probe for elements (see xml/xml)
109
+ - [x] xml syntax with binding support
110
+ - [x] properly require '/Users/wyeworks/.rubies/ruby-2.6.5/lib/ruby/2.6.0/rexml/document'
111
+ - [x] access self (the element instance) from attribute handlers: `action="proc {|e| e.target.text = 'asdasd'; e.target.render}"`
112
+ - [ ] complete widgets and attributes - padding, border, style.focus, stc
113
+
114
+ - [ ] fonts with http://www.figlet.org/ - https://github.com/miketierney/artii - also check http://github.com/piotrmurach/tty-font
115
+
116
+ - [ ] terminal capabilities http://github.com/piotrmurach/tty-color
117
+
118
+ - [ ] support drawing using morse unicodes like blessed-contrib
119
+
120
+ - [x] image rendering - see probes/pngProbe.rb using chunky_png
121
+ - [x] add renderer.image
122
+ - [x] improve perf by pre-reading pixels in memory?
123
+ - [x] try not to use binary dependencies like RMagick: https://github.com/nodanaonlyzuul/asciiart/blob/master/asciiart.gemspec - this other project is not so old also rely on rmagick https://github.com/nathanpc/ascii-image - also this https://github.com/pazdera/catpix
124
+ - [x] pure ruby https://github.com/wvanbergen/chunky_png maintained project - see https://github.com/wvanbergen/chunky_png/blob/master/spec/chunky_png/canvas_spec.rb -
125
+ - [x] alpha channel ? currently totally ignored - solution : mix fg and bg according with alpha(bg given by user) - maybe this could be handled by tco/colouring and not Image
126
+ - [ ] currently getting bg color using final_style or parent.final_style but is not correct - we should use renderer.buffer!
127
+ - [x] a simple image slider widget for demos - auto-resize large images to feet screen first - arrows to switch
128
+ - [ ] support ascii art chars like ? currently only printing fixed ch
129
+ - [w] set_pixel, rect, circle, poly, blezier, rotate, trim
130
+ - [x] screen.circle()
131
+ - [x] an ImageWidget - auto resize img to given dims - or viceversa, set widget bounds to fit given image size.
132
+ - [x] support render cache / dirty - just store print() and write it back - this should be done at renderer/nodes
133
+ - [x] use local imagemagick to support other formats than png
134
+ - [ ] use local imagemagick to render fonts
135
+
136
+ - [w] text rendering - use this : https://github.com/piotrmurach/strings#21-align
137
+ - [x] line wrap
138
+ - [ ] some kind of language so is easy to write stuff with attributes / colors like blessed has - or markdown-like syntax... `<red,bold,underline>Title</>` etc...
139
+ - [ ] use https://github.com/piotrmurach/strings for align and more sine supports unicode and ansi.
140
+ - [ ] use https://github.com/piotrmurach/strings also for line wrap and remove current impl.
141
+ - [ ] justified, https://rubydoc.info/gems/justify
142
+ - [x] left
143
+ - [ ] right, center (any gem for this?) https://github.com/piotrmurach/strings
144
+ - [ ] node.text_children or all_text - returns this node text plus all its children text recursively in children order (useful for testing)
145
+
146
+ - [w] idea: canvas drawing taking advantage of chunky_png Canvas class bleziers, resize, rotate, ellipse, etc. Example: draw bleziers in png canvas with transparent bg and only render fg.
147
+
148
+ - [ ] fix duplicated Event class ... see emitter.rb : " this is the same as event.rb Event. Move Event classes to individual - non dependency file"
149
+
150
+ - [w] easing/animations : adapt formulas from accursed project - see src/util/easing.rb
151
+
152
+ - [w] npm.org/inquirer like apis - see /inquirer
153
+
154
+ - [ ] promise like apis : `screen.wait_for(predicate1).then(proc {screen.wait_for(predicate2)}).then(verb2).catch(proc {|error|p error})` - right now is callback hell :(
155
+ - [x] Could RUby's then() help here ? ANSWER: NO
156
+ - [ ] based on our own event loop? or could we use a gem like concurrency? update - currently supporting method block which is similar ?
157
+
158
+ - [w] element query cssish query support : `element.queryAll '[a="b"] .item > add-button'`
159
+ - [x] query_by_attribute, query_one_by_attribute
160
+ - [x] CSS like language parser
161
+ - [ ] query engine based on css like language below.
162
+ - [ ] stylesheets CSS like for declare styles. Can we use ruby based language instead of CSSish ?
163
+
164
+
165
+ ### Done
166
+ - [x] fixed border and box model
167
+ - [x] wait_for/when : `screen.when( proc {element.query_one_by_attribute 'progress', 'ready'}, proc { print 'done' })`
168
+ - [x] issue when pipe to file, i.e. ruby a_screen_start_app.rb > file.txt `screen.rb:22:in winsize': Inappropriate ioctl for device (Errno::ENOTTY)`
169
+ - [x] renderer.buffer disabled by default (faster) - Screen.new_for_testing will enable buffer and silent screen.
170
+ - [x] renderer methods accepts style and always print "closed" styled strings.
171
+ - [w] Layouts
172
+ - [x] So I don't need to specify element bounds: `col = Col.new; top = Row.new(height: 9,4); bottom= Row.new(height: 0.6); col.append_child(top, bottom)`
173
+ - [x] text-box - how to lock focus ? how to implement the text-input experience ? WIP see src/widget/textbox
174
+ - [w] set_timeout, set_interval
175
+ - [x] separate input@set_timeout in a module
176
+ - [x] support set_interval correctly - test it
177
+ - [x] cli-driver for testing interactions / see probes/pty*
178
+ - [x] waitForData
179
+ - [x] change camelCase to snake_case
180
+ - [x] rubocop
181
+ - [x] styled box drawing to string
182
+ - [x] review callback's api and use yield, examples: `s.set_timeout(0.5){ p 'after'}` , `client.wait_for(proc { @ready }){ |timeout| p 'finished' unless timeout } ` - is it possible for set_timeout ?
183
+ - [x] element border using boxes
184
+ - [x] (box model different than html).
185
+ - [x] 1-size border support only.
186
+ - [x] border is a style on its own that by default equals its element's style.
187
+ - [x] element's padding
188
+ - [x] input.grab / ungrab
189
+ - [x] focus manager
190
+
191
+ - [x] put everything inside module TermGui
192
+ - [x] group widget hight -level in TermGui::Widget
193
+ - [x] an export * file - see termgui.rb
194
+
195
+ - [x] Keys : test support for key-names
196
+ - [x] test names - enter, left,up, right down, escape
197
+ - [x] test complex (C-x, S-C-right, escape, tab, etc) : `s.add_key_listener('S-C-right', proc {|ev|p 123})`
198
+
199
+
200
+ ### Editor TODO
201
+
202
+ I didn't saw this implemented in similar libraries like tty-reader, vedeu or shopify-cli ( tty-reader mentions multiline editor bur is not this... this is like terminal prompt - not text area)
203
+
204
+ Current status: implements a text area supporting configurable set of keys arrows, enter, backspace, delete, home, end, next-page, prev-page, tab, shift-tab. The basics are there, a text area could be implemented currently easily.
205
+
206
+
207
+ But what about a "real world" editor and which feature should be responsibility of this library?
208
+
209
+ * should this be in a separate project ?
210
+
211
+ * filesystem
212
+
213
+ * selection : shift arrows, shift-end, C-a, etc
214
+ * this impacts on handle_keys since if there's a selection,
215
+ * modifications will replace the selection.
216
+ * arrows - navigation changes semantics
217
+
218
+ * basic text buffer - TextChange, span, etc this will enable:
219
+ * undo-redo
220
+ * change notifications
221
+ * big buffers
222
+
223
+ * clipboard ? system clipboard ?
224
+
225
+ * MISSING KEYS: shift-tab, home, end, next-page, prev-page - these are not supported in keys currently
226
+
227
+ * scrolling for lines outside area
228
+ * alternatively implement word wrap -
229
+ * ideally we want both (toggle word wrap)
230
+ * right now text is truncated on the right and bottom.
231
+
232
+ * configurable key-shortcuts - ideally we should be able to move, scroll, undo, redo, copy, etc a-la-vim with just config
233
+
234
+ * UX we will need to ESCAPE to activate menus - like vim... or should we support complex key-shortcuts like emacs?
235
+ * ideally I want a menu that is activated with escape . escape or action to enter in the editor...
236
+ * in the future other widgets like folder explorer can be escape-tab to focus escape-tab enter to enter the editor again ? or the menu? like blessed/blessed-based-editor...
237
+
238
+ * file chooser - save/load files visually
239
+ * projects:
240
+ * multiple buffers (tabs?) opened
241
+ * file explorer - tree showing a folder allowing opening files - some actions like remove , rename, move ? visually!
242
+ * implies kind of MVC - an open file renamed
243
+
244
+ #### current editor_base implementation todo
245
+
246
+ * TODO: maybe is better to extend Element and use its coords and root_screen? or have a CursorElement or EnterableElement with cursor stuff? Maybe also move all this to a module instead of class
247
+ * x, y accessors should support percents - or we should just call abs_content_x, etc
248
+ * enable() should be called on_enter, disable() on_blur or on_escape
249
+ * render() should call super and compatible with element
250
+ * width, height - currently will print stuff outside screen
251
+ * line break - word wrap ?
252
+ * if no linebreak then we need a viewport for "scrolling" - if not is not usable for a text editor (can we leave this reponsibility to container Element - don't think so - another reason to make this an Element?)
253
+
254
+ * won't work for tab (currently hacking) and unicode chars width != 1
255
+
256
+
257
+ #### editor plan
258
+
259
+ * implement editor API only nothing visual but the text area: