tuile 0.14.0 → 0.16.0

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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +159 -49
  3. data/README.md +53 -17
  4. data/book/04-event-loop.md +12 -12
  5. data/book/05-focus.md +152 -22
  6. data/book/06-theming.md +105 -25
  7. data/book/07-components.md +531 -50
  8. data/book/08-testing.md +100 -20
  9. data/book/10-locale.md +216 -0
  10. data/book/README.md +19 -9
  11. data/examples/file_commander.rb +14 -5
  12. data/examples/hello_world.rb +17 -4
  13. data/examples/sampler.rb +654 -40
  14. data/lib/tuile/component/abstract_string_field.rb +114 -68
  15. data/lib/tuile/component/abstract_wrapping_field.rb +279 -0
  16. data/lib/tuile/component/big_decimal_field.rb +52 -79
  17. data/lib/tuile/component/button.rb +8 -8
  18. data/lib/tuile/component/checkbox.rb +9 -9
  19. data/lib/tuile/component/checkbox_group.rb +38 -21
  20. data/lib/tuile/component/combo_box.rb +102 -59
  21. data/lib/tuile/component/confirm_window.rb +7 -5
  22. data/lib/tuile/component/date_field.rb +347 -0
  23. data/lib/tuile/component/date_time_field.rb +275 -0
  24. data/lib/tuile/component/float_field.rb +57 -82
  25. data/lib/tuile/component/has_bad_input.rb +88 -0
  26. data/lib/tuile/component/has_caption.rb +8 -0
  27. data/lib/tuile/component/has_content.rb +32 -13
  28. data/lib/tuile/component/has_placeholder.rb +62 -0
  29. data/lib/tuile/component/has_validation.rb +115 -0
  30. data/lib/tuile/component/has_value.rb +28 -1
  31. data/lib/tuile/component/integer_field.rb +51 -78
  32. data/lib/tuile/component/label.rb +7 -39
  33. data/lib/tuile/component/layout/box.rb +90 -19
  34. data/lib/tuile/component/layout.rb +15 -5
  35. data/lib/tuile/component/list.rb +53 -38
  36. data/lib/tuile/component/list_dropdown.rb +7 -3
  37. data/lib/tuile/component/menu_bar/cascade.rb +5 -5
  38. data/lib/tuile/component/menu_bar.rb +18 -18
  39. data/lib/tuile/component/notification.rb +32 -18
  40. data/lib/tuile/component/overlay.rb +26 -8
  41. data/lib/tuile/component/picker_window.rb +27 -8
  42. data/lib/tuile/component/popup.rb +2 -2
  43. data/lib/tuile/component/progress_bar.rb +10 -4
  44. data/lib/tuile/component/radio_group.rb +41 -23
  45. data/lib/tuile/component/select.rb +23 -16
  46. data/lib/tuile/component/slot.rb +3 -3
  47. data/lib/tuile/component/tab_sheet.rb +6 -6
  48. data/lib/tuile/component/tabs.rb +11 -11
  49. data/lib/tuile/component/text_area.rb +26 -18
  50. data/lib/tuile/component/text_field.rb +55 -26
  51. data/lib/tuile/component/text_view.rb +40 -19
  52. data/lib/tuile/component/time_field.rb +479 -0
  53. data/lib/tuile/component/window.rb +26 -13
  54. data/lib/tuile/component.rb +635 -131
  55. data/lib/tuile/event_queue.rb +4 -4
  56. data/lib/tuile/fake_event_queue.rb +1 -1
  57. data/lib/tuile/fake_screen.rb +95 -3
  58. data/lib/tuile/final.rb +75 -0
  59. data/lib/tuile/locale.rb +851 -0
  60. data/lib/tuile/mouse/router.rb +217 -0
  61. data/lib/tuile/mouse.rb +177 -0
  62. data/lib/tuile/screen.rb +219 -68
  63. data/lib/tuile/screen_pane.rb +51 -42
  64. data/lib/tuile/styled_string.rb +5 -5
  65. data/lib/tuile/testing.rb +198 -0
  66. data/lib/tuile/theme.rb +110 -32
  67. data/lib/tuile/version.rb +1 -1
  68. data/lib/tuile/vertical_scroll_bar.rb +88 -12
  69. data/lib/tuile.rb +1 -0
  70. data/sig/tuile.rbs +4595 -825
  71. metadata +14 -9
  72. data/COMPARISON.md +0 -101
  73. data/DECISIONS.md +0 -5422
  74. data/TERMINOLOGY.md +0 -71
  75. data/ideas/arrow-key-navigation.md +0 -221
  76. data/ideas/modal-backdrop.md +0 -24
  77. data/ideas/new-components.md +0 -124
  78. data/ideas/per-component-buffers.md +0 -55
  79. data/lib/tuile/mouse_event.rb +0 -68
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tuile
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Vysny
@@ -113,11 +113,8 @@ extra_rdoc_files: []
113
113
  files:
