rtfm-filemanager 3.3 → 3.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -6
  3. data/bin/rtfm +159 -214
  4. data/rtfm-kb.png +0 -0
  5. metadata +7 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f93c42211b4b1f57fdec42841b7cfddf9d08797cc999f32da9816899016043b9
4
- data.tar.gz: cf1c10a981bea7b7f384cdbe5bba59f3138f58467d39644e65d8ccaad1386e43
3
+ metadata.gz: fe11017b37608ece785d04b740e858ee400a3518f7ec6e2e90d318c36069d431
4
+ data.tar.gz: c1f526b4b1a347c106915e6c4e03486e1adf1464c8050e153b625f1510fa6aa7
5
5
  SHA512:
6
- metadata.gz: 85564f159ec0be34424eb45715474ba75fd001711a93f9830f5d4c33b319ef509a216afac9ac809ba8a8ec39f15a6d61f1f9055250d9d3264b46cffa231fbcc3
7
- data.tar.gz: bd1fab6993c5f5bd735274f275d1195439b33d83cadad26a98541d266e3fe6dbc243d2a513f1aaac8697c5645ae567a13e6f8425fa0f1f5467345359b911b15b
6
+ metadata.gz: 8cb52b1a6b0d7bd0db5f76486cde99416a1a3fcb9ceee3d1e5e0cc912c6c79c567e104982e9fa32f6a8f53a7cbbe34481f72d30980e24c9a2ffc31ac544db96e
7
+ data.tar.gz: 8376fb44256d84321f755842daa76009c5e116a86024977bd1af5bc01c24915198b51c0c082f2e609cd6181ee5dfef36484a6394a376da8f08f1816ad76c5567
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?
@@ -64,9 +64,6 @@ 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
- When you start RTFM, you can supply a directory path as an argument to let
68
- RTFM start up in that directory.
69
-
70
67
  You can run any command in the bottom "command bar" and have the output
71
68
  presented in the right pane. Use LEFT and RIGHT keys to go back and forth on
72
69
  the command line, HOME to beginning of line, END to end of line, Backspace or
@@ -263,9 +260,8 @@ B | Toggle border
263
260
  y | Copy path of selected item to primary selection (for pasting with middle mouse button)
264
261
  Y | Copy path of selected item to clipboard
265
262
  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
268
263
  S | Show comprehensive system info (system, CPU, filesystem, latest dmesg messages)
