rtfm-filemanager 5.6.1 → 5.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/bin/rtfm +135 -56
  4. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 640b4b9aa3f52d8e006c1c11fff61446941383e284119f69d6766ec26581823d
4
- data.tar.gz: 225fc4b42a2b666e1e5a99788df045b943a5ec1e448509995b4ca8b6ea3061e0
3
+ metadata.gz: 1a161027d9022267d289243bfcaeca20a4f53c62f337950f1a8f0fde673e8052
4
+ data.tar.gz: 59fa34172a017c4b076623249eee783f648767431438be6e49ae947a4e08d1ca
5
5
  SHA512:
6
- metadata.gz: 176d2943cc0433a204017f43c41337ca78079d69e78f2131b6a932c0b47b61eedfa78cfc14a4f8d3f85f7eece1a5e4042ed0408a631bf27c395df7d107132ec4
7
- data.tar.gz: bdb702b5979b4737d1e05108b02cb0f80da1cfa098059dfc1456ca7738f241577b3ee1d3e69132194e04b2da6c70441b899a6614add4e4131a1e0ab4db5784f5
6
+ metadata.gz: cc373399f44b2686f22738a1e3241139391c42108f0a02e94ca157d8e38c5b21e73a0ceeff68f3dc26ce3c9f9e99ca6e2b7ec0e387c1ef9cc341e43988e56d87
7
+ data.tar.gz: 633482c052ea761d444c4bd5b9b6cbf72c5671709ce2f50769dd36ba76eb40d35cc2034c531cd9e99a7821bdfe7419c87239f4a006d855bd4374b7d072da9221
data/README.md CHANGED
@@ -368,7 +368,9 @@ add a program to the whitelist inside RTFM, press the `+` key. All ususal
368
368
  shell comands that do not take over the full terminal such as `ls`, `touch`,
369
369
  `neofetch`, etc. will run just fine in command mode without being whitelisted.
370
370
  You can also explicitly run a program as interactive by prefixing the command
371
- with a single `§` - e.g. `:` `§saidar`.***
371
+ with a single `§` - e.g. `:` `§saidar`. Programs added to @interactive will
372
+ open as interactive also when opened via xdg-open or runmailcap (when you
373
+ press `RIGHT` on a selected item).***
372
374
 
373
375
  All the variables above that you manually add to the top of the config files are
374
376
  undisturbed by launching and exiting RTFM.
data/bin/rtfm CHANGED
@@ -18,7 +18,7 @@
18
18
  # get a great understanding of the code itself by simply sending
19
19
  # or pasting this whole file into you favorite AI for coding with
20
20
  # a prompt like this: "Help me understand every part of this code".
21
- @version = '5.6.1' # Fixed a small copy path bug
21
+ @version = '5.7.1' # Removed debug output
22
22
 
23
23
  # SAVE & STORE TERMINAL {{{1
24
24
  ORIG_STTY = `stty -g`.chomp
@@ -431,7 +431,7 @@ $stdin.set_encoding(Encoding::UTF_8)
431
431
  @border = 1 # Set initial border config; 0 = none, 1 = Right pane, 2 = both panes, 3 = Left pane
432
432
  @preview = true # Preview in the Right pane
433
433
  @trash = false # Delete files permanently rather than moving them to ~/.rtfm/trash
434
- @interactive = 'fzf,navi,top,htop,less,vi,vim,nvim,ncdu,sh,zsh,bash,fish,git'
434
+ @interactive = 'fzf,navi,top,htop,less,vi,vim,nvim,ncdu,sh,zsh,bash,fish,git,mplayer'
435
435
  ### Not saved (but can be set in ~/.rtfm/conf)
436
436
  @topcolor = 249 # Default Top pane bg color
437
437
  @topmatch = [['', 249]] # Default Top pane bg color for matching directories
@@ -1869,6 +1869,139 @@ def mark_latest # UPDATE MARKS LIST {{{2
1869
1869
  @marks["'"] = Dir.pwd
1870
1870
  end
1871
1871
 
