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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/bin/rtfm +111 -2
  4. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d97437ca84138aaa2ad3fc03b54c2d607f39cda4e1d6fead69bef9d83278a9d
4
- data.tar.gz: feb00468052819fdbb1c7c109406db875eba2be13c98273f0d16cbd90fb968ce
3
+ metadata.gz: 1a3688f47ab7f42eaf8488abfd1035d3ffa36fba99368ab2dc1846dda3119415
4
+ data.tar.gz: 2bf042038eee3c18c764c136d87848f15ff623389ff08625c1f5a6dd2564abba
5
5
  SHA512:
6
- metadata.gz: 59981f04215c73a44f4821d1dbf3dddb74db5590521e746567c0970c157c96aca84b48c9c2ee3afa20037537734937e7b59c56b9a23c2cee8d947e67c0cefa2f
7
- data.tar.gz: ac25468b6d11effefb11b5debd5e006c9d11aa689e623f638d5ee35a06e798b93343481b8b8b4f7f3950ae7acf046f117cdaecc37de43e050abc2b2a39100de2
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.6.0' # LS_COLORS fallback (dircolors -b) + Terminal=true in .desktop honored
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rtfm-filemanager
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.6.0
4
+ version: 8.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene