ruby-shell 3.4.4 → 3.4.6
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/PLUGIN_GUIDE.md +107 -0
- data/README.md +21 -0
- data/bin/rsh +119 -38
- metadata +5 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8180bf48f336b9667d34fc01d5df5ddf7a3412ff5f35cfc443d10846a81f6686
|
|
4
|
+
data.tar.gz: acd063a28be3a5bfe7ccb9ec6623ddb7e061deba44806725c1b76781fcf45acb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 05d07658f8356edad6da19da615170e2423785fc4a3f9074cfb5b9ef3a7f602b3f109172cb6ba799f9b2bc0bbc7363a9c0ff29b4d9d27cfebb05b2883156aad6
|
|
7
|
+
data.tar.gz: 6e1d7c8d6c16c0ce6f2d7cf67a5229b3a31f3e0d096438fd59877c3647dd5f8b1530ff0b0c46cd95bd377d25663e79e7f0cbef8dc8599f61cb281a395c54bc94
|
data/PLUGIN_GUIDE.md
CHANGED
|
@@ -661,6 +661,113 @@ Planned for v4.0:
|
|
|
661
661
|
|
|
662
662
|
---
|
|
663
663
|
|
|
664
|
+
## Included Plugins
|
|
665
|
+
|
|
666
|
+
rsh comes with several useful plugins out of the box. Enable them with `:plugins "enable", "pluginname"`.
|
|
667
|
+
|
|
668
|
+
### venv - Virtual Environment Indicators
|
|
669
|
+
|
|
670
|
+
Shows active Python venv, Ruby rbenv/rvm, Node nvm, and Conda environments in your prompt.
|
|
671
|
+
|
|
672
|
+
**Features:**
|
|
673
|
+
- Detects Python virtualenv: `(py:myenv)`
|
|
674
|
+
- Shows Ruby rbenv/rvm versions: `(rb:3.2.0)`
|
|
675
|
+
- Displays Node version: `(node:18.0.0)`
|
|
676
|
+
- Shows Conda environments: `(conda:base)`
|
|
677
|
+
- Color-coded indicators (green for Python, red for Ruby, yellow for Node, cyan for Conda)
|
|
678
|
+
|
|
679
|
+
**Usage:** Simply enable the plugin, indicators appear automatically when in an active environment.
|
|
680
|
+
|
|
681
|
+
### extract - Universal Archive Handler
|
|
682
|
+
|
|
683
|
+
Extract any archive format with a single command.
|
|
684
|
+
|
|
685
|
+
**Features:**
|
|
686
|
+
- Handles: `.tar.gz`, `.tar.bz2`, `.tar.xz`, `.zip`, `.rar`, `.7z`, `.gz`, `.bz2`, `.xz`, `.Z`, `.deb`, `.rpm`
|
|
687
|
+
- Auto-detects format from extension
|
|
688
|
+
- Success/error feedback with color
|
|
689
|
+
|
|
690
|
+
**Commands:**
|
|
691
|
+
- `extract file.tar.gz` - Extract any supported archive
|
|
692
|
+
|
|
693
|
+
**Example:**
|
|
694
|
+
```ruby
|
|
695
|
+
extract project.tar.gz
|
|
696
|
+
extract backup.zip
|
|
697
|
+
extract archive.7z
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
### docker - Container Integration
|
|
701
|
+
|
|
702
|
+
Quick Docker container management with prompt indicators.
|
|
703
|
+
|
|
704
|
+
**Features:**
|
|
705
|
+
- Shows running container count in prompt: `[docker:3]`
|
|
706
|
+
- Quick container management commands
|
|
707
|
+
- Docker Compose shortcuts
|
|
708
|
+
|
|
709
|
+
**Commands:**
|
|
710
|
+
- `dps` - List running containers (docker ps)
|
|
711
|
+
- `dpsa` - List all containers (docker ps -a)
|
|
712
|
+
- `dex <container>` - Execute bash in container
|
|
713
|
+
- `dlogs <container> [lines]` - Show container logs (default 50 lines)
|
|
714
|
+
- `dstop` - Stop all running containers
|
|
715
|
+
- `dclean` - Remove all stopped containers
|
|
716
|
+
- `dcup` - Docker compose up -d
|
|
717
|
+
- `dcdown` - Docker compose down
|
|
718
|
+
- `dcrestart` - Docker compose restart
|
|
719
|
+
|
|
720
|
+
**Example:**
|
|
721
|
+
```ruby
|
|
722
|
+
dps # List running containers
|
|
723
|
+
dex web_1 # Enter bash in web_1 container
|
|
724
|
+
dlogs nginx 100 # Show last 100 log lines
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
### clipboard - Cross-Platform Clipboard
|
|
728
|
+
|
|
729
|
+
Copy and paste text to/from system clipboard.
|
|
730
|
+
|
|
731
|
+
**Features:**
|
|
732
|
+
- Auto-detects clipboard tool (xclip, xsel, wl-copy/paste, pbcopy/paste, clip.exe)
|
|
733
|
+
- Works on Linux (X11/Wayland), macOS, and Windows WSL
|
|
734
|
+
- Copy last command, arbitrary text, or file contents
|
|
735
|
+
|
|
736
|
+
**Commands:**
|
|
737
|
+
- `clip [text]` - Copy text to clipboard (copies last command if no args)
|
|
738
|
+
- `clipp` - Paste from clipboard and display
|
|
739
|
+
- `clipf <file>` - Copy file contents to clipboard
|
|
740
|
+
|
|
741
|
+
**Example:**
|
|
742
|
+
```ruby
|
|
743
|
+
clip # Copy last command
|
|
744
|
+
clip some text here # Copy this text
|
|
745
|
+
clipf config.yml # Copy file contents
|
|
746
|
+
clipp # Show clipboard contents
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
### git_prompt - Git Branch Indicator
|
|
750
|
+
|
|
751
|
+
Shows current git branch in prompt when in a git repository.
|
|
752
|
+
|
|
753
|
+
**Features:**
|
|
754
|
+
- Displays current branch: `[main]`
|
|
755
|
+
- Only shows when in a git repo
|
|
756
|
+
- Yellow color coding
|
|
757
|
+
|
|
758
|
+
**Usage:** Enable and branch appears automatically in prompt.
|
|
759
|
+
|
|
760
|
+
### command_logger - Command Logging
|
|
761
|
+
|
|
762
|
+
Logs all commands to a file for audit/review.
|
|
763
|
+
|
|
764
|
+
**Features:**
|
|
765
|
+
- Logs commands with timestamp
|
|
766
|
+
- Customizable log file location
|
|
767
|
+
- Useful for command history analysis
|
|
768
|
+
|
|
769
|
+
---
|
|
770
|
+
|
|
664
771
|
## Example Plugin Templates
|
|
665
772
|
|
|
666
773
|
### Minimal Plugin
|
data/README.md
CHANGED
|
@@ -476,6 +476,27 @@ Also, a special variable for better LS_COLOR setup:
|
|
|
476
476
|
```
|
|
477
477
|
Point `@lscolors` to a file that sets your LS_COLORS variable. Use [my extended LS_COLORS setup](https://github.com/isene/LS_COLORS) to make this really fancy.
|
|
478
478
|
|
|
479
|
+
### Directory Colors in Prompt
|
|
480
|
+
|
|
481
|
+
**rsh is fully LS_COLORS compliant** - both tab completion and prompt paths use LS_COLORS for consistent theming.
|
|
482
|
+
|
|
483
|
+
You can override directory colors in the prompt using pattern matching (like RTFM's @topmatch):
|
|
484
|
+
```ruby
|
|
485
|
+
@dir_colors = [
|
|
486
|
+
["PassionFruit", 171], # Paths containing "PassionFruit" -> magenta
|
|
487
|
+
["Dualog", 72], # Paths containing "Dualog" -> cyan
|
|
488
|
+
["/G", 172], # Paths containing "/G" -> orange
|
|
489
|
+
]
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
How it works:
|
|
493
|
+
- Array of `[pattern, color]` pairs
|
|
494
|
+
- First matching pattern wins (uses Ruby's `include?` method)
|
|
495
|
+
- If no pattern matches, uses LS_COLORS 'di' value (your configured directory color)
|
|
496
|
+
- Pattern matching is simple substring matching: "/G" matches "/home/user/Main/G/..."
|
|
497
|
+
|
|
498
|
+
This lets you visually distinguish different project directories at a glance in your prompt.
|
|
499
|
+
|
|
479
500
|
You can add any Ruby code to your .rshrc.
|
|
480
501
|
|
|
481
502
|
# Enter the world of Ruby
|
data/bin/rsh
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
# Web_site: http://isene.com/
|
|
9
9
|
# Github: https://github.com/isene/rsh
|
|
10
10
|
# License: Public domain
|
|
11
|
-
@version = "3.4.
|
|
11
|
+
@version = "3.4.6" # Plugin help system, 4 new plugins, plugins disabled by default, Ctrl-W fix
|
|
12
12
|
|
|
13
13
|
# MODULES, CLASSES AND EXTENSIONS
|
|
14
14
|
class String # Add coloring to strings (with escaping for Readline)
|
|
@@ -154,7 +154,7 @@ begin # Initialization
|
|
|
154
154
|
@slow_command_threshold = 0 # Threshold for slow command alerts (0 = disabled)
|
|
155
155
|
@plugin_dir = Dir.home + '/.rsh/plugins' # Plugins directory
|
|
156
156
|
@plugins = [] # Loaded plugin instances
|
|
157
|
-
@
|
|
157
|
+
@plugin_enabled = [] # List of enabled plugin names (whitelist)
|
|
158
158
|
@plugin_commands = {} # Commands added by plugins
|
|
159
159
|
@validation_rules = [] # Custom validation rules
|
|
160
160
|
@completion_weights = {} # Completion learning weights
|
|
@@ -352,7 +352,7 @@ def getstr # A custom Readline-like function
|
|
|
352
352
|
# The actual printing og the command line
|
|
353
353
|
@c.row(@row0)
|
|
354
354
|
@c.clear_line
|
|
355
|
-
print @
|
|
355
|
+
print @display_prompt
|
|
356
356
|
@c.clear_screen_down
|
|
357
357
|
row, @pos0 = @c.pos
|
|
358
358
|
#@history[0] = "" if @history[0].nil?
|
|
@@ -476,11 +476,13 @@ def getstr # A custom Readline-like function
|
|
|
476
476
|
@c.clear_line_after
|
|
477
477
|
when 'WBACK' # Delete one word to the left (Ctrl-W)
|
|
478
478
|
unless @pos == @pos0
|
|
479
|
-
|
|
479
|
+
# Skip over any trailing spaces first
|
|
480
|
+
while @pos > 0 && @history[0][@pos - 1] == " "
|
|
480
481
|
@pos -= 1
|
|
481
482
|
@history[0][@pos] = ""
|
|
482
483
|
end
|
|
483
|
-
|
|
484
|
+
# Delete the word (until we hit a space or start)
|
|
485
|
+
while @pos > 0 && @history[0][@pos - 1] != " "
|
|
484
486
|
@pos -= 1
|
|
485
487
|
@history[0][@pos] = ""
|
|
486
488
|
end
|
|
@@ -622,7 +624,7 @@ def tab(type)
|
|
|
622
624
|
@c_col = @pos0 + @pos
|
|
623
625
|
@c.clear_line
|
|
624
626
|
line_display = cmd_check(@history[0]).to_s
|
|
625
|
-
print @
|
|
627
|
+
print @display_prompt + line_display
|
|
626
628
|
@c.col(@c_col)
|
|
627
629
|
return
|
|
628
630
|
end
|
|
@@ -645,14 +647,22 @@ def tab(type)
|
|
|
645
647
|
@tabarray = @recordings.keys
|
|
646
648
|
when "plugin_args"
|
|
647
649
|
# Completions for :plugins command
|
|
648
|
-
@tabarray = %w[reload
|
|
649
|
-
# Add
|
|
650
|
+
@tabarray = %w[reload]
|
|
651
|
+
# Add help for all available plugins
|
|
652
|
+
if Dir.exist?(@plugin_dir)
|
|
653
|
+
available = Dir.glob(@plugin_dir + '/*.rb').map { |f| File.basename(f, '.rb') }
|
|
654
|
+
@tabarray += available.map { |p| "help #{p}" }
|
|
655
|
+
@tabarray += available.map { |p| "info #{p}" }
|
|
656
|
+
end
|
|
657
|
+
# Add plugin names for enable/disable
|
|
650
658
|
if @plugins.any?
|
|
651
659
|
@tabarray += @plugins.map { |p| "disable #{p[:name]}" }
|
|
652
|
-
@tabarray += @plugins.map { |p| "info #{p[:name]}" }
|
|
653
660
|
end
|
|
654
|
-
|
|
655
|
-
|
|
661
|
+
# Show "enable" for disabled plugins (available but not enabled)
|
|
662
|
+
if Dir.exist?(@plugin_dir)
|
|
663
|
+
available = Dir.glob(@plugin_dir + '/*.rb').map { |f| File.basename(f, '.rb') }
|
|
664
|
+
disabled = available - @plugin_enabled
|
|
665
|
+
@tabarray += disabled.map { |p| "enable #{p}" } if disabled.any?
|
|
656
666
|
end
|
|
657
667
|
when "switch"
|
|
658
668
|
cmdswitch = @pretab.split(/[|, ]/).last.to_s.strip
|
|
@@ -839,7 +849,7 @@ def tab(type)
|
|
|
839
849
|
# Escape regex special characters in @tabstr for pattern matching
|
|
840
850
|
escaped_tabstr = Regexp.escape(@tabstr)
|
|
841
851
|
tabline = display_choice.sub(/(.*)#{escaped_tabstr}(.*)/, '\1'.c(choice_color) + @tabstr.u.c(choice_color) + '\2'.c(choice_color))
|
|
842
|
-
print @
|
|
852
|
+
print @display_prompt + line1 + tabline + line2 # Print the commandline
|
|
843
853
|
@pos = @pretab.length.to_i + tabchoice.length.to_i # Set the position on that commandline
|
|
844
854
|
@c_col = @pos0 + @pos # The cursor position must include the prompt as well
|
|
845
855
|
@c.col(@c_col) # Set the cursor position
|
|
@@ -1262,6 +1272,18 @@ def get_file_color(filename) # Get color for a file based on LS_COLORS
|
|
|
1262
1272
|
file_color = 7 if file_color == 0 # 0 means "reset to default" in LS_COLORS
|
|
1263
1273
|
file_color
|
|
1264
1274
|
end
|
|
1275
|
+
def get_dir_color(path) # Get color for directory path in prompt
|
|
1276
|
+
# Check pattern matches first (like RTFM's @topmatch)
|
|
1277
|
+
# Set @dir_colors in .rshrc as array of [pattern, color] pairs
|
|
1278
|
+
# Example: @dir_colors = [["PassionFruit", 171], ["Dualog", 72], ["/G", 172], ["", 33]]
|
|
1279
|
+
if @dir_colors && @dir_colors.is_a?(Array)
|
|
1280
|
+
match = @dir_colors.find { |pattern, _| pattern.empty? || path.include?(pattern) }
|
|
1281
|
+
return match.last if match
|
|
1282
|
+
end
|
|
1283
|
+
|
|
1284
|
+
# Fall back to LS_COLORS directory color
|
|
1285
|
+
@ls_colors['di'] || 33
|
|
1286
|
+
end
|
|
1265
1287
|
def format_tab_item(item, show_metadata: false) # Format tab item with color and optional metadata
|
|
1266
1288
|
color = get_file_color(item)
|
|
1267
1289
|
formatted = item
|
|
@@ -1335,7 +1357,12 @@ def cmd_check(str) # Check if each element on the readline matches commands, nic
|
|
|
1335
1357
|
# Color bookmarks (after commands and nicks)
|
|
1336
1358
|
el.c(@c_bookmark)
|
|
1337
1359
|
elsif File.exist?(clean_el)
|
|
1338
|
-
|
|
1360
|
+
# Use directory color matching for directories, @c_path for files
|
|
1361
|
+
if File.directory?(clean_el)
|
|
1362
|
+
el.c(get_dir_color(File.expand_path(clean_el)))
|
|
1363
|
+
else
|
|
1364
|
+
el.c(@c_path)
|
|
1365
|
+
end
|
|
1339
1366
|
elsif el[0] == "-"
|
|
1340
1367
|
el.c(@c_switch)
|
|
1341
1368
|
else
|
|
@@ -1372,8 +1399,8 @@ def rshrc # Write user configuration to .rshrc (portable between machines)
|
|
|
1372
1399
|
conf += "@completion_learning = #{@completion_learning}\n" unless @completion_learning
|
|
1373
1400
|
conf.sub!(/^@completion_show_metadata.*(\n|$)/, "")
|
|
1374
1401
|
conf += "@completion_show_metadata = #{@completion_show_metadata}\n" if @completion_show_metadata
|
|
1375
|
-
conf.sub!(/^@
|
|
1376
|
-
conf += "@
|
|
1402
|
+
conf.sub!(/^@plugin_enabled.*(\n|$)/, "")
|
|
1403
|
+
conf += "@plugin_enabled = #{@plugin_enabled}\n" unless @plugin_enabled.empty?
|
|
1377
1404
|
conf.sub!(/^@validation_rules.*(\n|$)/, "")
|
|
1378
1405
|
conf += "@validation_rules = #{@validation_rules}\n" unless @validation_rules.empty?
|
|
1379
1406
|
|
|
@@ -2233,8 +2260,8 @@ def load_plugins # Load all plugins from plugin directory
|
|
|
2233
2260
|
plugin_files.each do |plugin_file|
|
|
2234
2261
|
plugin_name = File.basename(plugin_file, '.rb')
|
|
2235
2262
|
|
|
2236
|
-
#
|
|
2237
|
-
next
|
|
2263
|
+
# Only load if explicitly enabled (whitelist)
|
|
2264
|
+
next unless @plugin_enabled.include?(plugin_name)
|
|
2238
2265
|
|
|
2239
2266
|
begin
|
|
2240
2267
|
# Load the plugin file
|
|
@@ -2304,22 +2331,26 @@ def call_plugin_hook(hook_name, *args) # Call a lifecycle hook for all plugins
|
|
|
2304
2331
|
end
|
|
2305
2332
|
def plugins(*args) # Plugin management command
|
|
2306
2333
|
if args.empty?
|
|
2307
|
-
# List all plugins
|
|
2308
|
-
|
|
2309
|
-
|
|
2334
|
+
# List all available plugins
|
|
2335
|
+
available_plugins = Dir.exist?(@plugin_dir) ? Dir.glob(@plugin_dir + '/*.rb').map { |f| File.basename(f, '.rb') }.sort : []
|
|
2336
|
+
|
|
2337
|
+
if available_plugins.empty?
|
|
2338
|
+
puts "\nNo plugins found"
|
|
2310
2339
|
puts "Place .rb files in #{@plugin_dir}"
|
|
2311
2340
|
return
|
|
2312
2341
|
end
|
|
2313
2342
|
|
|
2314
|
-
puts "\n
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2343
|
+
puts "\n Available Plugins:".c(@c_prompt).b
|
|
2344
|
+
available_plugins.each do |name|
|
|
2345
|
+
if @plugin_enabled.include?(name)
|
|
2346
|
+
status = '[enabled]'.c(@c_path)
|
|
2347
|
+
plugin = @plugins.find { |p| p[:name] == name }
|
|
2348
|
+
class_info = plugin ? " (#{plugin[:class]})" : ""
|
|
2349
|
+
else
|
|
2350
|
+
status = '[disabled]'.c(196)
|
|
2351
|
+
class_info = ""
|
|
2352
|
+
end
|
|
2353
|
+
puts " #{name.ljust(20)} #{status}#{class_info}"
|
|
2323
2354
|
end
|
|
2324
2355
|
puts
|
|
2325
2356
|
elsif args[0] == 'reload'
|
|
@@ -2331,15 +2362,15 @@ def plugins(*args) # Plugin management command
|
|
|
2331
2362
|
elsif args[0] == 'enable' && args[1]
|
|
2332
2363
|
# Enable a plugin
|
|
2333
2364
|
plugin_name = args[1]
|
|
2334
|
-
@
|
|
2365
|
+
unless @plugin_enabled.include?(plugin_name)
|
|
2366
|
+
@plugin_enabled << plugin_name
|
|
2367
|
+
end
|
|
2335
2368
|
puts "Plugin '#{plugin_name}' enabled. Use :plugins reload to load it"
|
|
2336
2369
|
rshrc
|
|
2337
2370
|
elsif args[0] == 'disable' && args[1]
|
|
2338
2371
|
# Disable a plugin
|
|
2339
2372
|
plugin_name = args[1]
|
|
2340
|
-
|
|
2341
|
-
@plugin_disabled << plugin_name
|
|
2342
|
-
end
|
|
2373
|
+
@plugin_enabled.delete(plugin_name)
|
|
2343
2374
|
@plugins.reject! { |p| p[:name] == plugin_name }
|
|
2344
2375
|
puts "Plugin '#{plugin_name}' disabled"
|
|
2345
2376
|
rshrc
|
|
@@ -2365,6 +2396,51 @@ def plugins(*args) # Plugin management command
|
|
|
2365
2396
|
else
|
|
2366
2397
|
puts "Plugin '#{plugin_name}' not found"
|
|
2367
2398
|
end
|
|
2399
|
+
elsif args[0] == 'help' && args[1]
|
|
2400
|
+
# Show plugin help
|
|
2401
|
+
plugin_name = args[1]
|
|
2402
|
+
plugin_file = "#{@plugin_dir}/#{plugin_name}.rb"
|
|
2403
|
+
|
|
2404
|
+
if File.exist?(plugin_file)
|
|
2405
|
+
content = File.read(plugin_file)
|
|
2406
|
+
|
|
2407
|
+
# Extract help block (lines starting with # at top of file)
|
|
2408
|
+
help_lines = []
|
|
2409
|
+
in_help = true
|
|
2410
|
+
content.each_line do |line|
|
|
2411
|
+
if in_help && line =~ /^#\s*(.*)$/
|
|
2412
|
+
help_text = $1
|
|
2413
|
+
next if help_text =~ /^-+$/ # Skip separator lines
|
|
2414
|
+
help_lines << help_text
|
|
2415
|
+
elsif line.strip.empty?
|
|
2416
|
+
next
|
|
2417
|
+
else
|
|
2418
|
+
in_help = false
|
|
2419
|
+
break
|
|
2420
|
+
end
|
|
2421
|
+
end
|
|
2422
|
+
|
|
2423
|
+
if help_lines.any?
|
|
2424
|
+
puts "\n#{help_lines.join("\n")}\n"
|
|
2425
|
+
else
|
|
2426
|
+
puts "No help available for plugin '#{plugin_name}'"
|
|
2427
|
+
end
|
|
2428
|
+
|
|
2429
|
+
# Extract and show available commands
|
|
2430
|
+
commands = []
|
|
2431
|
+
content.scan(/def (\w+)\(/) { |match| commands << match[0] unless match[0] == 'initialize' }
|
|
2432
|
+
|
|
2433
|
+
if commands.any?
|
|
2434
|
+
puts "\nCommands: #{commands.join(', ')}".c(@c_nick)
|
|
2435
|
+
puts
|
|
2436
|
+
end
|
|
2437
|
+
else
|
|
2438
|
+
puts "Plugin '#{plugin_name}' not found"
|
|
2439
|
+
puts "Available plugins:"
|
|
2440
|
+
Dir.glob(@plugin_dir + '/*.rb').each do |file|
|
|
2441
|
+
puts " #{File.basename(file, '.rb')}"
|
|
2442
|
+
end
|
|
2443
|
+
end
|
|
2368
2444
|
else
|
|
2369
2445
|
puts "Usage:"
|
|
2370
2446
|
puts " :plugins List all plugins"
|
|
@@ -2372,6 +2448,7 @@ def plugins(*args) # Plugin management command
|
|
|
2372
2448
|
puts " :plugins enable NAME Enable a plugin"
|
|
2373
2449
|
puts " :plugins disable NAME Disable a plugin"
|
|
2374
2450
|
puts " :plugins info NAME Show plugin details"
|
|
2451
|
+
puts " :plugins help NAME Show plugin help/usage"
|
|
2375
2452
|
end
|
|
2376
2453
|
end
|
|
2377
2454
|
def validate_command(cmd) # Syntax validation before execution
|
|
@@ -2982,7 +3059,7 @@ def load_rshrc_safe
|
|
|
2982
3059
|
@session_autosave = 0 unless @session_autosave.is_a?(Integer)
|
|
2983
3060
|
@auto_correct = false unless [@auto_correct].any? { |v| v == true || v == false }
|
|
2984
3061
|
@slow_command_threshold = 0 unless @slow_command_threshold.is_a?(Integer)
|
|
2985
|
-
@
|
|
3062
|
+
@plugin_enabled = [] unless @plugin_enabled.is_a?(Array)
|
|
2986
3063
|
@plugins = [] unless @plugins.is_a?(Array)
|
|
2987
3064
|
@plugin_commands = {} unless @plugin_commands.is_a?(Hash)
|
|
2988
3065
|
@validation_rules = [] unless @validation_rules.is_a?(Array)
|
|
@@ -3137,7 +3214,7 @@ def load_defaults
|
|
|
3137
3214
|
@session_autosave ||= 0
|
|
3138
3215
|
@auto_correct ||= false
|
|
3139
3216
|
@slow_command_threshold ||= 0
|
|
3140
|
-
@
|
|
3217
|
+
@plugin_enabled ||= []
|
|
3141
3218
|
@plugins ||= []
|
|
3142
3219
|
@plugin_commands ||= {}
|
|
3143
3220
|
@validation_rules ||= []
|
|
@@ -3211,6 +3288,8 @@ begin # Load .rshrc and populate @history
|
|
|
3211
3288
|
exit
|
|
3212
3289
|
end
|
|
3213
3290
|
firstrun unless File.exist?(Dir.home+'/.rshrc') # Initial loading - to get history
|
|
3291
|
+
# Initialize @ls_colors with defaults so get_dir_color() works in .rshrc prompt
|
|
3292
|
+
@ls_colors = { 'di' => 33, 'ex' => 2, 'ln' => 14, 'fi' => 7 }
|
|
3214
3293
|
load_rshrc_safe
|
|
3215
3294
|
migrate_to_split_config # Migrate from old format if needed (v3.4.3+)
|
|
3216
3295
|
# Load login shell files if rsh is running as login shell
|
|
@@ -3235,6 +3314,7 @@ begin # Load .rshrc and populate @history
|
|
|
3235
3314
|
ENV["TERM"] = "rxvt-unicode-256color"
|
|
3236
3315
|
ENV["PATH"] ? ENV["PATH"] += ":" : ENV["PATH"] = ""
|
|
3237
3316
|
ENV["PATH"] += "/home/#{@user}/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
3317
|
+
# Load actual LS_COLORS from file (now that @lscolors is set from .rshrc)
|
|
3238
3318
|
if @lscolors and File.exist?(@lscolors)
|
|
3239
3319
|
ls = File.read(@lscolors)
|
|
3240
3320
|
ls.sub!(/export.*/, '')
|
|
@@ -3273,9 +3353,10 @@ loop do
|
|
|
3273
3353
|
load_plugins
|
|
3274
3354
|
@plugins_loaded = true
|
|
3275
3355
|
end
|
|
3276
|
-
#
|
|
3356
|
+
# Build display prompt with plugin additions (don't modify @prompt)
|
|
3277
3357
|
plugin_prompts = call_plugin_hook(:on_prompt)
|
|
3278
|
-
@
|
|
3358
|
+
@display_prompt = @prompt.dup
|
|
3359
|
+
@display_prompt += plugin_prompts.join if plugin_prompts.any?
|
|
3279
3360
|
# Auto-save session if enabled and interval elapsed
|
|
3280
3361
|
if @session_autosave && @session_autosave > 0
|
|
3281
3362
|
current_time = Time.now.to_i
|
|
@@ -3322,7 +3403,7 @@ loop do
|
|
|
3322
3403
|
# Move cursor to end of line and print the full command before clearing
|
|
3323
3404
|
@c.row(@row0)
|
|
3324
3405
|
@c.clear_line
|
|
3325
|
-
print @
|
|
3406
|
+
print @display_prompt + cmd_check(@cmd)
|
|
3326
3407
|
print "\n"; @c.clear_screen_down
|
|
3327
3408
|
if @cmd == "r" # Integration with rtfm (https://github.com/isene/RTFM)
|
|
3328
3409
|
t = Time.now
|
metadata
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby-shell
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.4.
|
|
4
|
+
version: 3.4.6
|
|
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-10-
|
|
11
|
+
date: 2025-10-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: 'A shell written in Ruby with extensive tab completions, aliases/nicks,
|
|
14
14
|
history, syntax highlighting, theming, auto-cd, auto-opening files and more. UPDATE
|
|
15
|
-
v3.4.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
parametrized nicks, Ctrl-G editing, validation rules, shell scripts!'
|
|
15
|
+
v3.4.6: PLUGIN SYSTEM ENHANCED - Plugin help system, 4 new plugins (venv/extract/docker/clipboard),
|
|
16
|
+
plugins disabled by default. Plus v3.4.5: Full LS_COLORS compliance with pattern-based
|
|
17
|
+
directory coloring (@dir_colors like RTFM''s @topmatch)!'
|
|
19
18
|
email: g@isene.com
|
|
20
19
|
executables:
|
|
21
20
|
- rsh
|