1872
+ def get_interactive_program(file_path) # HELPER FOR OPEN_SELECTED TO USE @interactive {{{2
1873
+ begin
1874
+ inter_list = (@interactive || '').split(',').map(&:strip)
1875
+ if @runmailcap
1876
+ # Check what run-mailcap would execute. Use --norun to see the command without executing it
1877
+ mailcap_output = `run-mailcap --norun #{Shellwords.escape(file_path)} 2>/dev/null`.chomp
1878
+ if !mailcap_output.empty?
1879
+ # Extract the program name from the command
1880
+ # Handle cases like "/usr/bin/mplayer file.mp4" or "mplayer %s"
1881
+ cmd_parts = mailcap_output.split
1882
+ prog = cmd_parts.first
1883
+ prog = File.basename(prog) if prog
1884
+ return prog if prog && inter_list.include?(prog)
1885
+ end
1886
+ else
1887
+ # Check what xdg-open would use
1888
+ mimetype = `file --mime-type -b #{Shellwords.escape(file_path)}`.chomp
1889
+ desktop_file = `xdg-mime query default #{Shellwords.escape(mimetype)}`.chomp
1890
+
1891
+ if desktop_file && !desktop_file.empty?
1892
+ # Read the desktop file to get the actual command
1893
+ desktop_path = nil
1894
+ ['/usr/share/applications/', '/usr/local/share/applications/',
1895
+ File.join(Dir.home, '.local/share/applications/')].each do |dir|
1896
+ path = File.join(dir, desktop_file)
1897
+ if File.exist?(path)
1898
+ desktop_path = path
1899
+ break
1900
+ end
1901
+ end
1902
+ if desktop_path
1903
+ content = File.read(desktop_path)
1904
+ exec_line = content[/^Exec=(.*)$/m, 1]
1905
+ if exec_line
1906
+ # Extract the program name (first word, remove path)
1907
+ prog = exec_line.split.first
1908
+ prog = File.basename(prog) if prog
1909
+ return prog if prog && inter_list.include?(prog)
1910
+ end
1911
+ end
1912
+ end
1913
+ end
1914
+ rescue
1915
+ # If detection fails, fall back to normal behavior
1916
+ end
1917
+ nil
1918
+ end
1919
+
1920
+ def open_selected(html = nil) # OPEN SELECTED FILE {{{2
1921
+ require 'tmpdir' unless Dir.respond_to?(:tmpdir)
1922
+ if File.directory?(@selected) # Dir? just cd into it
1923
+ mark_latest
1924
+ Dir.chdir(@selected) rescue nil
1925
+ return
1926
+ end
1927
+
1928
+ # Check if this file should use an interactive program (same as § prefix logic)
1929
+ if !html && (prog = get_interactive_program(@selected))
1930
+ cmd = "#{prog} #{Shellwords.escape(@selected)}"
1931
+ # Use exactly the same logic as command_mode with § prefix (force interactive)
1932
+ # Restore shell tty so Ctrl-C/D work
1933
+ system("stty #{ORIG_STTY} < /dev/tty")
1934
+ # Clear to top-left
1935
+ system('clear < /dev/tty > /dev/tty')
1936
+ Cursor.show
1937
+ # Spawn on real tty
1938
+ pid = Process.spawn(cmd,
1939
+ in: '/dev/tty',
1940
+ out: '/dev/tty',
1941
+ err: '/dev/tty')
1942
+ begin
1943
+ Process.wait(pid)
1944
+ rescue Interrupt
1945
+ Process.kill('TERM', pid) rescue nil
1946
+ retry
1947
+ end
1948
+ # Restore raw/no-echo for RTFM
1949
+ system('stty raw -echo isig < /dev/tty')
1950
+ $stdin.raw!
1951
+ $stdin.echo = false
1952
+ Cursor.hide
1953
+ Rcurses.clear_screen
1954
+ refresh
1955
+ render
1956
+ return
1957
+ end
1958
+ tmpfile = File.join(Dir.tmpdir, 'rtfm_err.log')
1959
+ paths = (@tagged + [@selected]).uniq
1960
+ if html # html mode - open in HTML-browser
1961
+ esc = paths.map { |p| Shellwords.escape(p) }.join(' ')
1962
+ shell("xdg-open #{esc} &", err: tmpfile)
1963
+ Rcurses.clear_screen; refresh; render
1964
+ if File.exist?(tmpfile)
1965
+ sleep 0.5
1966
+ err = File.read(tmpfile)
1967
+ showimage('clear') if @image
1968
+ @pR.say(err.fg(196))
1969
+ File.delete(tmpfile)
1970
+ end
1971
+ return
1972
+ end
1973
+ if File.read(@selected).force_encoding('UTF-8').valid_encoding? # Pure text
1974
+ system("stty #{ORIG_STTY} < /dev/tty")
1975
+ # Clear to top-left
1976
+ system('clear < /dev/tty > /dev/tty')
1977
+ Cursor.show
1978
+ editor = ENV.fetch('EDITOR', 'vi') # Launch $EDITOR on the real TTY
1979
+ system("#{editor} #{Shellwords.escape(@selected)}")
1980
+ $stdin.raw!
1981
+ $stdin.echo = false
1982
+ Cursor.hide
1983
+ Rcurses.clear_screen # Redraw RTFM
1984
+ refresh
1985
+ render
1986
+ return
1987
+ end
1988
+ if @runmailcap # Open with run-mailcap or xdg-open
1989
+ arg = paths.map { |p| Shellwords.escape(p) }.join(' ')
1990
+ shell("run-mailcap #{arg} &", err: tmpfile)
1991
+ else
1992
+ shell("xdg-open #{Shellwords.escape(@selected)} &", err: tmpfile)
1993
+ end
1994
+ # Clean up
1995
+ Rcurses.clear_screen; refresh; render
1996
+ if File.exist?(tmpfile)
1997
+ sleep 0.5
1998
+ err = File.read(tmpfile)
1999
+ showimage('clear') if @image
2000
+ @pR.say(err.fg(196))
2001
+ File.delete(tmpfile)
2002
+ end
2003
+ end
2004
+
1872
2005
  def conf_write(all: false) # WRITE TO ~/.rtfm/conf {{{2
