rcurses 4.9.0 → 4.9.1

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.
data/README.md CHANGED
@@ -1,257 +1,585 @@
1
- # rcurses - An alternative curses library written in pure Ruby
1
+ # RTFM - Ruby Terminal File Manager
2
2
 
3
- ![Ruby](https://img.shields.io/badge/language-Ruby-red) [![Gem Version](https://badge.fury.io/rb/rcurses.svg)](https://badge.fury.io/rb/rcurses) ![Unlicense](https://img.shields.io/badge/license-Unlicense-green) ![Stay Amazing](https://img.shields.io/badge/Stay-Amazing-important)
4
-
5
- <img src="img/rcurses-logo.png" width="150" height="150">
6
-
7
- Create curses applications for the terminal easier than ever.
8
-
9
- Here's a somewhat simple example of a TUI program using rcurses: The [T-REX](https://github.com/isene/T-REX) calculator.
10
-
11
- And here's a much more involved example: The [RTFM](https://github.com/isene/RTFM) terminal file manager.
12
-
13
- # NOTE: Version 4.5 gives full RGB support in addition to 256-colors
14
- Just write a color as a string - e.g. `"d533e0"` for a hexadecimal RGB color (or use the terminal 256 colors by supplying an integer in the range 0-255)
3
+ ![Ruby](https://img.shields.io/badge/language-Ruby-red) [![Gem Version](https://badge.fury.io/rb/rtfm-filemanager.svg)](https://badge.fury.io/rb/rtfm-filemanager) ![Unlicense](https://img.shields.io/badge/license-Unlicense-green) ![Stay Amazing](https://img.shields.io/badge/Stay-Amazing-important)
4
+
5
+ ## Version 5
6
+
7
+ Version 5 is a complete rewrite of RTFM using
8
+ [rcurses](https://github.com/isene/rcurses) as the underlying library. With
9
+ this, RTFM gains more stability, higher quality code and more features.
10
+
11
+ Among the new version 5 features are an optional trash bin, advanced OpenAI
12
+ integrations, plugin architectures for keybindings, user defined features and
13
+ file viewers. You also get better feedback, better visuals, more error
14
+ capture. Plenty.
15
+
16
+ The major feature additions in v5 are marked in ***bold italic***.
17
+
18
+ ## What?
19
+ <img src="img/logo.png" align="left" width="150" height="150"> RTFM is a
20
+ terminal file manager jam packed with features.
21
+
22
+ Apart from viewing and manipulating directories, you get syntax highlighting
23
+ of file content, image and video thumbnailing in the terminal, OpenAI
24
+ integration, system info panel, git status, fzf and navi integration and much,
25
+ much more.
26
+
27
+ Note: RTFM (Ruby Terminal File Manager) works best with the (u)rxvt, xterm and
28
+ Eterm terminal emulators.
29
+
30
+ ### Features
31
+ RTFM is one of the most feature rich terminal file managers. Some of the
32
+ features are:
33
+
34
+ * RTFM parses your LS_COLORS to ensure color consistency with the terminal experience
35
+ * Images are shown inline in the terminal (can be turned off)
36
+ * File contents is shown with proper syntax highlighting
37
+ * Item's meta data is shown at the top
38
+ * Easily browse file content (pdf, MS/OpenOffice, etc.)
39
+ * Move around the file systems using arrow keys or VI keys
40
+ * Copy, move, rename, symlink and delete files easily
41
+ * Simply use 'r' in your terminal to launch RTFM - and exit into the directory where you ended RTFM
42
+ * ***Toggle the use of a "trash bin" to move dirs/files there instead of deleting***
43
+ * Easily copy an item's path to clipboard or primary selection
44
+ * Order items the way you want, see only files of a certain type
45
+ * Filter out all files not matching a [regex](https://www.rubyguides.com/2015/06/ruby-regex/) pattern
46
+ * Mark files and directories and do group actions on them
47
+ * Bookmark directories for easy jumping
48
+ * Follow a symlink to where it points with one key stroke
49
+ * Highlight files and directories matching a given pattern
50
+ * Find items using `locate` and jump directly to the desired item
51
+ * Find items and jump there using fuzzy search (with [fzf](https://github.com/junegunn/fzf))
52
+ * Execute any shell command from inside RTFM - ***incuding other curses applications***
53
+ * [navi](https://github.com/denisidoro/navi) integration for easier command executions
54
+ * Easily unpack or create archives
55
+ * Show git status for the current directory
56
+ * Show comprehensive system info (processes running, disk space, dmesg, etc.)
57
+ * See if a directory (with sub dirs) has changed using cryptographic hashes
58
+ * Integration with OpenAI to get an executive summary of file content
59
+ * ***OpenAI chat integrated; Discuss files, content, commands with OpenAI***
60
+ * ***Enhanced tab management*** with duplication, renaming, and smart navigation
61
+ * ***Improved stability*** with simplified architecture and eliminated flickering
62
+ * ***Automatic image redraw*** after workspace switching (i3-wm compatible)
63
+ * Possibility to change top line background when matching a path
64
+ * Theming of pane colors
65
+
66
+ ## Why?
67
+ The idea came to mind as I was working on [a complete LS_COLORS
68
+ setup](https://github.com/isene/LS_COLORS) with a corresponding
69
+ [ranger](https://ranger.github.io/) theme. But making a separate theme for
70
+ ranger to mimic a massive LS_COLOR setup is rather stupid. File managers
71
+ should parse LS_COLORS as default rather than implement their own themes. This
72
+ became an itch that I kept scratching until I could happily replace ranger two
73
+ weeks later. But, coding RTFM based on the old curses library was clumsy,
74
+ inefficient and painful. So I decided to create
75
+ [rcurses](https://github.com/isene/rcurses) - a complete curses library
76
+ written from scratch in pure Ruby - and from v5 and onwards, RTFM is based
77
+ completely on this modern curses implementation.
78
+
79
+ ## How?
80
+ RTFM is a modern two-pane file manager with **enhanced tab support** for multi-directory navigation. You navigate in the left pane and the content of the selected item (directory or file) is shown in the right pane. The right pane is also used to show information such as the currently tagged items, your (book)marks, output from commands, error messages, etc.
81
+
82
+ The **tab system** is visible in the top-right corner showing your current position like `[2/5]` (tab 2 of 5 total tabs). The tab bar displays when you have multiple tabs or use tab commands, showing directory names and management shortcuts.
83
+
84
+ **Enhanced Tab Features:**
85
+ * **Multiple tabs** for easy multi-directory management
86
+ * **Tab duplication** (`}`) to quickly copy current directory context
87
+ * **Tab renaming** (`{`) for better organization
88
+ * **Smart tab display** showing current directory and shortcuts
89
+ * **Quick tab switching** with number keys (1-9), J/K navigation
90
+ * **Visual tab indicator** in top-right corner `[current/total]`
91
+
92
+ When you start RTFM, you can supply a directory path as an argument to let
93
+ RTFM start up in that directory. When you exit it exits into the current RTFM
94
+ directory.
95
+
96
+ You can run any command in the bottom "command bar" and have the output
97
+ presented in the right pane. History of commands are preserved like in your
98
+ shell.
99
+
100
+ ## Installation
101
+ You can install RTFM by cloning this repo and put the file `rtfm` in your
102
+ "bin" directory. If you do, you need to install
103
+ [rcurses](https://github.com/isene/rcurses) first.
104
+
105
+ Or you can simply run `gem install rtfm-filemanager`.
106
+
107
+ There are two basic prerequisites needed: `x11-utils` and `xdotool`. On
108
+ Ubuntu these would be installed via `apt install x11-utils xdotool`.
109
+
110
+ Content of text files are handled by `cat` - or by `bat` if you want beautiful
111
+ highlighting. Other files are shown via external programs (Debian/Ubuntu
112
+ family of Linux distros command in last column):
113
+
114
+ File type | Requirements | Installation
115
+ ----------------------------|----------------------------------|-------------------------------
116
+ Syntax highlighting of text | `bat` | `apt install bat`
117
+ Markdown | `pandoc` | `apt install pandoc`
118
+ PDFs | `pdftotext` | `apt install poppler-utils`
119
+ LibreOffice | `odt2txt` | `apt install odt2txt`
120
+ MS docx | `docx2txt` | `apt install docx2txt`
121
+ MS pptx | `unzip` | `apt install unzip`
122
+ MS xlsx | `ssconvert` | `apt install gnumeric`
123
+ MS doc/xls/ppt | `catdoc`, `xls2csv` and `catppt` | `apt install catdoc`
124
+ Images | `w3m` and `ImageMagick` | `apt install w3m imagemagick`
125
+ Video (thumbnails) | `ffmpegthumbnailer` | `apt install ffmpegthumbnailer`
126
+
127
+ Install rtfm from scratch with all of the above on Ubuntu:
128
+ ```
129
+ sudo apt update
130
+ sudo apt install ruby-full git libncurses-dev x11-utils xdotool bat pandoc poppler-utils odt2txt docx2txt unzip gnumeric catdoc w3m imagemagick ffmpegthumbnailer
131
+ sudo gem install rcurses
132
+ git clone https://github.com/isene/RTFM
133
+ cd RTFM
134
+ sudo cp rtfm /usr/bin/
135
+ ```
136
+ Or with a simpler gem install:
137
+ ```
138
+ sudo apt update
139
+ sudo apt install ruby-full git libncurses-dev x11-utils xdotool bat pandoc poppler-utils odt2txt docx2txt unzip gnumeric catdoc w3m imagemagick ffmpegthumbnailer
140
+ gem install rtfm-filemanager
141
+ ```
15
142
 
16
- # Why?
17
- Having struggled with the venerable curses library and the ruby interface to it for many years, I finally got around to write an alternative - in pure Ruby.
143
+ ## Screenshot
144
+ ![RTFM screenshot](img/screenshot-logo.png)
145
+
146
+
147
+ ## Image preview in the terminal
148
+ RTFM uses w3mimgdisplay (part of the w3m package) to show images in the
149
+ terminal. Some terminals have an issue with this - either the images don't
150
+ show, the previous image is not cleared (new image overlaps the previous) or
151
+ they show for only a flash or a few seconds. The table below shows how the
152
+ most popular terminals fare with this. An "O" indicates that the terminal is
153
+ OK, while an "X" indicates that it fails:
154
+
155
+ Terminal |Images | No overlap | Images stay
156
+ --------------|-------|------------|-----------
157
+ (u)rxvt | O | O | O
158
+ xterm | O | O | O
159
+ Eterm | O | O | O
160
+ kitty | O | O | O
161
+ alacritty | O | O | X
162
+ terminology | O | O | X
163
+ stterm | O | O | X
164
+ gnome-terminal| O | X |
165
+ xfce4-terminal| O | X |
166
+ mate-terminal | O | X |
167
+ lilyterm | O | X |
168
+ termit | X | |
169
+ lxterminal | X | |
170
+ qterminal | X | |
171
+
172
+
173
+ ## Keys
174
+ These are the set of keys to move around and do actions within RTFM:
175
+
176
+ ### Basic keys
177
+ Key | Description
178
+ ---------|------------------------------------------------------------------
179
+ ? | Show this help text
180
+ v | Display RTFM version (and latest Gem version) in bottom window/command bar
181
+ r | Refresh RTFM (recreates all windows. Use on terminal resize or when there is garbage somewhere)
182
+ R | Reload configuration (~/.rtfm/conf)
183
+ W | Write parameters to ~/.rtfm/conf: @marks, @hash, @history, @rubyhistory, @aihistory, @lslong, @lsall, @lsorder, @lsinvert, @width, @border, @preview, @trash
184
+ C | ***Show the current configuration in ~/.rtfm/conf***
185
+ q | Quit (save basic configuration: @marks, @hash, @history, @rubyhistory, @aihistory)
186
+ Q | QUIT (without writing any changes to the config file)
187
+
188
+ ### Layout
189
+ Key | Description
190
+ ---------|------------------------------------------------------------------
191
+ w | Change the width of the left/right panes (left pane ⇒ 20%, 30%, 40%, 50%, 60%)
192
+ B | Cycle border
193
+ \- | (Minus sign) Toggle preview in right pane (turn it off for faster traversing of directories)
194
+ _ | (Underscore) Toggle preview of images in right pane
195
+ b | Toggle syntax highlighting (and line numbering)
196
+
197
+ ### Motion
198
+ Key | Description
199
+ ---------|------------------------------------------------------------------
200
+ j/DOWN | Go one item down in left pane (rounds to top)
201
+ k/UP | Go one item up in left pane (rounds to bottom)
202
+ h/LEFT | Go up one directory level
203
+ l/RIGHT | Enter directory or open file (using run-mailcap or xdg-open) Use the key 'x' to force open using xdg-open (or run-mailcap) - used for opening html files in a browser rather than editing the file in your text editor
204
+ PgDown | Go one page down in left pane
205
+ PgUp | Go one page up in left pane
206
+ END | Go to last item in left pane
207
+ HOME | Go to first item in left pane
208
+
209
+ ### Marks and jumping
210
+ Key | Description
211
+ ---------|------------------------------------------------------------------
212
+ m | Mark current dir (persistent). Next letter is the name of the mark [a-zA-Z'] The special mark "'" jumps to the last directory (makes toggling dirs easy) Press '-' and a letter to delete that mark. Mark '0' is the dir where RTFM was started. Marks '1' - '5' are the past five directories visited
213
+ M | Show marked items in right pane
214
+ ' | Jump to mark (next letter is the name of the mark [a-zA-Z']) The 5 latest directories visited are stored in marks 1-5 (1 being the very latest)
215
+ ~ | Jump to Home directory
216
+ \> | Follow symlink to the directory where the target resides
217
+
218
+ ### Directory views
219
+ Key | Description
220
+ ---------|------------------------------------------------------------------
221
+ a | Show all (also hidden) items
222
+ A | Show long info per item (show item attributes)
223
+ o | Change the order/sorting of directories (circular toggle)
224
+ i | Invert/reverse the sorting
225
+ O | Show the Ordering in the bottom window (the full ls command)
226
+
227
+ ### Tagging
228
+ Key | Description
229
+ ---------|------------------------------------------------------------------
230
+ t | Tag item (toggles)
231
+ Ctrl-t | Add items matching a pattern to list of tagged items (Ctrl-t and then . will tag all items)
232
+ T | Show currently tagged items in right pane
233
+ u | Untag all tagged items
234
+
235
+ ### Tab management
236
+ Key | Description
237
+ ---------|------------------------------------------------------------------
238
+ ] | Create new tab in current directory
239
+ [ | Close current tab (keeps at least one tab open)
240
+ J | Previous tab (wraps around)
241
+ K | Next tab (wraps around)
242
+ } | Duplicate current tab (creates a copy with same directory)
243
+ { | Rename current tab
244
+ 1-9 | Switch to tab by number (1 = first tab, 2 = second tab, etc.)
245
+
246
+ ### Manipulate items
247
+ Key | Description
248
+ ---------|------------------------------------------------------------------
249
+ p | Put (copy) tagged items here
250
+ P | PUT (move) tagged items here
251
+ c | Change/rename selected (adds command to bottom window)
252
+ s | Create symlink to tagged items here
253
+ d | Delete selected item and tagged items. Confirm with 'y'. ***Moves items to trash directory (~/.rtfm/trash/) if @trash | true***
254
+ D | ***Empty trash directory***
255
+ Ctrl-d | ***Toggle use of trash directory***
256
+ Ctrl-o | Change ownership to user:group of selected and tagged items
257
+ Ctrl-p | Change permissions of selected and tagged items
258
+ Format | rwxr-xr-x or 755 or rwx (applies the trio to user, group and others)
259
+
260
+ ### Filter and search
261
+ Key | Description
262
+ ---------|------------------------------------------------------------------
263
+ f | Show only files in the left pane matching extension(s) (e.g. "txt" or "pdf,png,jpg")
264
+ F | Show only files matching a pattern (Ruby Regex) (e.g. "abc" or "ab.+12(\w3)+")
265
+ Ctrl-f | Clear all filtering
266
+ / | Enter search string in bottom window to highlight matching items and jump to the first match
267
+ \\ | Remove search pattern
268
+ n | Jump to the next item matched by '/'
269
+ N | Jump to the previous item matched by '/'
270
+ g | Run 'grep' to show files that contains the MATCH in current directory
271
+ L | Start 'locate' search for files, then use '#' to jump to desired line/directory
272
+ Ctrl-l | Locate files via fzf from the current directory down (fuzzy file finder must be installed https://github.com/junegunn/fzf)
273
+
274
+ ### Archives
275
+ Key | Description
276
+ ---------|------------------------------------------------------------------
277
+ z | Extract tagged zipped archive to current directory
278
+ Z | Create zipped archive from tagged files/directories
279
+
280
+ ### Git/hash/openai
281
+ Key | Description
282
+ ---------|------------------------------------------------------------------
283
+ G | Show git status for current directory
284
+ H | Do a cryptographic hash of the current directory with subdirs. If a previous hash was made, compare and report if there has been any change
285
+ I | Show OpenAI's description of the selected item and its content (if available). You must have installed the ruby-openai gem and added your openai secret key in the ~/.rtfm/conf (add `@ai | "your-secret-openai-key") for this to work.
286
+ Ctrl-a | ***Start an OpenAI chat (the context window is kept until you exit RTFM). The OpenAI agent is specialized in answering questions about cli, files and dirs***
287
+
288
+ ### Right pane controls
289
+ Key | Description
290
+ ---------|------------------------------------------------------------------
291
+ ENTER | Refresh the right pane
292
+ S-RIGHT | ***One line down in the preview***
293
+ S-LEFT | ***One line up in the preview***
294
+ S-DOWN | ***Next page of the preview (if doc long and ∇ in the bottom right)*** (TAB does the same)
295
+ S-UP | ***Previous page (if you have moved down the document first - ∆ in the top right)*** (or S-TAB)
296
+
297
+ ### Clipboard copy
298
+ Key | Description
299
+ ---------|------------------------------------------------------------------
300
+ y | Copy path of selected item to primary selection (for pasting with middle mouse button)
301
+ Y | Copy path of selected item to clipboard
302
+ Ctrl-y | Copy content of right pane to clipboard (turn off batcat syntax highlighting with 'b' for a clean copy of content)
303
+
304
+ ### System shortcuts
305
+ Key | Description
306
+ ---------|------------------------------------------------------------------
307
+ S | Show comprehensive System info (system, CPU, filesystem, latest dmesg messages)
308
+ = | Create a new directory (a shortcut for ":mkdir ")
309
+ Ctrl-n | Invoke navi (see https://github.com/denisidoro/navi) with any output in right window
310
+
311
+ ### Command mode
312
+ Key | Description
313
+ ---------|------------------------------------------------------------------
314
+ : | Enter "command mode" in bottom window (press ENTER to execute, press ESC to escape). Prefix the command with a '§' to force the program to run in interactive mode (full screen TUI programs like htop, vim or any shell)
315
+ ; | Show command history in right pane
316
+ \+ | ***Add program(s) to the list of full-UI interactive terminal programs***
317
+
318
+
319
+ ### Ruby debug mode
320
+ Key | Description
321
+ ---------|------------------------------------------------------------------
322
+ @ | Enter Ruby mode to execute any Ruby command (ENTER to execute, ESC to escape)
323
+
324
+
325
+ ## Keyboard cheat sheet
326
+ ![RTFM keyboard cheat sheet](img/rtfm-kb.png)
327
+
328
+ ## First run
329
+ The first time you run RTFM, you are greeted with a welcome message. RTFM will
330
+ add a simple function to your shell (bash, zsh, fish, maybe others) that will
331
+ let you launch RTFM via the one key command `r`. It also lets RTFM exit in the
332
+ directory you are currently in (inside of RTFM) rather than where you launched
333
+ RTFM.
334
+
335
+ With this, you can jump around in your directory structure via RTFM, exit to
336
+ the desired directory, do work in the terminal and go back into RTFM via `r`.
337
+
338
+ If you want to launch rtfm straight into a specified directory, do this
339
+ instead: `rtfm ~/mydir/subdir`
340
+
341
+ ## Configuration file
342
+ When you first exit RTFM, it will write your (book)marks and the set of tagged
343
+ files to `.rtfm/conf`. This ensures your marks and tagged files are
344
+ persistent. It also means you can launch rtfm tag a bunch of dirs and files,
345
+ drop out back to the terminal to do some work, back into rtfm and resume to
346
+ work with your previously tagged items.
347
+
348
+ You can also set persistent variables in the config file manually:
349
+
350
+ To have long info per item: `@lslong = true` (this is otherwise set to `false`)
351
+
352
+ To show hidden files: `@lsall = "-a"` (this is otherwise set to `""`)
353
+
354
+ To set a specific order for ls: `@lsorder = "-S"` (to order by size).
355
+
356
+ To revert your ls order: `@lsinvert = "-r"`
357
+
358
+ To set any additional 'ls' switches, set the variable `@lsuser`. To not list
359
+ any files containg the word "test", you could do this:
360
+ ```
361
+ @lsuser = "--ignore=test"
362
+ ```
363
+ To suppress image viewing in the terminal: `@showimage = false`
18
364
 
19
- # Design principles
20
- Simple and with minimum of external dependencies.
365
+ To suppress showing any content in the right pane: `@preview = false`
21
366
 
22
- # Installation
23
- Simply run `gem install rcurses`.
367
+ To change the default width of the left pane: `@width = 5` (experiment with numbers 2-8).
24
368
 
25
- To use this library do:
26
- ```
27
- require 'rcurses'
28
- ```
369
+ To toggle borders in RTFM: `@border = 1` (any number 0-3)
29
370
 
30
- # Features
31
- * Create panes (with the colors and(or border), manipulate the panes and add content
32
- * Dress up text (in panes or anywhere in the terminal) in bold, italic, underline, reverse color, blink and in any 256 terminal colors for foreground and background
33
- * Use a simple editor to let users edit text in panes
34
- * Left, right or center align text in panes
35
- * Cursor movement around the terminal
36
-
37
- # The elements
38
- `rcurses` gives you the following elements:
39
- * The class `Pane` to create and manilpulate panes/boxes
40
- * Extensions to the class String to print text in various degrees of fancy and also strip any fanciness
41
- * A module `Cursor` to give you cursor movements around the terminal
42
- * A module `Rinput` providing the function `getchr` to capture a single character input from the user (much better than any Ruby built-ins)
43
-
44
- # class Pane
45
- To create a pane do something like this:
371
+ To have some commands already prepared for the command history, you can set:
46
372
  ```
47
- mypane = Rcurses::Pane.new(80, 30, 30, 10, 19, 229)
373
+ @history = ["cat /home/me/MyTodo.txt", "neofetch --stdout"]
48
374
  ```
49
- This will create a pane/box starting at terminal column/x 80 and row/y 30 with the width of 30 characters and a hight of 10 characters and with the foreground color 19 and background color 229 (from the 256 choices available)
50
-
51
- The format for creating a pane is:
375
+ To open files with `run-mailcap` instead of `open-xdg` set:
52
376
  ```
53
- Rcurses::Pane.new(x, y, w, h, fg, bg)
377
+ @runmailcap = true
54
378
  ```
55
- You can drop the last two 256-color codes to create a pane with the defaults for your terminal.
56
-
57
- By adding values for the terminal size in your program:
379
+ ***To use the trash bin: `@trash = true`***
380
+
381
+ ***To change the list of "whitelisted full-UI programs", change the variable @interactive.
382
+ This is a comma separated string listing all programs that can be run from
383
+ within RTFM's "command mode" (via the key `:`). Programs such as `htop`, `vim`
384
+ and all shells will take over the terminal when they run and need explicit
385
+ permission via this variable to be able to "replace" RTFM in the terminal.
386
+ When you exit such a whitelisted program, RTFM resumes control. If you try to
387
+ run such a program while it is not whitelisted, it will hang the terminal. To
388
+ add a program to the whitelist inside RTFM, press the `+` key. All ususal
389
+ shell comands that do not take over the full terminal such as `ls`, `touch`,
390
+ `neofetch`, etc. will run just fine in command mode without being whitelisted.
391
+ You can also explicitly run a program as interactive by prefixing the command
392
+ with a single `§` - e.g. `:` `§saidar`. Programs added to @interactive will
393
+ open as interactive also when opened via xdg-open or runmailcap (when you
394
+ press `RIGHT` on a selected item).***
395
+
396
+ All the variables above that you manually add to the top of the config files are
397
+ undisturbed by launching and exiting RTFM.
398
+
399
+ You can structure the config file the way you want. Let your OCD make it pretty.
400
+
401
+ You can use `W` inside of RTFM to write all the parameters mentioned above to
402
+ the config file - instead of adding them manually. Example: You press `+` to
403
+ add `emacs` to your list of whitelisted interactive programs. Then you would
404
+ want to press `W` to update @interactive in your config file so that `emacs`
405
+ is permanently whitelisted as an interactive program for you.
406
+
407
+ To exit RTFM without writing any changes to you marks or list of tagged items,
408
+ exit with `Q`. They will then remain the same as when you launched RTFM for
409
+ that session.
410
+
411
+ ## Extra info
412
+ The top line shows information about the currently item in the left pane. When
413
+ you are at a file, the information is pretty self explanatory:
414
+
415
+ `Path: /home/geir/RTFM/README.md (-rw-r--r-- geir:geir 2023-04-25 11:49 16K)`
416
+
417
+ This shows the full path of the selected file as well as the permissions,
418
+ ownership, timestamp and the size of the file. When you are at a directory in
419
+ the left pane, you get two numbers in brackets. The first number is the number
420
+ of regular dirs/files in that directory. The second shows the total number of
421
+ entries, including the hidden directories and files:
422
+
423
+ `Path: /home/geir/RTFM (drwxr-xr-x geir:geir 2023-04-29 01:55 4,0) [4 8]`
424
+
425
+ Different file types may have extra self explanatory information included in
426
+ square brackets at the end of the top info line. Image files will have the
427
+ size of the image included while pdf files will have the number of pages. More
428
+ file specific information will be included when I feel like adding such.
429
+
430
+ ## Top and bottom line background colors
431
+ You can customize the background colors for the top and bottom lines/panes.
432
+
433
+ Bottom color is by default `238`. Change it by setting @bottomcolor to your
434
+ desired colors in your `.rtfm/conf`.
435
+
436
+ You can also set the background color at the bottom when you enter command
437
+ mode (via `:`) by setting @cmdcolor and the Ruby mode (via `@`) by setting
438
+ @rubycolor.
439
+
440
+ Background color for OpenAI chats (invoked with `Ctrl-a`) is set with @aicolor.
441
+
442
+ You can set the variable `@topmatch` in your `.rtfm/conf` so that it will change
443
+ the background color of the top line/pane when you are in a directory matching
444
+ a pattern.
445
+
446
+ Example:
58
447
  ```
59
- @max_h, @max_w = IO.console.winsize
448
+ @topmatch = [["passionfruit", 165], ["kiwi", 50], ["", 238]]
60
449
  ```
61
- ...you can use these values to create proportinally sized panes. So, a hight value of "@max_h/2" is valid to create a pane with the height of half the terminal height (the integer corresponding to half the terminal height will then be accessible as the variable `h`). Use the variables `@max_h` for terminal height and `@max_w` for terminal width.
62
-
63
- Avaliable properties/variables:
64
-
65
- Property | Description
66
- ---------------|---------------------------------------------------------------
67
- x | The x (column) position of the Pane
68
- y | The y (row) position of the Pane
69
- w | The width of the Pane
70
- h | The heigth of the Pane
71
- fg | Foreground color for the Pane
72
- bg | Background color for the Pane
73
- border | Draw border around the Pane (=true) or not (=false), default being false
74
- scroll | Whether to indicate more text to be shown above/below the Pane, default is true
75
- text | The text/content of the Pane
76
- ix | The line number at the top of the Pane, starts at 0, the first line of text in the Pane
77
- index | An attribute that can be used to track the selected line/element in the pane
78
- align | Text alignment in the Pane: "l" = lefts aligned, "c" = center, "r" = right, with the default "l"
79
- prompt | The prompt to print at the beginning of a one-liner Pane used as an input box
80
- moreup | Set to true when there is more text above what is shown (top scroll bar i showing)
81
- moredown | Set to true when there is more text below what is shown (bottom scroll bar i showing)
82
-
83
- The methods for Pane:
84
-
85
- Method | Description
86
- ---------------|---------------------------------------------------------------
87
- new/init | Initializes a Pane with optional arguments `x, y, w, h, fg and bg`
88
- move(x,y) | Move the pane by `x`and `y` (`mypane.move(-4,5)` will move the pane left four characters and five characters down)
89
- refresh | Refreshes/redraws the Pane with content
90
- border_refresh | Refresh the Pane border only
91
- full_refresh | Refreshes/redraws the Pane with content completely (without diff rendering)
92
- edit | An editor for the Pane. When this is invoked, all existing font dressing is stripped and the user gets to edit the raw text. The user can add font effects similar to Markdown; Use an asterisk before and after text to be drawn in bold, text between forward-slashes become italic, and underline before and after text means the text will be underlined, a hash-sign before and after text makes the text reverse colored. You can also combine a whole set of dressings in this format: `<23,245,biurl\|Hello World!>` - this will make "Hello World!" print in the color 23 with the background color 245 (regardless of the Pane's fg/bg setting) in bold, italic, underlined, reversed colored and blinking. Hitting `ESC` while in edit mode will disregard the edits, while `Ctrl-S` will save the edits
93
- editline | Used for one-line Panes. It will print the content of the property `prompt` and then the property `text` that can then be edited by the user. Hitting `ESC` will disregard the edits, while `ENTER` will save the edited text
94
- clear | Clears the pane
95
- say(text) | Short form for setting panel.text, then doing a refresh of that panel
96
- ask(prompt,text) | Short form of setting panel.prompt, then panel.text, doing a panel.editline and then returning panel.text
97
- pagedown | Scroll down one page height in the text (minus one line), but not longer than the length of the text
98
- pageup | Scroll up one page height in the text (minus one line)
99
- linedown | Scroll down one line in the text
100
- lineup | Scroll up one line in the text
101
- bottom | Scroll to the bottom of the text in the pane
102
- top | Scroll to the top of the text in the pane
103
-
104
- # class String extensions
105
- Method extensions provided for the class String.
106
-
107
- A color can either be an integer in the range 0-255 for the usual 256 colors in a terminal, or it can be a string representing RGB. So both of these are valid: `string.fg(219)` and `string.fg("4d22a0")`.
108
-
109
- Method | Description
110
- ---------------|---------------------------------------------------------------
111
- fg(fg) | Set text to be printed with the foreground color `fg` (example: `"TEST".fg(84)`)
112
- bg(bg) | Set text to be printed with the background color `bg` (example: `"TEST".bg("dd32a9")`)
113
- fb(fg, bg) | Set text to be printed with the foreground color `fg` and background color `bg` (example: `"TEST".fb(84,196)`)
114
- b | Set text to be printed in bold (example: `"TEST".b`)
115
- i | Set text to be printed in italic (example: `"TEST".i`)
116
- u | Set text to be printed underlined (example: `"TEST".u`)
117
- l | Set text to be printed blinking (example: `"TEST".l`)
118
- r | Set text to be printed in reverse colors (example: `"TEST".r`)
119
- c(code) | Use coded format like "TEST".c("204,45,bui") to print "TEST" in bold, underline italic, fg=204 and bg=45 (the format is `.c("fg,bg,biulr")`)
120
- pure | Strip text of any "dressing" (example: with `text = "TEST".b`, you will have bold text in the variable `text`, then with `text.pure` it will show "uncoded" or pure text)
121
- clean_ansi | Strip seemingly uncolored strings of ansi code (those that are enclosed in "\e[0m"
122
- shorten(n) | Shorten the pure version of the string to 'n' characters, preserving any ANSI coding
123
- inject("chars",pos) | Inject "chars" at position 'pos' in the pure version of the string (if 'pos' is '-1', then append at end). Preserves any ANSI code
124
-
125
- PS: Blink does not work in conjunction with setting a background color in urxvt. It does work in gnome-terminal. But the overall performance in urxvt as orders of magnitude better than gnome-terminal.
126
-
127
- # Cleaning up upon exit
128
- End a program with `Rcurses.clear_screen` to clear the screen for any rcurses residues.
129
-
130
- # module Cursor
131
- To use this module, first do `include Rcurses::Cursor`. Create a new cursor object with `mycursor = Rcurses::Cursor`. Then you can apply the following methods to `mycursor`:
132
-
133
- Method | Description
134
- ------------------|---------------------------------------------------------------
135
- save | Save current position
136
- restore | Restore cursor position
137
- pos | Query cursor current position (example: `row,col = mycursor.pos`)
138
- colget | Query cursor current cursor col/x position (example: `row = mycursor.rowget`)
139
- rowget | Query cursor current cursor row/y position (example: `row = mycursor.rowget`)
140
- set(c = 1, r = 1) | Set the position of the cursor to row/y,col/x (example: `mycursor.set(row,col)`) (default = top row, first column)
141
- col(c = 1) | Cursor moves to the nth position horizontally in the current line (default = first column)
142
- row(r = 1) | Cursor moves to the nth position vertically in the current column (default = first/top row)
143
- up(n = 1) | Move cursor up by n (default is 1 character up)
144
- down(n = 1) | Move cursor down by n (default is 1 character down)
145
- left(n = 1) | Move cursor backward by n (default is one character)
146
- right(n = 1) | Move cursor forward by n (default is one character)
147
- next_line | Move cursor down to beginning of next line
148
- prev_line | Move cursor up to beginning of previous line
149
- clear_char(n = 1) | Erase n characters from the current cursor position (default is one character)
150
- clear_line | Erase the entire current line and return to beginning of the line
151
- clear_line_before | Erase from the beginning of the line up to and including the current cursor position
152
- clear_line_after | Erase from the current position (inclusive) to the end of the line
153
- scroll_up | Scroll display up one line
154
- scroll_down | Scroll display down one line
155
- clear_screen_down | Clear screen down from current row
156
- hide | Hide the cursor
157
- show | Show cursor
158
-
159
- # The function getchr
160
- rcurses provides a vital extension to Ruby in reading characters entered by the user. This is especially needed for curses applications where readline inputs are required.
161
- The function getchr is automatically included in your arsenal when you first do `include Rcurses::Input`.
162
-
163
- Simply use `chr = getchr` in a program to read any character input by the user. The returning code (the content of `chr` in this example) could be any of the following:
164
-
165
- Key pressed | string returned
166
- ----------------|----------------------------------------------------------
167
- `esc` | "ESC"
168
- `up` | "UP"
169
- `shift-up` | "S-UP"
170
- `ctrl-up` | "C-UP"
171
- `down` | "DOWN"
172
- `shift-down` | "S-DOWN"
173
- `ctrl-down` | "C-DOWN"
174
- `right` | "RIGHT"
175
- `shift-right` | "S-RIGHT"
176
- `ctrl-right` | "C-RIGHT"
177
- `left` | "LEFT"
178
- `shifth-left` | "S-LEFT"
179
- `ctrl-left` | "C-LEFT"
180
- `shift-tab` | "S-TAB"
181
- `insert` | "INS"
182
- `ctrl-insert` | "C-INS"
183
- `del` | "DEL"
184
- `ctrl-del` | "C-DEL"
185
- `pageup` | "PgUP"
186
- `ctrl-pageup` | "C-PgUP"
187
- `pagedown` | "PgDOWN"
188
- `ctrl-pagedown` | "C-PgDOWN"
189
- `home` | "HOME"
190
- `ctrl-home` | "C-HOME"
191
- `end` | "END"
192
- `ctrl-end` | "C-END"
193
- `backspace` | "BACK"
194
- `ctrl- ` | "C-SPACE"
195
- `ctrl-h` | "BACK"
196
- `ctrl-a` | "C-A"
197
- `ctrl-b` | "C-B"
198
- `ctrl-c` | "C-C"
199
- `ctrl-d` | "C-D"
200
- `ctrl-e` | "C-E"
201
- `ctrl-f` | "C-F"
202
- `ctrl-g` | "C-G"
203
- `ctrl-i` | "C-I"
204
- `ctrl-j` | "C-J"
205
- `ctrl-k` | "C-K"
206
- `ctrl-l` | "C-L"
207
- `ctrl-m` | "C-M"
208
- `ctrl-n` | "C-N"
209
- `ctrl-o` | "C-O"
210
- `ctrl-p` | "C-P"
211
- `ctrl-q` | "C-Q"
212
- `ctrl-r` | "C-R"
213
- `ctrl-s` | "C-S"
214
- `ctrl-t` | "C-T"
215
- `ctrl-u` | "C-U"
216
- `ctrl-v` | "C-V"
217
- `ctrl-a` | "WBACK"
218
- `ctrl-x` | "C-X"
219
- `ctrl-y` | "C-Y"
220
- `ctrl-z` | "C-Z"
221
- `enter` | "ENTER"
222
- `tab` | "TAB"
223
- `F1` - `F12` | "F1" - "F12"
224
-
225
- Any other character enter will be returned (to `chr` in the example above).
226
-
227
- In order to handle several character pased into STDIN by the user (and not only returned the first character only, your program should empty the STDIN like this:
228
-
450
+ With this, the background color of the top line/pane will be set to `165` if
451
+ you are in a directory path that includes "passionfruits". The last pair is
452
+ the default background color when no match is found. If you don't set this
453
+ variable in your `.rtfm/conf`, rtfm will set this value to:
229
454
  ```
230
- while $stdin.ready?
231
- chr += $stdin.getc
232
- end
455
+ @topmatch = [["", 238]]
233
456
  ```
234
- You can also pass a timeout to `getchr` with `getchr(time)` to wait for `time` number of seconds and returning `nil` if the user does not press a key.
457
+ Make sure to have a default value set as the last pair in `@topmatch`.
235
458
 
459
+ ## Plugin architecture
460
+ ***Upon first running RTFM, a few files are created in the `.rtfm/` directory.***
236
461
 
237
- # Example
462
+ One is `preview.rb`, the other is `keys.rb`.
238
463
 
239
- Try this in `irb`:
464
+ You can add new "previewers" to show files with extensions that is not
465
+ previewed by default in RTFM. The `preview.rb` explains how you add thesea:
240
466
  ```
241
- require 'rcurses'
242
- @max_h, @max_w = IO.console.winsize
243
- mypane = Pane.new(@max_w/2, 30, 30, 10, 19, 229)
244
- mypane.border = true
245
- mypane.text = "Hello".i + " World!".b.i + "\n \n" + "rcurses".r + " " + "is cool".c("16,212")
246
- mypane.refresh
247
- mypane.edit
467
+ # ~/.rtfm/preview.rb
468
+ #
469
+ # Define one handler per line in the form:
470
+ #
471
+ # ext1, ext2, ext3 = command with @s placeholder
472
+ #
473
+ # @s will be replaced by the shell-escaped filename.
474
+ #
475
+ # Lines beginning with # or blank are ignored.
476
+ #
477
+ # Examples:
478
+ # # plain text, Ruby, Python, shell
479
+ # txt, rb, py, sh = bat -n --color=always @s
480
+ #
481
+ # # markdown via pandoc
482
+ # md = pandoc @s -t plain
483
+ #
484
+ # # PDFs
485
+ # pdf = pdftotext -f 1 -l 4 @s -
248
486
  ```
249
- ... and then try to add some bold text by enclosing it in '*' and italics by enclosing text in '/'. Then press 'ctrl-s' to save your edited text - and then type `mypane.refresh` to see the result.
250
-
251
- And - try running the example file `rcurses_example.rb`.
252
-
253
- # Not yet implemented
254
- Let me know what other features you like to see.
487
+ Likewise, you can add or rewrite any keys in RTFM and add new functionality to
488
+ RTFM by following the instructions in `keys.rb`:
489
+ ```
490
+ # ~/.rtfm/keys.rb
491
+ #
492
+ # Override or add key bindings simply by assigning into KEYMAP
493
+ # and defining the corresponding handler methods.
494
+ #
495
+ # Syntax:
496
+ # KEYMAP['X'] = :my_handler
497
+ #
498
+ # def my_handler(chr)
499
+ # # anything you like - use @pB, @pR, Dir.pwd, etc.
500
+ # @pB.say("You pressed X!")
501
+ # end
502
+ #
503
+ # Examples:
504
+ #
505
+ # # remap 'C' to show config
506
+ # KEYMAP['C'] = :show_config
507
+ #
508
+ # # add a new binding: 'Z'
509
+ # KEYMAP['Z'] = :zap_all
510
+ # def zap_all(_chr)
511
+ # @pB.say("ZAPPED!")
512
+ # end
513
+ ```
514
+ Here is another example of what you could add as a plugin:
515
+ ```
516
+ KEYMAP['C-G'] = :git_update
255
517
 
256
- # License and copyright
257
- Just steal or borrow anything you like. This is now Public Domain.
518
+ def git_update
519
+ @pR.say("Updating...")
520
+ message = @pCmd.ask('Commit message: ', '')
521
+ shellexec("git add . && git commit -m '#{message}' && git push")
522
+ @pB.full_refresh
523
+ end
524
+ ```
525
+ ***With this, you can mold RTFM to fit your needs better.***
526
+
527
+ When writing plugins, there are a few variables you should know:
528
+
529
+ Variable | Description
530
+ ----------|------------------------------------------------------------------
531
+ @pT | Top pane (info bar)
532
+ @pL | Left pane
533
+ @pR | Right pane
534
+ @pB | Bottom pane (status bar)
535
+ @pCmd | Command pane (asking for commands to execute)
536
+ @pSearch | Search pane (prompting for what to search for)
537
+ @pAI | Pane for interacting with (Open)AI
538
+ @pRuby | Ruby debug/command pane
539
+ @selected | The selected item in the Left pane
540
+
541
+ Here are three importan hook-ins to use with your plugins:
542
+
543
+ ### Summary of overlap & choice
544
+ - **Use `command`** when you need to _capture_ output as a value (and optionally handle stderr yourself).
545
+ - **Use `shell`** for fire-and-forget side-effects where you don't care about stdout but still want error reporting.
546
+ - **Use `shellexec`** when you want both stdout and stderr printed into RTFM's Right pane automatically.
547
+
548
+ #### `command(cmd, timeout: 5, return_both: false) → String or [stdout, stderr]`
549
+ - **What it does:** Runs `bash -c cmd`, captures both stdout and stderr, enforces a timeout.
550
+ - **When to use:** Programmatically grab output (and optionally errors) of a shell command (e.g. building directory listings or previews).
551
+ - **Key points:**
552
+ - By default prints stderr into the Right pane and returns stdout.
553
+ - `return_both: true` returns `[stdout, stderr]` instead of auto-printing errors.
554
+ - Times out after `timeout` seconds, killing the process if necessary.
555
+
556
+ #### `shell(cmd, background: false, err: nil) → nil`
557
+ - **What it does:** Fires off `cmd` via `system`, redirecting stderr into a log file (default: `$TMP/rtfm_err.log`), optionally in the background.
558
+ - **When to use:** Run side-effecting commands (e.g. `xdg-open`, `mv`) where you don't need stdout but still want error reporting.
559
+ - **Key points:**
560
+ - If `background: true`, runs `cmd &`.
561
+ - Any stderr output is read from the log and shown via `@pR.say`.
562
+ - Doesn't return command output, errors only.
563
+
564
+ #### `shellexec(cmd, timeout: 10) → nil`
565
+ - **What it does:** A thin wrapper over `command(cmd, timeout:, return_both: true)` that _always_ prints both stdout and stderr into the Right pane.
566
+ - **When to use:** Run a command and echo both its stdout and any errors back to the user—e.g. interactive grep, locate, or other one-off shell tools.
567
+ - **Key points:**
568
+ - Internally calls `command(..., return_both: true)`.
569
+ - Prints stderr first, then stdout.
570
+ - Doesn't return anything to the caller.
571
+
572
+ ## Screencast
573
+ Here's a screencast for an early version of RTFM, but it shows the basic stuff:
574
+ [![RTFM screencast](/img/screenshot.png)](https://youtu.be/ANUOlDryUng)
575
+
576
+ ## Development
577
+ I don't expect this program to be used by others. I do this for my own
578
+ enjoyment and because I want a file manager that fits my needs better than any
579
+ others I have found. If you come up with a feature request I feel is cool, I
580
+ may include it. Bug reports are always welcome.
581
+
582
+ A note to developers: You can hit the "@" key to enter the Ruby debug mode
583
+ where anything you enter in the bottom command bar will be sent to the Ruby
584
+ eval() function and output to the right pane. You can for instance issue
585
+ `puts @searched` to see the currently active search pattern.