rtfm-filemanager 5.6 → 5.7
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 +156 -57
- 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: 0a98e564810c828a6973aa5a7b968b560ee32af1ff3a2c916a9ae31f15a30489
|
4
|
+
data.tar.gz: dafe630653b09a6effb439fc0d79fce6636473b5eaa4a6104858f7311a5b01a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c3ba0bbf931a118c75ce53c2388b139b8684d25c63c83df565659697daf218f59533a5506883ae24c2a79feb614973546377d57c2ab7531bb8ec63c44b49cc8
|
7
|
+
data.tar.gz: 6c65eca97ca5898cbd9774564e1175ba859d29af622553a0cd93070e6d1bc3355e0d0bc08ef66d606da00b48cb5b6fd7d789909b0f95bd7e5f4966db642ccad2
|
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' # Added use of @interactive on automatic opening of selected files
|
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
|
@@ -1329,7 +1329,7 @@ end
|
|
1329
1329
|
# CLIPBOARD COPY {{{2
|
1330
1330
|
def copy_path # {{{3
|
1331
1331
|
if @selected
|
1332
|
-
clip = "xclip -selection #{
|
1332
|
+
clip = "xclip -selection #{getchr == 'Y' ? 'clipboard' : 'primary'} -in -loops 1"
|
1333
1333
|
@pB.say(' Path copied')
|
1334
1334
|
shell("echo -n '#{@selected}' | #{clip}")
|
1335
1335
|
else
|
@@ -1869,6 +1869,159 @@ 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
|
+
|
1876
|
+
if @runmailcap
|
1877
|
+
# Check what run-mailcap would actually execute
|
1878
|
+
# Use --norun to see the command without executing it
|
1879
|
+
mailcap_output = `run-mailcap --norun #{Shellwords.escape(file_path)} 2>/dev/null`.chomp
|
1880
|
+
|
1881
|
+
# Debug: log what we found
|
1882
|
+
@pB.say("Debug: mailcap would run: '#{mailcap_output}'") unless mailcap_output.empty?
|
1883
|
+
|
1884
|
+
if !mailcap_output.empty?
|
1885
|
+
# Extract the program name from the command
|
1886
|
+
# Handle cases like "/usr/bin/mplayer file.mp4" or "mplayer %s"
|
1887
|
+
cmd_parts = mailcap_output.split
|
1888
|
+
prog = cmd_parts.first
|
1889
|
+
prog = File.basename(prog) if prog
|
1890
|
+
|
1891
|
+
# Debug: log program detection
|
1892
|
+
@pB.say("Debug: detected program = '#{prog}', in interactive list? #{inter_list.include?(prog)}")
|
1893
|
+
|
1894
|
+
return prog if prog && inter_list.include?(prog)
|
1895
|
+
end
|
1896
|
+
else
|
1897
|
+
# Check what xdg-open would use
|
1898
|
+
mimetype = `file --mime-type -b #{Shellwords.escape(file_path)}`.chomp
|
1899
|
+
desktop_file = `xdg-mime query default #{Shellwords.escape(mimetype)}`.chomp
|
1900
|
+
|
1901
|
+
if desktop_file && !desktop_file.empty?
|
1902
|
+
# Read the desktop file to get the actual command
|
1903
|
+
desktop_path = nil
|
1904
|
+
['/usr/share/applications/', '/usr/local/share/applications/',
|
1905
|
+
File.join(Dir.home, '.local/share/applications/')].each do |dir|
|
1906
|
+
path = File.join(dir, desktop_file)
|
1907
|
+
if File.exist?(path)
|
1908
|
+
desktop_path = path
|
1909
|
+
break
|
1910
|
+
end
|
1911
|
+
end
|
1912
|
+
|
1913
|
+
if desktop_path
|
1914
|
+
content = File.read(desktop_path)
|
1915
|
+
exec_line = content[/^Exec=(.*)$/m, 1]
|
1916
|
+
if exec_line
|
1917
|
+
# Extract the program name (first word, remove path)
|
1918
|
+
prog = exec_line.split.first
|
1919
|
+
prog = File.basename(prog) if prog
|
1920
|
+
return prog if prog && inter_list.include?(prog)
|
1921
|
+
end
|
1922
|
+
end
|
1923
|
+
end
|
1924
|
+
end
|
1925
|
+
rescue
|
1926
|
+
# If detection fails, fall back to normal behavior
|
1927
|
+
end
|
1928
|
+
nil
|
1929
|
+
end
|
1930
|
+
|
1931
|
+
def open_selected(html = nil) # OPEN SELECTED FILE {{{2
|
1932
|
+
require 'tmpdir' unless Dir.respond_to?(:tmpdir)
|
1933
|
+
|
1934
|
+
if File.directory?(@selected) # Dir? just cd into it
|
1935
|
+
mark_latest
|
1936
|
+
Dir.chdir(@selected) rescue nil
|
1937
|
+
return
|
1938
|
+
end
|
1939
|
+
|
1940
|
+
# Check if this file should use an interactive program (same as § prefix logic)
|
1941
|
+
if !html && (prog = get_interactive_program(@selected))
|
1942
|
+
cmd = "#{prog} #{Shellwords.escape(@selected)}"
|
1943
|
+
|
1944
|
+
# Use exactly the same logic as command_mode with § prefix (force interactive)
|
1945
|
+
# Restore shell tty so Ctrl-C/D work
|
1946
|
+
system("stty #{ORIG_STTY} < /dev/tty")
|
1947
|
+
# Clear to top-left
|
1948
|
+
system('clear < /dev/tty > /dev/tty')
|
1949
|
+
Cursor.show
|
1950
|
+
|
1951
|
+
# Spawn on real tty
|
1952
|
+
pid = Process.spawn(cmd,
|
1953
|
+
in: '/dev/tty',
|
1954
|
+
out: '/dev/tty',
|
1955
|
+
err: '/dev/tty')
|
1956
|
+
begin
|
1957
|
+
Process.wait(pid)
|
1958
|
+
rescue Interrupt
|
1959
|
+
Process.kill('TERM', pid) rescue nil
|
1960
|
+
retry
|
1961
|
+
end
|
1962
|
+
|
1963
|
+
# Restore raw/no-echo for RTFM
|
1964
|
+
system('stty raw -echo isig < /dev/tty')
|
1965
|
+
$stdin.raw!
|
1966
|
+
$stdin.echo = false
|
1967
|
+
Cursor.hide
|
1968
|
+
Rcurses.clear_screen
|
1969
|
+
refresh
|
1970
|
+
render
|
1971
|
+
return
|
1972
|
+
end
|
1973
|
+
|
1974
|
+
tmpfile = File.join(Dir.tmpdir, 'rtfm_err.log')
|
1975
|
+
paths = (@tagged + [@selected]).uniq
|
1976
|
+
|
1977
|
+
if html # html mode - open in HTML-browser
|
1978
|
+
esc = paths.map { |p| Shellwords.escape(p) }.join(' ')
|
1979
|
+
shell("xdg-open #{esc} &", err: tmpfile)
|
1980
|
+
Rcurses.clear_screen; refresh; render
|
1981
|
+
if File.exist?(tmpfile)
|
1982
|
+
sleep 0.5
|
1983
|
+
err = File.read(tmpfile)
|
1984
|
+
showimage('clear') if @image
|
1985
|
+
@pR.say(err.fg(196))
|
1986
|
+
File.delete(tmpfile)
|
1987
|
+
end
|
1988
|
+
return
|
1989
|
+
end
|
1990
|
+
|
1991
|
+
if File.read(@selected).force_encoding('UTF-8').valid_encoding? # Pure text
|
1992
|
+
system("stty #{ORIG_STTY} < /dev/tty")
|
1993
|
+
# Clear to top-left
|
1994
|
+
system('clear < /dev/tty > /dev/tty')
|
1995
|
+
Cursor.show
|
1996
|
+
editor = ENV.fetch('EDITOR', 'vi') # Launch $EDITOR on the real TTY
|
1997
|
+
system("#{editor} #{Shellwords.escape(@selected)}")
|
1998
|
+
$stdin.raw!
|
1999
|
+
$stdin.echo = false
|
2000
|
+
Cursor.hide
|
2001
|
+
Rcurses.clear_screen # Redraw RTFM
|
2002
|
+
refresh
|
2003
|
+
render
|
2004
|
+
return
|
2005
|
+
end
|
2006
|
+
|
2007
|
+
if @runmailcap # Open with run-mailcap or xdg-open
|
2008
|
+
arg = paths.map { |p| Shellwords.escape(p) }.join(' ')
|
2009
|
+
shell("run-mailcap #{arg} &", err: tmpfile)
|
2010
|
+
else
|
2011
|
+
shell("xdg-open #{Shellwords.escape(@selected)} &", err: tmpfile)
|
2012
|
+
end
|
2013
|
+
|
2014
|
+
# Clean up
|
2015
|
+
Rcurses.clear_screen; refresh; render
|
2016
|
+
if File.exist?(tmpfile)
|
2017
|
+
sleep 0.5
|
2018
|
+
err = File.read(tmpfile)
|
2019
|
+
showimage('clear') if @image
|
2020
|
+
@pR.say(err.fg(196))
|
2021
|
+
File.delete(tmpfile)
|
2022
|
+
end
|
2023
|
+
end
|
2024
|
+
|
1872
2025
|
def conf_write(all: false) # WRITE TO ~/.rtfm/conf {{{2
|
1873
2026
|
@conf = @conf.dup # work on a mutable copy
|
1874
2027
|
assignments = {
|
@@ -2052,60 +2205,6 @@ def tagged_info # SHOW THE LIST OF TAGGED ITEMS IN @pR {{{2
|
|
2052
2205
|
@pR.say(info.fg(204))
|
2053
2206
|
end
|
2054
2207
|
|
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
2208
|
# MAIN PROGRAM {{{1
|
2110
2209
|
## Get terminal size {{{2
|
2111
2210
|
@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'
|
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: Added use of @interactive on automatic opening of selected files.
|
58
58
|
email: g@isene.com
|
59
59
|
executables:
|
60
60
|
- rtfm
|