ruby-shell 3.6.19 → 3.6.21

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 (3) hide show
  1. checksums.yaml +4 -4
  2. data/bin/rsh +54 -47
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a7f4341f245a647d8c45ea36e67f17af871a3dd8dd67b0344257b152d7284ab
4
- data.tar.gz: 3a5ec017025daf61f39070689728ef14b787a47964084058be21279b2ef9f795
3
+ metadata.gz: 6b32638dfedc89a3a3cf6260e9859b9f1a84abac6031b74f63aebb4c0c88bb9a
4
+ data.tar.gz: b2784feda7cf2240ffa15c60cb09bc6399d4c421c54ce9d4551d0d9256845933
5
5
  SHA512:
6
- metadata.gz: 1757bf42491dbde8d205d2756d8c3f41fba9dca3145e523d573ad40c6ffed4009ec35774f56da340936e8ddb71b7ebf53b6da366610a7564a296e08859a4a632
7
- data.tar.gz: 302631f9c4d365913bdb796179d8dcb2e67f45038230470d2ba3500e7d2f8606bee41543dfa35f4c87077150472327f7a9a156effc32435044809af9e15c4038
6
+ metadata.gz: 07eb2f410e2bd87dbdf053564595ff1aa204760b5d0d572b8ed80d50f6a79d4ffccec8119bf67b4c7236d169f49ab48c7c2edf36b07acd905f930344d19edf13
7
+ data.tar.gz: 72edff66208649aaf7460b5ac01ed71593135d075174351a5fbc52a91ad343f29b9c2af5632f5942c351382a87f01c45aa7d098b622df7794f295b5196d6770a
data/bin/rsh CHANGED
@@ -8,22 +8,29 @@
8
8
  # Web_site: http://isene.com/
9
9
  # Github: https://github.com/isene/rsh
10
10
  # License: Public domain
11
- @version = "3.6.19" # Fix nick deletion and hyphenated command handling
11
+ @version = "3.6.21" # Rename String .b/.i/.u to .bd/.it/.ul for Ruby core compatibility
12
12
 
13
13
  # MODULES, CLASSES AND EXTENSIONS
14
14
  class String # Add coloring to strings (with escaping for Readline)
15
- def c(code); color(self, "\001\e[38;5;#{code}m\002"); end # Color code
16
- def b; color(self, "\001\e[1m\002"); end # Bold
17
- def i; color(self, "\001\e[3m\002"); end # Italic
18
- def u; color(self, "\001\e[4m\002"); end # Underline
19
- def l; color(self, "\001\e[5m\002"); end # Blink
20
- def r; color(self, "\001\e[7m\002"); end # Reverse
21
- def color(text, color_code) "#{color_code}#{text}\001\e[0m\002" end
15
+ COLOR_CACHE = Hash.new { |h, k| h[k] = "\001\e[38;5;#{k}m\002".freeze }
16
+ RESET_CODE = "\001\e[0m\002".freeze
17
+ BOLD_CODE = "\001\e[1m\002".freeze
18
+ ITALIC_CODE = "\001\e[3m\002".freeze
19
+ ULINE_CODE = "\001\e[4m\002".freeze
20
+ BLINK_CODE = "\001\e[5m\002".freeze
21
+ REV_CODE = "\001\e[7m\002".freeze
22
+ def c(code); "#{COLOR_CACHE[code]}#{self}#{RESET_CODE}"; end # Color code
23
+ def bd; "#{BOLD_CODE}#{self}#{RESET_CODE}"; end # Bold
24
+ def it; "#{ITALIC_CODE}#{self}#{RESET_CODE}"; end # Italic
25
+ def ul; "#{ULINE_CODE}#{self}#{RESET_CODE}"; end # Underline
26
+ def l; "#{BLINK_CODE}#{self}#{RESET_CODE}"; end # Blink
27
+ def r; "#{REV_CODE}#{self}#{RESET_CODE}"; end # Reverse
22
28
  end
23
29
  module Cursor # Terminal cursor movement ANSI codes (thanks to https://github.com/piotrmurach/tty-cursor)
24
30
  module_function
25
31
  ESC = "\e".freeze
