fatty 0.99.0 → 0.99.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.org +11 -29
- data/README.md +2207 -18
- data/README.org +2066 -104
- data/exe/fatty +236 -93
- data/help/help.md +233 -0
- data/lib/fatty/action.rb +3 -7
- data/lib/fatty/actionable.rb +2 -0
- data/lib/fatty/alert.rb +65 -39
- data/lib/fatty/ansi/renderer.rb +26 -6
- data/lib/fatty/ansi.rb +1 -0
- data/lib/fatty/api/alert.rb +15 -0
- data/lib/fatty/api/choose.rb +145 -0
- data/lib/fatty/api/environment.rb +12 -0
- data/lib/fatty/api/keytest.rb +11 -0
- data/lib/fatty/api/menu.rb +104 -0
- data/lib/fatty/api/output.rb +55 -0
- data/lib/fatty/api/progress.rb +24 -0
- data/lib/fatty/api/prompt.rb +77 -0
- data/lib/fatty/api/status.rb +55 -0
- data/lib/fatty/api.rb +38 -0
- data/lib/fatty/callback_environment.rb +74 -0
- data/lib/fatty/colors/color.rb +366 -232
- data/lib/fatty/colors/pairs.rb +2 -0
- data/lib/fatty/command.rb +78 -0
- data/lib/fatty/config.rb +227 -39
- data/lib/fatty/config_files/config.yml +4 -12
- data/lib/fatty/config_files/keydefs.yml +13 -23
- data/lib/fatty/config_files/themes/capuchin_monk.yml +140 -0
- data/lib/fatty/config_files/themes/catppuccin_latte.yml +140 -0
- data/lib/fatty/config_files/themes/catppuccin_mocha.yml +140 -0
- data/lib/fatty/config_files/themes/cyberpunk.yml +141 -0
- data/lib/fatty/config_files/themes/dracula.yml +140 -0
- data/lib/fatty/config_files/themes/everforest_dark.yml +140 -0
- data/lib/fatty/config_files/themes/gruvbox_dark.yml +140 -0
- data/lib/fatty/config_files/themes/gruvbox_light.yml +140 -0
- data/lib/fatty/config_files/themes/mono.yml +119 -47
- data/lib/fatty/config_files/themes/monokai.yml +140 -0
- data/lib/fatty/config_files/themes/nordic.yml +1 -0
- data/lib/fatty/config_files/themes/onedark.yml +140 -0
- data/lib/fatty/config_files/themes/solarized_dark.yml +1 -0
- data/lib/fatty/config_files/themes/solarized_light.yml +140 -0
- data/lib/fatty/config_files/themes/terminal.yml +67 -0
- data/lib/fatty/config_files/themes/tokyo_night.yml +140 -0
- data/lib/fatty/config_files/themes/wordperfect.yml +80 -9
- data/lib/fatty/core_ext/hash.rb +19 -0
- data/lib/fatty/core_ext/string.rb +19 -12
- data/lib/fatty/core_ext.rb +1 -0
- data/lib/fatty/curses/context.rb +86 -84
- data/lib/fatty/curses/event_source.rb +128 -40
- data/lib/fatty/curses/key_decoder.rb +77 -11
- data/lib/fatty/env.rb +21 -20
- data/lib/fatty/help.rb +1 -29
- data/lib/fatty/history/entry.rb +2 -0
- data/lib/fatty/history.rb +17 -14
- data/lib/fatty/input_buffer.rb +71 -47
- data/lib/fatty/input_field.rb +216 -149
- data/lib/fatty/key_event.rb +67 -66
- data/lib/fatty/key_map.rb +54 -16
- data/lib/fatty/keymaps/emacs.rb +40 -6
- data/lib/fatty/log_formats/json.rb +2 -0
- data/lib/fatty/log_formats/text.rb +2 -0
- data/lib/fatty/logger.rb +7 -2
- data/lib/fatty/markdown/ansi_renderer.rb +75 -6
- data/lib/fatty/markdown/render.rb +2 -3
- data/lib/fatty/mouse_event.rb +142 -2
- data/lib/fatty/output_buffer.rb +2 -0
- data/lib/fatty/pager.rb +158 -47
- data/lib/fatty/progress.rb +417 -0
- data/lib/fatty/renderer/curses.rb +340 -184
- data/lib/fatty/renderer/truecolor.rb +266 -163
- data/lib/fatty/renderer.rb +115 -97
- data/lib/fatty/screen.rb +2 -0
- data/lib/fatty/session/alert_session.rb +39 -21
- data/lib/fatty/session/isearch_session.rb +92 -38
- data/lib/fatty/session/keytest_session.rb +105 -85
- data/lib/fatty/session/modal_session.rb +38 -1
- data/lib/fatty/session/output_session.rb +472 -21
- data/lib/fatty/session/popup_session.rb +251 -134
- data/lib/fatty/session/prompt_session.rb +68 -26
- data/lib/fatty/session/search_session.rb +79 -31
- data/lib/fatty/session/shell_session.rb +383 -368
- data/lib/fatty/session/status_session.rb +167 -0
- data/lib/fatty/session.rb +95 -95
- data/lib/fatty/terminal/popup_owner.rb +14 -11
- data/lib/fatty/terminal.rb +515 -813
- data/lib/fatty/themes/loader.rb +4 -2
- data/lib/fatty/themes/manager.rb +4 -0
- data/lib/fatty/themes/registry.rb +2 -0
- data/lib/fatty/themes/resolver.rb +175 -162
- data/lib/fatty/version.rb +1 -1
- data/lib/fatty/viewport.rb +8 -1
- data/lib/fatty.rb +35 -7
- metadata +42 -40
- data/.envrc +0 -2
- data/.simplecov +0 -23
- data/.yardopts +0 -4
- data/CHANGELOG.md +0 -34
- data/Rakefile +0 -15
- data/TODO.org +0 -163
- data/examples/markdown/native-markdown.md +0 -370
- data/examples/markdown/ox-gfm-markdown.md +0 -373
- data/examples/markdown/ox-gfm-markdown.org +0 -376
- data/fatty.gemspec +0 -42
- data/lib/fatty/accept_env.rb +0 -32
- data/lib/fatty/config_files/help.md +0 -120
- data/lib/fatty/config_files/help.org +0 -124
- data/lib/fatty/config_files/themes/wordperfect_light.yml +0 -77
- data/lib/fatty/menu_env.rb +0 -22
- data/lib/fatty/session/input_session.rb +0 -99
- data/lib/fatty/sessions.rb +0 -14
- data/lib/fatty/terminal/progress.rb +0 -374
- data/lib/fatty/view/alert_view.rb +0 -14
- data/lib/fatty/view/cursor_view.rb +0 -18
- data/lib/fatty/view/input_view.rb +0 -9
- data/lib/fatty/view/output_view.rb +0 -9
- data/lib/fatty/view/status_view.rb +0 -14
- data/lib/fatty/view.rb +0 -33
- data/lib/fatty/views.rb +0 -9
- data/sig/fatty.rbs +0 -4
data/README.md
CHANGED
|
@@ -1,31 +1,2220 @@
|
|
|
1
|
-
- [Introduction](#
|
|
2
|
-
- [
|
|
3
|
-
- [
|
|
1
|
+
- [Introduction](#org92a02ab)
|
|
2
|
+
- [Quick Start](#orga9758e6)
|
|
3
|
+
- [Installing](#org5d48af2)
|
|
4
|
+
- [Trying it Out with the \`fatty\` Demo](#orga0811d0)
|
|
5
|
+
- [Builtin commands](#org10b740e)
|
|
6
|
+
- [Screenshots](#orga21015c)
|
|
7
|
+
- [Command line editing](#orge811242)
|
|
8
|
+
- [Searchable Output](#org86db3fd)
|
|
9
|
+
- [Paging Markdown](#org465e882)
|
|
10
|
+
- [Popup Selection](#orged601b1)
|
|
11
|
+
- [Usage](#org0fbc008)
|
|
12
|
+
- [Launching a Fatty Terminal](#orgdd7a899)
|
|
13
|
+
- [`on_accept`](#orge36ae8e)
|
|
14
|
+
- [Parameters to `on_accept`](#org74e77b2)
|
|
15
|
+
- [The `line` parameter to `on_accept`](#org21b8961)
|
|
16
|
+
- [The callback parameter to `on_accept`](#org3091db0)
|
|
17
|
+
- [Output ordering](#orgcd415d8)
|
|
18
|
+
- [Long-running callbacks and interruption](#org0d9a504)
|
|
19
|
+
- [ANSI colors in output](#org89ae995)
|
|
20
|
+
- [Other parameters to `Terminal.new`](#orgce83cdf)
|
|
21
|
+
- [The Callback API](#orgef3914d)
|
|
22
|
+
- [`append(text, follow: true)`](#org1f2fcbb)
|
|
23
|
+
- [`append_now(text, follow: true, mode: nil)`](#org3318ee2)
|
|
24
|
+
- [`markdown(text)`](#org3da5738)
|
|
25
|
+
- [`status(text, role: :info)`](#org5e0ab5d)
|
|
26
|
+
- [`good(text, replace: false, render: true)`](#orgd2a8b1b)
|
|
27
|
+
- [`info(text, replace: false, render: true)`](#org8ec7886)
|
|
28
|
+
- [`warn(text, replace: false, render: true)`](#org6bb2e02)
|
|
29
|
+
- [`error(text, replace: false, render: true)`](#org6040c43)
|
|
30
|
+
- [`oops(text, replace: false, render: true)`](#org3e60ade)
|
|
31
|
+
- [`alert(text, role: :info)`](#org5e74284)
|
|
32
|
+
- [`prompt(prompt, initial: "", cancel_value: nil, history_key: nil, save_history: true)`](#org71a56a2)
|
|
33
|
+
- [`check_interrupt!`](#orgd0da92b)
|
|
34
|
+
- [`add_progress(label:, total: nil, style: :percent, role: :info, width: 40)`](#orgfbc8aa5)
|
|
35
|
+
- [Initialization `add_progress(label:, style: :percent, total: nil, role: :info, width: 40)`](#orgd758f7b)
|
|
36
|
+
- [Update `update(current: nil, indicator: nil, render: false)`](#orgbe50f7a)
|
|
37
|
+
- [Finish](#org058be1b)
|
|
38
|
+
- [Clear](#org22e4b8d)
|
|
39
|
+
- [`choose(prompt, choices:, initial_choice_idx: 0, cancel_value: nil)`](#orgcfb56dd)
|
|
40
|
+
- [`choose_multi(prompt, choices:, cancel_value: nil)`](#org5b1d7d1)
|
|
41
|
+
- [`confirm(prompt, yes_label: "Yes", no_label: "No", cancel_value: false)`](#org9b37a8e)
|
|
42
|
+
- [`menu(prompt, choices:, initial_choice_idx: 0, cancel_value: nil)`](#org8d63dae)
|
|
43
|
+
- [`environment`](#org1750b9e)
|
|
44
|
+
- [Default Interaction](#org727ceaf)
|
|
45
|
+
- [Parts of the Screen](#orgd560bdc)
|
|
46
|
+
- [Input Field](#org6ae09c7)
|
|
47
|
+
- [Output Pane](#org73b9106)
|
|
48
|
+
- [Status Area](#orga48a015)
|
|
49
|
+
- [Alert Area](#org5098d11)
|
|
50
|
+
- [Command-line Editing](#org2926c89)
|
|
51
|
+
- [Input Context](#orgbcdaaad)
|
|
52
|
+
- [Cursor Motion](#org1af96be)
|
|
53
|
+
- [Clearing](#org32a2afa)
|
|
54
|
+
- [Undo and Redo](#org72cce5e)
|
|
55
|
+
- [Deletion and Killing](#org5ac8fea)
|
|
56
|
+
- [Yanking, Mark, and Region](#org948d8d5)
|
|
57
|
+
- [Count Prefix](#orgb998032)
|
|
58
|
+
- [History Navigation](#org30cf355)
|
|
59
|
+
- [Completion](#org0c995ec)
|
|
60
|
+
- [Accept or Cancel](#orgf4edfcc)
|
|
61
|
+
- [Paging Context](#org8d58d09)
|
|
62
|
+
- [Searching Output](#org89f3027)
|
|
63
|
+
- [String and Regex Search](#org77137d8)
|
|
64
|
+
- [Incremental Search](#orgd90c796)
|
|
65
|
+
- [Configuration](#orgc8458e1)
|
|
66
|
+
- [General Configuration `config.yml`](#org0add8c9)
|
|
67
|
+
- [`word_char_re`](#org1099eb8)
|
|
68
|
+
- [`esc_delay`](#orgce3e466)
|
|
69
|
+
- [`history`](#org95b5e48)
|
|
70
|
+
- [`file`](#orgdc30f58)
|
|
71
|
+
- [`max`](#org0941468)
|
|
72
|
+
- [`theme`](#orgce1b37d)
|
|
73
|
+
- [`truecolor`](#orgdd529bd)
|
|
74
|
+
- [`log`](#org2b58449)
|
|
75
|
+
- [`file`](#org0e3b938)
|
|
76
|
+
- [`level`](#org9c70445)
|
|
77
|
+
- [`tags`](#orge47f304)
|
|
78
|
+
- [Key code definitions `keydefs.yml`](#org220de42)
|
|
79
|
+
- [Key bindings `keybindings.yml`](#orgbd79429)
|
|
80
|
+
- [Key Names](#org698f2a9)
|
|
81
|
+
- [Printable Keys](#org58581e4)
|
|
82
|
+
- [Curses and Fatty Named Keys](#org4b0cf5b)
|
|
83
|
+
- [Possibly Invisible Keys](#orgeab9ebe)
|
|
84
|
+
- [Unnamed but Recognized Keys](#orgde02d1d)
|
|
85
|
+
- [Mouse Events](#orge487bc7)
|
|
86
|
+
- [Modifiers](#orgcf36a39)
|
|
87
|
+
- [Contexts](#orgc29aad9)
|
|
88
|
+
- [Actions](#orgdb5aa78)
|
|
89
|
+
- [Input buffer actions](#orgf51a408)
|
|
90
|
+
- [Input field actions](#org3f876b8)
|
|
91
|
+
- [Shell session actions](#orge0c4e6e)
|
|
92
|
+
- [Pager actions](#org05813c6)
|
|
93
|
+
- [Pager search actions](#orgea58518)
|
|
94
|
+
- [Popup actions](#org6ea9ecc)
|
|
95
|
+
- [Prompt popup actions](#org8f3d6dc)
|
|
96
|
+
- [Utility Actions](#org4a9e2d4)
|
|
97
|
+
- [Themes `themes/`](#org7e9ed87)
|
|
98
|
+
- [Distributed Themes](#orgf951ab7)
|
|
99
|
+
- [Custom Themes](#orgcf6fbb1)
|
|
100
|
+
- [Theme Name](#orgb8ead89)
|
|
101
|
+
- [Inheritance from Another Theme](#orgc49dfe9)
|
|
102
|
+
- [Inheritance within a Theme](#org371d3bb)
|
|
103
|
+
- [Theme Roles](#org83d0479)
|
|
104
|
+
- [Role Colors and Attributes and Frame Style](#orgabf70f2)
|
|
4
105
|
|
|
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
106
|
|
|
12
|
-
[](https://github.com/ddoherty03/fatty/actions/workflows/main.yml)
|
|
13
107
|
|
|
108
|
+
<a id="org92a02ab"></a>
|
|
109
|
+
|
|
110
|
+
# Introduction
|
|
111
|
+
|
|
112
|
+
`Fatty` aims to provide a full-featured command-line environment that provides:
|
|
113
|
+
|
|
114
|
+
1. an emacs-like editing command-line input, including undo/redo and kill/yank
|
|
115
|
+
2. a history facility,
|
|
116
|
+
3. command completion,
|
|
117
|
+
4. completion of partially-typed file path names,
|
|
118
|
+
5. output into a paging environment,
|
|
119
|
+
6. searching within the paged output,
|
|
120
|
+
7. issuing messages to a "status" area separate from the output pane,
|
|
121
|
+
8. binding keys to pre-defined actions,
|
|
122
|
+
9. defining unrecognized key-codes as named keys,
|
|
123
|
+
10. color themes that can be selected in real time,
|
|
124
|
+
11. a way to define new themes,
|
|
125
|
+
12. processing completed command lines with a callback procedure of your choosing,
|
|
126
|
+
13. several user-interface widgets such as selection popups, text prompts, menus, and progress indicators,
|
|
127
|
+
14. a way to render markdown to the output pane,
|
|
128
|
+
|
|
129
|
+
In other words, fatty allows you to write a terminal-based REPL of your choosing but takes care of all the difficult parts.
|
|
130
|
+
|
|
131
|
+
`Fatty` is written entirely in Ruby and was born from my frustrations at the limitations of libraries like `readline` and `reline`. It uses `curses` and `truecolor` sequences for low-level rendering and is surprisingly snappy.
|
|
132
|
+
|
|
133
|
+
`Fatty` is *not* a terminal emulator but runs on top of one.
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
<a id="orga9758e6"></a>
|
|
137
|
+
|
|
138
|
+
# Quick Start
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
<a id="org5d48af2"></a>
|
|
142
|
+
|
|
143
|
+
## Installing
|
|
144
|
+
|
|
145
|
+
`Fatty` is a ruby gem, so it can be installed with
|
|
146
|
+
|
|
147
|
+
```sh
|
|
148
|
+
$ gem install fatty
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
<a id="orga0811d0"></a>
|
|
153
|
+
|
|
154
|
+
## Trying it Out with the \`fatty\` Demo
|
|
155
|
+
|
|
156
|
+
Once installed, you can try out `fatty` with the included program called `fatty`. It allows you to easily exercise all of the important features of the `fatty` library. At a normal shell prompt simply type `fatty`, and it will launch the `fatty` demo program.
|
|
157
|
+
|
|
158
|
+
Once inside `fatty` you will be prompted with a prompt that names your current directory. Type `help` to get a summary of the builtin commands available to you. If you type anything other than a builtin command, `fatty` attempts to run it as a shell command and displays the output.
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
<a id="org10b740e"></a>
|
|
162
|
+
|
|
163
|
+
### Builtin commands
|
|
164
|
+
|
|
165
|
+
Here are the commands builtin to `fatty`
|
|
166
|
+
|
|
167
|
+
| Command | Description |
|
|
168
|
+
|--------------------------- |----------------------------------------------------------------------- |
|
|
169
|
+
| help | Display this file on the output pane |
|
|
170
|
+
| cd | Change the current directory used by the shell |
|
|
171
|
+
| choose | Present a series of choices in a popup window |
|
|
172
|
+
| choosevals | Also present choices in a popup window but return an associated value |
|
|
173
|
+
| choose\_multi | Present choices with a "checkbox" for selecting multiple values |
|
|
174
|
+
| choosevals\_multi | Also present a checkbox but return associated values |
|
|
175
|
+
| menu | Present a menu of labeled routines to run |
|
|
176
|
+
| info | Display an "info" message on the status line |
|
|
177
|
+
| good | Display a "good" message colored to indicate success |
|
|
178
|
+
| warn | Display a "warn" message colored to indicate caution |
|
|
179
|
+
| oops | Display an "oops" message colored to indicate failure |
|
|
180
|
+
| interrupt | Test fatty's interrupt handling |
|
|
181
|
+
| prompt | Popup a text box for entering a value in response to a prompt |
|
|
182
|
+
| progress count <N> | Display an animated progress indicator counting up to 40 or the given N |
|
|
183
|
+
| progress percent <N> | Same but also show the percent complete |
|
|
184
|
+
| progress count\_percent <N> | Same but show both count and the percent complete |
|
|
185
|
+
| progress trail | Show progress by displaying an "indicator" character for each step |
|
|
186
|
+
| progress bar | Show progress by a filling bar using ASCII characters |
|
|
187
|
+
| progress unicode\_bar | Same, but using unicode characters |
|
|
188
|
+
| progress braille\_bar | Same, but using braille characters |
|
|
189
|
+
| progress spinner | Animate a "spinner" showing a busy state |
|
|
190
|
+
| markdown <file.md> | Render the markdown file to the output pane; defaults to a demo file |
|
|
191
|
+
| keytest | Enter key diagnostic mode to report keycodes, key names, and bindings |
|
|
192
|
+
| colors | Display ANSI, 256-color, and X11 color diagnostics |
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
<a id="orga21015c"></a>
|
|
196
|
+
|
|
197
|
+
### Screenshots
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
<a id="orge811242"></a>
|
|
201
|
+
|
|
202
|
+
#### Command line editing
|
|
203
|
+
|
|
204
|
+
Here is the command line, mid-edit showing a region selected and, in dim text to the right, a predictive completion based on history.
|
|
205
|
+
|
|
206
|
+

|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
<a id="org86db3fd"></a>
|
|
210
|
+
|
|
211
|
+
#### Searchable Output
|
|
212
|
+
|
|
213
|
+
While paging output, you can search for words, as here the user searches for the word `tty` in the output. The current match is highlighted in yellow with other matches highlighted in gray. The paging status line shows the search term and the direction of search. The user can navigate for other matches in the output using `n` and `N`.
|
|
214
|
+
|
|
215
|
+

|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
<a id="org465e882"></a>
|
|
219
|
+
|
|
220
|
+
#### Paging Markdown
|
|
221
|
+
|
|
222
|
+
The `fatty` demo running the `markdown` command and paging the output. It shows `fatty's` ability to render markdown using ANSI codes, including colorizing code blocks, as well as its paging interface.
|
|
223
|
+
|
|
224
|
+

|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
<a id="orged601b1"></a>
|
|
228
|
+
|
|
229
|
+
#### Popup Selection
|
|
230
|
+
|
|
231
|
+
One of the many "widgets" available through `fatty` is the ability to present the user with a set of choices to select from. After running the demo's `choose "AAA" "BBB" "CCC" "DDD" "EEE"`
|
|
232
|
+
|
|
233
|
+

|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
<a id="org0fbc008"></a>
|
|
237
|
+
|
|
238
|
+
# Usage
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
<a id="orgdd7a899"></a>
|
|
242
|
+
|
|
243
|
+
## Launching a Fatty Terminal
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
<a id="orge36ae8e"></a>
|
|
247
|
+
|
|
248
|
+
### `on_accept`
|
|
249
|
+
|
|
250
|
+
You can launch a `Fatty` terminal session that does arbitrary processing of an edited command line and returns a String to be displayed on the output pane by providing an `on_accept` proc as a parameter as shown in this file that we'll call `loudrev`:
|
|
251
|
+
|
|
252
|
+
```ruby
|
|
253
|
+
#! /usr/bin/env ruby
|
|
254
|
+
# -*- mode: ruby -*-
|
|
255
|
+
|
|
256
|
+
require 'fatty'
|
|
257
|
+
|
|
258
|
+
loud_reversal = lambda do |line|
|
|
259
|
+
line.upcase.reverse
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
Fatty::Terminal.new(
|
|
263
|
+
on_accept: loud_reversal,
|
|
264
|
+
).go
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Now you have an interactive application that allows you to type text and see what it looks like when written backwards in uppercase letters. It's as easy as that!
|
|
268
|
+
|
|
269
|
+
When a `fatty` application runs, `fatty` installs a few files if they do not exist:
|
|
270
|
+
|
|
271
|
+
- a history file at `~/.fatty_history`
|
|
272
|
+
- a config directory at `~/.config/fatty` that contains
|
|
273
|
+
- `config.yml`, the main configuration file
|
|
274
|
+
- `keydefs.yml`, a file for associating keycodes emitted by the underlying terminal with names when curses does not do so automatically,
|
|
275
|
+
- `keybindings.yml`, a file for associating named keys with actions above and beyond the emacs bindings that are used by default, and
|
|
276
|
+
- `themes`, a directory of pre-defined theme definitions that you can choose from and add to by adding your own themes.
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
<a id="org74e77b2"></a>
|
|
280
|
+
|
|
281
|
+
#### Parameters to `on_accept`
|
|
282
|
+
|
|
283
|
+
The `on_accept` proc passed to an instance of `Fatty::Terminal` can take one or two parameters: (1) `line`, the edited line as it exists when the user types `RETURN` and (2) an optional callback parameter that you can use to access the facilities of `fatty`.
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
<a id="org21b8961"></a>
|
|
287
|
+
|
|
288
|
+
#### The `line` parameter to `on_accept`
|
|
289
|
+
|
|
290
|
+
`Fatty` does not parse command lines for your application. When the user accepts a `line`, `Fatty` passes the line to `on_accept` as text. It is up to your callback to decide whether to strip whitespace, split words, interpret quotes, parse options, recognize subcommands, or treat punctuation specially.
|
|
291
|
+
|
|
292
|
+
This keeps `Fatty` useful for many different kinds of REPLs. Some applications want shell-like parsing. Others want to preserve the user's input exactly.
|
|
293
|
+
|
|
294
|
+
For shell-like parsing, Ruby's standard `Shellwords` library is often useful:
|
|
295
|
+
|
|
296
|
+
```ruby
|
|
297
|
+
#! /usr/bin/env ruby
|
|
298
|
+
# -*- mode: ruby -*-
|
|
299
|
+
|
|
300
|
+
require 'fatty'
|
|
301
|
+
require 'shellwords'
|
|
302
|
+
|
|
303
|
+
runner = lambda do |line, fatty|
|
|
304
|
+
words = Shellwords.split(line)
|
|
305
|
+
|
|
306
|
+
case words
|
|
307
|
+
when ["echo", *rest]
|
|
308
|
+
fatty.append("#{rest.join(" ")}\n")
|
|
309
|
+
when ["count", *rest]
|
|
310
|
+
fatty.append("#{rest.length}\n")
|
|
311
|
+
when []
|
|
312
|
+
fatty.status("Blank line", role: :info)
|
|
313
|
+
else
|
|
314
|
+
fatty.alert("Unknown command: #{words.first}", role: :warn)
|
|
315
|
+
end
|
|
316
|
+
rescue ArgumentError => e
|
|
317
|
+
fatty.alert("Could not parse line: #{e.message}", role: :error)
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
Fatty::Terminal.new(
|
|
321
|
+
prompt: "shellwords> ",
|
|
322
|
+
on_accept: runner,
|
|
323
|
+
).go
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
<a id="org3091db0"></a>
|
|
328
|
+
|
|
329
|
+
#### The callback parameter to `on_accept`
|
|
330
|
+
|
|
331
|
+
The `on_accept` proc can have a second parameter named whatever you like that serves as a callback into certain facilities provided by `fatty`. In this README we use the name `fatty` for the callback parameter since it provides access to the facilities provided by the `fatty` library. Here is a variation of the prior example that also echoes the original typed string into the so-called status area:
|
|
332
|
+
|
|
333
|
+
```ruby
|
|
334
|
+
#! /usr/bin/env ruby
|
|
335
|
+
# -*- mode: ruby -*-
|
|
336
|
+
|
|
337
|
+
require 'fatty'
|
|
338
|
+
|
|
339
|
+
loud_reversal = lambda do |line, fatty|
|
|
340
|
+
fatty.good(line)
|
|
341
|
+
line.upcase.reverse
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
Fatty::Terminal.new(
|
|
345
|
+
on_accept: loud_reversal,
|
|
346
|
+
).go
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
The callback parameter responds to several methods that allow your application to interact with the user. They are documented below.
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
<a id="orgcd415d8"></a>
|
|
353
|
+
|
|
354
|
+
#### Output ordering
|
|
355
|
+
|
|
356
|
+
The `on_accept` callback can send text to the output pane in three ways:
|
|
357
|
+
|
|
358
|
+
1. by returning a value from the callback;
|
|
359
|
+
2. by calling `append` or `markdown` on the callback environment; or
|
|
360
|
+
3. by calling `append_now` on the callback environment.
|
|
361
|
+
|
|
362
|
+
A returned `String` is the simplest output mechanism. It is displayed after the callback finishes:
|
|
363
|
+
|
|
364
|
+
```ruby
|
|
365
|
+
Fatty::Terminal.new(
|
|
366
|
+
on_accept: ->(line) { line.upcase.reverse },
|
|
367
|
+
).go
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Calls to `append` and `markdown` also queue output until the callback finishes. If a callback both calls `append` or `markdown` and returns a `String`, the queued output is displayed first and the returned string is displayed after it.
|
|
371
|
+
|
|
372
|
+
Calls to `append_now` are different. They append text and immediately render a frame, so the user can see output while the callback is still running. Use `append_now` for long-running callbacks that should stream progress to the output pane.
|
|
373
|
+
|
|
374
|
+
At the end of the callback, `Fatty` finishes the command and updates the pager state. Output produced with `append_now` may therefore appear during the callback, while output from `append`, `markdown`, and the callback's return value appears after the callback returns.
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
<a id="org0d9a504"></a>
|
|
378
|
+
|
|
379
|
+
#### Long-running callbacks and interruption
|
|
380
|
+
|
|
381
|
+
The `on_accept` callback runs synchronously. While it is running, control does not return to Fatty's normal event loop. A callback that performs lengthy work should therefore provide explicit safe points at which the user may interrupt it:
|
|
382
|
+
|
|
383
|
+
```ruby
|
|
384
|
+
runner = lambda do |_line, fatty|
|
|
385
|
+
records.find_each do |record|
|
|
386
|
+
process(record)
|
|
387
|
+
fatty.check_interrupt!
|
|
388
|
+
end
|
|
389
|
+
fatty.good("Processing complete.")
|
|
390
|
+
end
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
The `check_interrupt!` method performs a throttled, nonblocking input check. If the user has typed C-c or C-g, it raises `Fatty::Interrupt`. Fatty catches that exception at the callback boundary, finishes the current command cleanly, and returns to the normal input loop.
|
|
394
|
+
|
|
395
|
+
Calls to `check_interrupt!` should be placed only at points where it is safe to stop the application work. For example, they can go between records, batches, files, or other complete units of work. Fatty does not interrupt callbacks asynchronously and does not stop threads or raise exceptions at arbitrary instructions.
|
|
396
|
+
|
|
397
|
+
Fast callbacks do not need to call `check_interrupt!`. Long-running callbacks that already update a shared progress facility can often place the check there so that individual commands do not need separate interruption logic.
|
|
398
|
+
|
|
399
|
+
Code that needs to report interruption before allowing Fatty to perform its normal cleanup may rescue and re-raise the exception:
|
|
400
|
+
|
|
401
|
+
```ruby
|
|
402
|
+
begin
|
|
403
|
+
items.each do |item|
|
|
404
|
+
process(item)
|
|
405
|
+
fatty.check_interrupt!
|
|
406
|
+
end
|
|
407
|
+
rescue Fatty::Interrupt
|
|
408
|
+
fatty.warn("Processing interrupted.", replace: true)
|
|
409
|
+
raise
|
|
410
|
+
else
|
|
411
|
+
fatty.good("Processing complete.", replace: true)
|
|
412
|
+
end
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
<a id="org89ae995"></a>
|
|
417
|
+
|
|
418
|
+
#### ANSI colors in output
|
|
419
|
+
|
|
420
|
+
Text passed to `append`, `append_now`, `status`, and `alert` may contain ANSI SGR color/style sequences. Fatty interprets those sequences relative to the current theme role, so an ANSI reset returns to the active Fatty role rather than to the terminal's physical default colors. `fatty` includes the nice [`Rainbow` gem](https://github.com/ku1ik/rainbow) for colorizing text as a convenience.
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
<a id="orgce83cdf"></a>
|
|
424
|
+
|
|
425
|
+
### Other parameters to `Terminal.new`
|
|
426
|
+
|
|
427
|
+
When building a REPL with `Terminal.new` you can also supply several other parameters:
|
|
428
|
+
|
|
429
|
+
- **`prompt:`:** a `String` or a zero-argument callable such as a `Proc` or `lambda` that returns the prompt used for the input line to be edited. Because it can be a callable, it can change after each run of `on_accept`; if not given, it defaults to '> ';
|
|
430
|
+
- **`app_name`:** the name for the "app" using the `fatty` library; this allows app-specific configuration under `~/.config/fatty/apps/<app_name>` or a different directory specified by `app_config_dir`;
|
|
431
|
+
- **`app_config_dir`:** an alternative directory for app-specific configuration instead of the default;
|
|
432
|
+
- **`completion_proc`:** a callable that takes the current text of the input field's buffer and returns an `Array` of possible completions at that point in the input; by default, there is no completion proc;
|
|
433
|
+
- **`history_path`:** a `String` for the file path where command history is loaded from and saved. The default, `:default`, uses `history.file` from Fatty's configuration, falling back to `~/.fatty_history` if no history file is configured. Passing `nil` or `false` disables persistent history and keeps history in memory only. Passing a string uses that path directly.
|
|
434
|
+
- **`history_ctx`:** optional history context used to prefer relevant history entries. It may be a hash or a callable returning a hash. The context is stored in the history file with each accepted line and is used by history navigation and history autosuggestions. Matching context entries are preferred, but history is not strictly partitioned; Fatty can still fall back to other entries. This is useful when the same application wants different history behavior in different directories, ledgers, projects, modes, or accounts.
|
|
435
|
+
|
|
436
|
+
For example, the `fatty` demo executable uses the current working directory as history context:
|
|
437
|
+
|
|
438
|
+
```ruby
|
|
439
|
+
Fatty::Terminal.new(
|
|
440
|
+
history_ctx: -> { { pwd: Dir.pwd } },
|
|
441
|
+
on_accept: ->(line, env) {
|
|
442
|
+
# ...
|
|
443
|
+
},
|
|
444
|
+
).go
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
With that setup, commands entered in `~/src/byr` are favored when the terminal is again in `~/src/byr`, while commands entered elsewhere remain available as fallback history.
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
<a id="orgef3914d"></a>
|
|
451
|
+
|
|
452
|
+
## The Callback API
|
|
453
|
+
|
|
454
|
+
Here are the details on the messages that you can send to the callback parameter to the `on_accept` proc.
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
<a id="org1f2fcbb"></a>
|
|
458
|
+
|
|
459
|
+
### `append(text, follow: true)`
|
|
460
|
+
|
|
461
|
+
Add the given text to the output pane. After a full page of output is produced, enter paging mode so the user can view the output at leisure and search the output. If `follow` is true, keep the output pane's viewport covering the last lines of output.
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
<a id="org3318ee2"></a>
|
|
465
|
+
|
|
466
|
+
### `append_now(text, follow: true, mode: nil)`
|
|
467
|
+
|
|
468
|
+
Like `append`, but display output as it is produced rather than wait for a full page to be produced.
|
|
469
|
+
|
|
470
|
+
Setting the mode to `:scrolling` or `:paging` determines whether the output is scrolled continuously or paused on each page of output.
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
<a id="org3da5738"></a>
|
|
474
|
+
|
|
475
|
+
### `markdown(text)`
|
|
476
|
+
|
|
477
|
+
Render the given text as markdown source according to the current theme then `append` the result to the output pane.
|
|
478
|
+
|
|
479
|
+
We will not rehearse here how to compose markdown, but one thing that is a bit special with `fatty` is forcing a line break: you should use `<br>` to force a line break in the middle of a line.
|
|
480
|
+
|
|
481
|
+
```
|
|
482
|
+
This line has a forced line break <br> and this should appear on the next line.
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
will render as
|
|
486
|
+
|
|
487
|
+
```
|
|
488
|
+
This line has a forced line break
|
|
489
|
+
and this should appear on the next line.
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
<a id="org5e0ab5d"></a>
|
|
494
|
+
|
|
495
|
+
### `status(text, role: :info)`
|
|
496
|
+
|
|
497
|
+
Display the text in the "status" area, the lines immediately above the input field, using one of the following "roles":
|
|
498
|
+
|
|
499
|
+
- **:good:** colored to indicate something affirming according to the theme, usually something greenish;
|
|
500
|
+
- **:info:** colored something neutral simply for informational purposes;
|
|
501
|
+
- **:warn:** colored something to suggest caution, usually something in the orange to yellow range;
|
|
502
|
+
- **:error:** colored something to suggest danger, usually some tone of red.
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
<a id="orgd2a8b1b"></a>
|
|
506
|
+
|
|
507
|
+
### `good(text, replace: false, render: true)`
|
|
508
|
+
|
|
509
|
+
Display the text in the status area with the role :good.
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
<a id="org8ec7886"></a>
|
|
513
|
+
|
|
514
|
+
### `info(text, replace: false, render: true)`
|
|
515
|
+
|
|
516
|
+
Display the text in the status area with the role :info.
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
<a id="org6bb2e02"></a>
|
|
520
|
+
|
|
521
|
+
### `warn(text, replace: false, render: true)`
|
|
522
|
+
|
|
523
|
+
Display the text in the status area with the role :warn.
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
<a id="org6040c43"></a>
|
|
527
|
+
|
|
528
|
+
### `error(text, replace: false, render: true)`
|
|
529
|
+
|
|
530
|
+
Display the text in the status area with the role :error.
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
<a id="org3e60ade"></a>
|
|
534
|
+
|
|
535
|
+
### `oops(text, replace: false, render: true)`
|
|
536
|
+
|
|
537
|
+
An alias for `error(text)`
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
<a id="org5e74284"></a>
|
|
541
|
+
|
|
542
|
+
### `alert(text, role: :info)`
|
|
543
|
+
|
|
544
|
+
Display the text in the one-line alert panel just below the input field. In the alert panel, the role only controls the foreground color, not the background.
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
<a id="org71a56a2"></a>
|
|
548
|
+
|
|
549
|
+
### `prompt(prompt, initial: "", cancel_value: nil, history_key: nil, save_history: true)`
|
|
550
|
+
|
|
551
|
+
Display a popup dialog box that allows the user to type in any string and return it. Combine the input line with a prompted-for string and shuffle their letters together:
|
|
552
|
+
|
|
553
|
+
```ruby
|
|
554
|
+
#! /usr/bin/env -S ruby -Ilib
|
|
555
|
+
# -*- mode: ruby -*-
|
|
556
|
+
|
|
557
|
+
require 'fatty'
|
|
558
|
+
|
|
559
|
+
weaver = lambda do |line, fatty|
|
|
560
|
+
str = fatty.prompt("Secondary string to weave in with '#{line}'")
|
|
561
|
+
(line + str).downcase.gsub(/[^a-z]/, '').split('').shuffle.join
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
Fatty::Terminal.new(
|
|
565
|
+
on_accept: weaver,
|
|
566
|
+
prompt: "Primary String> "
|
|
567
|
+
).go
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
You can pre-fill the prompt's input line by passing in an `initial:` parameter.
|
|
571
|
+
|
|
572
|
+
The `prompt` input has its own history facility separate from the history in the main input command line. You can turn it off by setting `save_history` to `false`.
|
|
573
|
+
|
|
574
|
+
`prompt` returns whatever the user typed and returns `nil` if the user cancels with C-c or C-g unless you specify an alternative `cancel_value`.
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
<a id="orgd0da92b"></a>
|
|
578
|
+
|
|
579
|
+
### `check_interrupt!`
|
|
580
|
+
|
|
581
|
+
Provide a cooperative interruption point during a long-running `on_accept` callback. Fatty periodically performs a nonblocking input check and raises `Fatty::Interrupt` if the user has typed C-c or C-g.
|
|
582
|
+
|
|
583
|
+
The polling is throttled, so `check_interrupt!` may be called frequently. It should nevertheless be called only at points where the callback can safely stop its work.
|
|
584
|
+
|
|
585
|
+
Fatty catches `Fatty::Interrupt` at the callback boundary, finishes the current command, restores the terminal state, and resumes the normal input loop.
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
<a id="orgfbc8aa5"></a>
|
|
589
|
+
|
|
590
|
+
### `add_progress(label:, total: nil, style: :percent, role: :info, width: 40)`
|
|
591
|
+
|
|
592
|
+
Display a progress widget in the status area to show the user that the system is working, not frozen. The `add_progress` method returns a `Progress` object on which the `#update` method can be called to cause it to animate one step. To the left of the widget the `label:` is displayed, followed by the widget. For processes where the total size is known in advance, the `total:` parameter indicates that size. The `role:` parameter controls the styling of the widget. The `width:` parameter places a limit on the size of the widget. `Fatty` supports several styles of progress widgets:
|
|
593
|
+
|
|
594
|
+
- **:spinner:** a simple busy-wait indicator that just animates on every call;
|
|
595
|
+
- **:count:** count up to `total` on each call of `update(current: <count>)`
|
|
596
|
+
- **:percent:** count up to percent of `total` on each call of `update(current: <count>)`
|
|
597
|
+
- **:count\_percent:** count up and show percent of `total` on each call of `update(current: <count>)`
|
|
598
|
+
- **:bar:** display a filling ASCII progress bar with percent and count
|
|
599
|
+
- **:unicode\_bar:** display a filling Unicode progress bar with percent and count
|
|
600
|
+
- **:braille\_bar:** display a filling progress bar with percent and count using braille characters
|
|
601
|
+
- **:trail:** display an "indicator" on each call of `update(indicator: <string>)`
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
<a id="orgd758f7b"></a>
|
|
605
|
+
|
|
606
|
+
#### Initialization `add_progress(label:, style: :percent, total: nil, role: :info, width: 40)`
|
|
607
|
+
|
|
608
|
+
- **`label:`:** Text displayed before the progress widget, "Progress" by default.
|
|
609
|
+
- **`style:`:** The style of the progress widget from one of those named above.
|
|
610
|
+
- **`total:`:** For all styles except :trail and :spinner, the number that represents the size of the task. As the `#update` calls increase the value of `current` towards `total`, the widget indicates increasing completion.
|
|
611
|
+
- **`role:`:** One of :good, :info, :warn, or :error to color the widget according to the theme's idea of these roles. By default, :info.
|
|
612
|
+
- **`width`:** The number of characters for the full widget display: it is only relevant for the bar styles and the trail style; otherwise it is ignored.
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
<a id="orgbe50f7a"></a>
|
|
616
|
+
|
|
617
|
+
#### Update `update(current: nil, indicator: nil, render: false)`
|
|
618
|
+
|
|
619
|
+
You update the progress widget by calling `#update` on the Progress object, passing as the `current:` parameter a number that indicates progress so far.
|
|
620
|
+
|
|
621
|
+
```ruby
|
|
622
|
+
#! /usr/bin/env -S ruby -Ilib
|
|
623
|
+
# -*- mode: ruby -*-
|
|
624
|
+
|
|
625
|
+
require 'fatty'
|
|
626
|
+
require 'prime'
|
|
627
|
+
|
|
628
|
+
primer = lambda do |input, fatty|
|
|
629
|
+
if input.match?(/\A[1-9]\d*\z/)
|
|
630
|
+
k = input.to_i
|
|
631
|
+
prog = fatty.add_progress(label: "Thinking...", total: k, style: :bar)
|
|
632
|
+
out_line = +""
|
|
633
|
+
num_primes = 0
|
|
634
|
+
Prime.each do |p|
|
|
635
|
+
num_primes += 1
|
|
636
|
+
out = "#{p} "
|
|
637
|
+
|
|
638
|
+
if out_line.length + out.length > 100
|
|
639
|
+
fatty.append_now("#{out_line}\n", mode: :scrolling)
|
|
640
|
+
out_line.clear
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
out_line << out
|
|
644
|
+
prog.update(current: num_primes)
|
|
645
|
+
break if num_primes >= k
|
|
646
|
+
end
|
|
647
|
+
fatty.append_now("#{out_line}\n", mode: :scrolling) unless out_line.empty?
|
|
648
|
+
prog.finish("Done")
|
|
649
|
+
else
|
|
650
|
+
fatty.alert "Give me a positive integer", role: :error
|
|
651
|
+
end
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
Fatty::Terminal.new(
|
|
655
|
+
on_accept: primer,
|
|
656
|
+
prompt: 'How many primes? ',
|
|
657
|
+
).go
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
For the trail-style progress, you can use an arbitrary string to indicate progress by adding an `indicator:` parameter to the `#update` call.
|
|
661
|
+
|
|
662
|
+
Suppose, for example, you wanted to print a trail in which the last digit of the prime is displayed to indicate progress and colored so it stands out:
|
|
663
|
+
|
|
664
|
+
```ruby
|
|
665
|
+
#! /usr/bin/env -S ruby -Ilib
|
|
666
|
+
# -*- mode: ruby -*-
|
|
667
|
+
|
|
668
|
+
require 'fatty'
|
|
669
|
+
require 'prime'
|
|
670
|
+
require "rainbow/refinement"
|
|
671
|
+
|
|
672
|
+
using Rainbow
|
|
673
|
+
|
|
674
|
+
primer = lambda do |input, fatty|
|
|
675
|
+
if input.match?(/\A[1-9]\d*\z/)
|
|
676
|
+
k = input.to_i
|
|
677
|
+
prog = fatty.add_progress(label: "Thinking...", total: k, style: :trail, width: 100)
|
|
678
|
+
out_line = +""
|
|
679
|
+
num_primes = 0
|
|
680
|
+
Prime.each do |p|
|
|
681
|
+
num_primes += 1
|
|
682
|
+
out = "#{p} "
|
|
683
|
+
|
|
684
|
+
if out_line.length + out.length > 100
|
|
685
|
+
fatty.append_now("#{out_line}\n", mode: :scrolling)
|
|
686
|
+
out_line.clear
|
|
687
|
+
end
|
|
688
|
+
|
|
689
|
+
out_line << out
|
|
690
|
+
last_dig = p.to_s.split('').last
|
|
691
|
+
sig =
|
|
692
|
+
case last_dig
|
|
693
|
+
when '1'
|
|
694
|
+
last_dig.red
|
|
695
|
+
when '3'
|
|
696
|
+
last_dig.blue
|
|
697
|
+
when '7'
|
|
698
|
+
last_dig.green
|
|
699
|
+
when '9'
|
|
700
|
+
last_dig.yellow
|
|
701
|
+
else
|
|
702
|
+
'!'
|
|
703
|
+
end
|
|
704
|
+
prog.update(current: num_primes, indicator: sig)
|
|
705
|
+
break if num_primes >= k
|
|
706
|
+
end
|
|
707
|
+
fatty.append_now("#{out_line}\n", mode: :scrolling) unless out_line.empty?
|
|
708
|
+
prog.finish("Done")
|
|
709
|
+
else
|
|
710
|
+
fatty.alert "Give me a positive integer", role: :error
|
|
711
|
+
end
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
Fatty::Terminal.new(
|
|
715
|
+
on_accept: primer,
|
|
716
|
+
prompt: 'How many primes? ',
|
|
717
|
+
).go
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
<a id="org058be1b"></a>
|
|
722
|
+
|
|
723
|
+
#### Finish
|
|
724
|
+
|
|
725
|
+
As the prior examples illustrate, you can issue an ending message at the end of the process by calling `#finish` on the Progress object.
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
<a id="org22e4b8d"></a>
|
|
729
|
+
|
|
730
|
+
#### Clear
|
|
731
|
+
|
|
732
|
+
And, if you have occasion, you can clear the Progress by calling `#clear` on the Progress object.
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
<a id="orgcfb56dd"></a>
|
|
736
|
+
|
|
737
|
+
### `choose(prompt, choices:, initial_choice_idx: 0, cancel_value: nil)`
|
|
738
|
+
|
|
739
|
+
Present a set of `choices:`, which can be either:
|
|
740
|
+
|
|
741
|
+
- an `Array` of `String` choices, where the selected string is returned; or
|
|
742
|
+
- a `Hash` whose keys are converted to `String` labels and whose values are returned.
|
|
743
|
+
|
|
744
|
+
`choose` returns:
|
|
745
|
+
|
|
746
|
+
- the selected `String` when `choices:` is an `Array`;
|
|
747
|
+
- the associated value when `choices:` is a `Hash`; or
|
|
748
|
+
- `cancel_value` when the user cancels with C-c or C-g.
|
|
749
|
+
|
|
750
|
+
The `prompt` String (by default "Choose") can guide the user about the purpose of the choices.
|
|
751
|
+
|
|
752
|
+
If you want to set one of the choices as the initial choice, set `initial_choice_idx:` to the Integer index of one of the choices.
|
|
753
|
+
|
|
754
|
+
If you want a value associated with the user's cancellation of the chooser with C-c or C-g, set `cancel_value:` to that value.
|
|
755
|
+
|
|
756
|
+
With an Array of Strings:
|
|
757
|
+
|
|
758
|
+
```ruby
|
|
759
|
+
#! /usr/bin/env -S ruby -Ilib
|
|
760
|
+
# -*- mode: ruby -*-
|
|
761
|
+
|
|
762
|
+
require 'fatty'
|
|
763
|
+
|
|
764
|
+
rgb = lambda do |_line, fatty|
|
|
765
|
+
color = fatty.choose(
|
|
766
|
+
"Choose a color",
|
|
767
|
+
choices: ["red", "green", "blue"],
|
|
768
|
+
)
|
|
769
|
+
fatty.status("If you say so: #{Rainbow(color).send(color.to_sym)} it is!\n")
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
Fatty::Terminal.new(
|
|
773
|
+
prompt: "Hit RETURN to choose a color> ",
|
|
774
|
+
on_accept: rgb,
|
|
775
|
+
).go
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
Or with a Hash:
|
|
779
|
+
|
|
780
|
+
```ruby
|
|
781
|
+
#! /usr/bin/env -S ruby -Ilib
|
|
782
|
+
# -*- mode: ruby -*-
|
|
783
|
+
|
|
784
|
+
require 'fatty'
|
|
785
|
+
|
|
786
|
+
nums = lambda do |_line, fatty|
|
|
787
|
+
const = fatty.choose(
|
|
788
|
+
"Choose a constant",
|
|
789
|
+
choices: { "Pi" => 3.14159, "Euler" => 2.718281828, "Golden Ratio" => 1.61803398875 }
|
|
790
|
+
)
|
|
791
|
+
fatty.status("Somewhere around #{const}\n")
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
Fatty::Terminal.new(
|
|
795
|
+
prompt: "Hit RETURN to choose a constant> ",
|
|
796
|
+
on_accept: nums,
|
|
797
|
+
).go
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
<a id="org5b1d7d1"></a>
|
|
802
|
+
|
|
803
|
+
### `choose_multi(prompt, choices:, cancel_value: nil)`
|
|
804
|
+
|
|
805
|
+
Present a set of `choices:`, which can either be
|
|
806
|
+
|
|
807
|
+
- an Array whose items are converted to `Strings` and presented as choices
|
|
808
|
+
- a Hash whose keys converted to `Strings` and presented as choices
|
|
809
|
+
|
|
810
|
+
`choose_multi` returns
|
|
811
|
+
|
|
812
|
+
- a `Hash` whose keys and values are the user's selections if `choices:` was an `Array` of `Strings`,
|
|
813
|
+
- a `Hash` whose keys and values are those selected from the `choices:` `Hash` if `choices:` was an `Hash`,
|
|
814
|
+
- or the `cancel_value` if the user canceled the selection with C-c or C-g.
|
|
815
|
+
|
|
816
|
+
The `prompt` String (by default "Choose Many") can guide the user about the purpose of the choices.
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
<a id="org9b37a8e"></a>
|
|
820
|
+
|
|
821
|
+
### `confirm(prompt, yes_label: "Yes", no_label: "No", cancel_value: false)`
|
|
822
|
+
|
|
823
|
+
Present the user with a simple Yes/No choice using your choice of ways to express "Yes" or "No" with `yes_label:` and `no_label:`.
|
|
824
|
+
|
|
825
|
+
`confirm` returns `true` for "Yes" and `false` for "No."
|
|
826
|
+
|
|
827
|
+
`confirm` will return `false` on cancellation with C-c or C-g unless you provide an alternative `cancel_value:`, in which case it returns that.
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
<a id="org8d63dae"></a>
|
|
831
|
+
|
|
832
|
+
### `menu(prompt, choices:, initial_choice_idx: 0, cancel_value: nil)`
|
|
833
|
+
|
|
834
|
+
Present the user with a set of `choices:` representing actions to execute.
|
|
835
|
+
|
|
836
|
+
`choices:` is a `Hash` whose keys are labels presented to the user and whose values are procs, lambdas, or other objects that respond to `#call`.
|
|
837
|
+
|
|
838
|
+
```ruby
|
|
839
|
+
#! /usr/bin/env -S ruby -Ilib
|
|
840
|
+
# -*- mode: ruby -*-
|
|
841
|
+
|
|
842
|
+
require 'fatty'
|
|
843
|
+
|
|
844
|
+
asker = lambda do |_line, fatty|
|
|
845
|
+
result = fatty.menu(
|
|
846
|
+
"Pick an action",
|
|
847
|
+
choices: {
|
|
848
|
+
"Self Echo" => ->(fatty, label) {
|
|
849
|
+
fatty.append("You chose #{label}\n")
|
|
850
|
+
:echoed
|
|
851
|
+
},
|
|
852
|
+
"Say Hello" => ->(fatty, _label) {
|
|
853
|
+
name = fatty.prompt("Name?")
|
|
854
|
+
fatty.append("Hello, #{name}\n")
|
|
855
|
+
:greeted
|
|
856
|
+
},
|
|
857
|
+
},
|
|
858
|
+
)
|
|
859
|
+
fatty.good(result)
|
|
860
|
+
end
|
|
861
|
+
|
|
862
|
+
Fatty::Terminal.new(
|
|
863
|
+
on_accept: asker,
|
|
864
|
+
prompt: "Type RETURN for some action> ",
|
|
865
|
+
).go
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
Each callable has access to the `CallbackEnvironment`, called `fatty` here and the `String` label that the user selected.
|
|
869
|
+
|
|
870
|
+
Each callable can return a value that the `@on_accept` proc can process as it pleases. In the example, they are printed to the status area.
|
|
871
|
+
|
|
872
|
+
If you want to set one of the choices as the initial choice, set `initial_choice_idx:` to the Integer index of one of the choices.
|
|
873
|
+
|
|
874
|
+
If you want a value associated with the user's cancellation of the chooser with C-c or C-g, set `cancel_value:` to that value.
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
<a id="org1750b9e"></a>
|
|
878
|
+
|
|
879
|
+
### `environment`
|
|
880
|
+
|
|
881
|
+
This returns a `Hash` of runtime conditions detected by `Fatty`:
|
|
882
|
+
|
|
883
|
+
| Key | Description |
|
|
884
|
+
|--------------------- |---------------------------------------------------- |
|
|
885
|
+
| `:arch` | System CPU architecture, e.g., `x86_64` |
|
|
886
|
+
| `:os` | Operating system detected |
|
|
887
|
+
| `:ruby_platform` | Ruby platform, e.g., `x86_64-linux` |
|
|
888
|
+
| `:screen` | Whether the terminal is running under `screen` |
|
|
889
|
+
| `:ssh` | Whether the terminal is running under SSH |
|
|
890
|
+
| `:tmux` | Whether the terminal is running under `tmux` |
|
|
891
|
+
| `:terminal` | Detected underlying terminal, e.g., `kitty` |
|
|
892
|
+
| `:terminal_version` | Version of the terminal, if known |
|
|
893
|
+
| `:term` | The `TERM` terminal type |
|
|
894
|
+
| `:truecolor_detected` | Whether truecolor capability appears to be available |
|
|
895
|
+
| `:truecolor_enabled` | Whether Fatty is actually using truecolor rendering |
|
|
896
|
+
| `:curses` | Runtime curses capabilities and parameters |
|
|
897
|
+
|
|
898
|
+
The environment report also includes a nested `:curses` hash:
|
|
899
|
+
|
|
900
|
+
| Key | Description |
|
|
901
|
+
|------------------- |---------------------------------------------------- |
|
|
902
|
+
| `:started` | Whether curses has been initialized |
|
|
903
|
+
| `:truecolor` | Whether the active curses context is using truecolor |
|
|
904
|
+
| `:key_min` | Lowest keycode with a curses name |
|
|
905
|
+
| `:key_max` | Highest keycode with a curses name |
|
|
906
|
+
| `:lines` | Number of terminal rows available |
|
|
907
|
+
| `:cols` | Number of terminal columns available |
|
|
908
|
+
| `:has_colors` | Whether curses reports color support |
|
|
909
|
+
| `:colors` | Number of colors available to curses |
|
|
910
|
+
| `:color_pairs` | Number of color pairs available to curses |
|
|
911
|
+
| `:can_change_color` | Whether curses can redefine color values |
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
<a id="org727ceaf"></a>
|
|
915
|
+
|
|
916
|
+
# Default Interaction
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
<a id="orgd560bdc"></a>
|
|
920
|
+
|
|
921
|
+
## Parts of the Screen
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
<a id="org6ae09c7"></a>
|
|
925
|
+
|
|
926
|
+
### Input Field
|
|
927
|
+
|
|
928
|
+
Just above the bottom of the screen where all the action takes place: it is a line for editing the input. It displays a prompt followed by an area in which you build the command line using `fatty's` editing facilities.
|
|
929
|
+
|
|
930
|
+
|
|
931
|
+
<a id="org73b9106"></a>
|
|
932
|
+
|
|
933
|
+
### Output Pane
|
|
934
|
+
|
|
935
|
+
Most of the top part of the screen is reserved for displaying whatever output is sent to it with the `on_accept` callback to the `Terminal`. It can render colored ANSI-encoded strings and will page long output so you can view it a page at a time and even search the output.
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
<a id="orga48a015"></a>
|
|
939
|
+
|
|
940
|
+
### Status Area
|
|
941
|
+
|
|
942
|
+
The one to four lines just above the Input Field that displays output to the user that is out of band for the Output Pane. Brief messages of confirmation, warning, or error can be displayed there so as to get the user's immediate attention. Progress bars also render there where their visibility is made prominent.
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
<a id="org5098d11"></a>
|
|
946
|
+
|
|
947
|
+
### Alert Area
|
|
948
|
+
|
|
949
|
+
Alerts are short-lived, non-scrolling messages shown below the input field. They are intended for user-visible conditions that require attention. `Fatty` uses this area to warn the user of unrecognized key codes and of unbound key presses.
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
<a id="org2926c89"></a>
|
|
953
|
+
|
|
954
|
+
## Command-line Editing
|
|
955
|
+
|
|
956
|
+
`fatty` aims to have a full-featured command-line editor for editing a single line of text that is sent to the `on_accept` proc for the `Terminal`. The default keybindings are based on Emacs keybindings, but they are fully customizable. Implementing `vim`-like keybindings is not currently possible because `fatty` has no notion of editing "modes" as would be required for any kind of a modal editor—at least not yet. Maybe some day.
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
<a id="orgbcdaaad"></a>
|
|
960
|
+
|
|
961
|
+
### Input Context
|
|
962
|
+
|
|
963
|
+
When editing the input line or text input for widgets like the \`prompt\`, \`fatty\` provides emacs-like editing keybindings by default. Many of these commands can take a count prefix argument to repeat the command count times. For example, \`M-8 M-0 #\` will insert 80 '#' characters at the cursor.
|
|
964
|
+
|
|
965
|
+
|
|
966
|
+
<a id="org1af96be"></a>
|
|
967
|
+
|
|
968
|
+
#### Cursor Motion
|
|
969
|
+
|
|
970
|
+
`Fatty` implements all the expected actions for moving the cursor around the input buffer. You can move by characters or words or to the beginning or end of the buffer.
|
|
971
|
+
|
|
972
|
+
| Key | Description |
|
|
973
|
+
|-------- |--------------------------------- |
|
|
974
|
+
| C-a | move to the beginning of the line |
|
|
975
|
+
| :home | move to the beginning of the line |
|
|
976
|
+
| C-e | move to the end of the line |
|
|
977
|
+
| :end | move to the end of the line |
|
|
978
|
+
| C-f | move cursor right one character |
|
|
979
|
+
| :right | move cursor right one character |
|
|
980
|
+
| C-b | move cursor left one character |
|
|
981
|
+
| :left | move cursor left one character |
|
|
982
|
+
| M-f | move cursor right one word |
|
|
983
|
+
| M-:right | move cursor right one word |
|
|
984
|
+
| C-:right | move cursor right one word |
|
|
985
|
+
| M-b | move cursor left one word |
|
|
986
|
+
| M-:left | move cursor left one word |
|
|
987
|
+
| C-:left | move cursor left one word |
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
<a id="org32a2afa"></a>
|
|
991
|
+
|
|
992
|
+
#### Clearing
|
|
993
|
+
|
|
994
|
+
This is one action that does not affect the input buffer but the output pane. It clears it.
|
|
995
|
+
|
|
996
|
+
| Key | Description |
|
|
997
|
+
|--- |--------------------- |
|
|
998
|
+
| C-l | clear the output pane |
|
|
999
|
+
|
|
1000
|
+
|
|
1001
|
+
<a id="org72cce5e"></a>
|
|
1002
|
+
|
|
1003
|
+
#### Undo and Redo
|
|
1004
|
+
|
|
1005
|
+
`Fatty` keeps a stack of buffer-modifying actions, recording the buffer contents before any change is made. The undo-redo facility allows you to traverse that stack, `undo` travels backward to an earlier buffer state, and, once at an earlier state, `redo` travels forward to a more recent buffer state.
|
|
1006
|
+
|
|
1007
|
+
| Key | Description |
|
|
1008
|
+
|----- |----------- |
|
|
1009
|
+
| C-/ | undo |
|
|
1010
|
+
| C-\_ | undo |
|
|
1011
|
+
| C-M-/ | redo |
|
|
1012
|
+
| M-/ | redo |
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
<a id="org5ac8fea"></a>
|
|
1016
|
+
|
|
1017
|
+
#### Deletion and Killing
|
|
1018
|
+
|
|
1019
|
+
`Fatty` implements the emacs-esque notion of "killing" text by deleting it but also adding it to the "kill ring", a circular structure of all prior kills. It is circular in that successive "yanks", or pastes, traverse the kill ring and return to the beginning after reaching the end. By contrast a "deletion" merely removes text from the buffer without adding it to the kill ring.
|
|
1020
|
+
|
|
1021
|
+
When the region is active, destructive editing commands kill the region rather than deleting characters or words.
|
|
1022
|
+
|
|
1023
|
+
| Key | Description |
|
|
1024
|
+
|---------- |------------------------------ |
|
|
1025
|
+
| C-d | delete character at cursor |
|
|
1026
|
+
| :delete | delete character at cursor |
|
|
1027
|
+
| :backspace | delete character before cursor |
|
|
1028
|
+
| M-d | kill word at cursor |
|
|
1029
|
+
| C-w | kill word before cursor |
|
|
1030
|
+
| C-k | kill to end of line |
|
|
1031
|
+
| C-t | transpose characters |
|
|
1032
|
+
| M-t | transpose words |
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
<a id="org948d8d5"></a>
|
|
1036
|
+
|
|
1037
|
+
#### Yanking, Mark, and Region
|
|
1038
|
+
|
|
1039
|
+
Text that has been killed can be "yanked" into the buffer at the cursor position with the "yank" action. That text can be replaced by successive entries in the kill ring with the yank\_pop action.
|
|
1040
|
+
|
|
1041
|
+
In addition, `fatty` allows you to define a "region" by setting a mark and moving the cursor. The text between the mark and the cursor is the region. The region can be killed or copied, that is deleted and added to the kill ring or just added to the kill ring.
|
|
1042
|
+
|
|
1043
|
+
Notice that commands that normally delete characters or words, kill the region if the region is active.
|
|
1044
|
+
|
|
1045
|
+
| Key | Description |
|
|
1046
|
+
|---------- |------------------------------------------------- |
|
|
1047
|
+
| C-y | yank last kill at the cursor |
|
|
1048
|
+
| M-y | replace last yank with next item in the kill ring |
|
|
1049
|
+
| | |
|
|
1050
|
+
| C-d | when region active, kill the region |
|
|
1051
|
+
| :delete | when region active, kill the region |
|
|
1052
|
+
| :backspace | when region active, kill the region |
|
|
1053
|
+
| M-d | when region active, kill the region |
|
|
1054
|
+
| C-w | when region active, kill the region |
|
|
1055
|
+
| | |
|
|
1056
|
+
| C-:space | set the mark at the current cursor position |
|
|
1057
|
+
| C-@ | set the mark at the current cursor position |
|
|
1058
|
+
| C-g | clear the mark |
|
|
1059
|
+
| C-w | kill the region |
|
|
1060
|
+
| M-w | copy the region |
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
<a id="orgb998032"></a>
|
|
1064
|
+
|
|
1065
|
+
#### Count Prefix
|
|
1066
|
+
|
|
1067
|
+
By default each action acts on one item, so the default count is 1. But for certain commands that operate on characters or words, you can modify the count by typing `M-<digit>` keys before the command. For example, if you want to insert exactly 80 '#' characters into the buffer, `M-8 M-0 #` will do the trick.
|
|
1068
|
+
|
|
1069
|
+
There is one command, however, for which the count is not used as a repeat count: for `page_top` (bound in paging to `g`) the count is used as a line number to navigate to.
|
|
1070
|
+
|
|
1071
|
+
Fatty follows the emacs convention of making `C-u` multiply the count prefix by 4 with each press. So you can insert 64 '#' characters with `C-u C-u C-u #`.
|
|
1072
|
+
|
|
1073
|
+
| Key | Description |
|
|
1074
|
+
|--------- |-------------------------------------------------- |
|
|
1075
|
+
| C-u | universal count argument (times 4 with each press) |
|
|
1076
|
+
| M-<digit> | accumulate a count argument |
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
<a id="org30cf355"></a>
|
|
1080
|
+
|
|
1081
|
+
#### History Navigation
|
|
1082
|
+
|
|
1083
|
+
`Fatty` sports a rather sophisticated history system. It not only records each completed item of input but can also be made to note the kind of items and the "context" in which it was entered.
|
|
1084
|
+
|
|
1085
|
+
History is essentially partitioned into separate "kinds" of history so that the command line can occupy one part of history and search strings a different part of history. That way, the history is made relevant to the current input buffer that you are working on.
|
|
1086
|
+
|
|
1087
|
+
In addition, each history item can note its "context". This is less strict than "kinds" of history but allows the history mechanism to favor history items from the same "context" as the current context. For example, in the `fatty` demo, any line that is not a builtin command is treated as a shell
|
|
1088
|
+
|
|
1089
|
+
if you traverse history items, you will be shown command executed from the directory you are in before other history items. It still will give you items from other contexts, it just pushes items from the current context to the front of the list.
|
|
1090
|
+
|
|
1091
|
+
You can navigate history items with the `up` and `down` keys as you would expect. But you can also have the history items presented in a popup that shows all history items then allows you to narrow the items displayed by typing text into its narrowing input field. Bonus: the narrowing input field itself has a history that you can access with `M-p` and `M-n`. History on history.
|
|
1092
|
+
|
|
1093
|
+
| Key | Description |
|
|
1094
|
+
|----- |-------------------------------------------- |
|
|
1095
|
+
| C-p | replace the line with the prior history item |
|
|
1096
|
+
| :up | replace the line with the prior history item |
|
|
1097
|
+
| C-n | replace the line with the next history item |
|
|
1098
|
+
| :down | replace the line with the next history item |
|
|
1099
|
+
| C-r | search the history in a popup |
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
<a id="org0c995ec"></a>
|
|
1103
|
+
|
|
1104
|
+
#### Completion
|
|
1105
|
+
|
|
1106
|
+
`Fatty` also provides a completion facility that makes entering input easier.
|
|
1107
|
+
|
|
1108
|
+
1. Input Completion
|
|
1109
|
+
|
|
1110
|
+
As you type a command-line, `fatty` will auto-suggest ways to complete the line with dimmed text to the right of the cursor:
|
|
1111
|
+
|
|
1112
|
+

|
|
1113
|
+
|
|
1114
|
+
After typing 'ec' `fatty` suggests a command-line pulled from history using the dimmed text to the right of the cursor. The suggestion can be accepted by moving the cursor into the suggestion, and any text then to the left of the cursor becomes part of the input buffer.
|
|
1115
|
+
|
|
1116
|
+
`fatty` may have several completions suggested by the text-so-far and you can cycle through them by hitting the `tab` key. And if you want, you can see all the suggestions in a popup with `M-tab`. That allows narrowing by the text of the completions and the narrowing filter has its own history.
|
|
1117
|
+
|
|
1118
|
+

|
|
1119
|
+
|
|
1120
|
+
2. Sources for Input Completion
|
|
1121
|
+
|
|
1122
|
+
For input completion, `fatty` uses two sources:
|
|
1123
|
+
|
|
1124
|
+
1. The input history.
|
|
1125
|
+
2. The candidates returned by the `Terminal#completion_proc`.
|
|
1126
|
+
|
|
1127
|
+
History completion is always available when the terminal has history enabled. It lets the user complete from lines they have previously accepted. This is especially useful for command shells, REPL-style interfaces, and applications where users often repeat or slightly modify earlier input.
|
|
1128
|
+
|
|
1129
|
+
Application completion is supplied by the optional `completion_proc` passed to `Fatty::Terminal.new`. The proc is called with the input buffer's text-so-far and returns candidate strings. This is where an application can offer completions for commands, file names, account names, option names, object identifiers, or anything else meaningful to the application.
|
|
1130
|
+
|
|
1131
|
+
The two sources are combined before they are presented to the user. Fatty deduplicates candidates and then offers the result through the normal completion interface. `TAB` cycles through completions inline. `M-TAB` opens a completion popup, where the user can narrow the candidate list by typing in the `Complete:` field.
|
|
1132
|
+
|
|
1133
|
+
Application candidates are offered first. History candidates fill in behind them. This gives the host application priority for current, domain-specific completions while still letting users recover earlier accepted input.
|
|
1134
|
+
|
|
1135
|
+
The completion popup is still a popup filter. Its narrowing text has its own history, separate from command input history and from other popup filters. Use `M-p` and `M-n` inside the completion popup to recall previous completion filters.
|
|
1136
|
+
|
|
1137
|
+
3. File Name Completion
|
|
1138
|
+
|
|
1139
|
+
Apart from command-line completion, `fatty` offers completion of file names if the cursor is at the end of a string that looks like a file name: that is, it starts with './', '../', '~/' or '/'.
|
|
1140
|
+
|
|
1141
|
+
1. If the string-so-far matches only one directory or file name, it inserts that into the input buffer and continues completion from there.
|
|
1142
|
+
2. If the string-so-far matches multiple files or directories it auto-suggests the first and `TAB` cycles through each of the candidates which you can accept by moving the cursor past the suggestion. Likewise `S-TAB` cycles backwards through the list of candidates.
|
|
1143
|
+
3. If the string-so-far matches no files, completion does nothing.
|
|
1144
|
+
|
|
1145
|
+
Just as with command line completion, you can invoke a popup of completions with `M-TAB` and a popup of possible file names will appear within which you may filter the candidates down by narrowing. Unlike other forms of completion, the file name completion popup allows you to fill out the path by navigating directories within the popup by hitting `TAB` or `right` to descend into a sub-directory or `S-TAB` or `left` to ascend to the parent directory. The popup title shows the path so far.
|
|
1146
|
+
|
|
1147
|
+
|
|
1148
|
+
<a id="orgf4edfcc"></a>
|
|
1149
|
+
|
|
1150
|
+
#### Accept or Cancel
|
|
1151
|
+
|
|
1152
|
+
Finally, when the command-line is to your satisfaction, you can submit the line to the `on_accept` proc which determines how your app responds to it.
|
|
1153
|
+
|
|
1154
|
+
You can end a `fatty` session with `C-c` at the command line, or (only if the buffer is empty) with `C-d`.
|
|
1155
|
+
|
|
1156
|
+
| Key | Description |
|
|
1157
|
+
|-------- |------------------------------------------------------ |
|
|
1158
|
+
| :enter | feed the line to the on\_accept proc and page output |
|
|
1159
|
+
| M-:enter | feed the line to the on\_accept proc and scroll output |
|
|
1160
|
+
| C-c | quit \`fatty\` |
|
|
1161
|
+
| C-d | quit \`fatty\` only if the input line is empty |
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
<a id="org8d58d09"></a>
|
|
1165
|
+
|
|
1166
|
+
### Paging Context
|
|
1167
|
+
|
|
1168
|
+
Once the command-line is accepted, \`fatty\` sends output to the large output pane, and if the output is more than one screen long presents a paging environment for viewing and searching the output. From there, `fatty` offers the expected navigation aids for examining the output:
|
|
1169
|
+
|
|
1170
|
+
| Key | Count? | Description |
|
|
1171
|
+
|----------- |------ |--------------------------------------------------- |
|
|
1172
|
+
| `up` | Yes | move output one line up |
|
|
1173
|
+
| `k` | Yes | move output one line up |
|
|
1174
|
+
| `down` | Yes | move output one line down |
|
|
1175
|
+
| `j` | Yes | move output one line down |
|
|
1176
|
+
| `page_up` | Yes | move back one page |
|
|
1177
|
+
| `b` | Yes | move back one page |
|
|
1178
|
+
| `u` | Yes | move back one page |
|
|
1179
|
+
| `M-v` | Yes | move back one page |
|
|
1180
|
+
| `backspace` | Yes | move back one page |
|
|
1181
|
+
| `page_down` | Yes | move forward one page |
|
|
1182
|
+
| `f` | Yes | move forward one page |
|
|
1183
|
+
| `d` | Yes | move forward one page |
|
|
1184
|
+
| `space` | Yes | move forward one page |
|
|
1185
|
+
| `C-v` | Yes | move forward one page |
|
|
1186
|
+
| `home` | No | move to the top of output |
|
|
1187
|
+
| `M-<` | No | move to the top of output |
|
|
1188
|
+
| `g` | Yes | move to the top, or to the counted original line\* |
|
|
1189
|
+
| `end` | No | move to the end of output |
|
|
1190
|
+
| `M->` | No | move to the end of output |
|
|
1191
|
+
| `G` | No | move to the end of output |
|
|
1192
|
+
| `=` | No | toggle the display of line numbers |
|
|
1193
|
+
| `M-s` | No | toggle between paging and scrolling |
|
|
1194
|
+
| `/` | No | initiate a fixed-string search forward |
|
|
1195
|
+
| `?` | No | initiate a fixed-string search backward |
|
|
1196
|
+
| `C-s` | No | initiate an Isearch session forward |
|
|
1197
|
+
| `C-r` | No | initiate an Isearch session backward |
|
|
1198
|
+
| `C-M-s` | No | initiate an Regexp session forward |
|
|
1199
|
+
| `C-M-r` | No | initiate an Regexp session backward |
|
|
1200
|
+
| `C-/` | No | initiate an Regexp session forward |
|
|
1201
|
+
| `<` | No | narrow output to lines containing all entered terms |
|
|
1202
|
+
| `>` | No | widen output by clearing the narrowing |
|
|
1203
|
+
| `C-c` | No | quit paging |
|
|
1204
|
+
| `q` | No | quit paging |
|
|
1205
|
+
| `C-g` | No | quit paging |
|
|
1206
|
+
| `escape` | No | quit paging |
|
|
1207
|
+
| `n` | Yes | move to the next instance of the current search |
|
|
1208
|
+
| `N` | Yes | move to the prior instance of the current search |
|
|
1209
|
+
|
|
1210
|
+
`*` Without a count, `g` moves to the beginning of output. With a numeric prefix, it moves to that original output line; for example, `M-1 M-0 M-0 M-0 g` moves to line 1000. It uses the original line numbers even when output is narrowed.
|
|
1211
|
+
|
|
1212
|
+
As you can see, `fatty` tries to accommodate a number of finger habits besides `emacs`, including `vim` and `Emacs Info`, by offering several alternative ways to invoke navigation actions.
|
|
1213
|
+
|
|
1214
|
+
One unusual action is invoked by `M-s` which toggles the output between scrolling mode without pause and paging mode. It can be invoked while doing either to enter the other mode.
|
|
1215
|
+
|
|
1216
|
+
You can add line numbers to the display while paging by using the `=` key.
|
|
1217
|
+
|
|
1218
|
+
You can also "narrow" the output with `<`, which will prompt you for one or more terms to match. The output will then show only lines that match all the terms typed. To return to the full output, "widen" with `>`.
|
|
1219
|
+
|
|
1220
|
+
|
|
1221
|
+
<a id="org89f3027"></a>
|
|
1222
|
+
|
|
1223
|
+
### Searching Output
|
|
1224
|
+
|
|
1225
|
+
While paging, you can initiate a search of the output as indicated in the above key bindings for paging. Once a search session is initiated, `fatty` presents an input line for entering search terms.
|
|
1226
|
+
|
|
1227
|
+
After a search session has ended, `fatty` returns to paging but remembers the last search term and allows navigation among them with `n` and `N`: `n` searches in the direction of the last search and `N` searches in the opposite direction. Notice that the current search term and direction are added to the paging bar after the information on your location within the output.
|
|
14
1228
|
|
|
15
|
-
<a id="orga462d10"></a>
|
|
16
1229
|
|
|
17
|
-
|
|
1230
|
+
<a id="org77137d8"></a>
|
|
1231
|
+
|
|
1232
|
+
#### String and Regex Search
|
|
1233
|
+
|
|
1234
|
+
`/` and `?` prompt for a fixed string and search forward or backward. `C-M-s` (or `C-/`) and `C-M-r` (or `C-?`) perform the corresponding regular-expression searches. Accepting the search leaves the selected match active for later navigation with `n` and `N`.
|
|
1235
|
+
|
|
1236
|
+
|
|
1237
|
+
<a id="orgd90c796"></a>
|
|
1238
|
+
|
|
1239
|
+
#### Incremental Search
|
|
1240
|
+
|
|
1241
|
+
`C-s` and `C-r` begin forward or backward incremental search. The output moves to matching text as the search term is edited. Accepting commits the match; canceling restores the output position from before the search began.
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
<a id="orgc8458e1"></a>
|
|
1245
|
+
|
|
1246
|
+
# Configuration
|
|
1247
|
+
|
|
1248
|
+
When a Fatty application starts, Fatty installs default configuration files under `~/.config/fatty` if they do not already exist. Fatty does not overwrite files that are already there, so you can edit these files directly and keep them under version control.
|
|
1249
|
+
|
|
1250
|
+
The config files are:
|
|
1251
|
+
|
|
1252
|
+
- **`config.yml`:** general configuration;
|
|
1253
|
+
- **`keydefs.yml`:** terminal-specific keycode naming;
|
|
1254
|
+
- **`keybindings.yml`:** user-defined keybindings;
|
|
1255
|
+
- **`themes/`:** YAML theme files.
|
|
1256
|
+
|
|
1257
|
+
The default user-specific configuration directory follows `XDG_CONFIG_HOME` if it is set. Otherwise it is `~/.config/fatty`.
|
|
1258
|
+
|
|
1259
|
+
In addition to the user-specific configuration, fatty will read app-specific configuration files from `~/.config/fatty/apps/<app_name>` if `Terminal` was given an `app_name` parameter. It will use a different directory of your choosing if `Terminal` was given an `app_config_dir` directory name.
|
|
1260
|
+
|
|
1261
|
+
|
|
1262
|
+
<a id="org0add8c9"></a>
|
|
1263
|
+
|
|
1264
|
+
## General Configuration `config.yml`
|
|
1265
|
+
|
|
1266
|
+
`config.yml` controls general behavior such as word movement, ESC handling, logging, history, the initial theme, and truecolor rendering.
|
|
1267
|
+
|
|
1268
|
+
A small configuration might look like this:
|
|
1269
|
+
|
|
1270
|
+
```yaml
|
|
1271
|
+
word_char_re: "[[:alnum:]_.:-]"
|
|
1272
|
+
|
|
1273
|
+
esc_delay: 0
|
|
1274
|
+
|
|
1275
|
+
history:
|
|
1276
|
+
file: "~/.fatty_history"
|
|
1277
|
+
max: 10000
|
|
1278
|
+
|
|
1279
|
+
theme: wordperfect
|
|
1280
|
+
|
|
1281
|
+
truecolor: auto
|
|
1282
|
+
```
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
<a id="org1099eb8"></a>
|
|
1286
|
+
|
|
1287
|
+
### `word_char_re`
|
|
1288
|
+
|
|
1289
|
+
This setting is a Ruby regular expression fragment used to decide what counts as a word in the input buffer. It must be a `String` representing a `Regexp` that matches a single character that is meant to be a part of a "word" for purposes of cursor movement. The default setting treats letters, digits, and underscore as word characters:
|
|
1290
|
+
|
|
1291
|
+
```yaml
|
|
1292
|
+
word_char_re: "[[:alnum:]_]"
|
|
1293
|
+
```
|
|
1294
|
+
|
|
1295
|
+
For command-line applications, you may want dashes to be part of a word:
|
|
1296
|
+
|
|
1297
|
+
```yaml
|
|
1298
|
+
word_char_re: "[[:alnum:]_-]"
|
|
1299
|
+
```
|
|
1300
|
+
|
|
1301
|
+
For Ruby constants, hostnames, or command-like tokens, you may want a broader definition:
|
|
1302
|
+
|
|
1303
|
+
```yaml
|
|
1304
|
+
word_char_re: "[[:alnum:]_.:-]"
|
|
1305
|
+
```
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
<a id="orgce3e466"></a>
|
|
1309
|
+
|
|
1310
|
+
### `esc_delay`
|
|
1311
|
+
|
|
1312
|
+
`esc_delay` controls how long curses waits after receiving `ESC` before deciding whether another key is part of the same Meta-key sequence. The value is in milliseconds.
|
|
1313
|
+
|
|
1314
|
+
```yaml
|
|
1315
|
+
esc_delay: 0
|
|
1316
|
+
```
|
|
1317
|
+
|
|
1318
|
+
|
|
1319
|
+
<a id="org95b5e48"></a>
|
|
1320
|
+
|
|
1321
|
+
### `history`
|
|
1322
|
+
|
|
1323
|
+
|
|
1324
|
+
<a id="orgdc30f58"></a>
|
|
1325
|
+
|
|
1326
|
+
#### `file`
|
|
1327
|
+
|
|
1328
|
+
The path to the history file to use, by default `~/.fatty_history`
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
<a id="org0941468"></a>
|
|
1332
|
+
|
|
1333
|
+
#### `max`
|
|
1334
|
+
|
|
1335
|
+
The maximum number of lines of history retained, by default 10,000.
|
|
1336
|
+
|
|
1337
|
+
|
|
1338
|
+
<a id="orgce1b37d"></a>
|
|
1339
|
+
|
|
1340
|
+
### `theme`
|
|
1341
|
+
|
|
1342
|
+
The `theme` setting names the theme Fatty applies at startup:
|
|
1343
|
+
|
|
1344
|
+
```yaml
|
|
1345
|
+
theme: nordic
|
|
1346
|
+
```
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
<a id="orgdd529bd"></a>
|
|
1350
|
+
|
|
1351
|
+
### `truecolor`
|
|
1352
|
+
|
|
1353
|
+
The `truecolor` setting controls whether Fatty uses truecolor escape sequences for rendering colors. The usual setting is `auto`, meaning that `truecolor` is enabled if available. It can be set to `true`, `false`, `on`, `off` or `auto`.
|
|
1354
|
+
|
|
1355
|
+
```yaml
|
|
1356
|
+
truecolor: auto
|
|
1357
|
+
```
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
<a id="org2b58449"></a>
|
|
1361
|
+
|
|
1362
|
+
### `log`
|
|
1363
|
+
|
|
1364
|
+
Logging is configured under `log`:
|
|
1365
|
+
|
|
1366
|
+
```yaml
|
|
1367
|
+
log:
|
|
1368
|
+
file: "~/log/fatty.log"
|
|
1369
|
+
level: debug
|
|
1370
|
+
tags:
|
|
1371
|
+
- keycode
|
|
1372
|
+
- keyevent
|
|
1373
|
+
- keybinding
|
|
1374
|
+
- action
|
|
1375
|
+
- command
|
|
1376
|
+
- session
|
|
1377
|
+
- render
|
|
1378
|
+
- perf
|
|
1379
|
+
```
|
|
1380
|
+
|
|
1381
|
+
|
|
1382
|
+
<a id="org0e3b938"></a>
|
|
1383
|
+
|
|
1384
|
+
#### `file`
|
|
1385
|
+
|
|
1386
|
+
The path to the log file to use.
|
|
1387
|
+
|
|
1388
|
+
|
|
1389
|
+
<a id="org9c70445"></a>
|
|
1390
|
+
|
|
1391
|
+
#### `level`
|
|
1392
|
+
|
|
1393
|
+
Can be one of the following
|
|
1394
|
+
|
|
1395
|
+
- **`info`:** only informational messages
|
|
1396
|
+
- **`warn`:** only non-fatal warning messages and `info` messages
|
|
1397
|
+
- **`error`:** only fatal error messages and `warn` and `info` messages
|
|
1398
|
+
- **`debug`:** detailed messages to assist debugging `fatty` plus all of the above.
|
|
1399
|
+
|
|
1400
|
+
|
|
1401
|
+
<a id="orge47f304"></a>
|
|
1402
|
+
|
|
1403
|
+
#### `tags`
|
|
1404
|
+
|
|
1405
|
+
`log.tags` controls which tagged log messages are written. Tags are ordinary symbolic labels used by Fatty's logging calls; they are not checked against a fixed registry. A tag is useful if Fatty logs messages with that tag.
|
|
1406
|
+
|
|
1407
|
+
The special tag `all` enables all tagged log messages except `perf`. Performance logging is intentionally noisy and must be enabled explicitly with `perf`.
|
|
1408
|
+
|
|
1409
|
+
```yaml
|
|
1410
|
+
log:
|
|
1411
|
+
tags:
|
|
1412
|
+
- keycode
|
|
1413
|
+
- keybinding
|
|
1414
|
+
- render
|
|
1415
|
+
- perf
|
|
1416
|
+
```
|
|
1417
|
+
|
|
1418
|
+
|
|
1419
|
+
<a id="org220de42"></a>
|
|
1420
|
+
|
|
1421
|
+
## Key code definitions `keydefs.yml`
|
|
1422
|
+
|
|
1423
|
+
Most keys are named correctly by curses. Some terminal emulators, multiplexers, or keyboard modes emit numeric keycodes that curses does not name usefully. The `keydefs.yml` file lets you assign names and modifiers to those numeric codes.
|
|
1424
|
+
|
|
1425
|
+
When Fatty runs inside `tmux`, key definitions are looked up under `tmux`, not under the outer terminal emulator. `tmux` translates the outer terminal's input before Fatty sees it, so keycodes observed inside `tmux` may differ from keycodes observed directly under GNOME Terminal, Kitty, Alacritty, or another terminal. Use `keytest` in the same environment where the application will normally run. The same comment applies to `screen`.
|
|
1426
|
+
|
|
1427
|
+
A key definition is terminal-specific. For example:
|
|
1428
|
+
|
|
1429
|
+
```yaml
|
|
1430
|
+
tmux:
|
|
1431
|
+
555:
|
|
1432
|
+
key: left
|
|
1433
|
+
meta: true
|
|
1434
|
+
570:
|
|
1435
|
+
key: right
|
|
1436
|
+
meta: true
|
|
1437
|
+
557:
|
|
1438
|
+
key: left
|
|
1439
|
+
ctrl: true
|
|
1440
|
+
572:
|
|
1441
|
+
key: right
|
|
1442
|
+
ctrl: true
|
|
1443
|
+
```
|
|
1444
|
+
|
|
1445
|
+
This says that, when Fatty detects that the terminal is `tmux`, curses keycode `555` should be treated as `M-left`, keycode `570` as `M-right`, and so on.
|
|
1446
|
+
|
|
1447
|
+
The demo executable has a `keytest` command that is useful when building this file. Run `fatty`, use the `keytest` command, press the key you want to identify, and add an entry for the numeric code if Fatty does not already know what to call it.
|
|
1448
|
+
|
|
1449
|
+
Here is what I found running `keytest` on a variety of popular terminals to determine how each reported `PageDown`, `C-PageDown`, `M-PageDown`, and `C-M-PageDown`:
|
|
1450
|
+
|
|
1451
|
+
| Terminal | Key Pressed | Ctrl? | Meta? | Code | Status |
|
|
1452
|
+
|-------------- |----------- |----- |----- |------ |----------------- |
|
|
1453
|
+
| gnome-terminal | PageDown | no | no | 338 | Defined and bound |
|
|
1454
|
+
| gnome-terminal | PageDown | yes | no | 559 | Undefined |
|
|
1455
|
+
| gnome-terminal | PageDown | no | yes | 557 | Undefined |
|
|
1456
|
+
| gnome-terminal | PageDown | yes | yes | 561 | Undefined |
|
|
1457
|
+
| alacritty | PageDown | no | no | 338 | Defined and bound |
|
|
1458
|
+
| alacritty | PageDown | yes | no | 559 | Undefined |
|
|
1459
|
+
| alacritty | PageDown | no | yes | 557 | Undefined |
|
|
1460
|
+
| alacritty | PageDown | yes | yes | 561 | Undefined |
|
|
1461
|
+
| kitty | PageDown | no | no | 338 | Defined and bound |
|
|
1462
|
+
| kitty | PageDown | yes | no | 565 | Undefined |
|
|
1463
|
+
| kitty | PageDown | no | yes | 563 | Undefined |
|
|
1464
|
+
| kitty | PageDown | yes | yes | 567 | Undefined |
|
|
1465
|
+
| terminator | PageDown | no | no | 338 | Defined and bound |
|
|
1466
|
+
| terminator | PageDown | yes | no | <none> | Undefinable |
|
|
1467
|
+
| terminator | PageDown | no | yes | 557 | Undefined |
|
|
1468
|
+
| terminator | PageDown | yes | yes | 561 | Undefined |
|
|
1469
|
+
| ghostty | PageDown | no | no | 338 | Defined and bound |
|
|
1470
|
+
| ghostty | PageDown | yes | no | 564 | Undefined |
|
|
1471
|
+
| ghostty | PageDown | no | yes | 562 | Undefined |
|
|
1472
|
+
| ghostty | PageDown | yes | yes | 566 | Undefined |
|
|
1473
|
+
| konsole | PageDown | no | no | 338 | Defined and bound |
|
|
1474
|
+
| konsole | PageDown | yes | no | 559 | Undefined |
|
|
1475
|
+
| konsole | PageDown | no | yes | 557 | Undefined |
|
|
1476
|
+
| konsole | PageDown | yes | yes | 561 | Undefined |
|
|
1477
|
+
|
|
1478
|
+
I could turn this into a `keydefs.yml` file that would allow me to define all those keys:
|
|
1479
|
+
|
|
1480
|
+
```yaml
|
|
1481
|
+
gnome-terminal:
|
|
1482
|
+
559:
|
|
1483
|
+
key: page_down
|
|
1484
|
+
ctrl: true
|
|
1485
|
+
557:
|
|
1486
|
+
key: page_down
|
|
1487
|
+
meta: true
|
|
1488
|
+
561:
|
|
1489
|
+
key: page_down
|
|
1490
|
+
ctrl: true
|
|
1491
|
+
meta: true
|
|
1492
|
+
|
|
1493
|
+
alacritty:
|
|
1494
|
+
559:
|
|
1495
|
+
key: page_down
|
|
1496
|
+
ctrl: true
|
|
1497
|
+
557:
|
|
1498
|
+
key: page_down
|
|
1499
|
+
meta: true
|
|
1500
|
+
561:
|
|
1501
|
+
key: page_down
|
|
1502
|
+
ctrl: true
|
|
1503
|
+
meta: true
|
|
1504
|
+
|
|
1505
|
+
kitty:
|
|
1506
|
+
565:
|
|
1507
|
+
key: page_down
|
|
1508
|
+
ctrl: true
|
|
1509
|
+
563:
|
|
1510
|
+
key: page_down
|
|
1511
|
+
meta: true
|
|
1512
|
+
567:
|
|
1513
|
+
key: page_down
|
|
1514
|
+
ctrl: true
|
|
1515
|
+
meta: true
|
|
1516
|
+
|
|
1517
|
+
terminator:
|
|
1518
|
+
# 559:
|
|
1519
|
+
# key: page_down
|
|
1520
|
+
# ctrl: true
|
|
1521
|
+
557:
|
|
1522
|
+
key: page_down
|
|
1523
|
+
meta: true
|
|
1524
|
+
561:
|
|
1525
|
+
key: page_down
|
|
1526
|
+
ctrl: true
|
|
1527
|
+
meta: true
|
|
1528
|
+
|
|
1529
|
+
ghostty:
|
|
1530
|
+
564:
|
|
1531
|
+
key: page_down
|
|
1532
|
+
ctrl: true
|
|
1533
|
+
562:
|
|
1534
|
+
key: page_down
|
|
1535
|
+
meta: true
|
|
1536
|
+
566:
|
|
1537
|
+
key: page_down
|
|
1538
|
+
ctrl: true
|
|
1539
|
+
meta: true
|
|
1540
|
+
|
|
1541
|
+
konsole:
|
|
1542
|
+
559:
|
|
1543
|
+
key: page_down
|
|
1544
|
+
ctrl: true
|
|
1545
|
+
557:
|
|
1546
|
+
key: page_down
|
|
1547
|
+
meta: true
|
|
1548
|
+
561:
|
|
1549
|
+
key: page_down
|
|
1550
|
+
ctrl: true
|
|
1551
|
+
meta: true
|
|
1552
|
+
```
|
|
1553
|
+
|
|
1554
|
+
After installing that keydefs, I find that the PageDown variants are all recognized by name and modifiers (except for the strange failure of `terminator` to recognize `C-PageDown`!).
|
|
1555
|
+
|
|
1556
|
+
|
|
1557
|
+
<a id="orgbd79429"></a>
|
|
1558
|
+
|
|
1559
|
+
## Key bindings `keybindings.yml`
|
|
1560
|
+
|
|
1561
|
+
Fatty has built-in Emacs-style bindings for ordinary input editing, history, completion, popup navigation, and paging. The `keybindings.yml` file lets you add or override bindings without changing Ruby code.
|
|
1562
|
+
|
|
1563
|
+
A keybinding names a key chord, the context in which it applies, and the Fatty action to run:
|
|
1564
|
+
|
|
1565
|
+
```yaml
|
|
1566
|
+
- key: left
|
|
1567
|
+
meta: true
|
|
1568
|
+
action: move_word_left
|
|
1569
|
+
|
|
1570
|
+
- key: right
|
|
1571
|
+
meta: true
|
|
1572
|
+
action: move_word_right
|
|
1573
|
+
|
|
1574
|
+
- key: space
|
|
1575
|
+
context: paging
|
|
1576
|
+
action: page_down
|
|
1577
|
+
|
|
1578
|
+
- key: backspace
|
|
1579
|
+
context: paging
|
|
1580
|
+
action: page_up
|
|
1581
|
+
```
|
|
1582
|
+
|
|
1583
|
+
|
|
1584
|
+
<a id="org698f2a9"></a>
|
|
1585
|
+
|
|
1586
|
+
### Key Names
|
|
1587
|
+
|
|
1588
|
+
A keybinding uses the unmodified key name under the `key` field:
|
|
1589
|
+
|
|
1590
|
+
```yaml
|
|
1591
|
+
- key: f
|
|
1592
|
+
meta: true
|
|
1593
|
+
context: text
|
|
1594
|
+
action: move_word_right
|
|
1595
|
+
```
|
|
1596
|
+
|
|
1597
|
+
|
|
1598
|
+
<a id="org58581e4"></a>
|
|
1599
|
+
|
|
1600
|
+
#### Printable Keys
|
|
1601
|
+
|
|
1602
|
+
Most printable keys can be written as the character itself. Quote keys that YAML might otherwise treat specially or make hard to read, such as `":"`, `"#"`, `"["`, `"]"`, `"{"`, `"}"`, `"\""`, and `"\\"`.
|
|
1603
|
+
|
|
1604
|
+
```yaml
|
|
1605
|
+
- key: a
|
|
1606
|
+
- key: /
|
|
1607
|
+
- key: .
|
|
1608
|
+
- key: =
|
|
1609
|
+
- key: "\\"
|
|
1610
|
+
- key: "\""
|
|
1611
|
+
```
|
|
1612
|
+
|
|
1613
|
+
|
|
1614
|
+
<a id="org4b0cf5b"></a>
|
|
1615
|
+
|
|
1616
|
+
#### Curses and Fatty Named Keys
|
|
1617
|
+
|
|
1618
|
+
`Fatty` translates codes returned by curses for special keys into names:
|
|
1619
|
+
|
|
1620
|
+
| | | | | |
|
|
1621
|
+
|-------------- |-------------- |--------------- |----------------- |-------------- |
|
|
1622
|
+
| `tab` | `insert` | `delete` | `home` | `end` |
|
|
1623
|
+
| `left` | `right` | `page_up` | `page_down` | `up` |
|
|
1624
|
+
| `down` | `f1` | `f2` | `f3` | `f4` |
|
|
1625
|
+
| `f8` | `f9` | `f10` | `f11` | `f12` |
|
|
1626
|
+
| `keypad_0` | `keypad_1` | `keypad_2` | `keypad_3` | `keypad_4` |
|
|
1627
|
+
| `keypad_8` | `keypad_9` | `keypad_divide` | `keypad_multiply` | `keypad_minus` |
|
|
1628
|
+
| `keypad_enter` | `keypad_comma` | | | |
|
|
1629
|
+
|
|
1630
|
+
Some terminals can report application-keypad sequences such as `keypad_divide`, `keypad_multiply`, or `keypad_enter`, but numeric keypad digits are often not distinguishable from ordinary digits when NumLock is on, and are often reported as navigation keys such as `end`, `down`, `page_down`, or `left` when NumLock is off. Use `keytest` to see what your terminal actually sends.
|
|
1631
|
+
|
|
1632
|
+
`Fatty` also provides convenient names to other common keys:
|
|
1633
|
+
|
|
1634
|
+
- `enter`,
|
|
1635
|
+
- `escape`, and
|
|
1636
|
+
- `space`
|
|
1637
|
+
|
|
1638
|
+
|
|
1639
|
+
<a id="orgeab9ebe"></a>
|
|
1640
|
+
|
|
1641
|
+
#### Possibly Invisible Keys
|
|
1642
|
+
|
|
1643
|
+
Some physical keys may never reach Fatty at all. They may be handled by the keyboard firmware, the kernel, the desktop environment, the window manager, or the terminal emulator before curses can report them. Common examples include `Print Screen`, `Scroll Lock`, `Pause/Break`, `Caps Lock`, `Num Lock`, `Fn`, `Menu/Application`, `Super/Windows`, power/sleep/wake keys, brightness keys, volume/media keys, keyboard-backlight keys, airplane-mode keys, and touchpad toggle keys.
|
|
1644
|
+
|
|
1645
|
+
Use `keytest` to check. If Fatty sees a key as a raw numeric code, you can name it in `keydefs.yml` and bind it. If `keytest` shows nothing, the key is being intercepted before Fatty receives it.
|
|
1646
|
+
|
|
1647
|
+
|
|
1648
|
+
<a id="orgde02d1d"></a>
|
|
1649
|
+
|
|
1650
|
+
#### Unnamed but Recognized Keys
|
|
1651
|
+
|
|
1652
|
+
Some terminals report modified special keys as distinct numeric keycodes that `fatty` and `curses` do not name. Use `keytest` to discover those codes, then assign names to them in `keydefs.yml`. The name can be one of Fatty's usual names, or a new name of your own.
|
|
1653
|
+
|
|
1654
|
+
For example, if a keyboard has an extra thumb key and `keytest` reports it as an uncoded keycode `601`, you could name it:
|
|
1655
|
+
|
|
1656
|
+
```yaml
|
|
1657
|
+
gnome-terminal:
|
|
1658
|
+
601:
|
|
1659
|
+
key: thumb_left
|
|
1660
|
+
```
|
|
1661
|
+
|
|
1662
|
+
Then bind it in `keybindings.yml`:
|
|
1663
|
+
|
|
1664
|
+
```yaml
|
|
1665
|
+
- key: thumb_left
|
|
1666
|
+
context: text
|
|
1667
|
+
action: move_word_left
|
|
1668
|
+
```
|
|
1669
|
+
|
|
1670
|
+
Fatty does not require custom key names to come from a fixed registry. A custom name only needs to be used consistently between `keydefs.yml` and `keybindings.yml`.
|
|
1671
|
+
|
|
1672
|
+
|
|
1673
|
+
<a id="orge487bc7"></a>
|
|
1674
|
+
|
|
1675
|
+
### Mouse Events
|
|
1676
|
+
|
|
1677
|
+
Mouse events can also be bound:
|
|
1678
|
+
|
|
1679
|
+
```yaml
|
|
1680
|
+
- button: left_clicked
|
|
1681
|
+
context: popup
|
|
1682
|
+
action: choose
|
|
1683
|
+
```
|
|
1684
|
+
|
|
1685
|
+
Recognized mouse button names include:
|
|
1686
|
+
|
|
1687
|
+
```org
|
|
1688
|
+
left_pressed
|
|
1689
|
+
left_released
|
|
1690
|
+
left_clicked
|
|
1691
|
+
left_double_clicked
|
|
1692
|
+
left_triple_clicked
|
|
1693
|
+
middle_pressed
|
|
1694
|
+
middle_released
|
|
1695
|
+
middle_clicked
|
|
1696
|
+
middle_double_clicked
|
|
1697
|
+
middle_triple_clicked
|
|
1698
|
+
right_pressed
|
|
1699
|
+
right_released
|
|
1700
|
+
right_clicked
|
|
1701
|
+
right_double_clicked
|
|
1702
|
+
right_triple_clicked
|
|
1703
|
+
scroll_up
|
|
1704
|
+
scroll_down
|
|
1705
|
+
```
|
|
1706
|
+
|
|
1707
|
+
|
|
1708
|
+
<a id="orgcf36a39"></a>
|
|
1709
|
+
|
|
1710
|
+
### Modifiers
|
|
1711
|
+
|
|
1712
|
+
A binding may include these modifiers:
|
|
1713
|
+
|
|
1714
|
+
```yaml
|
|
1715
|
+
ctrl: true
|
|
1716
|
+
meta: true
|
|
1717
|
+
shift: true
|
|
1718
|
+
```
|
|
1719
|
+
|
|
1720
|
+
|
|
1721
|
+
<a id="orgc29aad9"></a>
|
|
1722
|
+
|
|
1723
|
+
### Contexts
|
|
1724
|
+
|
|
1725
|
+
In `Fatty`, the key map is partitioned by "contexts" and in different environments the contexts are tried in order from highest priority to lowest and the first binding found wins. The following table lists the contexts associated with each interaction environment:
|
|
1726
|
+
|
|
1727
|
+
| Environment | Contexts High to Low |
|
|
1728
|
+
|------------------ |--------------------------------------- |
|
|
1729
|
+
| Input Field | :input, :text, :terminal |
|
|
1730
|
+
| Output Paging | :paging, :terminal |
|
|
1731
|
+
| Output Scrolling | :terminal |
|
|
1732
|
+
| String Search | :search, :text, :terminal |
|
|
1733
|
+
| Incremental Search | :isearch, :text, :terminal |
|
|
1734
|
+
| Prompt Popup | :prompt, :text, :terminal |
|
|
1735
|
+
| Popup Choose | :popup, :text, :terminal |
|
|
1736
|
+
| Popup Multi-Choose | :popup\_multi, :popup, :text, :terminal |
|
|
1737
|
+
|
|
1738
|
+
The available contexts are:
|
|
1739
|
+
|
|
1740
|
+
| Context | Meaning |
|
|
1741
|
+
|-------------- |----------------------------------------------------- |
|
|
1742
|
+
| `:terminal` | global terminal/session commands |
|
|
1743
|
+
| `:text` | ordinary text-editing commands shared by input fields |
|
|
1744
|
+
| `:input` | the main command input field |
|
|
1745
|
+
| `:paging` | output pager navigation |
|
|
1746
|
+
| `:search` | non-incremental search field |
|
|
1747
|
+
| `:isearch` | incremental search field |
|
|
1748
|
+
| `:prompt` | prompt popup input |
|
|
1749
|
+
| `:popup` | popup selection/navigation |
|
|
1750
|
+
| `:popup_multi` | multi-select popup behavior |
|
|
1751
|
+
|
|
1752
|
+
The \`:terminal\` context is the lowest-priority fallback context for terminal-wide commands. It is where Fatty puts bindings that are not specific to text editing, paging, search, or popup selection, such as theme selection, key testing, and quitting. Because \`:terminal\` is searched last, any more specific context can override a terminal-wide binding.
|
|
1753
|
+
|
|
1754
|
+
|
|
1755
|
+
<a id="orgdb5aa78"></a>
|
|
1756
|
+
|
|
1757
|
+
### Actions
|
|
1758
|
+
|
|
1759
|
+
A keybinding connects a key event in a context to an "action." An action is a named Fatty command such as \`move\_left\`, \`delete\_backward\`, \`accept\_line\`, \`page\_down\`, \`choose\_theme\`, or \`quit\`.
|
|
1760
|
+
|
|
1761
|
+
A binding entry names the action with the \`action\` field:
|
|
1762
|
+
|
|
1763
|
+
```yaml
|
|
1764
|
+
- key: left
|
|
1765
|
+
context: text
|
|
1766
|
+
action: move_left
|
|
1767
|
+
|
|
1768
|
+
- key: f
|
|
1769
|
+
meta: true
|
|
1770
|
+
context: text
|
|
1771
|
+
action: move_word_right
|
|
1772
|
+
|
|
1773
|
+
- key: page_down
|
|
1774
|
+
context: paging
|
|
1775
|
+
action: page_down
|
|
1776
|
+
```
|
|
1777
|
+
|
|
1778
|
+
Most movement, deletion, history, completion, paging, and popup-navigation actions honor Fatty's numeric count argument. The count is entered before the command, Emacs-style. For example, `M-5 C-f` moves forward five characters if `C-f` is bound to move\_right, and `M-3 C-n` moves down three items if `C-n` is bound to the current environment's `next-item` action.
|
|
1779
|
+
|
|
1780
|
+
Use \`keytest\` to check what action is currently bound to a key. If a key is bound, \`keytest\` reports the matching context, action name, arguments, and the object that handles the action.
|
|
1781
|
+
|
|
1782
|
+
|
|
1783
|
+
<a id="orgf51a408"></a>
|
|
1784
|
+
|
|
1785
|
+
#### Input buffer actions
|
|
1786
|
+
|
|
1787
|
+
Input buffer actions edit the contents of a text buffer. These are the ordinary line-editing operations shared by the main input field, search fields, prompt popups, and other text-like interactions. Many of these actions honor the numeric prefix count.
|
|
1788
|
+
|
|
1789
|
+
Terminology notes:
|
|
1790
|
+
|
|
1791
|
+
- **kill ring:** like emacs, `fatty` keeps a "clipboard" of items with the newest item in the current position and older items "before" it but in a "ring" that return to the beginning;
|
|
1792
|
+
- **yank:** retrieve the most recent item from the kill ring
|
|
1793
|
+
- **yank pop:** retrieve successively older items from the kill ring
|
|
1794
|
+
- **delete:** removes text without copying it to the kill ring;
|
|
1795
|
+
- **kill:** removes text and copies it to the kill ring for later yank;
|
|
1796
|
+
- **word:** a sequence of contiguous characters that are each matched by the `word_char_re` from the config file or "[[:alnum]\_]" by default;
|
|
1797
|
+
|
|
1798
|
+
| Action Name | Count? | Description |
|
|
1799
|
+
|---------------------- |------ |------------------------------------------ |
|
|
1800
|
+
| bol | No | Move cursor to beginning of buffer |
|
|
1801
|
+
| clear | No | Clear the buffer |
|
|
1802
|
+
| clear\_mark | No | Clear the region mark |
|
|
1803
|
+
| copy\_region | No | Copy the text in the region to kill ring |
|
|
1804
|
+
| delete\_char\_backward | Yes | Delete char to the left of cursor |
|
|
1805
|
+
| delete\_char\_forward | Yes | Delete char to the right of cursor |
|
|
1806
|
+
| delete\_region | No | Delete the text in the region |
|
|
1807
|
+
| eol | No | Move cursor to end of buffer |
|
|
1808
|
+
| kill\_region | No | Kill the text in the region |
|
|
1809
|
+
| kill\_to\_bol | No | Kill the text from cursor to beginning |
|
|
1810
|
+
| kill\_to\_eol | No | Kill the text from cursor to end |
|
|
1811
|
+
| kill\_word\_backward | Yes | Kill the word to the left of cursor |
|
|
1812
|
+
| kill\_word\_forward | Yes | Kill the word to the right of cursor |
|
|
1813
|
+
| move\_left | Yes | Move cursor one char left |
|
|
1814
|
+
| move\_right | Yes | Move cursor one char right |
|
|
1815
|
+
| move\_word\_left | Yes | Move cursor one word left |
|
|
1816
|
+
| move\_word\_right | Yes | Move cursor one word right |
|
|
1817
|
+
| redo | No | Redo an undone action |
|
|
1818
|
+
| set\_mark | No | Set the region mark at cursor |
|
|
1819
|
+
| transpose\_chars | Yes | Switch position of char with prior char |
|
|
1820
|
+
| transpose\_words | Yes | Switch position of word with prior char |
|
|
1821
|
+
| undo | No | Revert last edit action |
|
|
1822
|
+
| yank | No | Copy kill ring to buffer at cursor |
|
|
1823
|
+
| yank\_pop | Yes | Copy next kill ring item and replace prior |
|
|
1824
|
+
|
|
1825
|
+
|
|
1826
|
+
<a id="org3f876b8"></a>
|
|
1827
|
+
|
|
1828
|
+
#### Input field actions
|
|
1829
|
+
|
|
1830
|
+
Input field actions operate on an editable input field. An input field occurs at the main input prompt, but also in things like search-narrowing input, incremental-search, a prompt for text, etc. It is lower level than the shell session input described in the next section. In particular, it can have its own history attached to it depending on its purpose. They handle accepting the current line, moving through history, and receiving pasted text.
|
|
1831
|
+
|
|
1832
|
+
| Action Name | Count? | Description |
|
|
1833
|
+
|------------- |------ |--------------------------------------------------------- |
|
|
1834
|
+
| accept\_line | No | Accept the current text as the input |
|
|
1835
|
+
| history\_prev | No | Insert the prior relevant history item in the input field |
|
|
1836
|
+
| history\_next | No | Insert the next relevant history item in the input field |
|
|
1837
|
+
|
|
1838
|
+
|
|
1839
|
+
<a id="orge0c4e6e"></a>
|
|
1840
|
+
|
|
1841
|
+
#### Shell session actions
|
|
1842
|
+
|
|
1843
|
+
Shell session actions operate at the session level around the main command input and output area. They submit input, interrupt running work, clear output, start completion, open completion/history popups, and manage numeric prefix entry.
|
|
1844
|
+
|
|
1845
|
+
| Action Name | Count? | Description |
|
|
1846
|
+
|-------------------- |------ |---------------------------------------------------------------- |
|
|
1847
|
+
| submit\_line | No | Pass the current text to the on\_accept proc and page output |
|
|
1848
|
+
| submit\_and\_scroll | No | Pass the current text to the on\_accept proc and scroll output |
|
|
1849
|
+
| interrupt | No | End the current session |
|
|
1850
|
+
| interrupt\_if\_empty | No | End the current session only if the current text is empty |
|
|
1851
|
+
| clear\_output | No | Clear the output pane |
|
|
1852
|
+
| complete | No | Suggest the next possible completion as an autosuggestion |
|
|
1853
|
+
| complete\_previous | No | Suggest the prior possible completion as an autosuggestion |
|
|
1854
|
+
| completion\_popup | No | Display all possible completions in a popup for selection |
|
|
1855
|
+
| history\_search | No | Display history item starting with the text-so-far for selection |
|
|
1856
|
+
| count\_digit | No | Add a digit to the numeric prefix |
|
|
1857
|
+
| universal\_argument | No | Set the numeric argument to 4 or multiply the current one by 4 |
|
|
1858
|
+
|
|
1859
|
+
|
|
1860
|
+
<a id="org05813c6"></a>
|
|
1861
|
+
|
|
1862
|
+
#### Pager actions
|
|
1863
|
+
|
|
1864
|
+
Pager actions navigate output when the output area is in paging mode. They move by line, page, top, bottom, or end of output, handle mouse-wheel scrolling, and switch between paging and scrolling behavior. Most movement actions honor the numeric prefix count.
|
|
1865
|
+
|
|
1866
|
+
| Action Name | Count? | Description |
|
|
1867
|
+
|--------------------- |------ |------------------------------------------------ |
|
|
1868
|
+
| page\_up | Yes | Move the output view one page up |
|
|
1869
|
+
| page\_down | Yes | Move the output view one page down |
|
|
1870
|
+
| end\_of\_output | No | Move the output to the end of output and scroll |
|
|
1871
|
+
| line\_up | Yes | Move the output view one line up |
|
|
1872
|
+
| line\_down | Yes | Move the output view one line down |
|
|
1873
|
+
| scroll\_up | Yes | Move the output view six lines up |
|
|
1874
|
+
| scroll\_down | Yes | Move the output view six lines down |
|
|
1875
|
+
| page\_top | Yes | Move to the beginning, or to the counted line |
|
|
1876
|
+
| page\_bottom | No | Move the output to the end of output |
|
|
1877
|
+
| paging\_to\_scrolling | No | Quit paging and scroll output as it is produced |
|
|
1878
|
+
| toggle\_paging | No | Toggle output mode between paging and scrolling |
|
|
1879
|
+
| quit\_paging | No | Quit paging and return control to the input line |
|
|
1880
|
+
|
|
1881
|
+
|
|
1882
|
+
<a id="orgea58518"></a>
|
|
1883
|
+
|
|
1884
|
+
#### Pager search actions
|
|
1885
|
+
|
|
1886
|
+
Pager search actions can *initiate* a search session within the pager: a string search, a regular expression search, or an incremental-search. Once a search session is entered, other actions navigate matches in the output. There are also actions to end a search session.
|
|
1887
|
+
|
|
1888
|
+
While the search session is active, accepting commits the current match and canceling restores the pager to the position it had when the search began. After the search is accepted, `n` and `N` repeat the committed search in the pager; at that point the search session is no longer active.
|
|
1889
|
+
|
|
1890
|
+
| Action Name | Count? | Description |
|
|
1891
|
+
|------------------------------ |------ |------------------------------------------------------------------- |
|
|
1892
|
+
| pager\_search\_forward | No | Initiate a string search forward from current output point |
|
|
1893
|
+
| pager\_search\_backward | No | Initiate a string search backward from current output point |
|
|
1894
|
+
| pager\_regex\_search\_forward | No | Initiate a regex search forward from current output point |
|
|
1895
|
+
| pager\_regex\_search\_backward | No | Initiate a regex search backward from current output point |
|
|
1896
|
+
| pager\_isearch\_forward | No | Initiate an incremental search forward from current output point |
|
|
1897
|
+
| pager\_isearch\_backward | No | Initiate an incremental search backward from current output point |
|
|
1898
|
+
| pager\_search\_next | No | Move output to the next search match |
|
|
1899
|
+
| pager\_search\_prev | No | Move output to the prior search match |
|
|
1900
|
+
| search\_toggle\_regex | No | Toggle between regex and string search |
|
|
1901
|
+
| search\_step\_forward | No | Preview the next match using the current search text |
|
|
1902
|
+
| search\_step\_backward | No | Preview the prior match using the current search text |
|
|
1903
|
+
| isearch\_next | No | Move output to the next isearch match |
|
|
1904
|
+
| isearch\_prev | No | Move output to the prior isearch match |
|
|
1905
|
+
| search\_accept | No | Commit the current search and close the search session |
|
|
1906
|
+
| search\_cancel | No | Cancel the active search session and restore its starting point |
|
|
1907
|
+
| isearch\_accept | No | Commit the current incremental search and close the search session |
|
|
1908
|
+
| isearch\_cancel | No | Cancel the active incremental search and restore its starting point |
|
|
1909
|
+
|
|
1910
|
+
|
|
1911
|
+
<a id="org6ea9ecc"></a>
|
|
1912
|
+
|
|
1913
|
+
#### Popup actions
|
|
1914
|
+
|
|
1915
|
+
Popup actions control selection and narrowing popups such as choose, menu, completion, and history popups. You can narrow the selections presented by typing in the input field presented. You can move through the list, accept or cancel the selection, page through choices, jump to the top or bottom, recenter the selection, and toggle selection in multi-select popups.
|
|
1916
|
+
|
|
1917
|
+
| Action Name | Count? | Description |
|
|
1918
|
+
|----------------------- |------ |--------------------------------------------------------- |
|
|
1919
|
+
| popup\_cancel | No | Close the popup and return its cancel\_value |
|
|
1920
|
+
| popup\_accept | No | Close the popup and return the selection |
|
|
1921
|
+
| popup\_next | No | Move the selection cursor to the next item |
|
|
1922
|
+
| popup\_prev | No | Move the selection cursor to the prior item |
|
|
1923
|
+
| popup\_page\_down | No | Move the selection list down one page |
|
|
1924
|
+
| popup\_page\_up | No | Move the selection list up one page |
|
|
1925
|
+
| popup\_top | No | Move to the top of the selection list |
|
|
1926
|
+
| popup\_bottom | No | Move to the bottom of the selection list |
|
|
1927
|
+
| popup\_recenter | No | Recenter the selection list on the current item |
|
|
1928
|
+
| popup\_toggle\_selected | No | In multi-select, toggle the selection of the current item |
|
|
1929
|
+
|
|
1930
|
+
|
|
1931
|
+
<a id="org8f3d6dc"></a>
|
|
1932
|
+
|
|
1933
|
+
#### Prompt popup actions
|
|
1934
|
+
|
|
1935
|
+
Prompt popup actions control prompt dialogs that collect a string from the user. They accept the prompt, cancel it, or cancel only when the prompt is empty.
|
|
1936
|
+
|
|
1937
|
+
| Action Name | Count? | Description |
|
|
1938
|
+
|------------------------- |------ |---------------------------------------------------- |
|
|
1939
|
+
| prompt\_accept | No | Close the prompt popup and return the current string |
|
|
1940
|
+
| prompt\_cancel | No | Close the prompt popup and return its cancel\_value |
|
|
1941
|
+
| prompt\_cancel\_if\_empty | No | Cancel only if the input buffer is empty |
|
|
1942
|
+
|
|
1943
|
+
|
|
1944
|
+
<a id="org4a9e2d4"></a>
|
|
1945
|
+
|
|
1946
|
+
#### Utility Actions
|
|
1947
|
+
|
|
1948
|
+
Some actions exist to support `Fatty`'s own input machinery and are not normally useful as ordinary user bindings. For example, `insert`, `replace`, and `paste` need text supplied by code: `paste` is used for bracketed paste events from the terminal and normalizes pasted text for a one-line input field; `self_insert` is selected automatically for printable characters. They are listed here for completeness.
|
|
1949
|
+
|
|
1950
|
+
| Action Name | Args | Count? | Description |
|
|
1951
|
+
|------------ |---- |------ |---------------------------------- |
|
|
1952
|
+
| insert | str | Yes | Insert the string at point |
|
|
1953
|
+
| self\_insert | | Yes | Insert the bound key at point |
|
|
1954
|
+
| replace | str | No | Replace the buffer with the string |
|
|
1955
|
+
| set | str | No | Alias for `replace` |
|
|
1956
|
+
| paste | str | No | Insert pasted text at point |
|
|
1957
|
+
|
|
1958
|
+
|
|
1959
|
+
<a id="org7e9ed87"></a>
|
|
1960
|
+
|
|
1961
|
+
## Themes `themes/`
|
|
1962
|
+
|
|
1963
|
+
|
|
1964
|
+
<a id="orgf951ab7"></a>
|
|
1965
|
+
|
|
1966
|
+
### Distributed Themes
|
|
1967
|
+
|
|
1968
|
+
As distributed, `fatty` comes with the following themes, most of which are based on popular themes used in many text editors and IDEs.
|
|
1969
|
+
|
|
1970
|
+
Within a `fatty` terminal, themes can be changed interactively. The default Emacs-style bindings include:
|
|
1971
|
+
|
|
1972
|
+
| Key | Action |
|
|
1973
|
+
|------- |--------------------------------------- |
|
|
1974
|
+
| `C-M-t` | cycle to the next loaded theme |
|
|
1975
|
+
| `M-=` | preview and choose a theme from a popup |
|
|
1976
|
+
|
|
1977
|
+
Here are the builtin themes:
|
|
1978
|
+
|
|
1979
|
+
| Name | Description |
|
|
1980
|
+
|----------------- |-------------------------------------------------- |
|
|
1981
|
+
| capuchin\_monk | A tribute to St. Francis of Assisi |
|
|
1982
|
+
| catppuccin\_latte | Pastel theme of the latte flavor |
|
|
1983
|
+
| catppuccin\_mocha | Pastel theme of the mocha flavor |
|
|
1984
|
+
| cyberpunk | Brash colorful theme |
|
|
1985
|
+
| dracula | Dark theme inspired by the Count |
|
|
1986
|
+
| everforest\_dark | Dark green-esque theme |
|
|
1987
|
+
| gruvbox\_dark | Engineered for focus, built for developers |
|
|
1988
|
+
| gruvbox\_light | Engineered for focus, built for developers |
|
|
1989
|
+
| mono | Minimal black-and-white theme |
|
|
1990
|
+
| monokai | Based on <https://monokai.pro/history> |
|
|
1991
|
+
| nordic | Shiver me timbers, it's northern |
|
|
1992
|
+
| onedark | Shameless imitation of Atom editor theme |
|
|
1993
|
+
| solarized\_dark | Ethan Schoonover's famous terminal theme |
|
|
1994
|
+
| solarized\_light | And its light variant |
|
|
1995
|
+
| terminal | Use the terminal's color scheme |
|
|
1996
|
+
| tokyo\_night | Celebrates the neon lights and dark vibes of Tokyo |
|
|
1997
|
+
| wordperfect | Nostalgic nod to the good old word processor |
|
|
1998
|
+
|
|
1999
|
+
|
|
2000
|
+
<a id="orgcf6fbb1"></a>
|
|
2001
|
+
|
|
2002
|
+
### Custom Themes
|
|
2003
|
+
|
|
2004
|
+
|
|
2005
|
+
<a id="orgb8ead89"></a>
|
|
2006
|
+
|
|
2007
|
+
#### Theme Name
|
|
2008
|
+
|
|
2009
|
+
A Fatty theme is a YAML file in the user-specific config directory (normally `~/.config/fatty/themes`) or the app-specific config directory (by default `~/.config/fatty/apps/<app_name>/themes`). The filename does not determine the theme name: the theme file must have a `name` field to set the name:
|
|
2010
|
+
|
|
2011
|
+
```yaml
|
|
2012
|
+
name: nordic
|
|
2013
|
+
```
|
|
2014
|
+
|
|
2015
|
+
|
|
2016
|
+
<a id="orgc49dfe9"></a>
|
|
2017
|
+
|
|
2018
|
+
#### Inheritance from Another Theme
|
|
2019
|
+
|
|
2020
|
+
Themes can inherit from other themes with the `inherit:` tag:
|
|
2021
|
+
|
|
2022
|
+
```yaml
|
|
2023
|
+
name: my_nordic
|
|
2024
|
+
inherit: nordic
|
|
2025
|
+
|
|
2026
|
+
output:
|
|
2027
|
+
fg: "#eeeeee"
|
|
2028
|
+
```
|
|
2029
|
+
|
|
2030
|
+
This means that all the theme setting from the `nordic` theme apply except to the extent changed by the rest of the `my_nordic` theme file.
|
|
2031
|
+
|
|
2032
|
+
|
|
2033
|
+
<a id="org371d3bb"></a>
|
|
2034
|
+
|
|
2035
|
+
#### Inheritance within a Theme
|
|
2036
|
+
|
|
2037
|
+
Not only may one theme inherit from another theme, some roles within a theme inherit from other roles. For example, the `input` role inherits from the `output` role.
|
|
2038
|
+
|
|
2039
|
+
Thus, a minimal theme can define only `output` and inherit everything else through Fatty's role defaults:
|
|
2040
|
+
|
|
2041
|
+
```yaml
|
|
2042
|
+
name: simple_dark
|
|
2043
|
+
inherit: null
|
|
2044
|
+
|
|
2045
|
+
output:
|
|
2046
|
+
fg: white
|
|
2047
|
+
bg: black
|
|
2048
|
+
```
|
|
2049
|
+
|
|
2050
|
+
This means that the input field will have the same coloring and attributes as the output pane.
|
|
2051
|
+
|
|
2052
|
+
|
|
2053
|
+
<a id="org83d0479"></a>
|
|
2054
|
+
|
|
2055
|
+
#### Theme Roles
|
|
2056
|
+
|
|
2057
|
+
Here is a listing of what roles act as the parent for each of the roles, their purpose, and the role, if any, from which they inherit.
|
|
2058
|
+
|
|
2059
|
+
| Role name | Used for | Parent Role |
|
|
2060
|
+
|----------------------- |----------------------------------------- |--------------------- |
|
|
2061
|
+
| `output` | Main output area text. | <none> |
|
|
2062
|
+
| `input` | Main command/input field. | `output` |
|
|
2063
|
+
| `input_suggestion` | Autosuggestion or completion suffix text. | `input` |
|
|
2064
|
+
| `cursor` | Cursor cell styling where applicable. | `input` |
|
|
2065
|
+
| `region` | Selected text / active region. | `output` |
|
|
2066
|
+
| `status` | Status area base role. | `output` |
|
|
2067
|
+
| `info` | Informational messages. | `output` |
|
|
2068
|
+
| `good` | Success messages. | `info` |
|
|
2069
|
+
| `warn` | Warning messages. | `info` |
|
|
2070
|
+
| `error` | Error messages. | `warn` |
|
|
2071
|
+
| `alert` | Alert panel base role. | `output` |
|
|
2072
|
+
| `pager_status` | Pager status / prompt row. | `status` |
|
|
2073
|
+
| `line_number` | Line numbers when toggled on | `output` |
|
|
2074
|
+
| `search_input` | Search input field. | `popup` |
|
|
2075
|
+
| `match_current` | Current search match. | `region` |
|
|
2076
|
+
| `match_other` | Other search matches. | `region` |
|
|
2077
|
+
| `popup` | Popup body. | `output` |
|
|
2078
|
+
| `popup_frame` | Popup border/frame. | `popup` |
|
|
2079
|
+
| `popup_input` | Popup filter/input field. | `input` |
|
|
2080
|
+
| `popup_selection` | Selected popup item row. | `region` |
|
|
2081
|
+
| `popup_counts` | Popup counts/status row. | `popup` |
|
|
2082
|
+
| `markdown_h1` | Markdown level-1 headings. | `output` |
|
|
2083
|
+
| `markdown_h2` | Markdown level-2 headings. | `markdown_h1` |
|
|
2084
|
+
| `markdown_h3` | Markdown level-3 headings. | `markdown_h2` |
|
|
2085
|
+
| `markdown_code` | Inline markdown code. | `output` |
|
|
2086
|
+
| `markdown_code_block` | Markdown fenced-code block base role. | `markdown_code` |
|
|
2087
|
+
| `markdown_code_gutter` | Code block gutter/prefix. | `markdown_code_block` |
|
|
2088
|
+
| `markdown_strong` | Markdown strong/bold text. | `output` |
|
|
2089
|
+
| `markdown_emphasis` | Markdown emphasized text. | `output` |
|
|
2090
|
+
| `markdown_link` | Markdown link text. | `output` |
|
|
2091
|
+
| `markdown_url` | Markdown displayed URL text. | `markdown_link` |
|
|
2092
|
+
| `markdown_quote_gutter` | Markdown block quote gutter. | `output` |
|
|
2093
|
+
| `markdown_highlight` | Markdown highlight / marked text. | `output` |
|
|
2094
|
+
| `markdown_table_header` | Markdown table header cells. | `markdown_strong` |
|
|
2095
|
+
| `markdown_table_cell` | Markdown table body cells. | `output` |
|
|
2096
|
+
| `markdown_underline` | Markdown underline text. | `output` |
|
|
2097
|
+
| `markdown_hrule` | Markdown horizontal rules. | `output` |
|
|
2098
|
+
|
|
2099
|
+
|
|
2100
|
+
<a id="orgabf70f2"></a>
|
|
2101
|
+
|
|
2102
|
+
#### Role Colors and Attributes and Frame Style
|
|
2103
|
+
|
|
2104
|
+
Each role can have assigned to it a foreground color (`fg:`), a background color (`bg:`), and one or more "attributes" (`attrs:`).
|
|
18
2105
|
|
|
2106
|
+
1. Colors
|
|
19
2107
|
|
|
20
|
-
|
|
2108
|
+
The colors can be a hex string of the form "#RRGGBB", that is a mixture of red, green, and blue at level given by three valid hexadecimal numbers RR, GG, and BB. For example "#FF0000" is pure red, "#330044" is a middling mixture of red and blue, a shade of purple. In addition, `fatty` recognizes color names defined as 16 ANSI colors, 256 xterm colors, and X11 colors, all of which you can see by invoking `fatty`'s CLI command `colors`.
|
|
2109
|
+
|
|
2110
|
+
The special color `default` means to inherit colors from the underlying terminal program.
|
|
21
2111
|
|
|
22
|
-
|
|
2112
|
+
2. Attributes
|
|
23
2113
|
|
|
24
|
-
|
|
2114
|
+
Each role can also have non-color attributes applied by specifying an `attrs` list. Supported attributes are `bold`, `dim`, `italic`, `underline`, and `reverse`. Italic is emitted by the truecolor renderer and by markdown ANSI output, but curses terminals may display it inconsistently or not at all.
|
|
25
2115
|
|
|
2116
|
+
3. Frame Style
|
|
26
2117
|
|
|
27
|
-
|
|
2118
|
+
In addition, one role, `popup_frame:`, in addition to these have two attributes for styling the "frame" drawn around popup:
|
|
2119
|
+
|
|
2120
|
+
| `border:` | single, double, or ascii |
|
|
2121
|
+
| `corners:` | rounded or square |
|
|
28
2122
|
|
|
29
|
-
|
|
2123
|
+
4. An Example Theme
|
|
30
2124
|
|
|
31
|
-
|
|
2125
|
+
```yaml
|
|
2126
|
+
name: example
|
|
2127
|
+
inherit: null
|
|
2128
|
+
|
|
2129
|
+
output:
|
|
2130
|
+
fg: "#d8dee9"
|
|
2131
|
+
bg: "#2e3440"
|
|
2132
|
+
|
|
2133
|
+
input:
|
|
2134
|
+
fg: "#eceff4"
|
|
2135
|
+
bg: "#3b4252"
|
|
2136
|
+
attrs: [bold]
|
|
2137
|
+
|
|
2138
|
+
input_suggestion:
|
|
2139
|
+
fg: "#81a1c1"
|
|
2140
|
+
bg: "#3b4252"
|
|
2141
|
+
|
|
2142
|
+
cursor:
|
|
2143
|
+
fg: "#2e3440"
|
|
2144
|
+
bg: "#88c0d0"
|
|
2145
|
+
|
|
2146
|
+
region:
|
|
2147
|
+
fg: "#2e3440"
|
|
2148
|
+
bg: "#88c0d0"
|
|
2149
|
+
|
|
2150
|
+
info:
|
|
2151
|
+
fg: "#d8dee9"
|
|
2152
|
+
bg: "#2e3440"
|
|
2153
|
+
|
|
2154
|
+
good:
|
|
2155
|
+
fg: green
|
|
2156
|
+
bg: "#2e3440"
|
|
2157
|
+
|
|
2158
|
+
warn:
|
|
2159
|
+
fg: "#2e3440"
|
|
2160
|
+
bg: "#ebcb8b"
|
|
2161
|
+
|
|
2162
|
+
error:
|
|
2163
|
+
fg: "#eceff4"
|
|
2164
|
+
bg: "#bf616a"
|
|
2165
|
+
|
|
2166
|
+
pager_status:
|
|
2167
|
+
fg: black
|
|
2168
|
+
bg: lightgreen
|
|
2169
|
+
|
|
2170
|
+
search_input:
|
|
2171
|
+
fg: black
|
|
2172
|
+
bg: cyan
|
|
2173
|
+
|
|
2174
|
+
match_current:
|
|
2175
|
+
fg: black
|
|
2176
|
+
bg: yellow
|
|
2177
|
+
|
|
2178
|
+
match_other:
|
|
2179
|
+
fg: black
|
|
2180
|
+
bg: lightgray
|
|
2181
|
+
|
|
2182
|
+
popup:
|
|
2183
|
+
fg: "#d8dee9"
|
|
2184
|
+
bg: "#3b4252"
|
|
2185
|
+
|
|
2186
|
+
popup_input:
|
|
2187
|
+
fg: "#eceff4"
|
|
2188
|
+
bg: "#434c5e"
|
|
2189
|
+
|
|
2190
|
+
popup_selection:
|
|
2191
|
+
fg: "#2e3440"
|
|
2192
|
+
bg: "#88c0d0"
|
|
2193
|
+
|
|
2194
|
+
popup_counts:
|
|
2195
|
+
fg: "#2e3440"
|
|
2196
|
+
bg: white
|
|
2197
|
+
|
|
2198
|
+
popup_frame:
|
|
2199
|
+
fg: "#81a1c1"
|
|
2200
|
+
bg: "#3b4252"
|
|
2201
|
+
border: single
|
|
2202
|
+
corners: rounded
|
|
2203
|
+
```
|
|
2204
|
+
|
|
2205
|
+
Or you can group them under `markdown` without the `markdown_` prefix:
|
|
2206
|
+
|
|
2207
|
+
```yaml
|
|
2208
|
+
markdown:
|
|
2209
|
+
h1:
|
|
2210
|
+
fg: yellow
|
|
2211
|
+
bg: navy
|
|
2212
|
+
attrs: [bold]
|
|
2213
|
+
code:
|
|
2214
|
+
fg: lightgreen
|
|
2215
|
+
bg: black
|
|
2216
|
+
link:
|
|
2217
|
+
fg: cyan
|
|
2218
|
+
bg: navy
|
|
2219
|
+
attrs: [underline]
|
|
2220
|
+
```
|