fatty 0.99.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 (108) hide show
  1. checksums.yaml +7 -0
  2. data/.envrc +2 -0
  3. data/.simplecov +23 -0
  4. data/.yardopts +4 -0
  5. data/CHANGELOG.md +34 -0
  6. data/CHANGELOG.org +38 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +31 -0
  9. data/README.org +166 -0
  10. data/Rakefile +15 -0
  11. data/TODO.org +163 -0
  12. data/examples/markdown/native-markdown.md +370 -0
  13. data/examples/markdown/ox-gfm-markdown.md +373 -0
  14. data/examples/markdown/ox-gfm-markdown.org +376 -0
  15. data/exe/fatty +275 -0
  16. data/fatty.gemspec +42 -0
  17. data/lib/fatty/accept_env.rb +32 -0
  18. data/lib/fatty/action.rb +103 -0
  19. data/lib/fatty/action_environment.rb +42 -0
  20. data/lib/fatty/actionable.rb +73 -0
  21. data/lib/fatty/alert.rb +93 -0
  22. data/lib/fatty/ansi/renderer.rb +168 -0
  23. data/lib/fatty/ansi.rb +352 -0
  24. data/lib/fatty/colors/color.rb +379 -0
  25. data/lib/fatty/colors/pairs.rb +73 -0
  26. data/lib/fatty/colors/palette.rb +73 -0
  27. data/lib/fatty/colors/rgb.txt +788 -0
  28. data/lib/fatty/colors.rb +5 -0
  29. data/lib/fatty/config.rb +86 -0
  30. data/lib/fatty/config_files/config.yml +50 -0
  31. data/lib/fatty/config_files/help.md +120 -0
  32. data/lib/fatty/config_files/help.org +124 -0
  33. data/lib/fatty/config_files/keybindings.yml +49 -0
  34. data/lib/fatty/config_files/keydefs.yml +23 -0
  35. data/lib/fatty/config_files/themes/mono.yml +76 -0
  36. data/lib/fatty/config_files/themes/nordic.yml +77 -0
  37. data/lib/fatty/config_files/themes/solarized_dark.yml +77 -0
  38. data/lib/fatty/config_files/themes/terminal.yml +90 -0
  39. data/lib/fatty/config_files/themes/wordperfect.yml +77 -0
  40. data/lib/fatty/config_files/themes/wordperfect_light.yml +77 -0
  41. data/lib/fatty/core_ext/string.rb +21 -0
  42. data/lib/fatty/core_ext.rb +3 -0
  43. data/lib/fatty/counter.rb +81 -0
  44. data/lib/fatty/curses/context.rb +279 -0
  45. data/lib/fatty/curses/curses_coder.rb +684 -0
  46. data/lib/fatty/curses/event_source.rb +230 -0
  47. data/lib/fatty/curses/key_decoder.rb +183 -0
  48. data/lib/fatty/curses/patch.rb +116 -0
  49. data/lib/fatty/curses/window_styling.rb +32 -0
  50. data/lib/fatty/curses.rb +16 -0
  51. data/lib/fatty/env.rb +100 -0
  52. data/lib/fatty/help.rb +41 -0
  53. data/lib/fatty/history/entry.rb +71 -0
  54. data/lib/fatty/history.rb +289 -0
  55. data/lib/fatty/input_buffer.rb +998 -0
  56. data/lib/fatty/input_field.rb +507 -0
  57. data/lib/fatty/key_event.rb +342 -0
  58. data/lib/fatty/key_map.rb +392 -0
  59. data/lib/fatty/keymaps/emacs.rb +189 -0
  60. data/lib/fatty/log_formats/json.rb +47 -0
  61. data/lib/fatty/log_formats/text.rb +67 -0
  62. data/lib/fatty/logger.rb +142 -0
  63. data/lib/fatty/markdown/ansi_renderer.rb +373 -0
  64. data/lib/fatty/markdown/render.rb +22 -0
  65. data/lib/fatty/markdown.rb +4 -0
  66. data/lib/fatty/menu_env.rb +22 -0
  67. data/lib/fatty/mouse_event.rb +32 -0
  68. data/lib/fatty/output_buffer.rb +78 -0
  69. data/lib/fatty/pager.rb +801 -0
  70. data/lib/fatty/prompt.rb +40 -0
  71. data/lib/fatty/renderer/curses.rb +697 -0
  72. data/lib/fatty/renderer/truecolor.rb +607 -0
  73. data/lib/fatty/renderer.rb +419 -0
  74. data/lib/fatty/screen.rb +96 -0
  75. data/lib/fatty/search.rb +43 -0
  76. data/lib/fatty/session/alert_session.rb +52 -0
  77. data/lib/fatty/session/input_session.rb +99 -0
  78. data/lib/fatty/session/isearch_session.rb +172 -0
  79. data/lib/fatty/session/keytest_session.rb +236 -0
  80. data/lib/fatty/session/modal_session.rb +61 -0
  81. data/lib/fatty/session/output_session.rb +105 -0
  82. data/lib/fatty/session/popup_session.rb +540 -0
  83. data/lib/fatty/session/prompt_session.rb +157 -0
  84. data/lib/fatty/session/search_session.rb +136 -0
  85. data/lib/fatty/session/shell_session.rb +566 -0
  86. data/lib/fatty/session.rb +173 -0
  87. data/lib/fatty/sessions.rb +14 -0
  88. data/lib/fatty/terminal/popup_owner.rb +26 -0
  89. data/lib/fatty/terminal/progress.rb +374 -0
  90. data/lib/fatty/terminal.rb +1067 -0
  91. data/lib/fatty/themes/loader.rb +136 -0
  92. data/lib/fatty/themes/manager.rb +71 -0
  93. data/lib/fatty/themes/registry.rb +64 -0
  94. data/lib/fatty/themes/resolver.rb +224 -0
  95. data/lib/fatty/themes/themes.rb +131 -0
  96. data/lib/fatty/themes.rb +6 -0
  97. data/lib/fatty/version.rb +5 -0
  98. data/lib/fatty/view/alert_view.rb +14 -0
  99. data/lib/fatty/view/cursor_view.rb +18 -0
  100. data/lib/fatty/view/input_view.rb +9 -0
  101. data/lib/fatty/view/output_view.rb +9 -0
  102. data/lib/fatty/view/status_view.rb +14 -0
  103. data/lib/fatty/view.rb +33 -0
  104. data/lib/fatty/viewport.rb +90 -0
  105. data/lib/fatty/views.rb +9 -0
  106. data/lib/fatty.rb +55 -0
  107. data/sig/fatty.rbs +4 -0
  108. metadata +250 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a0bfc64f40dcca4bf86300fc22de71e6947b4f9abbc616604c6e5a24a6636a2c
