rtfm-filemanager 8.6.0 → 8.7.2
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/CHANGELOG.md +16 -0
- data/bin/rtfm +111 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1a3688f47ab7f42eaf8488abfd1035d3ffa36fba99368ab2dc1846dda3119415
|
|
4
|
+
data.tar.gz: 2bf042038eee3c18c764c136d87848f15ff623389ff08625c1f5a6dd2564abba
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 89fec0164f4abec21cdcca454f77db2293dd4bed441f9edb26cb80148a7ffa0278b1af35c2e2d08eee19786ce1ff4fcc42afa128b6cd4349d71cf99695cca2d8
|
|
7
|
+
data.tar.gz: 827d9f52fb1cd639740b7f0d515ac076153f9bdde3ba4742f8d5bf71b1d9cc56df25029c25bd4e342a011707ee31ceb2c38edcfadebd75552bfbcede929edbd8
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,22 @@ All notable changes to RTFM will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [8.7.2] - 2026-05-19
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **`$` script-evaluator clears right pane first** - Short output (or `(no output)`) used to leave residual lines from the prior directory preview underneath. Now calls `@pR.clear` before painting the new content
|
|
12
|
+
|
|
13
|
+
## [8.7.1] - 2026-05-19
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- **`$` script-evaluator output now sticks** - The right pane was getting overwritten by the directory preview after the script returned. Mirrors `command_mode`'s pattern: explicit `@pR.full_refresh` + `@pR.update = false` so the script's output remains visible until the user navigates
|
|
17
|
+
- **Directive trace footer** - Stderr directives (`cd:`, `select:`, `status:`) now produce a small `── directives applied ──` footer at the bottom of the output so it's clear *something* happened even when stdout is empty. Previously a pure-directive script just showed `(no output)`
|
|
18
|
+
|
|
19
|
+
## [8.7.0] - 2026-05-19
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- **Script evaluator (`$` key)** - Run any shell command (any language) with RTFM context exposed as environment variables. Output shows in the right pane. Variables: `RTFM_SELECTED` (full path), `RTFM_DIR` (cwd), `RTFM_TAGGED` (newline-separated tagged paths), `RTFM_INDEX` (0-based selection), `RTFM_COUNT` (file count), `RTFM_CONTEXT` (JSON object with all of the above). Scripts can control RTFM by emitting stderr directives one per line: `cd:/path` changes directory, `select:NAME` moves cursor onto NAME, `status:MSG` shows MSG in the bottom pane. The Ruby debug mode (`@`) is unchanged. Makes RTFM scriptable from Python, Bash, Perl, jq, anything — without writing Ruby plugins
|
|
23
|
+
|
|
8
24
|
## [8.6.0] - 2026-05-19
|
|
9
25
|
|
|
10
26
|
### Added
|
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 = '8.
|
|
21
|
+
@version = '8.7.2' # $ script-eval clears right pane before writing output
|
|
22
22
|
|
|
23
23
|
# SAVE & STORE TERMINAL {{{1
|
|
24
24
|
ORIG_STTY = `stty -g`.chomp
|
|
@@ -353,6 +353,20 @@ CONFIG_FILE = File.join(RTFM_HOME, 'conf')
|
|
|
353
353
|
RUBY DEBUG MODE
|
|
354
354
|
@ = Enter Ruby mode to execute any Ruby command (ENTER to execute, ESC to escape)
|
|
355
355
|
|
|
356
|
+
SCRIPT EVALUATOR
|
|
357
|
+
$ = Run any shell command (any language) with RTFM context as env vars.
|
|
358
|
+
Output is shown in the right pane.
|
|
359
|
+
RTFM_SELECTED Full path of selected item
|
|
360
|
+
RTFM_DIR Current working directory
|
|
361
|
+
RTFM_TAGGED Newline-separated tagged paths
|
|
362
|
+
RTFM_INDEX Selected index (0-based)
|
|
363
|
+
RTFM_COUNT Number of files in listing
|
|
364
|
+
RTFM_CONTEXT JSON object with all of the above
|
|
365
|
+
Scripts can control RTFM via stderr directives, one per line:
|
|
366
|
+
cd:/path Change to /path
|
|
367
|
+
select:NAME Place cursor on NAME in current directory
|
|
368
|
+
status:MSG Show MSG in the bottom pane
|
|
369
|
+
|
|
356
370
|
COPYRIGHT: Geir Isene, 2025+. No rights reserved. See http://isene.com for more.
|
|
357
371
|
HELPTEXT
|
|
358
372
|
|
|
@@ -1178,7 +1192,10 @@ KEYMAP = { # {{{2
|
|
|
1178
1192
|
'e' => :show_file_properties,
|
|
1179
1193
|
|
|
1180
1194
|
# RUBY MODE {{{3
|
|
1181
|
-
'@' => :ruby_debug
|
|
1195
|
+
'@' => :ruby_debug,
|
|
1196
|
+
|
|
1197
|
+
# SCRIPT EVALUATOR {{{3
|
|
1198
|
+
'$' => :script_eval
|
|
1182
1199
|
}
|
|
1183
1200
|
|
|
1184
1201
|
# USER KEYS (override or extend KEYMAP) {{{2
|
|
@@ -5574,6 +5591,98 @@ def ruby_debug # {{{3
|
|
|
5574
5591
|
@pB.full_refresh
|
|
5575
5592
|
end
|
|
5576
5593
|
|
|
5594
|
+
# SCRIPT EVALUATOR {{{2
|
|
5595
|
+
# Run a shell command (any language) with RTFM context exposed as env vars.
|
|
5596
|
+
# stdout shows in the right pane. stderr is scanned for control directives:
|
|
5597
|
+
# cd:/path change current directory
|
|
5598
|
+
# select:NAME move cursor onto NAME in the (new) cwd
|
|
5599
|
+
# status:MSG show MSG in the bottom pane
|
|
5600
|
+
# Any other stderr line is appended to the right-pane output in red.
|
|
5601
|
+
def script_eval # {{{3
|
|
5602
|
+
cmd = @pCmd.ask('$ ', '').to_s.strip
|
|
5603
|
+
if cmd.empty?
|
|
5604
|
+
@pB.clear; @pB.update = true
|
|
5605
|
+
return
|
|
5606
|
+
end
|
|
5607
|
+
|
|
5608
|
+
require 'json'
|
|
5609
|
+
selected = @selected.to_s
|
|
5610
|
+
tagged_paths = @tagged.dup
|
|
5611
|
+
context = {
|
|
5612
|
+
selected: selected,
|
|
5613
|
+
directory: Dir.pwd,
|
|
5614
|
+
tagged: tagged_paths,
|
|
5615
|
+
index: @index,
|
|
5616
|
+
count: (@files || []).size
|
|
5617
|
+
}
|
|
5618
|
+
|
|
5619
|
+
env = {
|
|
5620
|
+
'RTFM_SELECTED' => selected,
|
|
5621
|
+
'RTFM_DIR' => Dir.pwd,
|
|
5622
|
+
'RTFM_TAGGED' => tagged_paths.join("\n"),
|
|
5623
|
+
'RTFM_INDEX' => @index.to_s,
|
|
5624
|
+
'RTFM_COUNT' => (@files || []).size.to_s,
|
|
5625
|
+
'RTFM_CONTEXT' => context.to_json
|
|
5626
|
+
}
|
|
5627
|
+
|
|
5628
|
+
begin
|
|
5629
|
+
out, err, _status = Open3.capture3(env, 'sh', '-c', cmd)
|
|
5630
|
+
rescue StandardError => e
|
|
5631
|
+
@pB.say("script: #{e.class}: #{e.message}".fg(196))
|
|
5632
|
+
return
|
|
5633
|
+
end
|
|
5634
|
+
|
|
5635
|
+
# Process stderr line-by-line: directives consumed, other lines kept.
|
|
5636
|
+
leftover_err = []
|
|
5637
|
+
directive_msgs = []
|
|
5638
|
+
err.each_line do |line|
|
|
5639
|
+
l = line.chomp
|
|
5640
|
+
case l
|
|
5641
|
+
when /\Acd:(.+)\z/
|
|
5642
|
+
target = File.expand_path($1.strip)
|
|
5643
|
+
if File.directory?(target)
|
|
5644
|
+
@directory[Dir.pwd] = @index
|
|
5645
|
+
mark_latest
|
|
5646
|
+
Dir.chdir(target)
|
|
5647
|
+
directive_msgs << "cd: #{target}"
|
|
5648
|
+
else
|
|
5649
|
+
leftover_err << "cd: no such directory: #{target}"
|
|
5650
|
+
end
|
|
5651
|
+
when /\Aselect:(.+)\z/
|
|
5652
|
+
name = $1.strip
|
|
5653
|
+
# Applied after the upcoming render populates @files (handles both
|
|
5654
|
+
# same-dir selection and post-cd selection in the new dir).
|
|
5655
|
+
@startup_select = name
|
|
5656
|
+
directive_msgs << "select: #{name}"
|
|
5657
|
+
when /\Astatus:(.+)\z/
|
|
5658
|
+
msg = $1.strip
|
|
5659
|
+
@pB.say(msg.fg(156))
|
|
5660
|
+
directive_msgs << "status: #{msg}"
|
|
5661
|
+
else
|
|
5662
|
+
leftover_err << l unless l.empty?
|
|
5663
|
+
end
|
|
5664
|
+
end
|
|
5665
|
+
|
|
5666
|
+
body = out.dup
|
|
5667
|
+
body << "\n" << leftover_err.join("\n").fg(196) unless leftover_err.empty?
|
|
5668
|
+
|
|
5669
|
+
# Show directive trace as a subtle footer so the user can see what fired
|
|
5670
|
+
unless directive_msgs.empty?
|
|
5671
|
+
body << "\n\n" unless body.empty?
|
|
5672
|
+
body << '── directives applied ──'.fg(238) << "\n"
|
|
5673
|
+
body << directive_msgs.map { |m| " #{m}" }.join("\n").fg(244)
|
|
5674
|
+
end
|
|
5675
|
+
|
|
5676
|
+
clear_image
|
|
5677
|
+
@pR.clear # wipe leftover preview lines so short output doesn't sit atop them
|
|
5678
|
+
text = body.empty? ? ' (no output)'.fg(244) : body
|
|
5679
|
+
@pR.text = text
|
|
5680
|
+
@pR.ix = 0
|
|
5681
|
+
@pR.full_refresh
|
|
5682
|
+
@pR.update = false
|
|
5683
|
+
@pB.update = true
|
|
5684
|
+
end
|
|
5685
|
+
|
|
5577
5686
|
# GENERIC FUNCTIONS {{{1
|
|
5578
5687
|
def get_cached_dirlist(dir, ls_options, ls_options_with_long = nil) # {{{2
|
|
5579
5688
|
# Use ls_options_with_long for display, or fall back to ls_options
|