rtfm-filemanager 3.0.3 → 3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +43 -31
  3. data/bin/rtfm +262 -173
  4. data/rtfm-kb.png +0 -0
  5. metadata +8 -8
  6. data/.rtfm.launch +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76bd197d0a9c8613ab381e40e427d4784ad70304c65799a2a939777be9cf6e54
4
- data.tar.gz: e386caba16205f6f9ae5694bbd6e56f58fa7c7d4947bff08380dd7ca483cfabe
3
+ metadata.gz: f93c42211b4b1f57fdec42841b7cfddf9d08797cc999f32da9816899016043b9
4
+ data.tar.gz: cf1c10a981bea7b7f384cdbe5bba59f3138f58467d39644e65d8ccaad1386e43
5
5
  SHA512:
6
- metadata.gz: 0ffee736412785328cdeaf2d29860d9ff0dfb948d653be36c3b82a279d579f13fcdce37c53ec4ec3dcbd67757d2e4c4397394520c73013ab67b28cf8542e38bf
7
- data.tar.gz: cf758653dbdc1894fad957729cdd25783f70545e6d26cabe48eaca62c324e7e21ac98182478094108fbee0c8a470097baf971748cfa9f2c19cbc37999b4ebd42
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
- You can run any command in the bottom "command line" and have the output
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 simply coloning this repo and put the file `rtfm` in
77
- your "bin" directory. Or you can simply run `gem install rtfm-filemanager`.
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. It is shown if you
89
- have the program installed (Debian/Ubuntu family of Linux distros command in
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
- cp .rtfm.launch ~/
113
- echo "source ~/.rtfm.launch" >> .zshrc # or .bashrc if you run bash as shell
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 all windows. Use on terminal resize or when there is garbage somewhere)
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 window to highlight matching items and jump to the first match
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 bottom window)
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 window (the full ls command)
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 window (press ENTER to execute, press Ctrl-G to escape)
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
- C-Y | Copy content of right pane to clipboard
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
- `source ~/.rtfm.launch`
270
+ ## Keyboard cheat sheet
271
+ ![RTFM keyboard cheat sheet](img/rtfm-kb.png)
266
272
 
267
- ... and place the file `.rtfm.launch` in your home directory.
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 ⅕th).
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 window will be sent to the Ruby
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.0.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
- S = Show comprehensive System info (system, CPU, filesystem, latest dmesg messages)
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-3. No rights reserved. See http://isene.com for more.
118
+ COPYRIGHT: Geir Isene, 2020-4. No rights reserved. See http://isene.com for more.
118
119
  HELPTEXT
