termgui 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +14 -0
- data/LICENSE +19 -0
- data/README.md +321 -0
- data/TODO.md +259 -0
- data/src/action.rb +58 -0
- data/src/box.rb +90 -0
- data/src/color.rb +174 -0
- data/src/cursor.rb +69 -0
- data/src/editor/editor_base.rb +152 -0
- data/src/editor/editor_base_handlers.rb +116 -0
- data/src/element.rb +61 -0
- data/src/element_bounds.rb +111 -0
- data/src/element_box.rb +64 -0
- data/src/element_render.rb +102 -0
- data/src/element_style.rb +51 -0
- data/src/emitter.rb +102 -0
- data/src/emitter_state.rb +19 -0
- data/src/enterable.rb +93 -0
- data/src/event.rb +92 -0
- data/src/focus.rb +102 -0
- data/src/geometry.rb +53 -0
- data/src/image.rb +60 -0
- data/src/input.rb +85 -0
- data/src/input_grab.rb +17 -0
- data/src/input_time.rb +97 -0
- data/src/key.rb +114 -0
- data/src/log.rb +24 -0
- data/src/node.rb +117 -0
- data/src/node_attributes.rb +27 -0
- data/src/node_visit.rb +52 -0
- data/src/renderer.rb +119 -0
- data/src/renderer_cursor.rb +18 -0
- data/src/renderer_draw.rb +28 -0
- data/src/renderer_image.rb +31 -0
- data/src/renderer_print.rb +40 -0
- data/src/screen.rb +96 -0
- data/src/screen_element.rb +59 -0
- data/src/screen_input.rb +43 -0
- data/src/screen_renderer.rb +53 -0
- data/src/style.rb +149 -0
- data/src/tco/colouring.rb +248 -0
- data/src/tco/config.rb +57 -0
- data/src/tco/palette.rb +603 -0
- data/src/tco/tco_termgui.rb +30 -0
- data/src/termgui.rb +29 -0
- data/src/util.rb +110 -0
- data/src/util/css.rb +98 -0
- data/src/util/css_query.rb +23 -0
- data/src/util/easing.rb +364 -0
- data/src/util/hash_object.rb +131 -0
- data/src/util/imagemagick.rb +27 -0
- data/src/util/justify.rb +20 -0
- data/src/util/unicode-categories.rb +572 -0
- data/src/util/wrap.rb +102 -0
- data/src/widget/button.rb +33 -0
- data/src/widget/checkbox.rb +47 -0
- data/src/widget/col.rb +30 -0
- data/src/widget/image.rb +106 -0
- data/src/widget/inline.rb +40 -0
- data/src/widget/input_number.rb +73 -0
- data/src/widget/inputbox.rb +85 -0
- data/src/widget/label.rb +33 -0
- data/src/widget/modal.rb +69 -0
- data/src/widget/row.rb +26 -0
- data/src/widget/selectbox.rb +100 -0
- data/src/widget/textarea.rb +54 -0
- data/src/xml/xml.rb +80 -0
- data/test/action_test.rb +34 -0
- data/test/box_test.rb +15 -0
- data/test/css_test.rb +39 -0
- data/test/editor/editor_base_test.rb +201 -0
- data/test/element_bounds_test.rb +77 -0
- data/test/element_box_test.rb +8 -0
- data/test/element_render_test.rb +124 -0
- data/test/element_style_test.rb +85 -0
- data/test/element_test.rb +10 -0
- data/test/emitter_test.rb +108 -0
- data/test/event_test.rb +19 -0
- data/test/focus_test.rb +37 -0
- data/test/geometry_test.rb +12 -0
- data/test/input_test.rb +47 -0
- data/test/key_test.rb +14 -0
- data/test/log_test.rb +21 -0
- data/test/node_test.rb +105 -0
- data/test/performance/performance1.rb +48 -0
- data/test/renderer_test.rb +74 -0
- data/test/renderer_test_rect.rb +4 -0
- data/test/screen_test.rb +58 -0
- data/test/style_test.rb +18 -0
- data/test/termgui_test.rb +10 -0
- data/test/test_all.rb +30 -0
- data/test/util_hash_object_test.rb +93 -0
- data/test/util_test.rb +26 -0
- data/test/widget/checkbox_test.rb +99 -0
- data/test/widget/col_test.rb +87 -0
- data/test/widget/inline_test.rb +40 -0
- data/test/widget/label_test.rb +94 -0
- data/test/widget/row_test.rb +40 -0
- data/test/wrap_test.rb +11 -0
- data/test/xml_test.rb +77 -0
- metadata +101 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de4eb3e84f29fd18258803d8e4e7b9d34bdecdc6d7831cca3471c5116f43a2ff
|
4
|
+
data.tar.gz: 8b7d86b1debb3a37e2e7a31223effaee8da41f6053978e2a6b172059a0f656f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
data/README.md
ADDED
@@ -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:
|