rtfm-filemanager 7.0.5 → 7.0.9

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 +7 -0
  3. data/bin/rtfm +48 -23
  4. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a868de1ca6a2f8cb3706cd0d297fa452c20e08b96fcac59146c560779b991f7d
4
- data.tar.gz: 670836887ce9581a5d2083e7cd12c38e8c52817bd0bf5eb40ebfe62e4b66df96
3
+ metadata.gz: 03a8e8292ab2ffb9794497f688bf72000ea65dff64efdb5433847bbadac29b2e
4
+ data.tar.gz: 9c6e85c2a38c06c73568c41617f2137261a65d785139a68578412d6f56fe18af
5
5
  SHA512:
6
- metadata.gz: 12ea6e3767d8816c3e80e85888521fd8a772014d3480b4f59e9bfa68c7c0fd7a83aa3bd1f0a901e35595895e8eda5f4d48397de629d5a5ef57d4e9149c7ecd88
7
- data.tar.gz: b3376a6308e4a5e415ceb688074017ba8ce44d9dfd66fa0da9150b75b24b8b11a0a65488566b175695e8e77822d6080ddc86bf125fddf3c602ed8f5f8f0229a7
6
+ metadata.gz: 8c668b4c6ef30a233b217315a6dd47f3af79618a27e92ba1f162d827a83fa198f84c5e021ff8ba7a04af90241549e246e80cfd08fd10bfc0f017093b21db9933
7
+ data.tar.gz: 1e2664f8fc5eb7881b6048dce9f5896bfec8c3f674873640416627a8f1908d7685635971d44d96587afc4710f762248f00a75da37476512cb4b2f51dac803f0e
data/README.md CHANGED
@@ -523,9 +523,16 @@ previewed by default in RTFM. The `preview.rb` explains how you add thesea:
523
523
  # # plain text, Ruby, Python, shell
524
524
  # txt, rb, py, sh = bat -n --color=always @s
525
525
  #
526
+ # # Alternative syntax highlighters (e.g., on macOS without bat)
527
+ # # txt, rb, py, sh = highlight -O ansi --force --line-numbers @s
528
+ #
526
529
  # # markdown via pandoc
527
530
  # md = pandoc @s -t plain
528
531
  #
532
+ # # Alternative markdown viewers (e.g., lowdown, termmark)
533
+ # # md = lowdown -Tterm @s
534
+ # # md = termmark @s
535
+ #
529
536
  # # PDFs
530
537
  # pdf = pdftotext -f 1 -l 4 @s -