119
- @firstrun = <<FIRSTRUN
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
- Welcome to RTFM - the Ruby Terminal File Manager. This help text is shown on the first run.
122
- To benefit fully from all the features, you need to install some auxilliary software.
123
- On Ubuntu Linux you would use "apt install":
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
- Basic requirments is "x11-utils" and "xdotool": apt install x11-utils xdotool
126
- Syntax highlighting of text uses "bat": apt install bat
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
- unless File.exist?(Dir.home+'/.rtfm.conf')
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 RTFM help text."
140
- STDIN.gets
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
- STDIN.set_encoding(Encoding::UTF_8) # Set encoding for STDIN
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 = "--group-directories-first" # Basic ls setup
181
- @lslong = false # Set short form ls (toggled by pressing "l")
182
- @lsall = "" # Set "ls -a" to false (toggled by pressing "a" - sets it to "-a")
183
- @lsorder = "" # Change the order/sorting by pressing 'o' (circular toggle)
184
- @lsinvert = "" # Set to "-r" to reverse/invert sorting order
185
- @lsuser = "" # Set this variable in .rtfm.conf to any 'ls' switch you want to customize directory listings
186
- @width = 4 # Set width of the left pane to the default ⅓ of the terminal width
187
- @history = [] # Initialize the command line history array
188
- @border = false
189
- @preview = true
190
- @runmailcap = false # Set to 'true' in .rtfm.conf if you want to use run-mailcap instead of xdg-open
191
- @batuse = true # Use batcat for syntax highlighting
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 = {} # Initialize (book)marks hash
194
- @hash = {} # Initialize the sha directory hashing
195
- @tagged = [] # Initialize the tagged array - for collecting all tagged items
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 = {} # Initialize the directory hash for remembering directories visited
198
- @searched = "" # Initialize the active searched for items
199
- @lsfiles = "" # File types to show (initially set to all file types) - not saved on exit
200
- @lsmatch = "" # Files to match (initially set to matching all files) - not saved on exit
201
- @index = 0 # Set chosen item to first on startup
202
- @cont = ""
203
- @tagsize = 0
204
- @navi = ""
205
- @marks["'"] = Dir.pwd
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 = /\.jpg$|\.JPG$|\.jpeg$|\.png$|\.bmp$|\.gif$|\.tif$|\.tiff$/
208
- @pptfile = /\.ppt$/
209
- @xlsfile = /\.xls$/
210
- @docfile = /\.doc$/
211
- @docxfile = /\.docx$/
212
- @xlsxfile = /\.xlsx$/
213
- @pptxfile = /\.pptx$/
214
- @oolofile = /\.odt$|\.odc$|\.odp$|\.odg$/
215
- @pdffile = /\.pdf$|\.ps$/
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
- class Curses::Window # CLASS EXTENSION
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!( /\e\[\d;38;5;(\d+);*(\d*)m/, '¤¤\1¤¤\2¤¤')
278
- input.gsub!( /\e\[38;5;(\d+);*(\d*)m/, '¤¤\1¤¤\2¤¤')
279
- input.gsub!( /\e\[\d;38;2;(\d+);*(\d*);\d*m/, '¤¤\1¤¤\2¤¤')
280
- input.gsub!( /\e\[38;2;(\d+);*(\d*);\d*m/, '¤¤\1¤¤\2¤¤')
281
- input.gsub!( /\e\[0m/, "\t")
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 = STDIN.getch(min: 0, time: 3)
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 STDIN.getc == "^"
303
- when '3' then chr = "DEL" ; chr = "C-DEL" if STDIN.getc == "^"
304
- when '5' then chr = "PgUP" ; chr = "C-PgUP" if STDIN.getc == "^"
305
- when '6' then chr = "PgDOWN" ; chr = "C-PgDOWN" if STDIN.getc == "^"
306
- when '7' then chr = "HOME" ; chr = "C-HOME" if STDIN.getc == "^"
307
- when '8' then chr = "END" ; chr = "C-END" if STDIN.getc == "^"
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 "" then chr = "WBACK"
319
- when "" then chr = "LDEL"
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 /./ then chr = c
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 = STDIN.getc
492
+ m = $stdin.getc
424
493
  if m.match(/[\w']/)
425
494
  @marks[m] = Dir.pwd
426
495
  elsif m == "-"
427
- r = STDIN.getc
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 STDIN.getc == 'y'
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 StandardError => e
859
- info += "Error: #{e.inspect}"
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
- @files = `#{ls_cmd}`.split("\n")
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 = @files[ix]
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
- fg, bold = get_ls_color(ftype) unless ftype == "" # Color from LS_COLORS
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 += 1
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
- if @runmailcap
1084
- Thread.new { system("run-mailcap #{@selected_safe} 2>/dev/null") }
1085
- else
1086
- Thread.new { system("xdg-open #{@selected_safe} 2>/dev/null") }
1087
- end
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 StandardError => err
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
- image_show("clear") if @image; @image = false
1211
- @w_r.clr
1212
- @w_r.refresh
1213
- w_r_width = Curses.cols - (Curses.cols * @width / 10) - 2
1214
- info.gsub!(/(.{1,#{w_r_width}})( +|$\n?)|(.{1,#{w_r_width}})/, "\\1\\3\n")
1215
- @w_r.text = info
1216
- @w_r.pager_cmd = ""
1217
- pager_start
1218
- pager_show
1219
- @w_r.update = false
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
- response = client.completions( parameters: { model: "text-davinci-003", prompt: p, max_tokens: 200 })
1344
- if response["error"]["message"] == ""
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
- else
1347
- text = response["error"]["message"]
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][/(.*),.*/, 1] + "MHz "
1377
- cpu += "Min: " + cpuinfo[/^.*CPU min MHz:\s*(.*)/, 1][/(.*),.*/, 1] + "MHz\n\n"
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
- dmesg += `dmesg | tail -6`.split("\n").sort.reverse.join("\n")
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 + @history[stk]
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 == "C-G"
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 == @history.length - 1
1523
+ unless stk == @history_copy.length - 1
1440
1524
  stk += 1
1441
- pos = @history[stk].length
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 = @history[stk].length
1532
+ pos = @history_copy[stk].length
1449
1533
  end
1450
1534
  end
1451
1535
  when 'RIGHT'
1452
- pos += 1 unless pos > @history[stk].length
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 = @history[stk].length
1542
+ pos = @history_copy[stk].length
1459
1543
  when 'DEL'
1460
- @history[stk][pos] = ""
1544
+ @history_copy[stk][pos] = ""
1461
1545
  when 'BACK'
1462
1546
  unless pos == 0
1463
1547
  pos -= 1
1464
- @history[stk][pos] = ""
1548
+ @history_copy[stk][pos] = ""
1465
1549
  end
1466
1550
  when 'WBACK'
1467
1551
  unless pos == 0
1468
- until @history[stk][pos - 1] == " " or pos == 0
1552
+ until @history_copy[stk][pos - 1] == " " or pos == 0
1469
1553
  pos -= 1
1470
- @history[stk][pos] = ""
1554
+ @history_copy[stk][pos] = ""
1471
1555
  end
1472
- if @history[stk][pos - 1] == " "
1556
+ if @history_copy[stk][pos - 1] == " "
1473
1557
  pos -= 1
1474
- @history[stk][pos] = ""
1558
+ @history_copy[stk][pos] = ""
1475
1559
  end
1476
1560
  end
1477
1561
  when 'LDEL'
1478
- @history[stk] = ""
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 = @history[stk][0..(p1)].sub(/^.* /, '')
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
- @history[stk].sub!(c,compl)
1601
+ @history_copy[stk].sub!(c,compl)
1518
1602
  pos = pos - c.length + compl.length
1519
1603
  when /^.$/
1520
- @history[stk].insert(pos,chr)
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 = @history[stk]
1525
- @history.shift if @w_b.nohistory
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 2>/dev/null"
1553
- @w_r.text = `#{@w_r.pager_cmd}`
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>/dev/null"
1556
- @w_r.text = `#{@w_r.pager_cmd}`
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, 0, 0, 0)
1589
- @w_b = Curses::Window.new(1, 0, maxy - 1, 0)
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
- @selected_safe == sel_old ? @change = false : @change = true
1642
- @change = true if @change_tag; @change_tag = false
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\/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.0.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: 2023-05-02 00:00:00.000000000 Z
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.0.3: Fixed OpenAI error message'
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.3.5
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
- }