114
114
  - CHANGELOG.md
115
115
  - CODE_OF_CONDUCT.md
116
- - COMPARISON.md
117
- - DECISIONS.md
118
116
  - LICENSE.txt
119
117
  - README.md
120
- - TERMINOLOGY.md
121
118
  - book/01-first-app.md
122
119
  - book/02-repaint.md
123
120
  - book/03-layout.md
@@ -127,14 +124,11 @@ files:
127
124
  - book/07-components.md
128
125
  - book/08-testing.md
129
126
  - book/09-styled-text.md
127
+ - book/10-locale.md
130
128
  - book/README.md
131
129
  - examples/file_commander.rb
132
130
  - examples/hello_world.rb
133
131
  - examples/sampler.rb
134
- - ideas/arrow-key-navigation.md
135
- - ideas/modal-backdrop.md
136
- - ideas/new-components.md
137
- - ideas/per-component-buffers.md
138
132
  - lib/tuile.rb
139
133
  - lib/tuile/ansi.rb
140
134
  - lib/tuile/buffer.rb
@@ -142,15 +136,21 @@ files:
142
136
  - lib/tuile/color_depth.rb
143
137
  - lib/tuile/component.rb
144
138
  - lib/tuile/component/abstract_string_field.rb
139
+ - lib/tuile/component/abstract_wrapping_field.rb
145
140
  - lib/tuile/component/big_decimal_field.rb
146
141
  - lib/tuile/component/button.rb
147
142
  - lib/tuile/component/checkbox.rb
148
143
  - lib/tuile/component/checkbox_group.rb
149
144
  - lib/tuile/component/combo_box.rb
150
145
  - lib/tuile/component/confirm_window.rb
146
+ - lib/tuile/component/date_field.rb
147
+ - lib/tuile/component/date_time_field.rb
151
148
  - lib/tuile/component/float_field.rb
149
+ - lib/tuile/component/has_bad_input.rb
152
150
  - lib/tuile/component/has_caption.rb
153
151
  - lib/tuile/component/has_content.rb
152
+ - lib/tuile/component/has_placeholder.rb
153
+ - lib/tuile/component/has_validation.rb
154
154
  - lib/tuile/component/has_value.rb
155
155
  - lib/tuile/component/info_window.rb
156
156
  - lib/tuile/component/integer_field.rb
@@ -180,13 +180,17 @@ files:
180
180
  - lib/tuile/component/text_area/wrapped_text.rb
181
181
  - lib/tuile/component/text_field.rb
182
182
  - lib/tuile/component/text_view.rb
183
+ - lib/tuile/component/time_field.rb
183
184
  - lib/tuile/component/window.rb
184
185
  - lib/tuile/event_queue.rb
185
186
  - lib/tuile/fake_event_queue.rb
186
187
  - lib/tuile/fake_screen.rb
188
+ - lib/tuile/final.rb
187
189
  - lib/tuile/fraction.rb
188
190
  - lib/tuile/keys.rb
189
- - lib/tuile/mouse_event.rb
191
+ - lib/tuile/locale.rb
192
+ - lib/tuile/mouse.rb
193
+ - lib/tuile/mouse/router.rb
190
194
  - lib/tuile/point.rb
191
195
  - lib/tuile/rect.rb
192
196
  - lib/tuile/screen.rb
@@ -194,6 +198,7 @@ files:
194
198
  - lib/tuile/size.rb
195
199
  - lib/tuile/styled_string.rb
196
200
  - lib/tuile/terminal_background.rb
201
+ - lib/tuile/testing.rb
197
202
  - lib/tuile/theme.rb
198
203
  - lib/tuile/theme_def.rb
199
204
  - lib/tuile/version.rb