4
+ data.tar.gz: 4dc3d290ce33c14c17603272b16134dd88ced0cb2889286ad64da4b512b3f2e0
5
+ SHA512:
6
+ metadata.gz: 93f7710ce74df70a16b2abdc63456a4efb117089bc83ab4c17f138bd9081fb8a1d028ea14a15c5647cdcd344bb37b3b7747dab4b2aefb1b36cfce20aa1a69e63
7
+ data.tar.gz: 29c0d4b081c7189c953f4e7fd38eda394a76ec43359d607e488a726cd5b6084f69e64248d021e0e6e3704a5b9b36ab5274142e4046d5f8edadb0e827500a3ff3
data/.envrc ADDED
@@ -0,0 +1,2 @@
1
+ PATH_add .bundle/bin
2
+ PATH_add ./scripts
data/.simplecov ADDED
@@ -0,0 +1,23 @@
1
+ SimpleCov.start do
2
+ track_files "lib/**/*.rb"
3
+
4
+ # any custom configs like groups and filters can be here at a central place
5
+ add_filter %r{^/spec/}
6
+ add_filter %r{^/bin/}
7
+ add_filter %r{^/doc/}
8
+ add_filter %r{^/sig/}
9
+ add_filter %r{^/coverage/}
10
+ add_filter %r{^/\.yardoc/}
11
+ add_filter %r{^/\.ruby-lsp/}
12
+ add_filter %r{^/\.git/}
13
+ add_filter %r{^/\.githib/}
14
+
15
+ add_group "Core", %r{^/lib/fatty/[^/]*\.rb}
16
+ add_group "Views", %r{^/lib/fatty/view/[^/]*\.rb}
17
+ add_group "Sessions", %r{^/lib/fatty/session/[^/]*\.rb}
18
+ add_group "Curses", %r{^/lib/fatty/backends/curses/[^/]*\.rb}
19
+ merge_timeout 3600
20
+ # Make this true to merge rspec and cucumber coverage together
21
+ use_merging false
22
+ # enable_coverage :branch
23
+ end
data/.yardopts ADDED
@@ -0,0 +1,4 @@
1
+ --markup markdown
2
+ --output-dir doc
3
+ --readme README.md
4
+ lib/**/*.rb
data/CHANGELOG.md ADDED
@@ -0,0 +1,34 @@
1
+ - [Version 0.5.0 <span class="timestamp-wrapper"><span class="timestamp">[2026-05-03 Sun]</span></span>](#orgb0bc550)
2
+ - [Version 0.4.0 <span class="timestamp-wrapper"><span class="timestamp">[2026-04-30 Thu]</span></span>](#org805c7ee)
3
+ - [Version 0.3.0 <span class="timestamp-wrapper"><span class="timestamp">[2025-04-26 Sat]</span></span>](#org2c7a225)
4
+
5
+
6
+ <a id="orgb0bc550"></a>
7
+
8
+ # Version 0.5.0 <span class="timestamp-wrapper"><span class="timestamp">[2026-05-03 Sun]</span></span>
9
+
10
+ - Implemented YAML-driven theme system with inheritance, both for themes and for roles within a theme.
11
+ - Themes allow popup frames to be styled now with single or double lines and square or rounded corners.
12
+ - Use the default multi-term matcher for popups
13
+ - Fix auto-completion regression on input line to trigger on self-insert.
14
+
15
+
16
+ <a id="org805c7ee"></a>
17
+
18
+ # Version 0.4.0 <span class="timestamp-wrapper"><span class="timestamp">[2026-04-30 Thu]</span></span>
19
+
20
+ - Add \`keytest\` interactive keybinding inspector
21
+ - Add markdown rendering support in demo
22
+ - Internal: unified action dispatch system (actionize)
23
+
24
+
25
+ <a id="org2c7a225"></a>
26
+
27
+ # Version 0.3.0 <span class="timestamp-wrapper"><span class="timestamp">[2025-04-26 Sat]</span></span>
28
+
29
+ - Change name from fat\_term to fatty: it was too tempting to resist
30
+ - Add widgets for \`choose\` \`choosevals\` \`progress\` \`prompt\` \`menu\` \`choose\_multi\` \`choosevals\_multi\`
31
+ - Add status line
32
+ - Improve scroll speed
33
+ - Add completions and predictive completions
34
+ - Many, many internal improvements
data/CHANGELOG.org ADDED
@@ -0,0 +1,38 @@
1
+ * COMMENT CHANGELOG tips:
2
+ 1. Don't dump your git change logs into this file, write them yourself.
3
+ 2. Keep entries short and user-focused,
4
+ 3. Use non-technical language, but do speak in the vocabulary of your gem.
5
+ 4. Don't document changes only of interest to the programmers, just those the
6
+ user would find useful.
7
+ 5. Give each heading a version number and an inactive date (C-c ! is useful here).
8
+
9
+ * Version 0.99.0 [2026-05-23 Sat]
10
+ - Rewrite the rendering to allow Truecolor writing to screen instead of just
11
+ Curses writing based on config truecolor setting, with auto detection of
12
+ truecolor terminal capability.
13
+ - Duplicates removed from history popup.
14
+ - Integrate markdown output into the theme system such that markdown elements
15
+ can be styled within a theme's YAML file.
16
+ - Ready to try to integrate into an actual app before version 1.0.0.
17
+
18
+ * Version 0.5.0 [2026-05-03 Sun]
19
+ - Implemented YAML-driven theme system with inheritance, both for themes and
20
+ for roles within a theme.
21
+ - Themes allow popup frames to be styled now with single or double lines and
22
+ square or rounded corners.
23
+ - Use the default multi-term matcher for popups
24
+ - Fix auto-completion regression on input line to trigger on self-insert.
25
+
26
+ * Version 0.4.0 [2026-04-30 Thu]
27
+ - Add `keytest` interactive keybinding inspector
28
+ - Add markdown rendering support in demo
29
+ - Internal: unified action dispatch system (actionize)
30
+
31
+ * Version 0.3.0 [2025-04-26 Sat]
32
+ - Change name from fat_term to fatty: it was too tempting to resist
33
+ - Add widgets for `choose` `choosevals` `progress` `prompt` `menu`
34
+ `choose_multi` `choosevals_multi`
35
+ - Add status line
36
+ - Improve scroll speed
37
+ - Add completions and predictive completions
38
+ - Many, many internal improvements
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 Daniel E. Doherty
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ - [Introduction](#orga462d10)
2
+ - [Reading Keys](#org64156e4)
3
+ - [Alerts](#org38ad970)
4
+
5
+ #+PROPERTY: header-args:ruby :results value :colnames no :hlines yes :exports both :dir "./"
6
+ #+PROPERTY: header-args:ruby+ :wrap example :session fatty_session :eval yes
7
+ #+PROPERTY: header-args:ruby+ :prologue "$:.unshift('./lib') unless $:.first == './lib'; require 'fatty'"
8
+ #+PROPERTY: header-args:ruby+ :ruby "bundle exec irb"
9
+ #+PROPERTY: header-args:sh :exports code :eval no
10
+ #+PROPERTY: header-args:bash :exports code :eval no
11
+
12
+ [![CI](https://github.com/ddoherty03/fatty/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/ddoherty03/fatty/actions/workflows/main.yml)
13
+
14
+
15
+ <a id="orga462d10"></a>
16
+
17
+ # Introduction
18
+
19
+
20
+ <a id="org64156e4"></a>
21
+
22
+ # Reading Keys
23
+
24
+ Shift/Ctrl/Meta F-keys are normalized when ncurses provides distinct constants.
25
+
26
+
27
+ <a id="org38ad970"></a>
28
+
29
+ # Alerts
30
+
31
+ Alerts are short-lived, non-scrolling messages shown below the input line. They are intended for user-visible conditions that require attention.
data/README.org ADDED
@@ -0,0 +1,166 @@
1
+ #+BEGIN_EXPORT markdown
2
+ #+PROPERTY: header-args:ruby :results value :colnames no :hlines yes :exports both :dir "./"
3
+ #+PROPERTY: header-args:ruby+ :wrap example :session fatty_session :eval yes
4
+ #+PROPERTY: header-args:ruby+ :prologue "$:.unshift('./lib') unless $:.first == './lib'; require 'fatty'"
5
+ #+PROPERTY: header-args:ruby+ :ruby "bundle exec irb"
6
+ #+PROPERTY: header-args:sh :exports code :eval no
7
+ #+PROPERTY: header-args:bash :exports code :eval no
8
+
9
+ [![CI](https://github.com/ddoherty03/fatty/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/ddoherty03/fatty/actions/workflows/main.yml)
10
+ #+END_EXPORT
11
+
12
+
13
+ #+PROPERTY: header-args:ruby :results value :colnames no :hlines yes :exports both :dir "./"
14
+ #+PROPERTY: header-args:ruby+ :wrap example :session fatty_session :eval yes
15
+ #+PROPERTY: header-args:ruby+ :prologue "$:.unshift('./lib') unless $:.first == './lib'; require 'fatty'"
16
+ #+PROPERTY: header-args:ruby+ :ruby "bundle exec irb"
17
+ #+PROPERTY: header-args:sh :exports code :eval no
18
+ #+PROPERTY: header-args:bash :exports code :eval no
19
+
20
+ * Introduction
21
+
22
+ * Reading Keys
23
+
24
+ Shift/Ctrl/Meta F-keys are normalized when ncurses provides distinct constants.
25
+
26
+ * Fatty Help
27
+ ** The =fatty= demo command
28
+
29
+ When you =fatty=, it operates as a simple demo of the =fatty= gem by
30
+ presenting an editable command-line using emacs key bindings. It has several
31
+ builtin commands to demonstrate =fatty= features, and any command it does not
32
+ recognized is handed off to the shell.
33
+
34
+ ** Builtin commands
35
+
36
+ Here are the commands builtin to =fatty=
37
+
38
+ | Command | Description |
39
+ |-----------------------------+-------------------------------------------------------------------------|
40
+ | help | Display this file on the output pane |
41
+ | cd | Change the current directory used by the shell |
42
+ | choose | Present a series of choices in a popup window |
43
+ | choosevals | Also present choices in a popup window but return an associated value |
44
+ | choose_multi | Present choices with a "checkbox" for selecting multiple values |
45
+ | choosevals_multi | Also present a checkbox but return associated values |
46
+ | menu | Present a menu of labeled routines to run |
47
+ | info | Display an "info" message on the status line |
48
+ | good | Display a "good" message colored to indicate success |
49
+ | warn | Display a "warn" message colored to indicate caution |
50
+ | oops | Display an "oops" message colored to indicate failure |
51
+ | prompt | Popup a text box for entering a value in response to a prompt |
52
+ | progress count <N> | Display an animated progress indicator counting up to 40 or the given N |
53
+ | progress percent <N> | Same but also show the percent complete |
54
+ | progress simple_percent <N> | Same but show only the percent complete |
55
+ | progress trail | Show progress by displaying an "indicator" character for each step |
56
+ | progress bar | Show progress by a filling bar using ASCII characters |
57
+ | progress unicode_bar | Same, but using unicode characters |
58
+ | progress braille_bar | Same, but using braille characters |
59
+ | progress spinner | Animate a "spinner" showing a busy state |
60
+ | markdown <file.md> | Render the markdown file to the output pane; defaults to a demo file |
61
+ | keytest | Enter key diagnostic mode report keycodes, key names, and bindings |
62
+
63
+
64
+ ** Keybindings
65
+
66
+ The following tables explain the keybindings available in `fatty` in different
67
+ contexts. Named keys are indicated by `:name` and key categories, such as
68
+ `<digits>` are indicated with brackets.
69
+
70
+ *** Input Context
71
+
72
+ When editing the input line or text input for widgets like the `prompt`,
73
+ `fatty` provides emacs-like editing keybindings by default. Many of these
74
+ commands can take a count prefix argument to repeat the command count times.
75
+ For example, `M-8 M-0 #` will insert 80 '#' characters at the cursor.
76
+
77
+ | Key | Description |
78
+ |------------+-------------------------------------------------------|
79
+ | C-a | move to the beginning of the line |
80
+ | :home | move to the beginning of the line |
81
+ | C-e | move to the end of the line |
82
+ | :end | move to the end of the line |
83
+ | C-f | move cursor right one character |
84
+ | :right | move cursor right one character |
85
+ | C-b | move cursor left one character |
86
+ | :left | move cursor left one character |
87
+ | M-f | move cursor right one word |
88
+ | M-:right | move cursor right one word |
89
+ | C-:right | move cursor right one word |
90
+ | M-b | move cursor left one word |
91
+ | M-:left | move cursor left one word |
92
+ | C-:left | move cursor left one word |
93
+ | C-t | transpose characters |
94
+ | M-t | transpose words |
95
+ | | |
96
+ | C-d | delete character at cursor |
97
+ | :delete | delete character at cursor |
98
+ | :backspace | delete character before cursor |
99
+ | M-d | kill word at cursor |
100
+ | C-w | kill word before cursor |
101
+ | C-k | kill to end of line |
102
+ | | |
103
+ | C-/ | undo |
104
+ | C-_ | undo |
105
+ | C-M-/ | redo |
106
+ | M-/ | redo |
107
+ | | |
108
+ | C-:space | set the mark at the current cursor position |
109
+ | C-@ | set the mark at the current cursor position |
110
+ | C-g | clear the mark |
111
+ | C-w | kill the region |
112
+ | M-w | copy the region |
113
+ | | |
114
+ | C-y | yank last kill at cursor |
115
+ | M-y | replace last yank with next in kill ring |
116
+ | | |
117
+ | C-u | universal count argument (time 4 each press) |
118
+ | M-<digit> | accumulate count argument |
119
+ | | |
120
+ | C-p | replace the line with the prior history item |
121
+ | :up | replace the line with the prior history item |
122
+ | C-n | replace the line with the next history item |
123
+ | :down | replace the line with the prior history item |
124
+ | C-r | search the history in a popup |
125
+ | | |
126
+ | :enter | feed the line to the on_accept proc and page output |
127
+ | M-:enter | feed the line to the on_accept proc and scroll output |
128
+ | C-c | quit `fatty` |
129
+ | C-d | quit `fatty` only if the input line is empty |
130
+ | C-l | clear the output pane |
131
+ | | |
132
+
133
+
134
+ *** Paging Context
135
+
136
+ By default, `fatty` sends output to the large output pane, and if the output
137
+ is more than one screen long presents a paging environment for viewing and
138
+ searching the environment.
139
+
140
+ | Key | Description |
141
+ |-------+---------------------------|
142
+ | :up | move output one line up |
143
+ | k | move output one line up |
144
+ | :down | move output one line down |
145
+ | j | move output one line down |
146
+ | | |
147
+
148
+
149
+ * Alerts
150
+ Alerts are short-lived, non-scrolling messages shown below the input line.
151
+ They are intended for user-visible conditions that require attention.
152
+
153
+ * Markdown
154
+ ** Forced line breaks
155
+ Use ~<br>~ to force a line break.
156
+
157
+ #+begin_example
158
+ This line has a forced line break <br> and this should appear on the next line.
159
+ #+end_example
160
+
161
+ will render as
162
+
163
+ #+begin_example
164
+ This line has a forced line break
165
+ and this should appear on the next line.
166
+ #+end_example
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ require 'gem_docs'
13
+ GemDocs.install
14
+
15
+ task default: %i[spec rubocop]
data/TODO.org ADDED
@@ -0,0 +1,163 @@
1
+ * TODO Horizontal Scrolling
2
+ * TODO Add modes for vi-like keybindings
3
+ - will require changing keybindongs.yml format to include a mode qualifier
4
+ - for advanced two-step actions, e.g. dw, will require an action-pending
5
+ capability
6
+ * DONE Theming
7
+ CLOSED: [2026-05-22 Fri 09:28]
8
+ ** Add attributes (like bold to themes)
9
+ So, in themes, this would be possible:
10
+ #+begin_src ruby
11
+ status_info: { fg: "white", bg: "navy", attrs: [:bold] }
12
+ #+end_src
13
+ ** Develop a ruby DSL for defining themes
14
+ ** Develop more builtin themes
15
+ * DONE Truecolor Support
16
+ CLOSED: [2026-05-22 Fri 09:28]
17
+ Remember this from ChatGPT:
18
+
19
+ #+begin_quote
20
+ 1. Can you detect truecolor support?
21
+
22
+ Yes—best practice is a combination of environment hints:
23
+
24
+ def truecolor_supported?
25
+ ct = ENV["COLORTERM"]&.downcase
26
+ return true if ct&.include?("truecolor") || ct&.include?("24bit")
27
+
28
+ term = ENV["TERM"]&.downcase
29
+ return true if term&.include?("direct") # e.g. xterm-direct
30
+
31
+ false
32
+ end
33
+
34
+ This catches most modern terminals:
35
+
36
+ COLORTERM=truecolor (very common)
37
+ TERM=xterm-direct (less common but explicit)
38
+
39
+ You can also sanity-check:
40
+
41
+ ENV["TERM_PROGRAM"] # iTerm, Apple_Terminal, etc.
42
+
43
+ …but COLORTERM is the main signal.
44
+
45
+ 2. The real blocker: ncurses
46
+
47
+ Even if truecolor is available, ncurses color pairs:
48
+
49
+ Curses.init_pair(...)
50
+
51
+ are limited to:
52
+
53
+ 256 colors (best case)
54
+ often fewer
55
+
56
+ So your current renderer cannot display truecolor, even if the terminal supports it.
57
+
58
+ 3. What it would take to use truecolor
59
+
60
+ You’d need to bypass color pairs and emit ANSI directly:
61
+
62
+ \e[38;2;R;G;Bm # foreground
63
+ \e[48;2;R;G;Bm # background
64
+
65
+ Example:
66
+
67
+ "\e[48;2;135;206;250m"
68
+
69
+ That means:
70
+
71
+ no color_pair
72
+ renderer writes ANSI sequences inline
73
+ you manage resets (\e[0m or partial resets)
74
+ 4. Can you mix curses + truecolor?
75
+
76
+ Sort of—but awkwardly:
77
+
78
+ keep curses for cursor/window management
79
+ use ANSI for colors
80
+ don’t rely on attrset / color pairs
81
+
82
+ This is doable, but:
83
+
84
+ you lose some curses conveniences
85
+ you must be careful about redraws and state
86
+ 5. Recommended path (incremental)
87
+
88
+ Don’t rewrite everything yet. Do this:
89
+
90
+ Step 1 — detect capability
91
+ Fatty.truecolor? = truecolor_supported?
92
+ Step 2 — extend color model
93
+
94
+ Your Color object should carry:
95
+
96
+ { r: 135, g: 206, b: 250 }
97
+
98
+ in addition to (or instead of) pair indices.
99
+
100
+ Step 3 — dual rendering path (later)
101
+
102
+ In renderer:
103
+
104
+ if truecolor?
105
+ emit ANSI
106
+ else
107
+ use color_pair
108
+ end
109
+ 6. Why this is worth it
110
+
111
+ Your theme system is now perfectly positioned for truecolor:
112
+
113
+ you already use semantic roles
114
+ you already parse X11 names
115
+ you already separate rendering
116
+
117
+ So switching later is contained.
118
+
119
+ Bottom line
120
+ ✅ You can detect truecolor
121
+ ❌ You cannot use it with curses color pairs
122
+ ✅ Your architecture is ready to support it later
123
+
124
+ #+end_quote
125
+
126
+ * DONE Change to Fatty?
127
+ CLOSED: [2026-04-30 Thu 03:39]
128
+ and change the name of the demo to fatty for user testing.
129
+
130
+ * DONE Additional UI components
131
+ CLOSED: [2026-04-30 Thu 03:39]
132
+ - [X] prompt :: ask the user for an arbitrary string
133
+ - [X] notice, warn, error :: put messages in the status line
134
+ - [X] choose_many :: present a list of choices that a user can pick many items
135
+ from
136
+ - [X] menu :: user picks an action by name attached to a proc
137
+
138
+ * DONE In demo, add `help` and `keytest` commands
139
+ CLOSED: [2026-04-30 Thu 03:39]
140
+ - help :: would explain what commands are available for the demo
141
+ - keytest :: would echo to the output information about pressed keys, including
142
+ - the detected terminal type
143
+ - the keycode returned by the keyboard/terminal
144
+ - the keyname that the key is mapped to
145
+ - the bindings for the keyname in all contexts
146
+ - if no keyname, a suggested keydef entry to give it a name in the config
147
+ - if not bound, a suggested keybinding entry to add to config
148
+
149
+ * DONE Add cut and paste
150
+ CLOSED: [2026-04-13 Mon 07:48]
151
+ * DONE Add history
152
+ CLOSED: [2026-01-27 Tue 05:44]
153
+ * DONE Add completion
154
+ CLOSED: [2026-04-13 Mon 07:48]
155
+ * DONE Add undo
156
+ CLOSED: [2026-01-27 Tue 05:44]
157
+ * DONE Scrollback Navigation (PgUp/PgDn)
158
+ CLOSED: [2026-04-13 Mon 07:48]
159
+
160
+ * DONE Add Output Search
161
+ CLOSED: [2026-04-13 Mon 07:48]
162
+ * CNCL SIGINT forwarding to child process
163
+ CLOSED: [2026-05-22 Fri 09:28]