531
538
  ```
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 = '7.0.4' # Fixed platform-specific issues for macOS/BSD and improved first-run message
21
+ @version = '7.0.9' # Fixed image preview for filenames with spaces and special characters
22
22
 
23
23
  # SAVE & STORE TERMINAL {{{1
24
24
  ORIG_STTY = `stty -g`.chomp
@@ -57,7 +57,7 @@ def check_image_redraw # {{{2
57
57
  img_processes = `pgrep w3mimgdisplay 2>/dev/null`.chomp
58
58
  if img_processes.empty? && File.exist?(@current_image_path)
59
59
  # Redraw the image
60
- showimage(Shellwords.escape(@current_image_path))
60
+ showimage(@current_image_path)
61
61
  end
62
62
  rescue
63
63
  # Silently fail - we don't want focus checking to break anything
@@ -1634,13 +1634,15 @@ def undo_delete(operation) # {{{3
1634
1634
  if operation[:trash]
1635
1635
  # Restore from trash
1636
1636
  operation[:paths].each do |path_info|
1637
- source = File.join(TRASH_DIR, File.basename(path_info[:path]))
1637
+ # Use the unique trash name if available (new format), otherwise fallback to basename (old format)
1638
+ trash_name = path_info[:trash_name] || File.basename(path_info[:path])
1639
+ source = File.join(TRASH_DIR, trash_name)
1638
1640
  dest = path_info[:path]
1639
1641
 
1640
1642
  if File.exist?(source)
1641
1643
  FileUtils.mv(source, dest)
1642
1644
  else
1643
- raise "Cannot restore #{path_info[:path]}: not found in trash"
1645
+ raise "Cannot restore #{path_info[:path]}: not found in trash (looked for #{trash_name})"
1644
1646
  end
1645
1647
  end
1646
1648
  else
@@ -3197,7 +3199,7 @@ def delete_items # {{{3
3197
3199
  if @trash
3198
3200
  warning_text << "Items will be moved to:\n".fg(249)
3199
3201
  warning_text << " ~/.rtfm/trash/\n".fg(240)
3200
- warning_text << "\nYou can restore them with " + "C-z".fg(156) + "\n".fg(249)
3202
+ warning_text << "\nYou can restore them with " + "U".fg(156) + " (undo)\n".fg(249)
3201
3203
  else
3202
3204
  warning_text << "⚠️ WARNING: PERMANENT DELETION!\n".fg(196).b
3203
3205
  warning_text << "Files will be permanently removed\n".fg(196)
@@ -3220,18 +3222,27 @@ def delete_items # {{{3
3220
3222
  else
3221
3223
  # Record undo information before deletion
3222
3224
  if @trash
3225
+ # Generate unique trash names to avoid overwriting
3226
+ timestamp = Time.now.strftime('%Y%m%d_%H%M%S')
3227
+ trash_mappings = paths.map do |p|
3228
+ basename = File.basename(p)
3229
+ # Add timestamp and a random suffix to ensure uniqueness
3230
+ trash_name = "#{timestamp}_#{basename}_#{rand(1000..9999)}"
3231
+ trash_path = File.join(TRASH_DIR, trash_name)
3232
+ { path: p, trash_name: trash_name, trash_path: trash_path }
3233
+ end
3234
+
3223
3235
  undo_info = {
3224
3236
  type: 'delete',
3225
3237
  trash: true,
3226
- paths: paths.map { |p| { path: p } },
3238
+ paths: trash_mappings.map { |m| { path: m[:path], trash_name: m[:trash_name] } },
3227
3239
  timestamp: Time.now
3228
3240
  }
3229
- end
3230
-
3231
- esc = paths.map { |p| Shellwords.escape(p) }.join(' ')
3232
- if @trash
3233
- esc_trash = Shellwords.escape(TRASH_DIR)
3234
- command("mv -f #{esc} #{esc_trash}")
3241
+
3242
+ # Move each file with its unique trash name
3243
+ trash_mappings.each do |mapping|
3244
+ command("mv -f #{Shellwords.escape(mapping[:path])} #{Shellwords.escape(mapping[:trash_path])}")
3245
+ end
3235
3246
  # Only add to undo history if operation succeeded and we can undo it
3236
3247
  add_undo_operation(undo_info)
3237
3248
  else
@@ -4295,7 +4306,10 @@ def get_cached_file_metadata(file_path) # {{{2
4295
4306
  metadata = nil
4296
4307
  begin
4297
4308
  if file_path.match(@imagefile) && cmd?('identify')
4298
- metadata = `identify -format " [%wx%h %m %[colorspace] %[bit-depth]-bit]" #{Shellwords.escape(file_path)} 2>/dev/null`.strip
4309
+ # Skip SVG files as identify can be very slow on them
4310
+ unless file_path =~ /\.svg$/i
4311
+ metadata = `identify -format " [%wx%h %m %[colorspace] %[bit-depth]-bit]" #{Shellwords.escape(file_path)} 2>/dev/null`.strip
4312
+ end
4299
4313
  elsif file_path.match(@pdffile)
4300
4314
  info = `pdfinfo #{Shellwords.escape(file_path)} 2>/dev/null`
4301
4315
  pages = info[/^Pages:\s+(\d+)/, 1]
@@ -4647,9 +4661,12 @@ def render # RENDER ALL PANES {{{2
4647
4661
  if cached_meta
4648
4662
  text += cached_meta
4649
4663
  elsif @selected&.match(@imagefile) && cmd?('identify')
4650
- # Fallback for non-cached image metadata
4651
- meta = `identify -format " [%wx%h %m %[colorspace] %[bit-depth]-bit]" #{Shellwords.escape(@selected)} 2>/dev/null`
4652
- text += meta
4664
+ # Skip SVG files as identify can be very slow on them
4665
+ unless @selected =~ /\.svg$/i
4666
+ # Fallback for non-cached image metadata
4667
+ meta = `identify -format " [%wx%h %m %[colorspace] %[bit-depth]-bit]" #{Shellwords.escape(@selected)} 2>/dev/null`
4668
+ text += meta
4669
+ end
4653
4670
  elsif @selected&.match(@pdffile)