1873
2006
  @conf = @conf.dup # work on a mutable copy
1874
2007
  assignments = {
@@ -2052,60 +2185,6 @@ def tagged_info # SHOW THE LIST OF TAGGED ITEMS IN @pR {{{2
2052
2185
  @pR.say(info.fg(204))
2053
2186
  end
2054
2187
 
2055
- def open_selected(html = nil) # OPEN SELECTED ITEM (when pressing RIGHT or via open_force) {{{2
2056
- require 'tmpdir' unless Dir.respond_to?(:tmpdir)
2057
- if File.directory?(@selected) # Dir? just cd into it
2058
- mark_latest
2059
- Dir.chdir(@selected) rescue nil
2060
- return
2061
- end
2062
- tmpfile = File.join(Dir.tmpdir, 'rtfm_err.log')
2063
- paths = (@tagged + [@selected]).uniq
2064
- if html # html mode - open in HTML-browser
2065
- esc = paths.map { |p| Shellwords.escape(p) }.join(' ')
2066
- shell("xdg-open #{esc} &", err: tmpfile)
2067
- Rcurses.clear_screen; refresh; render
2068
- if File.exist?(tmpfile)
2069
- sleep 0.5
2070
- err = File.read(tmpfile)
2071
- showimage('clear') if @image
2072
- @pR.say(err.fg(196))
2073
- File.delete(tmpfile)
2074
- end
2075
- return
2076
- end
2077
- if File.read(@selected).force_encoding('UTF-8').valid_encoding? # Pure text
2078
- system("stty #{ORIG_STTY} < /dev/tty")
2079
- # Clear to top-left
2080
- system('clear < /dev/tty > /dev/tty')
2081
- Cursor.show
2082
- editor = ENV.fetch('EDITOR', 'vi') # Launch $EDITOR on the real TTY
2083
- system("#{editor} #{Shellwords.escape(@selected)}")
2084
- $stdin.raw!
2085
- $stdin.echo = false
2086
- Cursor.hide
2087
- Rcurses.clear_screen # Redraw RTFM
2088
- refresh
2089
- render
2090
- return
2091
- end
2092
- if @runmailcap # Open with run-mailcap or xdg-open
2093
- arg = paths.map { |p| Shellwords.escape(p) }.join(' ')
2094
- shell("run-mailcap #{arg} &", err: tmpfile)
2095
- else
2096
- shell("xdg-open #{Shellwords.escape(@selected)} &", err: tmpfile)
2097
- end
2098
- # Clean up
2099
- Rcurses.clear_screen; refresh; render
2100
- if File.exist?(tmpfile)
2101
- sleep 0.5
2102
- err = File.read(tmpfile)
2103
- showimage('clear') if @image
2104
- @pR.say(err.fg(196))
2105
- File.delete(tmpfile)
2106
- end
2107
- end
2108
-
2109
2188
  # MAIN PROGRAM {{{1
2110
2189
  ## Get terminal size {{{2
2111
2190
  @h, @w = IO.console.winsize
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: 5.6.1
4
+ version: 5.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-22 00:00:00.000000000 Z
11
+ date: 2025-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rcurses
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '7.4'
55
55
  description: |-
56
56
  Major release - RTFM v5: Complete rewrite using rcurses (https://github.com/isene/rcurses). Massive improvements. AI integration.
57
- A full featured terminal browser with syntax highlighted files, images shown in the terminal, videos thumbnailed, etc. You can bookmark and jump around easily, delete, rename, copy, symlink and move files. RTFM is one of the most feature-packed terminal file managers. 5.6.1: Fixed a small copy path bug.
57
+ A full featured terminal browser with syntax highlighted files, images shown in the terminal, videos thumbnailed, etc. You can bookmark and jump around easily, delete, rename, copy, symlink and move files. RTFM is one of the most feature-packed terminal file managers. 5.7.1: Removed debug output.
58
58
  email: g@isene.com
59
59
  executables:
60
60
  - rtfm