26
32
  CSI = "\e[".freeze
33
+ POS_RE = /(?<row>\d+);(?<col>\d+)/.freeze
27
34
  def save # Save current position
28
35
  print(Gem.win_platform? ? CSI + 's' : ESC + '7')
29
36
  end
@@ -44,7 +51,7 @@ module Cursor # Terminal cursor movement ANSI codes (thanks to https://github.co
44
51
  # Not a TTY, return default values
45
52
  return 25, 80
46
53
  end
47
- m = res.match /(?<row>\d+);(?<col>\d+)/
54
+ m = res.match POS_RE
48
55
  return m ? [m[:row].to_i, m[:col].to_i] : [25, 80]
49
56
  end
50
57
  def rowget
@@ -104,7 +111,7 @@ begin # Initialization
104
111
  @c_archive = 11 # Color for archives (yellow)
105
112
  @c_file = 7 # Color for regular files (white/default)
106
113
  # Prompt
107
- @prompt = "rsh > ".c(@c_prompt).b # Very basic prompt if not defined in .rshrc
114
+ @prompt = "rsh > ".c(@c_prompt).bd # Very basic prompt if not defined in .rshrc
108
115
  # Hash & array initializations
109
116
  @nick = {} # Initiate alias/nick hash
110
117
  @gnick = {} # Initiate generic/global alias/nick hash
@@ -243,7 +250,7 @@ def firstrun
243
250
  rc = <<~RSHRC
244
251
  # PROMPT
245
252
  # The numbers in parenthesis are 256 color codes (the '.c()' is a String extention
246
- # to color text in the terminal. Add '.b' for bold and '.i' for italics.
253
+ # to color text in the terminal. Add '.bd' for bold and '.it' for italics.
247
254
  @prompt = "\#{@user}@\#{@node}".c(46) + ":".c(255) + " \#{Dir.pwd}/".c(196) + " ".c(7)
248
255
 
249
256
  # THEME
@@ -947,7 +954,7 @@ def tab(type)
947
954
  choice_color = get_file_color(tabchoice)
948
955
  # Escape regex special characters in @tabstr for pattern matching
949
956
  escaped_tabstr = Regexp.escape(@tabstr)
950
- tabline = display_choice.sub(/(.*)#{escaped_tabstr}(.*)/, '\1'.c(choice_color) + @tabstr.u.c(choice_color) + '\2'.c(choice_color))
957
+ tabline = display_choice.sub(/(.*)#{escaped_tabstr}(.*)/, '\1'.c(choice_color) + @tabstr.ul.c(choice_color) + '\2'.c(choice_color))
951
958
  print prompt_for_tab + line1 + tabline + line2 # Print the commandline (use last line only for multi-line)
952
959
  @pos = @pretab.length.to_i + tabchoice.length.to_i # Set the position on that commandline
953
960
  # Unified cursor positioning (always +1 since @pos0 is now string length)
@@ -966,12 +973,12 @@ def tab(type)
966
973
  # Can't nest ANSI codes, they must each complete/conclude or they will mess eachother up
967
974
  escaped_tabstr = Regexp.escape(@tabstr)
968
975
  if display_item.include?(@tabstr)
969
- tabline1 = display_item.sub(/(.*?)#{escaped_tabstr}.*/, '\1').c(file_color).b # Bold + color for selected
970
- tabline2 = display_item.sub(/.*?#{escaped_tabstr}(.*)/, '\1').c(file_color).b
971
- print " " + tabline1 + @tabstr.c(file_color).u.b + tabline2 # Bold, color & underline @tabstr
976
+ tabline1 = display_item.sub(/(.*?)#{escaped_tabstr}.*/, '\1').c(file_color).bd # Bold + color for selected
977
+ tabline2 = display_item.sub(/.*?#{escaped_tabstr}(.*)/, '\1').c(file_color).bd
978
+ print " " + tabline1 + @tabstr.c(file_color).ul.bd + tabline2 # Bold, color & underline @tabstr
972
979
  else
973
980
  # For fuzzy matches, just show the whole word highlighted
974
- print " " + display_item.c(file_color).b
981
+ print " " + display_item.c(file_color).bd
975
982
  end
976
983
  # Add metadata if enabled
977
984
  if @completion_show_metadata && File.exist?(clean_item)
@@ -1004,7 +1011,7 @@ def tab(type)
1004
1011
  if display_item.include?(@tabstr)
1005
1012
  tabline1 = display_item.sub(/(.*?)#{escaped_tabstr}.*/, '\1').c(file_color) # Color before @tabstr
1006
1013
  tabline2 = display_item.sub(/.*?#{escaped_tabstr}(.*)/, '\1').c(file_color) # Color after @tabstr
1007
- print " " + tabline1 + @tabstr.c(file_color).u + tabline2 # Print the whole line
1014
+ print " " + tabline1 + @tabstr.c(file_color).ul + tabline2 # Print the whole line
1008
1015
  else
1009
1016
  # For fuzzy matches, just show the whole word
1010
1017
  print " " + display_item.c(file_color)
@@ -1225,7 +1232,7 @@ def config(*args) # Configure rsh settings
1225
1232
 
1226
1233
  if setting.nil?
1227
1234
  # Show current configuration with aligned columns
1228
- puts "\n Current Configuration:".c(@c_prompt).b
1235
+ puts "\n Current Configuration:".c(@c_prompt).bd
1229
1236
  config_items = [
1230
1237
  ["history_dedup", @history_dedup],
1231
1238
  ["session_autosave", "#{@session_autosave}s", @session_autosave > 0 ? "(enabled)" : "(disabled)"],
@@ -1306,7 +1313,7 @@ def env(*args) # Environment variable management
1306
1313
 
1307
1314
  if args.empty?
1308
1315
  # List all environment variables
1309
- puts "\n Environment Variables:".c(@c_prompt).b
1316
+ puts "\n Environment Variables:".c(@c_prompt).bd
1310
1317
  ENV.sort.first(20).each do |key, value|
1311
1318
  value_display = value.length > 50 ? value[0..47] + '...' : value
1312
1319
  puts " #{key.c(@c_gnick).ljust(25)} = #{value_display}"
@@ -1503,7 +1510,7 @@ def cmd_check(str) # Check if each element on the readline matches commands, nic
1503
1510
  elsif @gnick.include?(el)
1504
1511
  el.c(@c_gnick)
1505
1512
  elsif self.respond_to?(el) && singleton_class.instance_methods(false).include?(el.to_sym)
1506
- el.c(@c_nick).b # Ruby functions in bold nick color
1513
+ el.c(@c_nick).bd # Ruby functions in bold nick color
1507
1514
  elsif @bookmarks && @bookmarks.include?(el)
1508
1515
  # Color bookmarks (after commands and nicks)
1509
1516
  el.c(@c_bookmark)
@@ -1650,7 +1657,7 @@ def help
1650
1657
  col3 = []
1651
1658
 
1652
1659
  # Column 1: Keyboard + Commands + Jobs
1653
- col1 << "KEYBOARD:".c(@c_prompt).b
1660
+ col1 << "KEYBOARD:".c(@c_prompt).bd
1654
1661
  col1 << "Ctrl-G Edit in \$EDITOR"
1655
1662
  col1 << "Ctrl-Y Copy line"
1656
1663
  col1 << "Ctrl-D Exit + save"
@@ -1658,7 +1665,7 @@ def help
1658
1665
  col1 << "TAB Complete"
1659
1666
  col1 << "Shift-TAB History search"
1660
1667
  col1 << ""
1661
- col1 << "CORE COMMANDS:".c(@c_prompt).b
1668
+ col1 << "CORE COMMANDS:".c(@c_prompt).bd
1662
1669
  col1 << ":nick a = b Create alias"
1663
1670
  col1 << ":nick List all"
1664
1671
  col1 << ":nick -a Delete"
@@ -1672,26 +1679,26 @@ def help
1672
1679
  col1 << ":theme name Color schemes"
1673
1680
  col1 << ":plugins Extensions"
1674
1681
  col1 << ""
1675
- col1 << "JOBS:".c(@c_prompt).b
1682
+ col1 << "JOBS:".c(@c_prompt).bd
1676
1683
  col1 << "cmd & Background"
1677
1684
  col1 << ":jobs List jobs"
1678
1685
  col1 << ":fg [id] Foreground"
1679
1686
 
1680
1687
  # Column 2: Sessions + Bookmarks + Recording
1681
- col2 << "SESSIONS:".c(@c_prompt).b
1688
+ col2 << "SESSIONS:".c(@c_prompt).bd
1682
1689
  col2 << ":save_session nm Save state"
1683
1690
  col2 << ":load_session nm Load state"
1684
1691
  col2 << ":list_sessions Show all"
1685
1692
  col2 << ":rmsession nm|* Delete"
1686
1693
  col2 << ""
1687
- col2 << "BOOKMARKS:".c(@c_prompt).b
1694
+ col2 << "BOOKMARKS:".c(@c_prompt).bd
1688
1695
  col2 << ":bm nm path #tag Create"
1689
1696
  col2 << "name Jump to bookmark"
1690
1697
  col2 << ":bm List all"
1691
1698
  col2 << ":bm --stats Statistics"
1692
1699
  col2 << ":bm --export f Export"
1693
1700
  col2 << ""
1694
- col2 << "RECORDING:".c(@c_prompt).b
1701
+ col2 << "RECORDING:".c(@c_prompt).bd
1695
1702
  col2 << ":record start nm Start recording"
1696
1703
  col2 << ":record stop Stop recording"
1697
1704
  col2 << ":record show nm Show commands"
@@ -1699,7 +1706,7 @@ def help
1699
1706
  col2 << ":replay nm Execute"
1700
1707
  col2 << ":record List all"
1701
1708
  col2 << ""
1702
- col2 << "FEATURES:".c(@c_prompt).b
1709
+ col2 << "FEATURES:".c(@c_prompt).bd
1703
1710
  col2 << "gp branch=main Nick template"
1704
1711
  col2 << "!! Repeat last"
1705
1712
  col2 << "!-2 2nd to last"
@@ -1708,21 +1715,21 @@ def help
1708
1715
  col2 << ":completion_stats Learn patterns"
1709
1716
 
1710
1717
  # Column 3: Config + Integrations + Expansions
1711
- col3 << "CONFIG:".c(@c_prompt).b
1718
+ col3 << "CONFIG:".c(@c_prompt).bd
1712
1719
  col3 << ":config auto_correct on Auto-fix"
1713
1720
  col3 << ":config completion_learning on Learn TAB"
1714
1721
  col3 << ":config slow_command_threshold 5 Slow warn"
1715
1722
  col3 << ":config session_autosave 300 Auto-save"
1716
1723
  col3 << ":config history_dedup smart Dedup"
1717
1724
  col3 << ""
1718
- col3 << "INTEGRATIONS:".c(@c_prompt).b
1725
+ col3 << "INTEGRATIONS:".c(@c_prompt).bd
1719
1726
  col3 << "r rtfm file manager"
1720
1727
  col3 << "f fzf fuzzy finder"
1721
1728
  col3 << "= expr xrpn calculator"
1722
1729
  col3 << "@ text AI text response"
1723
1730
  col3 << "@@ cmd AI command suggest"
1724
1731
  col3 << ""
1725
- col3 << "EXPANSIONS:".c(@c_prompt).b
1732
+ col3 << "EXPANSIONS:".c(@c_prompt).bd
1726
1733
  col3 << "~ Home directory"
1727
1734
  col3 << "$VAR Environment var"
1728
1735
  col3 << "$(cmd) Command subst"
@@ -1730,7 +1737,7 @@ def help
1730
1737
  col3 << "cmd1 && cmd2 Conditional AND"
1731
1738
  col3 << "for i in... Bash scripts"
1732
1739
  col3 << ""
1733
- col3 << "MORE:".c(@c_prompt).b
1740
+ col3 << "MORE:".c(@c_prompt).bd
1734
1741
  col3 << ":help This help"
1735
1742
  col3 << ":info About rsh"
1736
1743
  col3 << ":version Version info"
@@ -1810,7 +1817,7 @@ end
1810
1817
  def nick(nick_str = nil) # Define a new nick like this: `:nick "ls = ls --color"`
1811
1818
  if nick_str.nil? || nick_str.empty?
1812
1819
  # List all nicks
1813
- puts "\n Command nicks:".c(@c_nick).b
1820
+ puts "\n Command nicks:".c(@c_nick).bd
1814
1821
  if @nick.empty?
1815
1822
  puts " (none defined)"
1816
1823
  else
@@ -1850,7 +1857,7 @@ end
1850
1857
  def gnick(nick_str = nil) # Define a generic/global nick to match not only commands (format like nick)
1851
1858
  if nick_str.nil? || nick_str.empty?
1852
1859
  # List all gnicks
1853
- puts "\n General nicks:".c(@c_gnick).b
1860
+ puts "\n General nicks:".c(@c_gnick).bd
1854
1861
  if @gnick.empty?
1855
1862
  puts " (none defined)"
1856
1863
  else
@@ -2019,7 +2026,7 @@ def stats(*args) # Show command execution statistics and analytics
2019
2026
  end
2020
2027
 
2021
2028
  # Display stats (existing code)
2022
- puts "\n Command Execution Statistics".c(@c_prompt).b
2029
+ puts "\n Command Execution Statistics".c(@c_prompt).bd
2023
2030
  puts " " + "="*50
2024
2031
 
2025
2032
  # Most used commands
@@ -2059,7 +2066,7 @@ def stats(*args) # Show command execution statistics and analytics
2059
2066
  puts
2060
2067
  end
2061
2068
  def stats_graph # Visual graph mode for stats
2062
- puts "\n Command Usage Graph".c(@c_prompt).b
2069
+ puts "\n Command Usage Graph".c(@c_prompt).bd
2063
2070
  puts " " + "="*50
2064
2071
 
2065
2072
  return puts "No data to display" if @cmd_frequency.nil? || @cmd_frequency.empty?
@@ -2087,7 +2094,7 @@ def stats_graph # Visual graph mode for stats
2087
2094
 
2088
2095
  # Performance graph if data exists
2089
2096
  if @cmd_stats && !@cmd_stats.empty?
2090
- puts "\n Command Performance Graph (avg time)".c(@c_prompt).b
2097
+ puts "\n Command Performance Graph (avg time)".c(@c_prompt).bd
2091
2098
  puts " " + "="*50
2092
2099
  puts
2093
2100
 
@@ -2166,7 +2173,7 @@ def bm(arg_str = nil) # Enhanced bookmark management with tags
2166
2173
  puts "No bookmarks defined. Use :bm \"name\" to bookmark current directory"
2167
2174
  return
2168
2175
  end
2169
- puts "\n Bookmarks:".c(@c_prompt).b
2176
+ puts "\n Bookmarks:".c(@c_prompt).bd
2170
2177
  @bookmarks.each do |name, data|
2171
2178
  path = data.is_a?(Hash) ? data[:path] : data
2172
2179
  tags = data.is_a?(Hash) && data[:tags] ? " [#{data[:tags].join(', ')}]" : ""
@@ -2277,7 +2284,7 @@ def bookmark_stats # Show bookmark usage statistics
2277
2284
  return
2278
2285
  end
2279
2286
 
2280
- puts "\n Bookmark Statistics".c(@c_prompt).b
2287
+ puts "\n Bookmark Statistics".c(@c_prompt).bd
2281
2288
  puts " " + "="*50
2282
2289
  puts "\n Total bookmarks: #{@bookmarks.length}"
2283
2290
 
@@ -2382,7 +2389,7 @@ def list_sessions # List all saved sessions
2382
2389
  return
2383
2390
  end
2384
2391
 
2385
- puts "\n Saved Sessions:".c(@c_prompt).b
2392
+ puts "\n Saved Sessions:".c(@c_prompt).bd
2386
2393
  sessions.sort.each do |name|
2387
2394
  session_path = @session_dir + "/#{name}.json"
2388
2395
  begin
@@ -2437,7 +2444,7 @@ def theme(*args) # Apply color scheme presets
2437
2444
  name = args[0]
2438
2445
 
2439
2446
  if name.nil?
2440
- puts "\n Available themes:".c(@c_prompt).b
2447
+ puts "\n Available themes:".c(@c_prompt).bd
2441
2448
  puts " default, solarized, dracula, gruvbox, nord, monokai"
2442
2449
  puts "\n Current theme colors:"
2443
2450
  puts " prompt:#{' '*5}#{@c_prompt} cmd:#{' '*8}#{@c_cmd} nick:#{' '*7}#{@c_nick}"
@@ -2569,7 +2576,7 @@ def plugins(*args) # Plugin management command
2569
2576
  return
2570
2577
  end
2571
2578
 
2572
- puts "\n Available Plugins:".c(@c_prompt).b
2579
+ puts "\n Available Plugins:".c(@c_prompt).bd
2573
2580
  available_plugins.each do |name|
2574
2581
  if @plugin_enabled.include?(name)
2575
2582
  status = '[enabled]'.c(@c_path)
@@ -2608,7 +2615,7 @@ def plugins(*args) # Plugin management command
2608
2615
  plugin_name = args[1]
2609
2616
  plugin = @plugins.find { |p| p[:name] == plugin_name }
2610
2617
  if plugin
2611
- puts "\n Plugin: #{plugin_name}".c(@c_prompt).b
2618
+ puts "\n Plugin: #{plugin_name}".c(@c_prompt).bd
2612
2619
  puts " Class: #{plugin[:class]}"
2613
2620
  puts " File: #{@plugin_dir}/#{plugin_name}.rb"
2614
2621
 
@@ -2778,13 +2785,13 @@ def validate(rule_str = nil) # Custom validation rule management
2778
2785
  puts "Or try: :validate --templates"
2779
2786
  return
2780
2787
  end
2781
- puts "\n Validation Rules:".c(@c_prompt).b
2788
+ puts "\n Validation Rules:".c(@c_prompt).bd
2782
2789
  @validation_rules.each_with_index do |rule, i|
2783
2790
  puts " #{i+1}. #{rule[:pattern].inspect} → #{rule[:action]}"
2784
2791
  end
2785
2792
  puts
2786
2793
  elsif rule_str == '--templates'
2787
- puts "\n Common Validation Rule Templates:".c(@c_prompt).b
2794
+ puts "\n Common Validation Rule Templates:".c(@c_prompt).bd
2788
2795
  puts " Safety:"
2789
2796
  puts " :validate rm -rf / = block"
2790
2797
  puts " :validate DROP TABLE = block"
@@ -2876,7 +2883,7 @@ def completion_stats # Show completion learning statistics
2876
2883
  return
2877
2884
  end
2878
2885
 
2879
- puts "\n Completion Learning Statistics".c(@c_prompt).b
2886
+ puts "\n Completion Learning Statistics".c(@c_prompt).bd
2880
2887
  puts " " + "="*50
2881
2888
 
2882
2889
  # Group by context
@@ -2915,7 +2922,7 @@ def record(*args) # Command recording management
2915
2922
  return
2916
2923
  end
2917
2924
 
2918
- puts "\n Recordings:".c(@c_prompt).b
2925
+ puts "\n Recordings:".c(@c_prompt).bd
2919
2926
  @recordings.each do |rec_name, data|
2920
2927
  created = Time.at(data[:created] || Time.now.to_i).strftime("%Y-%m-%d %H:%M")
2921
2928
  count = data[:commands]&.length || 0
@@ -2962,7 +2969,7 @@ def record(*args) # Command recording management
2962
2969
  recording = @recordings[name]
2963
2970
  created = Time.at(recording[:created] || Time.now.to_i).strftime("%Y-%m-%d %H:%M:%S")
2964
2971
 
2965
- puts "\n Recording: #{name}".c(@c_prompt).b
2972
+ puts "\n Recording: #{name}".c(@c_prompt).bd
2966
2973
  puts " Created: #{created}"
2967
2974
  puts " Commands: #{recording[:commands].length}"
2968
2975
  puts
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-shell
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.19
4
+ version: 3.6.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-25 00:00:00.000000000 Z
11
+ date: 2026-04-11 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