rtfm-filemanager 3.0.3 → 3.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
![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
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
|
-
![](img/screenshot.png)
|
126
|
+
![RTFM screenshot](img/screenshot.png)
|
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
|
+
![RTFM keyboard cheat sheet](img/rtfm-kb.png)
|
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
|
-
}
|