264
+ Ctrl-n | Invoke navi (see https://github.com/denisidoro/navi) with any output in right pane
269
265
 
270
266
  ## Keyboard cheat sheet
271
267
  ![RTFM keyboard cheat sheet](img/rtfm-kb.png)
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.3"
17
+ @version = "3.5"
18
18
 
19
19
  # PRELIMINARIES
20
20
  @help = <<HELPTEXT
@@ -111,11 +111,10 @@ ADDITIONAL COMMANDS
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
- Ctrl-d = Create a new directory (a shortcut for ":mkdir ")
115
- Ctrl-n = Invoke navi (see https://github.com/denisidoro/navi) with any output in right window
116
114
  S = Show comprehensive System info (system, CPU, filesystem, latest dmesg messages)
115
+ Ctrl-n = Invoke navi (see https://github.com/denisidoro/navi) with any output in right window
117
116
 
118
- COPYRIGHT: Geir Isene, 2020-4. No rights reserved. See http://isene.com for more.
117
+ COPYRIGHT: Geir Isene, 2020-3. No rights reserved. See http://isene.com for more.
119
118
  HELPTEXT
120
119
  def firstrun
121
120
  @firstrun = <<~FIRSTRUN
@@ -143,38 +142,9 @@ def firstrun
143
142
 
144
143
  FIRSTRUN
145
144
 
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
145
+ if not File.exist?(Dir.home+'/.rtfm.launch')
146
+ @rtfmlaunch = <<RTFMLAUNCH
147
+ # This is the RTFM launcher (https://github.com/isene/RTFM)
178
148
  function r {
179
149
  f=$(mktemp)
180
150
  (
@@ -195,19 +165,18 @@ function r {
195
165
  cd "$d"
196
166
  }
197
167
  RTFMLAUNCH
198
- File.write(Dir.home+'/.rtfm.launch', @rtfmlaunch)
199
- `echo "source ~/.rtfm.launch" >> .#{@shell}rc`
200
- end
168
+ File.write(Dir.home+'/.rtfm.launch', @rtfmlaunch)
169
+ @shell = File.basename(`echo "$SHELL"`.chomp)
170
+ `echo "source ~/.rtfm.launch" >> .#{@shell}rc`
201
171
  end
202
172
 
203
173
  puts @firstrun
204
174
  puts "\n... hit ENTER to start RTFM. Hit ? inside RTFM to show the help text. Enjoy :-)"
205
- $stdin.gets
175
+ STDIN.gets
206
176
  end
207
177
  begin # BASIC SETUP
208
178
  require 'fileutils'
209
179
  require 'io/console'
210
- require 'io/wait'
211
180
  require 'date'
212
181
  require 'timeout'
213
182
  require 'curses'
@@ -229,7 +198,8 @@ begin # BASIC SETUP
229
198
 
230
199
  cmd?('bat') ? @bat = "bat" : @bat = "batcat"
231
200
 
232
- $stdin.set_encoding(Encoding::UTF_8) # Set encoding for $stdin
201
+ STDIN.set_encoding(Encoding::UTF_8) # Set encoding for STDIN
202
+ LScolors = `echo $LS_COLORS` # Import LS_COLORS
233
203
 
234
204
  ## Curses setup
235
205
  Curses.init_screen
@@ -241,52 +211,48 @@ begin # BASIC SETUP
241
211
 
242
212
  # INITIALIZE VARIABLES
243
213
  ## These can be set by user in .rtfm.conf
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
214
+ @lsbase = "--group-directories-first" # Basic ls setup
215
+ @lslong = false # Set short form ls (toggled by pressing "l")
216
+ @lsall = "" # Set "ls -a" to false (toggled by pressing "a" - sets it to "-a")
217
+ @lsorder = "" # Change the order/sorting by pressing 'o' (circular toggle)
218
+ @lsinvert = "" # Set to "-r" to reverse/invert sorting order
219
+ @lsuser = "" # Set this variable in .rtfm.conf to any 'ls' switch you want to customize directory listings
220
+ @width = 4 # Set width of the left pane to the default ⅓ of the terminal width
221
+ @history = [] # Initialize the command line history array
222
+ @border = false
223
+ @preview = true
224
+ @runmailcap = false # Set to 'true' in .rtfm.conf if you want to use run-mailcap instead of xdg-open
225
+ @batuse = true # Use batcat for syntax highlighting
258
226
  ## These are automatically written on exit
259
- @marks = {} # Initialize (book)marks hash
260
- @hash = {} # Initialize the sha directory hashing
261
- @tagged = [] # Initialize the tagged array - for collecting all tagged items
227
+ @marks = {} # Initialize (book)marks hash
228
+ @hash = {} # Initialize the sha directory hashing
229
+ @tagged = [] # Initialize the tagged array - for collecting all tagged items
262
230
  ## These should not be set by user in .rtfm.conf
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
231
+ @directory = {} # Initialize the directory hash for remembering directories visited
232
+ @searched = "" # Initialize the active searched for items
233
+ @lsfiles = "" # File types to show (initially set to all file types) - not saved on exit
234
+ @lsmatch = "" # Files to match (initially set to matching all files) - not saved on exit
235
+ @index = 0 # Set chosen item to first on startup
236
+ @cont = ""
237
+ @tagsize = 0
238
+ @navi = ""
239
+ @marks["'"] = Dir.pwd
272
240
  ## File type recognizers
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$/
241
+ @imagefile = /\.jpg$|\.JPG$|\.jpeg$|\.png$|\.bmp$|\.gif$|\.tif$|\.tiff$/
242
+ @pptfile = /\.ppt$/
243
+ @xlsfile = /\.xls$/
244
+ @docfile = /\.doc$/
245
+ @docxfile = /\.docx$/
246
+ @xlsxfile = /\.xlsx$/
247
+ @pptxfile = /\.pptx$/
248
+ @oolofile = /\.odt$|\.odc$|\.odp$|\.odg$/
249
+ @pdffile = /\.pdf$|\.ps$/
282
250
  ## Get variables from config file (written back to .rtf.conf upon exit via 'q')
283
251
  if File.exist?(Dir.home+'/.rtfm.conf')
284
252
  load(Dir.home+'/.rtfm.conf')
285
253
  end
286
- Dir.chdir(ARGV[0]) if ARGV[0] and Dir.exist?(ARGV[0]) and ARGV[0] !~ /\/tmp/
287
254
  end
288
- # CLASS EXTENSIONS
289
- class Curses::Window
255
+ class Curses::Window # CLASS EXTENSION
290
256
  attr_accessor :fg, :bg, :attr, :text, :update, :pager, :pager_more, :pager_cmd, :locate, :nohistory
291
257
  # General extensions (see https://github.com/isene/Ruby-Curses-Class-Extension)
292
258
  def clr
@@ -316,6 +282,16 @@ class Curses::Window
316
282
  # RTFM specific extensions
317
283
  end
318
284
  # GENERIC FUNCTIONS
285
+ def get_ls_color(type) # GET THE COLOR FOR THE FILETYPE FROM IMPORTED LS_COLORS
286
+ bold = 0
287
+ begin
288
+ color = LScolors.match(/#{type}=\d*;\d*;(\d*)/)[1]
289
+ bold = 1 if LScolors.match(/#{type}=\d*;\d*;\d*;1/)
290
+ rescue
291
+ color = 7 # Default color
292
+ end
293
+ return color.to_i, bold
294
+ end
319
295
  def syntax_highlight(input) # SYNTAX HIGHLIGHTING FROM ANSI COLOR CODES
320
296
  color_ary = color_parse(input)
321
297
  color_ary.each do | pair |
@@ -332,15 +308,13 @@ def syntax_highlight(input) # SYNTAX HIGHLIGHTING FROM ANSI COLOR CODES
332
308
  end
333
309
  end
334
310
  def color_parse(input) # PARSE ANSI COLOR SEQUENCES
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/, "")
311
+ input.gsub!( /\e\[\d;38;5;(\d+);*(\d*)m/, '¤¤\1¤¤\2¤¤')
312
+ input.gsub!( /\e\[38;5;(\d+);*(\d*)m/, '¤¤\1¤¤\2¤¤')
313
+ input.gsub!( /\e\[\d;38;2;(\d+);*(\d*);\d*m/, '¤¤\1¤¤\2¤¤')
314
+ input.gsub!( /\e\[38;2;(\d+);*(\d*);\d*m/, '¤¤\1¤¤\2¤¤')
315
+ input.gsub!( /\e\[0m/, "\t")
341
316
  color_array = input.split("¤¤")
342
317
  color_array = color_array.drop(1)
343
- #color_array.map! { |x| x || 0 }
344
318
  output = color_array.each_slice(3).to_a
345
319
  return output
346
320
  end
@@ -348,10 +322,9 @@ def getchr # PROCESS KEY PRESSES
348
322
  # Note: Curses.getch blanks out @w_t
349
323
  # @w_l.getch makes Curses::KEY_DOWN etc not work
350
324
  # Therefore resorting to the generic method
351
- c = $stdin.getch(min: 0, time: 3)
325
+ c = STDIN.getch(min: 0, time: 3)
352
326
  case c
353
327
  when "\e" # ANSI escape sequences
354
- return "ESC" if $stdin.ready? == nil
355
328
  case $stdin.getc
356
329
  when '[' # CSI
357
330
  case $stdin.getc
@@ -360,13 +333,12 @@ def getchr # PROCESS KEY PRESSES
360
333
  when 'C' then chr = "RIGHT"
361
334
  when 'D' then chr = "LEFT"
362
335
  when 'Z' then chr = "S-TAB"
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 = ""
336
+ when '2' then chr = "INS" ; chr = "C-INS" if STDIN.getc == "^"
337
+ when '3' then chr = "DEL" ; chr = "C-DEL" if STDIN.getc == "^"
338
+ when '5' then chr = "PgUP" ; chr = "C-PgUP" if STDIN.getc == "^"
339
+ when '6' then chr = "PgDOWN" ; chr = "C-PgDOWN" if STDIN.getc == "^"
340
+ when '7' then chr = "HOME" ; chr = "C-HOME" if STDIN.getc == "^"
341
+ when '8' then chr = "END" ; chr = "C-END" if STDIN.getc == "^"
370
342
  end
371
343
  when 'O' # Set Ctrl+ArrowKey equal to ArrowKey; May be used for other purposes in the future
372
344
  case $stdin.getc
@@ -374,29 +346,22 @@ def getchr # PROCESS KEY PRESSES
374
346
  when 'b' then chr = "C-DOWN"
375
347
  when 'c' then chr = "C-RIGHT"
376
348
  when 'd' then chr = "C-LEFT"
377
- else chr = ""
378
349
  end
379
350
  end
380
351
  when "", "" then chr = "BACK"
381
- when "" then chr = "C-C"
382
- when "" then chr = "C-D"
383
- when "" then chr = "C-E"
352
+ when "" then chr = "WBACK"
353
+ when "" then chr = "LDEL"
384
354
  when "" then chr = "C-G"
385
- when " " then chr = "C-K"
386
355
  when " " then chr = "C-L"
387
356
  when "" then chr = "C-N"
388
357
  when "" then chr = "C-O"
389
358
  when "" then chr = "C-P"
390
359
  when "" then chr = "C-T"
391
360
  when "" then chr = "C-Y"
392
- when "" then chr = "WBACK"
393
- when "" then chr = "LDEL"
394
361
  when "\r" then chr = "ENTER"
395
362
  when "\t" then chr = "TAB"
396
- when /[[:print:]]/ then chr = c
397
- else chr = ""
363
+ when /./ then chr = c
398
364
  end
399
- #stdin_clear
400
365
  return chr
401
366
  end
402
367
  def main_getkey # GET KEY FROM USER
@@ -489,11 +454,11 @@ def main_getkey # GET KEY FROM USER
489
454
  # JUMPING AND MARKS
490
455
  when 'm' # Set mark
491
456
  marks_info
492
- m = $stdin.getc
457
+ m = STDIN.getc
493
458
  if m.match(/[\w']/)
494
459
  @marks[m] = Dir.pwd
495
460
  elsif m == "-"
496
- r = $stdin.getc
461
+ r = STDIN.getc
497
462
  @marks.delete(r)
498
463
  end
499
464
  marks_info
@@ -648,7 +613,7 @@ def main_getkey # GET KEY FROM USER
648
613
  @tagged.push("\"#{Dir.pwd}/#{@selected}\"")
649
614
  @tagged.uniq!
650
615
  deletes = @tagged.join(" ")
651
- if $stdin.getc == 'y'
616
+ if STDIN.getc == 'y'
652
617
  `rm -rf #{deletes} 2>/dev/null`
653
618
  items_number = @tagged.length
654
619
  @tagged = []
@@ -907,9 +872,6 @@ def main_getkey # GET KEY FROM USER
907
872
  system("echo -n '#{@cont}' | #{clip}")
908
873
  when 'S' # Show comprehensive system info
909
874
  sysinfo
910
- when 'C-D' # Create new directory (shortcut for ":mkdir ")
911
- cmd = w_b_getstr(": ", "mkdir ")
912
- w_b_exec(cmd + " -p")
913
875
  when 'C-N' # navi integration (https://github.com/denisidoro/navi)
914
876
  begin
915
877
  @navi = `navi`
@@ -919,7 +881,7 @@ def main_getkey # GET KEY FROM USER
919
881
  @break = true
920
882
  when '@' # Enter "Ruby debug"
921
883
  @w_b.nohistory = false
922
- cmd = w_b_getstr("◆ ", "", true)
884
+ cmd = w_b_getstr("◆ ", "")
923
885
  @w_b.clr
924
886
  @w_b.refresh
925
887
  @w_b.update = true
@@ -927,8 +889,8 @@ def main_getkey # GET KEY FROM USER
927
889
  info = "Command: #{cmd}\n\n"
928
890
  begin
929
891
  info += eval(cmd).to_s
930
- rescue Exception => err
931
- info += "Error: #{err.inspect}"
892
+ rescue StandardError => e
893
+ info += "Error: #{e.inspect}"
932
894
  end
933
895
  w_r_info(info)
934
896
  @w_r.update = false
@@ -943,12 +905,6 @@ def main_getkey # GET KEY FROM USER
943
905
  rescue
944
906
  end
945
907
  end
946
- def stdin_clear
947
- begin
948
- $stdin.getc while $stdin.ready?
949
- rescue
950
- end
951
- end
952
908
  def conf_write
953
909
  if File.exist?(Dir.home+'/.rtfm.conf')
954
910
  conf = File.read(Dir.home+'/.rtfm.conf')
@@ -961,10 +917,6 @@ def conf_write
961
917
  conf += "@hash = #{@hash}\n"
962
918
  conf.sub!(/^@tagged.*\[.*\]\n/, "")
963
919
  conf += "@tagged = #{@tagged}\n"
964
- conf.sub!(/^@history.*\[.*\]\n/, "")
965
- conf += "@history = #{@history}\n"
966
- conf.sub!(/^@rubyhistory.*\[.*\]\n/, "")
967
- conf += "@rubyhistory = #{@rubyhistory}\n"
968
920
  if @write_conf_all
969
921
  conf.sub!(/^@lslong.*\n/, "")
970
922
  conf += "@lslong = #{@lslong}\n"
@@ -1008,8 +960,7 @@ end
1008
960
  def get_files(win) # The core of the directory listings
1009
961
  ls_cmd = "ls 2>/dev/null #{@lsbase} #{@lsall} #{@lsorder} #{@lsinvert} #{@lsuser}" # Get files in current directory
1010
962
  ls_cmd += @selected_safe if win == "right"
1011
- @cfiles = `#{ls_cmd} --color`.split("\n")
1012
- @files = @cfiles.map {|f| f.sub(/^.*\d+m(.+)\e\[0m/, '\1')}
963
+ @files = `#{ls_cmd}`.split("\n")
1013
964
  ls_cmd += " -H " if win == "right"
1014
965
  ls_cmd += %q[ -lh --time-style="long-iso" | awk '{printf "%s%s%s%11s%6s%6s", $1, " " $3, ":" $4,$6,$7,$5"\n"}']
1015
966
  @fspes = `#{ls_cmd}`.split("\n").drop(1)
@@ -1076,8 +1027,7 @@ def list_dir(active) # LIST CONTENT OF A DIRECTORY (BOTH active AND RIGHT WINDOW
1076
1027
  @cont = ""
1077
1028
  end
1078
1029
  while ix < @files.size and t < win.maxy do
1079
- str = @files[ix]
1080
- cstr = @cfiles[ix]
1030
+ str = @files[ix]
1081
1031
  active ? str_path = str : str_path = "#{@selected}/#{str}"
1082
1032
  begin # Add items matching @tag to @tagged
1083
1033
  if str.match(/#{@tag}/) and @tag != false
@@ -1086,9 +1036,25 @@ def list_dir(active) # LIST CONTENT OF A DIRECTORY (BOTH active AND RIGHT WINDOW
1086
1036
  end
1087
1037
  rescue
1088
1038
  end
1039
+ # Determine the filetype of the item
1040
+ ftype = ""
1041
+ ftype = str.match(/\.([^.]*$)/)[1] if str.match?(/\.([^.]*$)/)
1042
+ # Set special filetypes (sequence matters)
1043
+ ftype = "bd" if File.blockdev?(str_path)
1044
+ ftype = "cd" if File.chardev?(str_path)
1045
+ ftype = "pi" if File.pipe?(str_path)
1046
+ ftype = "st" if File.sticky?(str_path)
1047
+ ftype = "so" if File.socket?(str_path)
1048
+ ftype = "ex" if File.executable?(str_path)
1049
+ ftype = "di" if File.directory?(str_path)
1050
+ ftype = "ln" if File.symlink?(str_path)
1051
+ begin
1052
+ File.stat(str_path) # Checking if not an orphaned link
1053
+ rescue
1054
+ ftype = "or" # Set to orphant if no link target
1055
+ end
1089
1056
  fg = 7; bold = 0; bg = 0 # Set default color
1090
- fl = color_parse(cstr)
1091
- fg, bold = fl[0][0].to_i, fl[0][1].to_i unless fl[0] == nil
1057
+ fg, bold = get_ls_color(ftype) unless ftype == "" # Color from LS_COLORS
1092
1058
  init_pair(fg, fg, bg)
1093
1059
  file_marker = color_pair(fg)
1094
1060
  file_marker = file_marker | Curses::A_BOLD if bold == 1
@@ -1110,8 +1076,6 @@ def list_dir(active) # LIST CONTENT OF A DIRECTORY (BOTH active AND RIGHT WINDOW
1110
1076
  ext_name = File.extname(str)
1111
1077
  ext_length = ext_name.length
1112
1078
  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
1115
1079
  str = base_name[0..nbl] + "…" + ext_name
1116
1080
  end
1117
1081
  if !active and ix == win.maxy - 1 # Add indicator of more at bottom @w_r list
@@ -1123,7 +1087,7 @@ def list_dir(active) # LIST CONTENT OF A DIRECTORY (BOTH active AND RIGHT WINDOW
1123
1087
  win.attron(file_marker) { win << str } # Implement color/bold to the item
1124
1088
  win.clrtoeol
1125
1089
  win << "\n"
1126
- ix += 1; t += 1
1090
+ ix += 1; t += 1
1127
1091
  end
1128
1092
  (win.maxy - win.cury).times {win.deleteln()} # Clear to bottom of window
1129
1093
  if active
@@ -1150,14 +1114,12 @@ def open_selected(html = nil) # OPEN SELECTED ITEM (when pressing RIGHT)
1150
1114
  if File.read(@selected).force_encoding("UTF-8").valid_encoding? and not html
1151
1115
  system("exec $EDITOR #{@selected_safe}")
1152
1116
  else
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")
1117
+ if @runmailcap
1118
+ Thread.new { system("run-mailcap #{@selected_safe} 2>/dev/null") }
1119
+ else
1120
+ Thread.new { system("xdg-open #{@selected_safe} 2>/dev/null") }
1121
+ end
1159
1122
  end
1160
- end
1161
1123
  @break = true
1162
1124
  rescue
1163
1125
  end
@@ -1185,7 +1147,7 @@ def copy_move_link(type) # COPY OR MOVE TAGGED ITEMS (COPY IF "keep == true")
1185
1147
  FileUtils.ln_s(item, dest)
1186
1148
  w_b_info(" Item(s) symlinked here.")
1187
1149
  end
1188
- rescue Exception => err
1150
+ rescue StandardError => err
1189
1151
  w_b_info(err.to_s)
1190
1152
  end
1191
1153
  end
@@ -1279,19 +1241,16 @@ def w_r_doc # GET FULL CONTENT TO PAGE
1279
1241
  @w_r << @w_r.text
1280
1242
  end
1281
1243
  def w_r_info(info) # SHOW INFO IN THE RIGHT WINDOW
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
1244
+ image_show("clear") if @image; @image = false
1245
+ @w_r.clr
1246
+ @w_r.refresh
1247
+ w_r_width = Curses.cols - (Curses.cols * @width / 10) - 2
1248
+ info.gsub!(/(.{1,#{w_r_width}})( +|$\n?)|(.{1,#{w_r_width}})/, "\\1\\3\n")
1249
+ @w_r.text = info
1250
+ @w_r.pager_cmd = ""
1251
+ pager_start
1252
+ pager_show
1253
+ @w_r.update = false
1295
1254
  end
1296
1255
  def marks_info # SHOW MARKS IN RIGHT WINDOW
1297
1256
  @w_r.fg = 183
@@ -1415,13 +1374,11 @@ def openai # INTERFACE TO OPENAI
1415
1374
  p += "#{f}? "
1416
1375
  p += "Give a brief summary of its content: " + c unless File.directory?(@selected) and c == ""
1417
1376
 
1418
- begin
1419
- response = client.completions( parameters: { model: @aimodel, prompt: p, max_tokens: 200 })
1377
+ response = client.completions( parameters: { model: "text-davinci-003", prompt: p, max_tokens: 200 })
1378
+ if response["error"]["message"] == ""
1420
1379
  text = "OpenAI description:\n" + response["choices"][0]["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
1380
+ else
1381
+ text = response["error"]["message"]
1425
1382
  end
1426
1383
 
1427
1384
  @w_r.fg = 229
@@ -1450,8 +1407,8 @@ def sysinfo
1450
1407
  cpu = "CPUs = " + `nproc`.chop + " "
1451
1408
  cpuinfo = `lscpu`
1452
1409
  cpu += cpuinfo[/^.*Model name:\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"
1410
+ cpu += "Max: " + cpuinfo[/^.*CPU max MHz:\s*(.*)/, 1][/(.*),.*/, 1] + "MHz "
1411
+ cpu += "Min: " + cpuinfo[/^.*CPU min MHz:\s*(.*)/, 1][/(.*),.*/, 1] + "MHz\n\n"
1455
1412
  text += [[154, 0, cpu]]
1456
1413
  mem = `free -h` + "\n"
1457
1414
  text += [[229, 0, mem]]
@@ -1460,8 +1417,7 @@ def sysinfo
1460
1417
  disk = `df -H | head -8`
1461
1418
  text += [[172, 0, disk]]
1462
1419
  dmesg = "\nDMESG (latest first):\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"
1420
+ dmesg += `dmesg | tail -6`.split("\n").sort.reverse.join("\n")
1465
1421
  text += [[219, 0, dmesg]]
1466
1422
  w_r_info(ansifix(text))
1467
1423
  rescue
@@ -1489,29 +1445,23 @@ def w_b_info(info) # SHOW INFO IN @W_B
1489
1445
  @w_b.write
1490
1446
  @w_b.update = false
1491
1447
  end
1492
- def w_b_getstr(pretext, text, ruby=false) # A SIMPLE READLINE-LIKE ROUTINE
1448
+ def w_b_getstr(pretext, text) # A SIMPLE READLINE-LIKE ROUTINE
1493
1449
  Curses.curs_set(1)
1494
1450
  Curses.echo
1495
1451
  stk = 0
1452
+ @history.insert(stk, text)
1453
+ pos = @history[stk].length
1496
1454
  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
1505
1455
  while chr != "ENTER"
1506
1456
  @w_b.setpos(0,0)
1507
1457
  init_pair(250, 250, 238)
1508
- text = pretext + @history_copy[stk]
1458
+ text = pretext + @history[stk]
1509
1459
  text += " " * (@w_b.maxx - text.length) if text.length < @w_b.maxx
1510
1460
  @w_b.attron(color_pair(250)) { @w_b << text }
1511
1461
  @w_b.setpos(0,pretext.length + pos)
1512
1462
  @w_b.refresh
1513
1463
  chr = getchr
1514
- if chr == 'C-G' or chr == 'C-C'
1464
+ if chr == "C-G"
1515
1465
  Curses.curs_set(0)
1516
1466
  Curses.noecho
1517
1467
  @w_b.update = true
@@ -1520,50 +1470,50 @@ def w_b_getstr(pretext, text, ruby=false) # A SIMPLE READLINE-LIKE ROUTINE
1520
1470
  case chr
1521
1471
  when 'UP'
1522
1472
  unless @w_b.nohistory
1523
- unless stk == @history_copy.length - 1
1473
+ unless stk == @history.length - 1
1524
1474
  stk += 1
1525
- pos = @history_copy[stk].length
1475
+ pos = @history[stk].length
1526
1476
  end
1527
1477
  end
1528
1478
  when 'DOWN'
1529
1479
  unless @w_b.nohistory
1530
1480
  unless stk == 0
1531
1481
  stk -= 1
1532
- pos = @history_copy[stk].length
1482
+ pos = @history[stk].length
1533
1483
  end
1534
1484
  end
1535
1485
  when 'RIGHT'
1536
- pos += 1 unless pos > @history_copy[stk].length
1486
+ pos += 1 unless pos > @history[stk].length
1537
1487
  when 'LEFT'
1538
1488
  pos -= 1 unless pos == 0
1539
1489
  when 'HOME'
1540
1490
  pos = 0
1541
1491
  when 'END'
1542
- pos = @history_copy[stk].length
1492
+ pos = @history[stk].length
1543
1493
  when 'DEL'
1544
- @history_copy[stk][pos] = ""
1494
+ @history[stk][pos] = ""
1545
1495
  when 'BACK'
1546
1496
  unless pos == 0
1547
1497
  pos -= 1
1548
- @history_copy[stk][pos] = ""
1498
+ @history[stk][pos] = ""
1549
1499
  end
1550
1500
  when 'WBACK'
1551
1501
  unless pos == 0
1552
- until @history_copy[stk][pos - 1] == " " or pos == 0
1502
+ until @history[stk][pos - 1] == " " or pos == 0
1553
1503
  pos -= 1
1554
- @history_copy[stk][pos] = ""
1504
+ @history[stk][pos] = ""
1555
1505
  end
1556
- if @history_copy[stk][pos - 1] == " "
1506
+ if @history[stk][pos - 1] == " "
1557
1507
  pos -= 1
1558
- @history_copy[stk][pos] = ""
1508
+ @history[stk][pos] = ""
1559
1509
  end
1560
1510
  end
1561
1511
  when 'LDEL'
1562
- @history_copy[stk] = ""
1512
+ @history[stk] = ""
1563
1513
  pos = 0
1564
1514
  when 'TAB' # Tab completion of dirs and files
1565
1515
  p1 = pos - 1
1566
- c = @history_copy[stk][0..(p1)].sub(/^.* /, '')
1516
+ c = @history[stk][0..(p1)].sub(/^.* /, '')
1567
1517
  p0 = p1 - c.length
1568
1518
  compl = File.expand_path(c)
1569
1519
  compl += "/" if Dir.exist?(compl)
@@ -1598,28 +1548,19 @@ def w_b_getstr(pretext, text, ruby=false) # A SIMPLE READLINE-LIKE ROUTINE
1598
1548
  Curses.echo
1599
1549
  end
1600
1550
  end
1601
- @history_copy[stk].sub!(c,compl)
1551
+ @history[stk].sub!(c,compl)
1602
1552
  pos = pos - c.length + compl.length
1603
1553
  when /^.$/
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)
1554
+ @history[stk].insert(pos,chr)
1610
1555
  pos += 1
1611
1556
  end
1612
1557
  end
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])
1558
+ curstr = @history[stk]
1559
+ @history.shift if @w_b.nohistory
1616
1560
  unless @w_b.nohistory
1617
1561
  @history.uniq!
1618
1562
  @history.compact!
1619
1563
  @history.delete("")
1620
- @rubyhistory.uniq!
1621
- @rubyhistory.compact!
1622
- @rubyhistory.delete("")
1623
1564
  end
1624
1565
  Curses.curs_set(0)
1625
1566
  Curses.noecho
@@ -1642,11 +1583,11 @@ def w_b_exec(cmd) # EXECUTE COMMAND FROM @W_B
1642
1583
  status = Timeout::timeout(15) {
1643
1584
  @w_r.clr
1644
1585
  begin
1645
- @w_r.pager_cmd = "#{cmd} 2>&1 | #{@bat} -n --color=always"
1646
- @w_r.text = %x(#{@w_r.pager_cmd})
1586
+ @w_r.pager_cmd = "#{cmd} | #{@bat} -n --color=always 2>/dev/null"
1587
+ @w_r.text = `#{@w_r.pager_cmd}`
1647
1588
  rescue
1648
- @w_r.pager_cmd = "#{cmd} 2>&1"
1649
- @w_r.text = %x(#{@w_r.pager_cmd})
1589
+ @w_r.pager_cmd = "#{cmd} 2>/dev/null"
1590
+ @w_r.text = `#{@w_r.pager_cmd}`
1650
1591
  end
1651
1592
  unless @w_r.text == "" or @w_r.text == nil
1652
1593
  pager_start
@@ -1678,8 +1619,8 @@ loop do # OUTER LOOP - CATCHING REFRESHES VIA 'r'
1678
1619
  maxx = Curses.cols
1679
1620
  maxy = Curses.lines
1680
1621
  # Curses::Window.new(h,w,y,x)
1681
- @w_t = Curses::Window.new(1, maxx, 0, 0)
1682
- @w_b = Curses::Window.new(1, maxx, maxy - 1, 0)
1622
+ @w_t = Curses::Window.new(1, 0, 0, 0)
1623
+ @w_b = Curses::Window.new(1, 0, maxy - 1, 0)
1683
1624
  @w_l = Curses::Window.new(maxy - 3, (maxx * @width / 10) - 1, 2, 0)
1684
1625
  @w_r = Curses::Window.new(maxy - 4, maxx - (maxx * @width / 10), 2, maxx * @width / 10)
1685
1626
  @w_p = Curses::Window.new(1, maxx - (maxx * @width / 10), maxy - 2, maxx * @width / 10)
@@ -1698,6 +1639,8 @@ loop do # OUTER LOOP - CATCHING REFRESHES VIA 'r'
1698
1639
  tagged_info
1699
1640
  @w_r.update = false
1700
1641
  end
1642
+ @change = true
1643
+ @change_tag = true # For future need to force @change
1701
1644
  loop do # INNER, CORE LOOP
1702
1645
  begin # Jump to home dir if current dir is externally removed
1703
1646
  Dir.pwd
@@ -1729,8 +1672,13 @@ loop do # OUTER LOOP - CATCHING REFRESHES VIA 'r'
1729
1672
  @selected = @files[@index] # Get text of selected item
1730
1673
  sel_old = @selected_safe
1731
1674
  @selected_safe = "\"#{@selected}\"" # Make it safe for commands
1732
- system("printf \"\033]0;RTFM: #{Dir.pwd}\007\"") # Set Window title to path
1733
- w_t_info # Top window (info line)
1675
+ @selected_safe == sel_old ? @change = false : @change = true
1676
+ @change = true if @change_tag; @change_tag = false
1677
+ if @change
1678
+ system("printf \"\033]0;RTFM: #{Dir.pwd}\007\"") # Set Window title to path
1679
+ # Top window (info line)
1680
+ w_t_info
1681
+ end
1734
1682
  @w_l.setpos(0,0)
1735
1683
  list_dir(true)
1736
1684
  @w_l.refresh
@@ -1753,9 +1701,6 @@ loop do # OUTER LOOP - CATCHING REFRESHES VIA 'r'
1753
1701
  break if Curses.cols != maxx or Curses.lines != maxy # break on terminal resize
1754
1702
  break if @break # Break to outer loop, redrawing windows, if user hit 'r'
1755
1703
  end
1756
- rescue StandardError => err # Throw error nicely
1757
- w_r_info(err)
1758
- @w_r.update = false
1759
1704
  ensure # On exit: close curses, clear terminal
1760
1705
  @write_conf_all = false
1761
1706
  conf_write if @write_conf # Write marks to config file
@@ -1763,7 +1708,7 @@ loop do # OUTER LOOP - CATCHING REFRESHES VIA 'r'
1763
1708
  close_screen
1764
1709
  # If launched via the script "r", return current dir and "r" will cd to that
1765
1710
  begin
1766
- File.write(ARGV[0], Dir.pwd) if ARGV[0] and ARGV[0].match(/\/tmp/)
1711
+ File.write(ARGV[0], Dir.pwd) if ARGV[0] and ARGV[0].match(/\/tmp\/tmp/)
1767
1712
  rescue
1768
1713
  end
1769
1714
  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.3'
4
+ version: '3.5'
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: 2024-10-27 00:00:00.000000000 Z
11
+ date: 2023-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -47,8 +47,7 @@ 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.3: Updated default OpenAI model and adding the option to
51
- add own by setting @aimodel in .rtfm.conf.'
50
+ other features. New in 3.5: Simplified install :-)'
52
51
  email: g@isene.com
53
52
  executables:
54
53
  - rtfm
@@ -63,7 +62,7 @@ licenses:
63
62
  - Unlicense
64
63
  metadata:
65
64
  source_code_uri: https://github.com/isene/RTFM
66
- post_install_message:
65
+ post_install_message:
67
66
  rdoc_options: []
68
67
  require_paths:
69
68
  - lib
@@ -78,8 +77,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
77
  - !ruby/object:Gem::Version
79
78
  version: '0'
80
79
  requirements: []
81
- rubygems_version: 3.4.20
82
- signing_key:
80
+ rubygems_version: 3.3.5
81
+ signing_key:
83
82
  specification_version: 4
84
83
  summary: RTFM - Ruby Terminal File Manager
85
84
  test_files: []