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.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/bin/rtfm +135 -56
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a161027d9022267d289243bfcaeca20a4f53c62f337950f1a8f0fde673e8052
|
4
|
+
data.tar.gz: 59fa34172a017c4b076623249eee783f648767431438be6e49ae947a4e08d1ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
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-
|
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.
|
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
|