4654
4671
  # Fallback for non-cached PDF metadata
4655
4672
  info = `pdfinfo #{Shellwords.escape(@selected)} 2>/dev/null`
@@ -5200,6 +5217,9 @@ def showcommand(cmd) # Helper function for showcontent {{{2
5200
5217
  end
5201
5218
 
5202
5219
  def showcontent # SHOW CONTENTS IN THE RIGHT WINDOW {{{2
5220
+ # Only process content if preview is enabled
5221
+ return unless @preview
5222
+
5203
5223
  if @pR.update
5204
5224
  showimage('clear') if @image
5205
5225
  @image = false
@@ -5283,7 +5303,7 @@ def showcontent # SHOW CONTENTS IN THE RIGHT WINDOW {{{2
5283
5303
  if file_size > 50_000_000 # 50MB limit for images
5284
5304
  @pR.say("Image too large for preview (#{(file_size / 1024.0 / 1024.0).round(1)}MB > 50MB limit)")
5285
5305
  else
5286
- showimage(Shellwords.escape(@selected))
5306
+ showimage(@selected)
5287
5307
  @image = true
5288
5308
  end
5289
5309
  rescue => e
@@ -5411,8 +5431,12 @@ def showimage(image) # SHOW THE SELECTED IMAGE IN THE RIGHT WINDOW {{{2
5411
5431
  `echo "6;#{img_x};#{img_y};#{img_max_w};#{img_max_h};\n4;\n3;" | #{@imgdisplay} 2>/dev/null`
5412
5432
  @current_image_path = nil # Clear tracking when image is cleared
5413
5433
  else
5414
- # Use the already-escaped image for shell commands
5415
- dimensions = `identify -format "%wx%h" #{image} 2>/dev/null`
5434
+ # Ensure we have the absolute path
5435
+ img_path = File.absolute_path(image)
5436
+
5437
+ # Properly escape image path for shell commands
5438
+ escaped_image = Shellwords.escape(img_path)
5439
+ dimensions = `identify -format "%wx%h" #{escaped_image} 2>/dev/null`
5416
5440
  img_w, img_h = dimensions.split('x').map(&:to_i)
5417
5441
 
5418
5442
  # Fix: Use simultaneous scaling to prevent overflow
@@ -5425,10 +5449,11 @@ def showimage(image) # SHOW THE SELECTED IMAGE IN THE RIGHT WINDOW {{{2
5425
5449
  img_h = (img_h * scale).to_i
5426
5450
  end
5427
5451
 
5428
- # Fix: Unescape the filename for w3mimgdisplay protocol, then quote it
5429
- unescaped = image.gsub(/\\(.)/, '\1') # Remove shell escaping
5430
- `echo "0;1;#{img_x};#{img_y};#{img_w};#{img_h};;;;;\"#{unescaped}\"\n4;\n3;" | #{@imgdisplay} 2>/dev/null`
5431
- @current_image_path = unescaped # Track currently displayed image
5452
+ # Use the absolute path without extra quotes in the w3mimgdisplay protocol
5453
+ `echo '0;1;#{img_x};#{img_y};#{img_w};#{img_h};;;;;#{img_path}
5454
+ 4;
5455
+ 3;' | #{@imgdisplay} 2>/dev/null`
5456
+ @current_image_path = img_path # Track currently displayed image
5432
5457
  end
5433
5458
  rescue
5434
5459
  @pR.text = 'Error showing image'
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: 7.0.5
4
+ version: 7.0.9
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-08-19 00:00:00.000000000 Z
11
+ date: 2025-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rcurses
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '7.4'
55
55
  description: |-
56
- RTFM v7.0.5: Added fallback to 'cat' when pandoc or batcat are not available (Issue #8).
56
+ RTFM v7.0.9: Fixed image preview for filenames with spaces and special characters.
57
57
  A full featured terminal browser with syntax highlighted files, images shown in the terminal, videos thumbnailed, etc. Features include remote SSH/SFTP browsing, interactive SSH shell, comprehensive undo system, bookmarks, and much more. 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.
58
58
  email: g@isene.com
59
59
  executables: