rtfm-filemanager 3.0.3 → 3.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/README.md +43 -31
- data/bin/rtfm +262 -173
- data/rtfm-kb.png +0 -0
- metadata +8 -8
- data/.rtfm.launch +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f93c42211b4b1f57fdec42841b7cfddf9d08797cc999f32da9816899016043b9
|
4
|
+
data.tar.gz: cf1c10a981bea7b7f384cdbe5bba59f3138f58467d39644e65d8ccaad1386e43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85564f159ec0be34424eb45715474ba75fd001711a93f9830f5d4c33b319ef509a216afac9ac809ba8a8ec39f15a6d61f1f9055250d9d3264b46cffa231fbcc3
|
7
|
+
data.tar.gz: bd1fab6993c5f5bd735274f275d1195439b33d83cadad26a98541d266e3fe6dbc243d2a513f1aaac8697c5645ae567a13e6f8425fa0f1f5467345359b911b15b
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# RTFM - Ruby Terminal File Manager
|
2
|
-
|
2
|
+
|
3
3
|
 [](https://badge.fury.io/rb/rtfm-filemanager)  
|
4
4
|
|
5
5
|
What other features can I cram into this file manager?
|
@@ -18,7 +18,7 @@ Note: RTFM works best with the (u)rxvt, xterm and Eterm terminal emulators.
|
|
18
18
|
## Features
|
19
19
|
|
20
20
|
RTFM is one of the more feature rich terminal file managers. Some of the
|
21
|
-
features:
|
21
|
+
features are:
|
22
22
|
|
23
23
|
* RTFM shows images inline in the terminal (can be turned off)
|
24
24
|
* File contents is shown with proper syntax highlighting
|
@@ -64,17 +64,21 @@ of the selected item (directory or file) is shown in the right pane. The right
|
|
64
64
|
pane is also used to show information such as the currently tagged items, your
|
65
65
|
(book)marks, output from commands, etc.
|
66
66
|
|
67
|
-
|
67
|
+
When you start RTFM, you can supply a directory path as an argument to let
|
68
|
+
RTFM start up in that directory.
|
69
|
+
|
70
|
+
You can run any command in the bottom "command bar" and have the output
|
68
71
|
presented in the right pane. Use LEFT and RIGHT keys to go back and forth on
|
69
72
|
the command line, HOME to beginning of line, END to end of line, Backspace or
|
70
73
|
Ctrl-h to delete previous character, Ctrl-w to delete previous word, TAB to
|
71
74
|
complete directories and file names and ENTER to issue the command, while
|
72
|
-
Ctrl-u deletes the line. Issuing ENTER on a blank line has no effect.
|
75
|
+
Ctrl-u deletes the line. Issuing ENTER on a blank line has no effect. Use
|
76
|
+
Ctrl-g to leave the command bar without executing anything.
|
73
77
|
|
74
78
|
## Installation
|
75
79
|
|
76
|
-
You can install RTFM by
|
77
|
-
|
80
|
+
You can install RTFM by coloning this repo and put the file `rtfm` in your
|
81
|
+
"bin" directory. Or you can simply run `gem install rtfm-filemanager`.
|
78
82
|
|
79
83
|
There are two basic prerequisites needed: `x11-utils` and `xdotool`. On
|
80
84
|
Ubuntu these would be installed via `apt install x11-utils xdotool`.
|
@@ -82,12 +86,12 @@ Ubuntu these would be installed via `apt install x11-utils xdotool`.
|
|
82
86
|
In order to run RTFM (without generating [a bunch of
|
83
87
|
warnings](https://github.com/isene/RTFM/issues/1)), you need to do a `gem
|
84
88
|
install curses` (gets version 1.3.2) instead of installing via `apt install
|
85
|
-
ruby-curses` (gets version 1.2.4-1build1 on Ubuntu 20.04).
|
89
|
+
ruby-curses` (gets version 1.2.4-1build1 on Ubuntu 20.04). If you install RTFM
|
90
|
+
via `gem install rtfm-filemanager`, this dependency is already taken care of.
|
86
91
|
|
87
92
|
Content of text files are handled by `cat` - or by `bat` if you want beautiful
|
88
|
-
highlighting. Other files are shown via external programs
|
89
|
-
|
90
|
-
last column):
|
93
|
+
highlighting. Other files are shown via external programs (Debian/Ubuntu
|
94
|
+
family of Linux distros command in last column):
|
91
95
|
|
92
96
|
File type | Requirements | Installation
|
93
97
|
----------------------------|----------------------------------|-------------------------------
|
@@ -109,13 +113,17 @@ sudo gem install curses
|
|
109
113
|
git clone https://github.com/isene/RTFM
|
110
114
|
cd RTFM
|
111
115
|
sudo cp rtfm /usr/bin/
|
112
|
-
|
113
|
-
|
116
|
+
```
|
117
|
+
Or with a simpler gem install:
|
118
|
+
```
|
119
|
+
sudo apt update
|
120
|
+
sudo apt install ruby-full git libncurses-dev x11-utils xdotool bat poppler-utils odt2txt docx2txt catdoc w3m imagemagick ffmpegthumbnailer
|
121
|
+
gem install rtfm-filemanager
|
114
122
|
```
|
115
123
|
|
116
124
|
## Screenshot
|
117
125
|
|
118
|
-

|
126
|
+

|
119
127
|
|
120
128
|
## Image preview in the terminal
|
121
129
|
|
@@ -153,11 +161,12 @@ These are the set of keys to move around and do actions within RTFM:
|
|
153
161
|
Key | Description
|
154
162
|
-------|------------------------------------------------------------------
|
155
163
|
? | Show this help text
|
156
|
-
r | Refresh RTFM (recreates
|
164
|
+
r | Refresh RTFM (recreates the panes. Use on terminal resize or when there is garbage somewhere)
|
157
165
|
R | Reload configuration (~/.rtfm.conf)
|
158
166
|
W | Write parameters to ~/.rtfm.conf (@lsall, @lslong, @lsorder, @lsinvert, @border, @width, @preview, @tagged, @marks)
|
159
167
|
q | Quit
|
160
168
|
Q | QUIT (without writing changes to the config file)
|
169
|
+
v | Display RTFM version in bottom command bar
|
161
170
|
|
162
171
|
### Motion
|
163
172
|
|
@@ -186,7 +195,7 @@ M | Show marked items in right pane
|
|
186
195
|
|
187
196
|
Key | Description
|
188
197
|
-------|------------------------------------------------------------------
|
189
|
-
/ | Enter search string in bottom
|
198
|
+
/ | Enter search string in bottom command bar to highlight matching items and jump to the first match
|
190
199
|
\\ | Remove search pattern
|
191
200
|
n | Jump to the next item matched by '/'
|
192
201
|
N | Jump to the previous item matched by '/'
|
@@ -211,7 +220,7 @@ p | Put (copy) tagged items here
|
|
211
220
|
P | PUT (move) tagged items here
|
212
221
|
s | Create symlink to tagged items here
|
213
222
|
d | Delete selected item and tagged items. Press 'y' to confirm
|
214
|
-
c | Change/rename selected (adds command to
|
223
|
+
c | Change/rename selected (adds the proper command to change in the command bar)
|
215
224
|
Ctrl-o | Change ownership to user:group of selected and tagged items
|
216
225
|
Ctrl-p | Change permissions of selected and tagged items. Format = rwxr-xr-x or 755 or rwx (applies the trio to user, group and others)
|
217
226
|
z | Extract tagged zipped archive to current directory
|
@@ -225,7 +234,7 @@ a | Show all (also hidden) items
|
|
225
234
|
A | Show All info per item (show item attributes)
|
226
235
|
o | Change the order/sorting of directories (circular toggle)
|
227
236
|
i | Invert/reverse the sorting
|
228
|
-
O | Show the Ordering in the bottom
|
237
|
+
O | Show the Ordering in the bottom command bar (the full ls command)
|
229
238
|
G | Show git status for current directory
|
230
239
|
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
|
231
240
|
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. If RTFM is installed as a gem, the ruby-openai gem is included in the installation
|
@@ -237,7 +246,7 @@ Key | Description
|
|
237
246
|
ENTER | Refresh the right pane
|
238
247
|
TAB | Next page of the preview (if doc long and ∇ in the bottom right)
|
239
248
|
S-TAB | Previous page (if you have moved down the document first - ∆ in the top right)
|
240
|
-
w | Change the width of the left/right panes (left pane ⇒
|
249
|
+
w | Change the width of the left/right panes (left pane ⇒ 20%, 30%, 40%, 50%, 60%)
|
241
250
|
\- | Toggle preview in right pane (turn it off for faster traversing of directories)
|
242
251
|
_ | Toggle preview of images in right pane
|
243
252
|
b | Toggle syntax highlighting (and line numbering)
|
@@ -247,24 +256,26 @@ b | Toggle syntax highlighting (and line numbering)
|
|
247
256
|
Key | Description
|
248
257
|
-------|------------------------------------------------------------------
|
249
258
|
f | Show only files in the left pane matching extension(s) (e.g. "txt" or "pdf,png,jpg")
|
250
|
-
F | Show only files matching a pattern (Ruby Regex) (e.g. "abc" or "ab.+12(\w3)
|
259
|
+
F | Show only files matching a pattern (Ruby Regex) (e.g. "abc" or "ab.+12(\w3)+")
|
251
260
|
B | Toggle border
|
252
|
-
: | Enter "command mode" in bottom
|
261
|
+
: | Enter "command mode" in bottom command bar (press ENTER to execute, press Ctrl-G to escape)
|
253
262
|
; | Show command history in right pane
|
254
263
|
y | Copy path of selected item to primary selection (for pasting with middle mouse button)
|
255
264
|
Y | Copy path of selected item to clipboard
|
256
|
-
|
265
|
+
Ctrl-y | Copy content of right pane to clipboard
|
266
|
+
Ctrl-d | Create a new directory (a shortcut for ":mkdir ")
|
267
|
+
Ctrl-n | Invoke navi (see https://github.com/denisidoro/navi) with any output in right pane
|
257
268
|
S | Show comprehensive system info (system, CPU, filesystem, latest dmesg messages)
|
258
|
-
Ctrl-n | Invoke navi (see https://github.com/denisidoro/navi) with any output in right window
|
259
|
-
|
260
|
-
|
261
|
-
## A convenient shell function
|
262
|
-
Add this line to your `.bashrc` or `.zshrc` to make RTFM exit to the current
|
263
|
-
directory by launching the file manager via `r` in the terminal:
|
264
269
|
|
265
|
-
|
270
|
+
## Keyboard cheat sheet
|
271
|
+

|
266
272
|
|
267
|
-
|
273
|
+
## First run
|
274
|
+
The first time you run RTFM, you are greeted with a welcome message. RTFM will
|
275
|
+
then create a file (`.rtfm.launch`) in your home directory that will let you
|
276
|
+
launch RTFM via the one key command `r`. It also lets RTFM exit in the
|
277
|
+
directory you are currently in (inside of RTFM) rather than where you launched
|
278
|
+
RTFM.
|
268
279
|
|
269
280
|
With this, you can jump around in your directory structure via RTFM, exit to
|
270
281
|
the desired directory, do work in the terminal and go back into RTFM via `r`.
|
@@ -291,7 +302,8 @@ any files containg the word "test", you could do this:
|
|
291
302
|
```
|
292
303
|
|
293
304
|
To change the default width of the left pane to something other than ⅓rd of
|
294
|
-
the terminal width: `@width = 5` (would set the left pane width to
|
305
|
+
the terminal width: `@width = 5` (would set the left pane width to 50% of the
|
306
|
+
window size).
|
295
307
|
|
296
308
|
To add borders in RTFM: `@border = true`
|
297
309
|
|
@@ -345,6 +357,6 @@ others I have found. If you come up with a feature request I feel is cool, I
|
|
345
357
|
may include it. Bug reports are always welcome.
|
346
358
|
|
347
359
|
A note to developers: You can hit the "@" key to enter the Ruby debug mode
|
348
|
-
where anything you enter in the bottom command
|
360
|
+
where anything you enter in the bottom command bar will be sent to the Ruby
|
349
361
|
eval() function and output to the right pane. You can for instance issue
|
350
362
|
`puts @searched` to see the currently active search pattern.
|
data/bin/rtfm
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
# for any damages resulting from its use. Further, I am under no
|
15
15
|
# obligation to maintain or extend this software. It is provided
|
16
16
|
# on an 'as is' basis without any expressed or implied warranty.
|
17
|
-
@version = "3.
|
17
|
+
@version = "3.3"
|
18
18
|
|
19
19
|
# PRELIMINARIES
|
20
20
|
@help = <<HELPTEXT
|
@@ -104,52 +104,117 @@ RIGHT PANE
|
|
104
104
|
|
105
105
|
ADDITIONAL COMMANDS
|
106
106
|
f = Show only files in the left pane matching extension(s) (e.g. "txt" or "pdf,png,jpg")
|
107
|
-
F = Show only files matching a pattern (Ruby Regex) (e.g. "abc" or "ab.+12(\w3)
|
107
|
+
F = Show only files matching a pattern (Ruby Regex) (e.g. "abc" or "ab.+12(\w3)+")
|
108
108
|
B = Toggle border
|
109
109
|
: = Enter "command mode" in bottom window (press ENTER to execute, press Ctrl-G to escape)
|
110
110
|
; = Show command history in right pane
|
111
111
|
y = Copy path of selected item to primary selection (for pasting with middle mouse button)
|
112
112
|
Y = Copy path of selected item to clipboard
|
113
113
|
Ctrl-y = Copy content of right pane to clipboard
|
114
|
-
|
114
|
+
Ctrl-d = Create a new directory (a shortcut for ":mkdir ")
|
115
115
|
Ctrl-n = Invoke navi (see https://github.com/denisidoro/navi) with any output in right window
|
116
|
+
S = Show comprehensive System info (system, CPU, filesystem, latest dmesg messages)
|
116
117
|
|
117
|
-
COPYRIGHT: Geir Isene, 2020-
|
118
|
+
COPYRIGHT: Geir Isene, 2020-4. No rights reserved. See http://isene.com for more.
|
118
119
|
HELPTEXT
|
119
|
-
|
120
|
+
def firstrun
|
121
|
+
@firstrun = <<~FIRSTRUN
|
122
|
+
|
123
|
+
Welcome to RTFM - the Ruby Terminal File Manager. This help text is shown on the first run.
|
124
|
+
Next time you run RTFM, you can launch it from your terminal with a one letter command: "r"
|
125
|
+
When launched this way, RTFM will also exit in the directory you are currently in.
|
126
|
+
|
127
|
+
To benefit fully from all the features, you need to install some auxilliary software.
|
128
|
+
On Ubuntu Linux you would use "apt install":
|
120
129
|
|
121
|
-
|
122
|
-
|
123
|
-
|
130
|
+
Basic requirments is "x11-utils" and "xdotool": apt install x11-utils xdotool
|
131
|
+
Syntax highlighting of text uses "bat": apt install bat
|
132
|
+
Viewing PDFs uses "pdftotext": apt install poppler-utils
|
133
|
+
Viewing LibreOffice docs uses "odt2txt": apt install odt2txt
|
134
|
+
Viewing MS docx uses "docx2txt": apt install docx2txt
|
135
|
+
Viewing MS pptx uses "unzip": apt install unzip
|
136
|
+
Viewing MS xlsx uses "ssconvert": apt install gnumeric
|
137
|
+
Viewing MS doc/xls/ppt uses "catdoc, xls2csv and catppt": apt install catdoc
|
138
|
+
Viewing Images uses "w3m and ImageMagick": apt install w3m imagemagick
|
139
|
+
Viewing Video thumbnails uses "ffmpegthumbnailer" apt install ffmpegthumbnailer
|
124
140
|
|
125
|
-
|
126
|
-
|
127
|
-
Viewing PDFs uses "pdftotext": apt install poppler-utils
|
128
|
-
Viewing LibreOffice docs uses "odt2txt": apt install odt2txt
|
129
|
-
Viewing MS docx uses "docx2txt": apt install docx2txt
|
130
|
-
Viewing MS pptx uses "unzip": apt install unzip
|
131
|
-
Viewing MS xlsx uses "ssconvert": apt install gnumeric
|
132
|
-
Viewing MS doc/xls/ppt uses "catdoc, xls2csv and catppt": apt install catdoc
|
133
|
-
Viewing Images uses "w3m and ImageMagick": apt install w3m imagemagick
|
134
|
-
Viewing Video thumbnails uses "ffmpegthumbnailer" apt install ffmpegthumbnailer
|
141
|
+
All of the above:
|
142
|
+
apt install x11-utils xdotool bat poppler-utils odt2txt docx2txt unzip gnumeric catdoc w3m imagemagick ffmpegthumbnailer
|
135
143
|
|
136
144
|
FIRSTRUN
|
137
|
-
|
145
|
+
|
146
|
+
@shell = File.basename(`echo "$SHELL"`.chomp)
|
147
|
+
if @shell == "fish"
|
148
|
+
if not File.exist?(Dir.home+'/.config/fish/config.fish')
|
149
|
+
@rtfmlaunch = <<RTFMFISHLAUNCH
|
150
|
+
# This is the RTFM launcher (https://github.com/isene/RTFM) for fish
|
151
|
+
function r {
|
152
|
+
f=$(mktemp)
|
153
|
+
(
|
154
|
+
set +e
|
155
|
+
rtfm "$f"
|
156
|
+
code=$?
|
157
|
+
if [ "$code" != 0 ]; then
|
158
|
+
rm -f "$f"
|
159
|
+
exit "$code"
|
160
|
+
fi
|
161
|
+
)
|
162
|
+
code=$?
|
163
|
+
if [ "$code" != 0 ]; then
|
164
|
+
return "$code"
|
165
|
+
fi
|
166
|
+
d=$(<"$f")
|
167
|
+
rm -f "$f"
|
168
|
+
cd "$d"
|
169
|
+
}
|
170
|
+
RTFMFISHLAUNCH
|
171
|
+
File.write(Dir.home+'/.config/fish/config.fish', @rtfmlaunch)
|
172
|
+
`echo "source ~/.config/fish/config.fish" >> .#{@shell}rc`
|
173
|
+
end
|
174
|
+
else
|
175
|
+
if not File.exist?(Dir.home+'/.rtfm.launch')
|
176
|
+
@rtfmlaunch = <<RTFMLAUNCH
|
177
|
+
# This is the RTFM launcher (https://github.com/isene/RTFM) for bash/zsh
|
178
|
+
function r {
|
179
|
+
f=$(mktemp)
|
180
|
+
(
|
181
|
+
set +e
|
182
|
+
rtfm "$f"
|
183
|
+
code=$?
|
184
|
+
if [ "$code" != 0 ]; then
|
185
|
+
rm -f "$f"
|
186
|
+
exit "$code"
|
187
|
+
fi
|
188
|
+
)
|
189
|
+
code=$?
|
190
|
+
if [ "$code" != 0 ]; then
|
191
|
+
return "$code"
|
192
|
+
fi
|
193
|
+
d=$(<"$f")
|
194
|
+
rm -f "$f"
|
195
|
+
cd "$d"
|
196
|
+
}
|
197
|
+
RTFMLAUNCH
|
198
|
+
File.write(Dir.home+'/.rtfm.launch', @rtfmlaunch)
|
199
|
+
`echo "source ~/.rtfm.launch" >> .#{@shell}rc`
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
138
203
|
puts @firstrun
|
139
|
-
puts "... hit ENTER to show the
|
140
|
-
|
141
|
-
puts @help
|
142
|
-
puts "\n... hit ENTER to start RTFM. Enjoy :-)"
|
143
|
-
STDIN.gets
|
204
|
+
puts "\n... hit ENTER to start RTFM. Hit ? inside RTFM to show the help text. Enjoy :-)"
|
205
|
+
$stdin.gets
|
144
206
|
end
|
145
207
|
begin # BASIC SETUP
|
146
208
|
require 'fileutils'
|
147
209
|
require 'io/console'
|
210
|
+
require 'io/wait'
|
148
211
|
require 'date'
|
149
212
|
require 'timeout'
|
150
213
|
require 'curses'
|
151
214
|
include Curses
|
152
215
|
|
216
|
+
firstrun unless File.exist?(Dir.home+'/.rtfm.conf')
|
217
|
+
|
153
218
|
def cmd?(command)
|
154
219
|
system("which #{command} > /dev/null 2>&1")
|
155
220
|
end
|
@@ -164,8 +229,7 @@ begin # BASIC SETUP
|
|
164
229
|
|
165
230
|
cmd?('bat') ? @bat = "bat" : @bat = "batcat"
|
166
231
|
|
167
|
-
|
168
|
-
LScolors = `echo $LS_COLORS` # Import LS_COLORS
|
232
|
+
$stdin.set_encoding(Encoding::UTF_8) # Set encoding for $stdin
|
169
233
|
|
170
234
|
## Curses setup
|
171
235
|
Curses.init_screen
|
@@ -177,48 +241,52 @@ begin # BASIC SETUP
|
|
177
241
|
|
178
242
|
# INITIALIZE VARIABLES
|
179
243
|
## These can be set by user in .rtfm.conf
|
180
|
-
@lsbase
|
181
|
-
@lslong
|
182
|
-
@lsall
|
183
|
-
@lsorder
|
184
|
-
@lsinvert
|
185
|
-
@lsuser
|
186
|
-
@width
|
187
|
-
@history
|
188
|
-
@
|
189
|
-
@
|
190
|
-
@
|
191
|
-
@
|
244
|
+
@lsbase = "--group-directories-first" # Basic ls setup
|
245
|
+
@lslong = false # Set short form ls (toggled by pressing "l")
|
246
|
+
@lsall = "" # Set "ls -a" to false (toggled by pressing "a" - sets it to "-a")
|
247
|
+
@lsorder = "" # Change the order/sorting by pressing 'o' (circular toggle)
|
248
|
+
@lsinvert = "" # Set to "-r" to reverse/invert sorting order
|
249
|
+
@lsuser = "" # Set this variable in .rtfm.conf to any 'ls' switch you want to customize directory listings
|
250
|
+
@width = 4 # Set width of the left pane to the default ⅓ of the terminal width
|
251
|
+
@history = [] # Initialize the command line history array
|
252
|
+
@rubyhistory = [] # Initialize the command line history array for ruby commands
|
253
|
+
@border = false
|
254
|
+
@preview = true
|
255
|
+
@runmailcap = false # Set to 'true' in .rtfm.conf if you want to use run-mailcap instead of xdg-open
|
256
|
+
@batuse = true # Use batcat for syntax highlighting
|
257
|
+
@aimodel = "gpt-3.5-turbo-instruct" # The default OpenAI model, set another in .rtfm.conf if you like
|
192
258
|
## These are automatically written on exit
|
193
|
-
@marks
|
194
|
-
@hash
|
195
|
-
@tagged
|
259
|
+
@marks = {} # Initialize (book)marks hash
|
260
|
+
@hash = {} # Initialize the sha directory hashing
|
261
|
+
@tagged = [] # Initialize the tagged array - for collecting all tagged items
|
196
262
|
## These should not be set by user in .rtfm.conf
|
197
|
-
@directory
|
198
|
-
@searched
|
199
|
-
@lsfiles
|
200
|
-
@lsmatch
|
201
|
-
@index
|
202
|
-
@cont
|
203
|
-
@tagsize
|
204
|
-
@navi
|
205
|
-
@marks["'"]
|
263
|
+
@directory = {} # Initialize the directory hash for remembering directories visited
|
264
|
+
@searched = "" # Initialize the active searched for items
|
265
|
+
@lsfiles = "" # File types to show (initially set to all file types) - not saved on exit
|
266
|
+
@lsmatch = "" # Files to match (initially set to matching all files) - not saved on exit
|
267
|
+
@index = 0 # Set chosen item to first on startup
|
268
|
+
@cont = ""
|
269
|
+
@tagsize = 0
|
270
|
+
@navi = ""
|
271
|
+
@marks["'"] = Dir.pwd
|
206
272
|
## File type recognizers
|
207
|
-
@imagefile
|
208
|
-
@pptfile
|
209
|
-
@xlsfile
|
210
|
-
@docfile
|
211
|
-
@docxfile
|
212
|
-
@xlsxfile
|
213
|
-
@pptxfile
|
214
|
-
@oolofile
|
215
|
-
@pdffile
|
273
|
+
@imagefile = /\.jpg$|\.JPG$|\.jpeg$|\.png$|\.bmp$|\.gif$|\.tif$|\.tiff$/
|
274
|
+
@pptfile = /\.ppt$/
|
275
|
+
@xlsfile = /\.xls$/
|
276
|
+
@docfile = /\.doc$/
|
277
|
+
@docxfile = /\.docx$/
|
278
|
+
@xlsxfile = /\.xlsx$/
|
279
|
+
@pptxfile = /\.pptx$/
|
280
|
+
@oolofile = /\.odt$|\.odc$|\.odp$|\.odg$/
|
281
|
+
@pdffile = /\.pdf$|\.ps$/
|
216
282
|
## Get variables from config file (written back to .rtf.conf upon exit via 'q')
|
217
283
|
if File.exist?(Dir.home+'/.rtfm.conf')
|
218
284
|
load(Dir.home+'/.rtfm.conf')
|
219
285
|
end
|
286
|
+
Dir.chdir(ARGV[0]) if ARGV[0] and Dir.exist?(ARGV[0]) and ARGV[0] !~ /\/tmp/
|
220
287
|
end
|
221
|
-
|
288
|
+
# CLASS EXTENSIONS
|
289
|
+
class Curses::Window
|
222
290
|
attr_accessor :fg, :bg, :attr, :text, :update, :pager, :pager_more, :pager_cmd, :locate, :nohistory
|
223
291
|
# General extensions (see https://github.com/isene/Ruby-Curses-Class-Extension)
|
224
292
|
def clr
|
@@ -248,16 +316,6 @@ class Curses::Window # CLASS EXTENSION
|
|
248
316
|
# RTFM specific extensions
|
249
317
|
end
|
250
318
|
# GENERIC FUNCTIONS
|
251
|
-
def get_ls_color(type) # GET THE COLOR FOR THE FILETYPE FROM IMPORTED LS_COLORS
|
252
|
-
bold = 0
|
253
|
-
begin
|
254
|
-
color = LScolors.match(/#{type}=\d*;\d*;(\d*)/)[1]
|
255
|
-
bold = 1 if LScolors.match(/#{type}=\d*;\d*;\d*;1/)
|
256
|
-
rescue
|
257
|
-
color = 7 # Default color
|
258
|
-
end
|
259
|
-
return color.to_i, bold
|
260
|
-
end
|
261
319
|
def syntax_highlight(input) # SYNTAX HIGHLIGHTING FROM ANSI COLOR CODES
|
262
320
|
color_ary = color_parse(input)
|
263
321
|
color_ary.each do | pair |
|
@@ -274,13 +332,15 @@ def syntax_highlight(input) # SYNTAX HIGHLIGHTING FROM ANSI COLOR CODES
|
|
274
332
|
end
|
275
333
|
end
|
276
334
|
def color_parse(input) # PARSE ANSI COLOR SEQUENCES
|
277
|
-
input.gsub!(
|
278
|
-
input.gsub!(
|
279
|
-
input.gsub!(
|
280
|
-
input.gsub!(
|
281
|
-
input.gsub!(
|
335
|
+
input.gsub!(/\e\[\d;38;5;(\d+);*(\d*)m/, '¤¤\1¤¤\2¤¤')
|
336
|
+
input.gsub!(/\e\[38;5;(\d+);*(\d*)m/, '¤¤\1¤¤\2¤¤')
|
337
|
+
input.gsub!(/\e\[\d;38;2;(\d+);*(\d*);\d*m/, '¤¤\1¤¤\2¤¤')
|
338
|
+
input.gsub!(/\e\[38;2;(\d+);*(\d*);\d*m/, '¤¤\1¤¤\2¤¤')
|
339
|
+
input.gsub!(/\e\[\d+;(\d+);*(\d*)m/, '¤¤\1¤¤\2¤¤')
|
340
|
+
input.gsub!(/\e\[0m/, "")
|
282
341
|
color_array = input.split("¤¤")
|
283
342
|
color_array = color_array.drop(1)
|
343
|
+
#color_array.map! { |x| x || 0 }
|
284
344
|
output = color_array.each_slice(3).to_a
|
285
345
|
return output
|
286
346
|
end
|
@@ -288,9 +348,10 @@ def getchr # PROCESS KEY PRESSES
|
|
288
348
|
# Note: Curses.getch blanks out @w_t
|
289
349
|
# @w_l.getch makes Curses::KEY_DOWN etc not work
|
290
350
|
# Therefore resorting to the generic method
|
291
|
-
c =
|
351
|
+
c = $stdin.getch(min: 0, time: 3)
|
292
352
|
case c
|
293
353
|
when "\e" # ANSI escape sequences
|
354
|
+
return "ESC" if $stdin.ready? == nil
|
294
355
|
case $stdin.getc
|
295
356
|
when '[' # CSI
|
296
357
|
case $stdin.getc
|
@@ -299,12 +360,13 @@ def getchr # PROCESS KEY PRESSES
|
|
299
360
|
when 'C' then chr = "RIGHT"
|
300
361
|
when 'D' then chr = "LEFT"
|
301
362
|
when 'Z' then chr = "S-TAB"
|
302
|
-
when '2' then chr = "INS" ; chr = "C-INS" if
|
303
|
-
when '3' then chr = "DEL" ; chr = "C-DEL" if
|
304
|
-
when '5' then chr = "PgUP" ; chr = "C-PgUP" if
|
305
|
-
when '6' then chr = "PgDOWN" ; chr = "C-PgDOWN" if
|
306
|
-
when '7' then chr = "HOME" ; chr = "C-HOME" if
|
307
|
-
when '8' then chr = "END" ; chr = "C-END" if
|
363
|
+
when '2' then chr = "INS" ; chr = "C-INS" if $stdin.getc == "^"
|
364
|
+
when '3' then chr = "DEL" ; chr = "C-DEL" if $stdin.getc == "^"
|
365
|
+
when '5' then chr = "PgUP" ; chr = "C-PgUP" if $stdin.getc == "^"
|
366
|
+
when '6' then chr = "PgDOWN" ; chr = "C-PgDOWN" if $stdin.getc == "^"
|
367
|
+
when '7' then chr = "HOME" ; chr = "C-HOME" if $stdin.getc == "^"
|
368
|
+
when '8' then chr = "END" ; chr = "C-END" if $stdin.getc == "^"
|
369
|
+
else chr = ""
|
308
370
|
end
|
309
371
|
when 'O' # Set Ctrl+ArrowKey equal to ArrowKey; May be used for other purposes in the future
|
310
372
|
case $stdin.getc
|
@@ -312,22 +374,29 @@ def getchr # PROCESS KEY PRESSES
|
|
312
374
|
when 'b' then chr = "C-DOWN"
|
313
375
|
when 'c' then chr = "C-RIGHT"
|
314
376
|
when 'd' then chr = "C-LEFT"
|
377
|
+
else chr = ""
|
315
378
|
end
|
316
379
|
end
|
317
380
|
when "", "" then chr = "BACK"
|
318
|
-
when "
|
319
|
-
when "
|
381
|
+
when "" then chr = "C-C"
|
382
|
+
when "" then chr = "C-D"
|
383
|
+
when "" then chr = "C-E"
|
320
384
|
when "" then chr = "C-G"
|
385
|
+
when "" then chr = "C-K"
|
321
386
|
when "" then chr = "C-L"
|
322
387
|
when "" then chr = "C-N"
|
323
388
|
when "" then chr = "C-O"
|
324
389
|
when "" then chr = "C-P"
|
325
390
|
when "" then chr = "C-T"
|
326
391
|
when "" then chr = "C-Y"
|
392
|
+
when "" then chr = "WBACK"
|
393
|
+
when "" then chr = "LDEL"
|
327
394
|
when "\r" then chr = "ENTER"
|
328
395
|
when "\t" then chr = "TAB"
|
329
|
-
when
|
396
|
+
when /[[:print:]]/ then chr = c
|
397
|
+
else chr = ""
|
330
398
|
end
|
399
|
+
#stdin_clear
|
331
400
|
return chr
|
332
401
|
end
|
333
402
|
def main_getkey # GET KEY FROM USER
|
@@ -420,11 +489,11 @@ def main_getkey # GET KEY FROM USER
|
|
420
489
|
# JUMPING AND MARKS
|
421
490
|
when 'm' # Set mark
|
422
491
|
marks_info
|
423
|
-
m =
|
492
|
+
m = $stdin.getc
|
424
493
|
if m.match(/[\w']/)
|
425
494
|
@marks[m] = Dir.pwd
|
426
495
|
elsif m == "-"
|
427
|
-
r =
|
496
|
+
r = $stdin.getc
|
428
497
|
@marks.delete(r)
|
429
498
|
end
|
430
499
|
marks_info
|
@@ -579,7 +648,7 @@ def main_getkey # GET KEY FROM USER
|
|
579
648
|
@tagged.push("\"#{Dir.pwd}/#{@selected}\"")
|
580
649
|
@tagged.uniq!
|
581
650
|
deletes = @tagged.join(" ")
|
582
|
-
if
|
651
|
+
if $stdin.getc == 'y'
|
583
652
|
`rm -rf #{deletes} 2>/dev/null`
|
584
653
|
items_number = @tagged.length
|
585
654
|
@tagged = []
|
@@ -838,6 +907,9 @@ def main_getkey # GET KEY FROM USER
|
|
838
907
|
system("echo -n '#{@cont}' | #{clip}")
|
839
908
|
when 'S' # Show comprehensive system info
|
840
909
|
sysinfo
|
910
|
+
when 'C-D' # Create new directory (shortcut for ":mkdir ")
|
911
|
+
cmd = w_b_getstr(": ", "mkdir ")
|
912
|
+
w_b_exec(cmd + " -p")
|
841
913
|
when 'C-N' # navi integration (https://github.com/denisidoro/navi)
|
842
914
|
begin
|
843
915
|
@navi = `navi`
|
@@ -847,7 +919,7 @@ def main_getkey # GET KEY FROM USER
|
|
847
919
|
@break = true
|
848
920
|
when '@' # Enter "Ruby debug"
|
849
921
|
@w_b.nohistory = false
|
850
|
-
cmd = w_b_getstr("◆ ", "")
|
922
|
+
cmd = w_b_getstr("◆ ", "", true)
|
851
923
|
@w_b.clr
|
852
924
|
@w_b.refresh
|
853
925
|
@w_b.update = true
|
@@ -855,8 +927,8 @@ def main_getkey # GET KEY FROM USER
|
|
855
927
|
info = "Command: #{cmd}\n\n"
|
856
928
|
begin
|
857
929
|
info += eval(cmd).to_s
|
858
|
-
rescue
|
859
|
-
info += "Error: #{
|
930
|
+
rescue Exception => err
|
931
|
+
info += "Error: #{err.inspect}"
|
860
932
|
end
|
861
933
|
w_r_info(info)
|
862
934
|
@w_r.update = false
|
@@ -871,6 +943,12 @@ def main_getkey # GET KEY FROM USER
|
|
871
943
|
rescue
|
872
944
|
end
|
873
945
|
end
|
946
|
+
def stdin_clear
|
947
|
+
begin
|
948
|
+
$stdin.getc while $stdin.ready?
|
949
|
+
rescue
|
950
|
+
end
|
951
|
+
end
|
874
952
|
def conf_write
|
875
953
|
if File.exist?(Dir.home+'/.rtfm.conf')
|
876
954
|
conf = File.read(Dir.home+'/.rtfm.conf')
|
@@ -883,6 +961,10 @@ def conf_write
|
|
883
961
|
conf += "@hash = #{@hash}\n"
|
884
962
|
conf.sub!(/^@tagged.*\[.*\]\n/, "")
|
885
963
|
conf += "@tagged = #{@tagged}\n"
|
964
|
+
conf.sub!(/^@history.*\[.*\]\n/, "")
|
965
|
+
conf += "@history = #{@history}\n"
|
966
|
+
conf.sub!(/^@rubyhistory.*\[.*\]\n/, "")
|
967
|
+
conf += "@rubyhistory = #{@rubyhistory}\n"
|
886
968
|
if @write_conf_all
|
887
969
|
conf.sub!(/^@lslong.*\n/, "")
|
888
970
|
conf += "@lslong = #{@lslong}\n"
|
@@ -926,7 +1008,8 @@ end
|
|
926
1008
|
def get_files(win) # The core of the directory listings
|
927
1009
|
ls_cmd = "ls 2>/dev/null #{@lsbase} #{@lsall} #{@lsorder} #{@lsinvert} #{@lsuser}" # Get files in current directory
|
928
1010
|
ls_cmd += @selected_safe if win == "right"
|
929
|
-
@
|
1011
|
+
@cfiles = `#{ls_cmd} --color`.split("\n")
|
1012
|
+
@files = @cfiles.map {|f| f.sub(/^.*\d+m(.+)\e\[0m/, '\1')}
|
930
1013
|
ls_cmd += " -H " if win == "right"
|
931
1014
|
ls_cmd += %q[ -lh --time-style="long-iso" | awk '{printf "%s%s%s%11s%6s%6s", $1, " " $3, ":" $4,$6,$7,$5"\n"}']
|
932
1015
|
@fspes = `#{ls_cmd}`.split("\n").drop(1)
|
@@ -993,7 +1076,8 @@ def list_dir(active) # LIST CONTENT OF A DIRECTORY (BOTH active AND RIGHT WINDOW
|
|
993
1076
|
@cont = ""
|
994
1077
|
end
|
995
1078
|
while ix < @files.size and t < win.maxy do
|
996
|
-
str
|
1079
|
+
str = @files[ix]
|
1080
|
+
cstr = @cfiles[ix]
|
997
1081
|
active ? str_path = str : str_path = "#{@selected}/#{str}"
|
998
1082
|
begin # Add items matching @tag to @tagged
|
999
1083
|
if str.match(/#{@tag}/) and @tag != false
|
@@ -1002,25 +1086,9 @@ def list_dir(active) # LIST CONTENT OF A DIRECTORY (BOTH active AND RIGHT WINDOW
|
|
1002
1086
|
end
|
1003
1087
|
rescue
|
1004
1088
|
end
|
1005
|
-
# Determine the filetype of the item
|
1006
|
-
ftype = ""
|
1007
|
-
ftype = str.match(/\.([^.]*$)/)[1] if str.match?(/\.([^.]*$)/)
|
1008
|
-
# Set special filetypes (sequence matters)
|
1009
|
-
ftype = "bd" if File.blockdev?(str_path)
|
1010
|
-
ftype = "cd" if File.chardev?(str_path)
|
1011
|
-
ftype = "pi" if File.pipe?(str_path)
|
1012
|
-
ftype = "st" if File.sticky?(str_path)
|
1013
|
-
ftype = "so" if File.socket?(str_path)
|
1014
|
-
ftype = "ex" if File.executable?(str_path)
|
1015
|
-
ftype = "di" if File.directory?(str_path)
|
1016
|
-
ftype = "ln" if File.symlink?(str_path)
|
1017
|
-
begin
|
1018
|
-
File.stat(str_path) # Checking if not an orphaned link
|
1019
|
-
rescue
|
1020
|
-
ftype = "or" # Set to orphant if no link target
|
1021
|
-
end
|
1022
1089
|
fg = 7; bold = 0; bg = 0 # Set default color
|
1023
|
-
|
1090
|
+
fl = color_parse(cstr)
|
1091
|
+
fg, bold = fl[0][0].to_i, fl[0][1].to_i unless fl[0] == nil
|
1024
1092
|
init_pair(fg, fg, bg)
|
1025
1093
|
file_marker = color_pair(fg)
|
1026
1094
|
file_marker = file_marker | Curses::A_BOLD if bold == 1
|
@@ -1042,6 +1110,8 @@ def list_dir(active) # LIST CONTENT OF A DIRECTORY (BOTH active AND RIGHT WINDOW
|
|
1042
1110
|
ext_name = File.extname(str)
|
1043
1111
|
ext_length = ext_name.length
|
1044
1112
|
nbl = win.maxx - 5 - ext_length # nbl: new_base_length
|
1113
|
+
nbl -= 1 if dir != "" # Account for one extra character
|
1114
|
+
nbl -= 1 if link != "" # Account for one extra character
|
1045
1115
|
str = base_name[0..nbl] + "…" + ext_name
|
1046
1116
|
end
|
1047
1117
|
if !active and ix == win.maxy - 1 # Add indicator of more at bottom @w_r list
|
@@ -1053,7 +1123,7 @@ def list_dir(active) # LIST CONTENT OF A DIRECTORY (BOTH active AND RIGHT WINDOW
|
|
1053
1123
|
win.attron(file_marker) { win << str } # Implement color/bold to the item
|
1054
1124
|
win.clrtoeol
|
1055
1125
|
win << "\n"
|
1056
|
-
ix += 1; t
|
1126
|
+
ix += 1; t += 1
|
1057
1127
|
end
|
1058
1128
|
(win.maxy - win.cury).times {win.deleteln()} # Clear to bottom of window
|
1059
1129
|
if active
|
@@ -1080,12 +1150,14 @@ def open_selected(html = nil) # OPEN SELECTED ITEM (when pressing RIGHT)
|
|
1080
1150
|
if File.read(@selected).force_encoding("UTF-8").valid_encoding? and not html
|
1081
1151
|
system("exec $EDITOR #{@selected_safe}")
|
1082
1152
|
else
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1153
|
+
if @runmailcap
|
1154
|
+
#Thread.new { system("run-mailcap #{@selected_safe} 2>/dev/null") }
|
1155
|
+
system("run-mailcap #{@selected_safe} 2>/dev/null")
|
1156
|
+
else
|
1157
|
+
#Thread.new { system("xdg-open #{@selected_safe} 2>/dev/null") }
|
1158
|
+
system("xdg-open #{@selected_safe} 2>/dev/null")
|
1088
1159
|
end
|
1160
|
+
end
|
1089
1161
|
@break = true
|
1090
1162
|
rescue
|
1091
1163
|
end
|
@@ -1113,7 +1185,7 @@ def copy_move_link(type) # COPY OR MOVE TAGGED ITEMS (COPY IF "keep == true")
|
|
1113
1185
|
FileUtils.ln_s(item, dest)
|
1114
1186
|
w_b_info(" Item(s) symlinked here.")
|
1115
1187
|
end
|
1116
|
-
rescue
|
1188
|
+
rescue Exception => err
|
1117
1189
|
w_b_info(err.to_s)
|
1118
1190
|
end
|
1119
1191
|
end
|
@@ -1207,16 +1279,19 @@ def w_r_doc # GET FULL CONTENT TO PAGE
|
|
1207
1279
|
@w_r << @w_r.text
|
1208
1280
|
end
|
1209
1281
|
def w_r_info(info) # SHOW INFO IN THE RIGHT WINDOW
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1282
|
+
begin
|
1283
|
+
image_show("clear") if @image; @image = false
|
1284
|
+
@w_r.clr
|
1285
|
+
@w_r.refresh
|
1286
|
+
w_r_width = Curses.cols - (Curses.cols * @width / 10) - 2
|
1287
|
+
info.gsub!(/(.{1,#{w_r_width}})( +|$\n?)|(.{1,#{w_r_width}})/, "\\1\\3\n")
|
1288
|
+
@w_r.text = info
|
1289
|
+
@w_r.pager_cmd = ""
|
1290
|
+
pager_start
|
1291
|
+
pager_show
|
1292
|
+
@w_r.update = false
|
1293
|
+
rescue
|
1294
|
+
end
|
1220
1295
|
end
|
1221
1296
|
def marks_info # SHOW MARKS IN RIGHT WINDOW
|
1222
1297
|
@w_r.fg = 183
|
@@ -1340,11 +1415,13 @@ def openai # INTERFACE TO OPENAI
|
|
1340
1415
|
p += "#{f}? "
|
1341
1416
|
p += "Give a brief summary of its content: " + c unless File.directory?(@selected) and c == ""
|
1342
1417
|
|
1343
|
-
|
1344
|
-
|
1418
|
+
begin
|
1419
|
+
response = client.completions( parameters: { model: @aimodel, prompt: p, max_tokens: 200 })
|
1345
1420
|
text = "OpenAI description:\n" + response["choices"][0]["text"]
|
1346
|
-
|
1347
|
-
text
|
1421
|
+
rescue
|
1422
|
+
text = "Error retrieving OpenAI request.\n\n"
|
1423
|
+
text += "Check your connection and @ai secret key (in .rtfm.conf).\n\n"
|
1424
|
+
text += response.to_s
|
1348
1425
|
end
|
1349
1426
|
|
1350
1427
|
@w_r.fg = 229
|
@@ -1373,8 +1450,8 @@ def sysinfo
|
|
1373
1450
|
cpu = "CPUs = " + `nproc`.chop + " "
|
1374
1451
|
cpuinfo = `lscpu`
|
1375
1452
|
cpu += cpuinfo[/^.*Model name:\s*(.*)/, 1] + " "
|
1376
|
-
cpu += "Max: " + cpuinfo[/^.*CPU max MHz:\s*(.*)/, 1]
|
1377
|
-
cpu += "Min: " + cpuinfo[/^.*CPU min MHz:\s*(.*)/, 1]
|
1453
|
+
cpu += "Max: " + cpuinfo[/^.*CPU max MHz:\s*(.*)/, 1].to_i.to_s + "MHz "
|
1454
|
+
cpu += "Min: " + cpuinfo[/^.*CPU min MHz:\s*(.*)/, 1].to_i.to_s + "MHz\n\n"
|
1378
1455
|
text += [[154, 0, cpu]]
|
1379
1456
|
mem = `free -h` + "\n"
|
1380
1457
|
text += [[229, 0, mem]]
|
@@ -1383,7 +1460,8 @@ def sysinfo
|
|
1383
1460
|
disk = `df -H | head -8`
|
1384
1461
|
text += [[172, 0, disk]]
|
1385
1462
|
dmesg = "\nDMESG (latest first):\n"
|
1386
|
-
|
1463
|
+
dcmd = `dmesg 2>/dev/null | tail -6`.split("\n").sort.reverse.join("\n")
|
1464
|
+
dcmd != "" ? dmesg += dcmd : dmesg += "dmesg requires root, run 'sudo sysctl kernel.dmesg_restrict=0' if you need permission\n"
|
1387
1465
|
text += [[219, 0, dmesg]]
|
1388
1466
|
w_r_info(ansifix(text))
|
1389
1467
|
rescue
|
@@ -1411,23 +1489,29 @@ def w_b_info(info) # SHOW INFO IN @W_B
|
|
1411
1489
|
@w_b.write
|
1412
1490
|
@w_b.update = false
|
1413
1491
|
end
|
1414
|
-
def w_b_getstr(pretext, text) # A SIMPLE READLINE-LIKE ROUTINE
|
1492
|
+
def w_b_getstr(pretext, text, ruby=false) # A SIMPLE READLINE-LIKE ROUTINE
|
1415
1493
|
Curses.curs_set(1)
|
1416
1494
|
Curses.echo
|
1417
1495
|
stk = 0
|
1418
|
-
@history.insert(stk, text)
|
1419
|
-
pos = @history[stk].length
|
1420
1496
|
chr = ""
|
1497
|
+
if ruby
|
1498
|
+
@rubyhistory.insert(stk, text)
|
1499
|
+
@history_copy = @rubyhistory.map(&:clone)
|
1500
|
+
else
|
1501
|
+
@history.insert(stk, text)
|
1502
|
+
@history_copy = @history.map(&:clone)
|
1503
|
+
end
|
1504
|
+
pos = @history_copy[stk].length
|
1421
1505
|
while chr != "ENTER"
|
1422
1506
|
@w_b.setpos(0,0)
|
1423
1507
|
init_pair(250, 250, 238)
|
1424
|
-
text = pretext + @
|
1508
|
+
text = pretext + @history_copy[stk]
|
1425
1509
|
text += " " * (@w_b.maxx - text.length) if text.length < @w_b.maxx
|
1426
1510
|
@w_b.attron(color_pair(250)) { @w_b << text }
|
1427
1511
|
@w_b.setpos(0,pretext.length + pos)
|
1428
1512
|
@w_b.refresh
|
1429
1513
|
chr = getchr
|
1430
|
-
if chr ==
|
1514
|
+
if chr == 'C-G' or chr == 'C-C'
|
1431
1515
|
Curses.curs_set(0)
|
1432
1516
|
Curses.noecho
|
1433
1517
|
@w_b.update = true
|
@@ -1436,50 +1520,50 @@ def w_b_getstr(pretext, text) # A SIMPLE READLINE-LIKE ROUTINE
|
|
1436
1520
|
case chr
|
1437
1521
|
when 'UP'
|
1438
1522
|
unless @w_b.nohistory
|
1439
|
-
unless stk == @
|
1523
|
+
unless stk == @history_copy.length - 1
|
1440
1524
|
stk += 1
|
1441
|
-
pos = @
|
1525
|
+
pos = @history_copy[stk].length
|
1442
1526
|
end
|
1443
1527
|
end
|
1444
1528
|
when 'DOWN'
|
1445
1529
|
unless @w_b.nohistory
|
1446
1530
|
unless stk == 0
|
1447
1531
|
stk -= 1
|
1448
|
-
pos = @
|
1532
|
+
pos = @history_copy[stk].length
|
1449
1533
|
end
|
1450
1534
|
end
|
1451
1535
|
when 'RIGHT'
|
1452
|
-
pos += 1 unless pos > @
|
1536
|
+
pos += 1 unless pos > @history_copy[stk].length
|
1453
1537
|
when 'LEFT'
|
1454
1538
|
pos -= 1 unless pos == 0
|
1455
1539
|
when 'HOME'
|
1456
1540
|
pos = 0
|
1457
1541
|
when 'END'
|
1458
|
-
pos = @
|
1542
|
+
pos = @history_copy[stk].length
|
1459
1543
|
when 'DEL'
|
1460
|
-
@
|
1544
|
+
@history_copy[stk][pos] = ""
|
1461
1545
|
when 'BACK'
|
1462
1546
|
unless pos == 0
|
1463
1547
|
pos -= 1
|
1464
|
-
@
|
1548
|
+
@history_copy[stk][pos] = ""
|
1465
1549
|
end
|
1466
1550
|
when 'WBACK'
|
1467
1551
|
unless pos == 0
|
1468
|
-
until @
|
1552
|
+
until @history_copy[stk][pos - 1] == " " or pos == 0
|
1469
1553
|
pos -= 1
|
1470
|
-
@
|
1554
|
+
@history_copy[stk][pos] = ""
|
1471
1555
|
end
|
1472
|
-
if @
|
1556
|
+
if @history_copy[stk][pos - 1] == " "
|
1473
1557
|
pos -= 1
|
1474
|
-
@
|
1558
|
+
@history_copy[stk][pos] = ""
|
1475
1559
|
end
|
1476
1560
|
end
|
1477
1561
|
when 'LDEL'
|
1478
|
-
@
|
1562
|
+
@history_copy[stk] = ""
|
1479
1563
|
pos = 0
|
1480
1564
|
when 'TAB' # Tab completion of dirs and files
|
1481
1565
|
p1 = pos - 1
|
1482
|
-
c = @
|
1566
|
+
c = @history_copy[stk][0..(p1)].sub(/^.* /, '')
|
1483
1567
|
p0 = p1 - c.length
|
1484
1568
|
compl = File.expand_path(c)
|
1485
1569
|
compl += "/" if Dir.exist?(compl)
|
@@ -1514,19 +1598,28 @@ def w_b_getstr(pretext, text) # A SIMPLE READLINE-LIKE ROUTINE
|
|
1514
1598
|
Curses.echo
|
1515
1599
|
end
|
1516
1600
|
end
|
1517
|
-
@
|
1601
|
+
@history_copy[stk].sub!(c,compl)
|
1518
1602
|
pos = pos - c.length + compl.length
|
1519
1603
|
when /^.$/
|
1520
|
-
@
|
1604
|
+
@history_copy[stk].insert(pos,chr)
|
1605
|
+
pos += 1
|
1606
|
+
end
|
1607
|
+
while $stdin.ready?
|
1608
|
+
chr = $stdin.getc
|
1609
|
+
@history_copy[stk].insert(pos,chr)
|
1521
1610
|
pos += 1
|
1522
1611
|
end
|
1523
1612
|
end
|
1524
|
-
curstr = @
|
1525
|
-
@
|
1613
|
+
curstr = @history_copy[stk]
|
1614
|
+
@history_copy.shift if @w_b.nohistory
|
1615
|
+
ruby ? @rubyhistory.insert(0, @history_copy[stk]) : @history.insert(0, @history_copy[stk])
|
1526
1616
|
unless @w_b.nohistory
|
1527
1617
|
@history.uniq!
|
1528
1618
|
@history.compact!
|
1529
1619
|
@history.delete("")
|
1620
|
+
@rubyhistory.uniq!
|
1621
|
+
@rubyhistory.compact!
|
1622
|
+
@rubyhistory.delete("")
|
1530
1623
|
end
|
1531
1624
|
Curses.curs_set(0)
|
1532
1625
|
Curses.noecho
|
@@ -1549,11 +1642,11 @@ def w_b_exec(cmd) # EXECUTE COMMAND FROM @W_B
|
|
1549
1642
|
status = Timeout::timeout(15) {
|
1550
1643
|
@w_r.clr
|
1551
1644
|
begin
|
1552
|
-
@w_r.pager_cmd = "#{cmd} | #{@bat} -n --color=always
|
1553
|
-
@w_r.text =
|
1645
|
+
@w_r.pager_cmd = "#{cmd} 2>&1 | #{@bat} -n --color=always"
|
1646
|
+
@w_r.text = %x(#{@w_r.pager_cmd})
|
1554
1647
|
rescue
|
1555
|
-
@w_r.pager_cmd = "#{cmd} 2
|
1556
|
-
@w_r.text =
|
1648
|
+
@w_r.pager_cmd = "#{cmd} 2>&1"
|
1649
|
+
@w_r.text = %x(#{@w_r.pager_cmd})
|
1557
1650
|
end
|
1558
1651
|
unless @w_r.text == "" or @w_r.text == nil
|
1559
1652
|
pager_start
|
@@ -1585,8 +1678,8 @@ loop do # OUTER LOOP - CATCHING REFRESHES VIA 'r'
|
|
1585
1678
|
maxx = Curses.cols
|
1586
1679
|
maxy = Curses.lines
|
1587
1680
|
# Curses::Window.new(h,w,y,x)
|
1588
|
-
@w_t = Curses::Window.new(1,
|
1589
|
-
@w_b = Curses::Window.new(1,
|
1681
|
+
@w_t = Curses::Window.new(1, maxx, 0, 0)
|
1682
|
+
@w_b = Curses::Window.new(1, maxx, maxy - 1, 0)
|
1590
1683
|
@w_l = Curses::Window.new(maxy - 3, (maxx * @width / 10) - 1, 2, 0)
|
1591
1684
|
@w_r = Curses::Window.new(maxy - 4, maxx - (maxx * @width / 10), 2, maxx * @width / 10)
|
1592
1685
|
@w_p = Curses::Window.new(1, maxx - (maxx * @width / 10), maxy - 2, maxx * @width / 10)
|
@@ -1605,8 +1698,6 @@ loop do # OUTER LOOP - CATCHING REFRESHES VIA 'r'
|
|
1605
1698
|
tagged_info
|
1606
1699
|
@w_r.update = false
|
1607
1700
|
end
|
1608
|
-
@change = true
|
1609
|
-
@change_tag = true # For future need to force @change
|
1610
1701
|
loop do # INNER, CORE LOOP
|
1611
1702
|
begin # Jump to home dir if current dir is externally removed
|
1612
1703
|
Dir.pwd
|
@@ -1638,13 +1729,8 @@ loop do # OUTER LOOP - CATCHING REFRESHES VIA 'r'
|
|
1638
1729
|
@selected = @files[@index] # Get text of selected item
|
1639
1730
|
sel_old = @selected_safe
|
1640
1731
|
@selected_safe = "\"#{@selected}\"" # Make it safe for commands
|
1641
|
-
|
1642
|
-
|
1643
|
-
if @change
|
1644
|
-
system("printf \"\033]0;RTFM: #{Dir.pwd}\007\"") # Set Window title to path
|
1645
|
-
# Top window (info line)
|
1646
|
-
w_t_info
|
1647
|
-
end
|
1732
|
+
system("printf \"\033]0;RTFM: #{Dir.pwd}\007\"") # Set Window title to path
|
1733
|
+
w_t_info # Top window (info line)
|
1648
1734
|
@w_l.setpos(0,0)
|
1649
1735
|
list_dir(true)
|
1650
1736
|
@w_l.refresh
|
@@ -1667,6 +1753,9 @@ loop do # OUTER LOOP - CATCHING REFRESHES VIA 'r'
|
|
1667
1753
|
break if Curses.cols != maxx or Curses.lines != maxy # break on terminal resize
|
1668
1754
|
break if @break # Break to outer loop, redrawing windows, if user hit 'r'
|
1669
1755
|
end
|
1756
|
+
rescue StandardError => err # Throw error nicely
|
1757
|
+
w_r_info(err)
|
1758
|
+
@w_r.update = false
|
1670
1759
|
ensure # On exit: close curses, clear terminal
|
1671
1760
|
@write_conf_all = false
|
1672
1761
|
conf_write if @write_conf # Write marks to config file
|
@@ -1674,7 +1763,7 @@ loop do # OUTER LOOP - CATCHING REFRESHES VIA 'r'
|
|
1674
1763
|
close_screen
|
1675
1764
|
# If launched via the script "r", return current dir and "r" will cd to that
|
1676
1765
|
begin
|
1677
|
-
File.write(ARGV[0], Dir.pwd) if ARGV[0] and ARGV[0].match(/\/tmp
|
1766
|
+
File.write(ARGV[0], Dir.pwd) if ARGV[0] and ARGV[0].match(/\/tmp/)
|
1678
1767
|
rescue
|
1679
1768
|
end
|
1680
1769
|
end
|
data/rtfm-kb.png
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rtfm-filemanager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: '3.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Geir Isene
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: curses
|
@@ -47,14 +47,14 @@ dependencies:
|
|
47
47
|
description: 'A full featured terminal browser with syntax highlighted files, images
|
48
48
|
shown in the terminal, videos thumbnailed, etc. You can bookmark and jump around
|
49
49
|
easily, delete, rename, copy, symlink and move files. RTFM has a a wide range of
|
50
|
-
other features. New in 3.
|
50
|
+
other features. New in 3.3: Updated default OpenAI model and adding the option to
|
51
|
+
add own by setting @aimodel in .rtfm.conf.'
|
51
52
|
email: g@isene.com
|
52
53
|
executables:
|
53
54
|
- rtfm
|
54
55
|
extensions: []
|
55
56
|
extra_rdoc_files: []
|
56
57
|
files:
|
57
|
-
- ".rtfm.launch"
|
58
58
|
- README.md
|
59
59
|
- bin/rtfm
|
60
60
|
- rtfm-kb.png
|
@@ -63,7 +63,7 @@ licenses:
|
|
63
63
|
- Unlicense
|
64
64
|
metadata:
|
65
65
|
source_code_uri: https://github.com/isene/RTFM
|
66
|
-
post_install_message:
|
66
|
+
post_install_message:
|
67
67
|
rdoc_options: []
|
68
68
|
require_paths:
|
69
69
|
- lib
|
@@ -78,8 +78,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
78
|
- !ruby/object:Gem::Version
|
79
79
|
version: '0'
|
80
80
|
requirements: []
|
81
|
-
rubygems_version: 3.
|
82
|
-
signing_key:
|
81
|
+
rubygems_version: 3.4.20
|
82
|
+
signing_key:
|
83
83
|
specification_version: 4
|
84
84
|
summary: RTFM - Ruby Terminal File Manager
|
85
85
|
test_files: []
|
data/.rtfm.launch
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
# This function starts RTFM and will cd to the exit dir
|
2
|
-
#
|
3
|
-
# Add this line to your .bashrc or .zshrc to make RTFM exit to the
|
4
|
-
# current directory by launching the file manager via r in the terminal:
|
5
|
-
# source ~/.rtfm.launch
|
6
|
-
# ... and place the file .rtfm.launch in your home directory.
|
7
|
-
# With this, you can jump around in your directory structure via RTFM, exit to
|
8
|
-
# the desired directory, do work in the terminal and go back into RTFM via r.
|
9
|
-
|
10
|
-
function r {
|
11
|
-
f=$(mktemp)
|
12
|
-
(
|
13
|
-
set +e
|
14
|
-
rtfm "$f"
|
15
|
-
code=$?
|
16
|
-
if [ "$code" != 0 ]; then
|
17
|
-
rm -f "$f"
|
18
|
-
exit "$code"
|
19
|
-
fi
|
20
|
-
)
|
21
|
-
code=$?
|
22
|
-
if [ "$code" != 0 ]; then
|
23
|
-
return "$code"
|
24
|
-
fi
|
25
|
-
d=$(<"$f")
|
26
|
-
rm -f "$f"
|
27
|
-
cd "$d"
|
28
|
-
}
|