data/COMPARISON.md DELETED
@@ -1,101 +0,0 @@
1
- # COMPARISON.md
2
-
3
- Tuile's neighbours: what else exists, and — the question this file exists to
4
- answer — how much of it you can actually *reach from Ruby* on an ordinary Linux
5
- box without building bindings first.
6
-
7
- The short version: of the three alternatives the README names, **none** is
8
- callable from Ruby via the distro package manager. What is callable is a pair
9
- of curses bindings that sit *below* Tuile, and the tty-toolkit that Tuile is
10
- already built on.
11
-
12
- ## The alternatives
13
-
14
- The three the README points here for:
15
-
16
- - **[tty-toolkit](https://ttytoolkit.org/)** (`tty-prompt`, `tty-cursor`, …) —
17
- low-level building blocks, not a framework: no component tree, no event loop,
18
- no invalidation. Tuile sits on top of `tty-cursor` / `tty-screen` and adds
19
- the framework layer.
20
- - **[vedeu](https://github.com/gavinlaking/vedeu)** — the closest Ruby
21
- comparable, unmaintained since 2017.
22
- - **[ratatui](https://github.com/ratatui/ratatui)** — the popular Rust TUI
23
- framework; its immediate-mode API is closer to `tty-prompt` than to Tuile's
24
- retained component tree.
25
-
26
- Beyond those, DECISIONS.md surveys **Textual**, **urwid**, **brick**,
27
- **Lipgloss**, **notcurses**, **FTXUI** and **Ink** — but as per-decision
28
- precedent inside `D_` entries (`D_bg_inherit`, `D_key_dispatch`,
29
- `D_box_layouts`, `D_list_items` are the dense ones), not as a roster. Look
30
- there for "what does Textual do about focus-first key dispatch", not for
31
- "should I use Textual".
32
-
33
- ## Reachable from Ruby, via apt
34
-
35
- Surveyed on Ubuntu 26.04 (resolute) in 2026-08, against the distro's own
36
- `/usr/bin/ruby` 3.3.8 — which matters, see the caveats below.
37
-
38
- | Candidate | apt package | Callable from Ruby? |
39
- |---|---|---|
40
- | vedeu | *no package at all* | — |
41
- | ratatui | `librust-ratatui-dev` (Rust source only) | no |
42
- | Textual | `python3-textual` | no |
43
- | urwid | `python3-urwid` | no |
44
- | notcurses | `libnotcurses-dev`, `notcurses-bin` | no bindings — you would write the FFI |
45
- | CDK, newt | `libcdk5-dev`, `libnewt-dev` | C and Python only |
46
- | tty-toolkit | `ruby-tty-prompt`, `-cursor`, `-screen`, `-reader`, `-color`, `-pastel` | **yes** — but this is Tuile's own substrate |
47
- | curses | `ruby-curses` | **yes** |
48
- | ncurses + panel/form/menu | `ruby-ncurses` | **yes** — the closest of the lot |
49
-
50
- `dialog` and `whiptail` are also packaged and can be shelled out to from Ruby,
51
- but a subprocess that paints one dialog and exits is a different tool from a
52
- framework that owns a running screen; they are out of scope here.
53
-
54
- ### The two curses bindings
55
-
56
- Neither is in the README's list, and between them they are the only way to
57
- reach anything Tuile-shaped from Ruby without a compiler and a binding project.
58
-
59
- - **`ruby-curses`** — the [ruby/curses](https://github.com/ruby/curses) gem,
60
- wide-char, shipping `curses.so` plus a gemspec under
61
- `rubygems-integration`, so `gem "curses"` resolves under Bundler with no
62
- build step. Strictly low-level: windows, `addstr`, `getch`. No widgets, no
63
- tree, no invalidation — *below* tty-toolkit, not beside it.
64
- - **`ruby-ncurses`** — the `ncursesw` gem
65
- ([sup-heliotrope fork](https://github.com/sup-heliotrope/ncursesw-ruby)), and
66
- the interesting one. Its extension links `libpanelw`, `libformw` **and**
67
- `libmenu`, and exports `new_form` / `new_menu` / `form_driver` /
68
- `menu_driver`; `examples/form.rb` ships in the package. So you get
69
- overlapping windows (Tuile's popup stack), field editing with validation, and
70
- list selection, out of the box.
71
-
72
- ### Why `ruby-ncurses` still is not a substitute
73
-
74
- The gap is the framework layer, and the framework layer is the whole of Tuile.
75
- ncurses forms and menus are a *fixed* widget set driven by a
76
- `form_driver(request)` call. What is missing, in Tuile's own terms:
77
-
78
- - no `parent` / `children` tree you compose your own components into — you
79
- cannot write a component, only configure theirs;
80
- - no top-down layout: nothing assigns a child its `rect`, so every rectangle is
81
- arithmetic you keep by hand (book ch3 for why Tuile made that a rule rather
82
- than an engine);
83
- - no invalidate-and-batch-repaint, so no minimal-diff flush — you decide when
84
- to `refresh` and pay for whatever you redraw;
85
- - no theme or inherited `bg_color`, no `HasValue` value seam a forms layer can
86
- iterate, no `FakeScreen` to assert painted cells against.
87
-
88
- You would be building Tuile *on top of* it, not replacing Tuile with it — and
89
- since `ncursesw-ruby` is a 1.4.x mirror of the C API, whatever you built would
90
- sit directly on `WINDOW*` semantics.
91
-
92
- ### Caveats on the apt route
93
-
94
- - **`ruby-ncurses` and `ruby-curses` are built against the distro's Ruby** —
95
- `Depends: libruby (<< 1:3.4~)` on resolute. They are invisible to any
96
- rbenv/rvm/chruby Ruby, and they break on a distro Ruby upgrade. The gems
97
- (`gem install curses` / `ncursesw`) compile against `libncurses-dev` and do
98
- not have that problem.
99
- - **The table above is a snapshot of one release.** Package availability is the
100
- fastest-rotting fact in this file; re-run `apt-cache policy <pkg>` before
101
- trusting a row.