ruby-shell 3.4.9 → 3.5.0
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/bin/rsh +117 -16
- metadata +4 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: bac3cf4ea368be8c2991ee650e1977c7fafd7b1548645c1e3daaa94fd29bae2d
         | 
| 4 | 
            +
              data.tar.gz: 31b8ae6ffcf460c7a236c72c8188254243879ab8b83ac690fcf8e61fc0aa46ad
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: bb8eb4cef6df5403bc751cf29d440a4289877fd9f7684f153e82196a3f24e425f88fabbe2ccae63c0ef108cae205feb241e84b52f138ad07975d03bd38834a7b
         | 
| 7 | 
            +
              data.tar.gz: 96eb9e448ffd6c20b469e1b0d0f11e7f8dc274e809c4cc543dea3aa7ff5b5a5121a1aae6de7522cb3af1b3ff59e8e655df7af68ed54322f96844c5df910b4904
         | 
    
        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. | 
| 11 | 
            +
            @version    = "3.5.0" # Polish release: Nick/history export, default nicks, expanded completions, startup tips, validation templates
         | 
| 12 12 |  | 
| 13 13 | 
             
            # MODULES, CLASSES AND EXTENSIONS
         | 
| 14 14 | 
             
            class String # Add coloring to strings (with escaping for Readline)
         | 
| @@ -137,8 +137,18 @@ begin # Initialization | |
| 137 137 | 
             
                "cargo" => %w[build run test check clean doc new init add search publish install update],
         | 
| 138 138 | 
             
                "npm" => %w[install uninstall update run build test start init publish],
         | 
| 139 139 | 
             
                "gem" => %w[install uninstall update list search build push],
         | 
| 140 | 
            -
                "bundle" => %w[install update exec check config]
         | 
| 140 | 
            +
                "bundle" => %w[install update exec check config],
         | 
| 141 | 
            +
                "kubectl" => %w[get describe create delete apply edit logs exec port-forward scale rollout top explain diff patch],
         | 
| 142 | 
            +
                "terraform" => %w[init plan apply destroy import output show],
         | 
| 143 | 
            +
                "aws" => %w[s3 ec2 lambda cloudformation iam rds dynamodb sns sqs],
         | 
| 144 | 
            +
                "brew" => %w[install uninstall update upgrade search info list],
         | 
| 145 | 
            +
                "yarn" => %w[add remove install build test start init],
         | 
| 146 | 
            +
                "make" => %w[clean install build test all],
         | 
| 147 | 
            +
                "ansible" => %w[playbook galaxy vault inventory],
         | 
| 148 | 
            +
                "poetry" => %w[add remove install update build publish],
         | 
| 149 | 
            +
                "pipenv" => %w[install uninstall update shell run]
         | 
| 141 150 | 
             
              }
         | 
| 151 | 
            +
              @show_tips = true                           # Show startup tips (configurable)
         | 
| 142 152 | 
             
              # New v3.0 features initialization
         | 
| 143 153 | 
             
              @switch_cache = {}                      # Cache for command switches from --help
         | 
| 144 154 | 
             
              @switch_cache_time = {}                 # Timestamp for cache expiry
         | 
| @@ -277,7 +287,9 @@ def firstrun | |
| 277 287 | 
             
              @completion_show_descriptions = false # Show help text inline
         | 
| 278 288 | 
             
              @completion_fuzzy = true            # Enable fuzzy matching
         | 
| 279 289 |  | 
| 280 | 
            -
              @nick = { | 
| 290 | 
            +
              @nick = {
         | 
| 291 | 
            +
                "ls" => "ls --color -F"
         | 
| 292 | 
            +
              }
         | 
| 281 293 | 
             
            RSHRC
         | 
| 282 294 | 
             
              File.write(Dir.home+'/.rshrc', rc)
         | 
| 283 295 | 
             
            end
         | 
| @@ -1063,11 +1075,25 @@ def suggest_command(cmd) # Smart command suggestions for typos | |
| 1063 1075 | 
             
              return nil if cmd.nil? || cmd.empty?
         | 
| 1064 1076 | 
             
              return nil if @exe.include?(cmd) || @nick.include?(cmd)
         | 
| 1065 1077 |  | 
| 1078 | 
            +
              max_dist = [cmd.length / 3, 2].max
         | 
| 1079 | 
            +
             | 
| 1080 | 
            +
              # Pre-filter by length and first letter (huge optimization for large @exe)
         | 
| 1081 | 
            +
              length_range = (cmd.length - max_dist)..(cmd.length + max_dist)
         | 
| 1082 | 
            +
              first_letter = cmd[0]
         | 
| 1083 | 
            +
             | 
| 1084 | 
            +
              # Filter: similar length AND (same first letter OR within 1 char distance)
         | 
| 1085 | 
            +
              pool = (@exe + @nick.keys).select do |c|
         | 
| 1086 | 
            +
                c.length >= 2 &&
         | 
| 1087 | 
            +
                length_range.include?(c.length) &&
         | 
| 1088 | 
            +
                (c[0] == first_letter || (c[0].ord - first_letter.ord).abs <= 1)
         | 
| 1089 | 
            +
              end
         | 
| 1090 | 
            +
             | 
| 1091 | 
            +
              # Hard limit to prevent any hang
         | 
| 1092 | 
            +
              pool = pool.first(100)
         | 
| 1093 | 
            +
             | 
| 1066 1094 | 
             
              # Find commands with small edit distance
         | 
| 1067 | 
            -
              candidates =  | 
| 1068 | 
            -
                next false if c.length < 2
         | 
| 1095 | 
            +
              candidates = pool.select do |c|
         | 
| 1069 1096 | 
             
                dist = levenshtein_distance(cmd, c)
         | 
| 1070 | 
            -
                max_dist = [cmd.length / 3, 2].max
         | 
| 1071 1097 | 
             
                dist <= max_dist && dist > 0
         | 
| 1072 1098 | 
             
              end
         | 
| 1073 1099 |  | 
| @@ -1115,6 +1141,7 @@ def config(*args) # Configure rsh settings | |
| 1115 1141 | 
             
                puts "    auto_correct:       #{@auto_correct ? 'on' : 'off'}"
         | 
| 1116 1142 | 
             
                puts "    slow_command_threshold: #{@slow_command_threshold}s #{@slow_command_threshold > 0 ? '(enabled)' : '(disabled)'}"
         | 
| 1117 1143 | 
             
                puts "    completion_learning: #{@completion_learning ? 'on' : 'off'}"
         | 
| 1144 | 
            +
                puts "    show_tips:          #{@show_tips ? 'on' : 'off'}"
         | 
| 1118 1145 | 
             
                puts "    completion_limit:   #{@completion_limit}"
         | 
| 1119 1146 | 
             
                puts "    completion_fuzzy:   #{@completion_fuzzy}"
         | 
| 1120 1147 | 
             
                puts "    completion_case_sensitive: #{@completion_case_sensitive}"
         | 
| @@ -1155,9 +1182,13 @@ def config(*args) # Configure rsh settings | |
| 1155 1182 | 
             
                @completion_show_metadata = %w[on true yes 1].include?(value.to_s.downcase)
         | 
| 1156 1183 | 
             
                puts "Completion metadata display #{@completion_show_metadata ? 'enabled' : 'disabled'}"
         | 
| 1157 1184 | 
             
                rshrc
         | 
| 1185 | 
            +
              when 'show_tips'
         | 
| 1186 | 
            +
                @show_tips = %w[on true yes 1].include?(value.to_s.downcase)
         | 
| 1187 | 
            +
                puts "Startup tips #{@show_tips ? 'enabled' : 'disabled'}"
         | 
| 1188 | 
            +
                rshrc
         | 
| 1158 1189 | 
             
              else
         | 
| 1159 1190 | 
             
                puts "Unknown setting '#{setting}'"
         | 
| 1160 | 
            -
                puts "Available: history_dedup, session_autosave, auto_correct, slow_command_threshold, completion_learning,  | 
| 1191 | 
            +
                puts "Available: history_dedup, session_autosave, auto_correct, slow_command_threshold, completion_learning, show_tips, completion_limit"
         | 
| 1161 1192 | 
             
              end
         | 
| 1162 1193 | 
             
            end
         | 
| 1163 1194 | 
             
            def env(*args) # Environment variable management
         | 
| @@ -1588,15 +1619,38 @@ def help | |
| 1588 1619 | 
             
              end
         | 
| 1589 1620 | 
             
              puts
         | 
| 1590 1621 | 
             
            end
         | 
| 1591 | 
            -
            def info
         | 
| 1592 | 
            -
               | 
| 1622 | 
            +
            def info(*args)
         | 
| 1623 | 
            +
              option = args[0]
         | 
| 1624 | 
            +
             | 
| 1625 | 
            +
              if option == '--quick'
         | 
| 1626 | 
            +
                puts "\nrsh v#{@version} - Ruby SHell"
         | 
| 1627 | 
            +
                puts "Type :help for commands, :info for full intro"
         | 
| 1628 | 
            +
              elsif option == '--features'
         | 
| 1629 | 
            +
                puts "\nKey Features:"
         | 
| 1630 | 
            +
                puts "• Nicks (aliases) with {{parameters}}"
         | 
| 1631 | 
            +
                puts "• Completion learning (adapts to you)"
         | 
| 1632 | 
            +
                puts "• Command recording & replay"
         | 
| 1633 | 
            +
                puts "• Plugin system"
         | 
| 1634 | 
            +
                puts "• Stats & analytics"
         | 
| 1635 | 
            +
                puts "• 6 color themes"
         | 
| 1636 | 
            +
                puts "• AI integration"
         | 
| 1637 | 
            +
                puts "Type :help for details"
         | 
| 1638 | 
            +
              else
         | 
| 1639 | 
            +
                puts @info
         | 
| 1640 | 
            +
              end
         | 
| 1593 1641 | 
             
            end
         | 
| 1594 1642 | 
             
            def version
         | 
| 1595 1643 | 
             
              puts "rsh version = #{@version} (latest RubyGems version is #{Gem.latest_version_for("ruby-shell").version} - https://github.com/isene/rsh)"
         | 
| 1596 1644 | 
             
            end
         | 
| 1597 | 
            -
            def history # Show most recent history (up to 50 entries)
         | 
| 1598 | 
            -
               | 
| 1599 | 
            -
             | 
| 1645 | 
            +
            def history(*args) # Show most recent history (up to 50 entries)
         | 
| 1646 | 
            +
              if args[0] == '--export'
         | 
| 1647 | 
            +
                filename = args[1] || 'history.txt'
         | 
| 1648 | 
            +
                File.write(filename, @history.join("\n"))
         | 
| 1649 | 
            +
                puts "History exported to #{filename} (#{@history.length} commands)"
         | 
| 1650 | 
            +
              else
         | 
| 1651 | 
            +
                puts "History:"
         | 
| 1652 | 
            +
                @history.each_with_index {|h,i| puts i.to_s + "; " + h if i < 50}
         | 
| 1653 | 
            +
              end
         | 
| 1600 1654 | 
             
            end
         | 
| 1601 1655 | 
             
            def rmhistory # Delete history
         | 
| 1602 1656 | 
             
              @history = []
         | 
| @@ -1620,6 +1674,19 @@ def nick(nick_str = nil)  # Define a new nick like this: `:nick "ls = ls --color | |
| 1620 1674 | 
             
                  @nick.sort.each {|key, value| puts "  #{key.c(@c_nick)} = #{value}"}
         | 
| 1621 1675 | 
             
                end
         | 
| 1622 1676 | 
             
                puts
         | 
| 1677 | 
            +
              elsif nick_str =~ /^--export\s*(.*)/
         | 
| 1678 | 
            +
                filename = $1.strip.empty? ? 'nicks.json' : $1.strip
         | 
| 1679 | 
            +
                require 'json' unless defined?(JSON)
         | 
| 1680 | 
            +
                File.write(filename, JSON.pretty_generate(@nick))
         | 
| 1681 | 
            +
                puts "Nicks exported to #{filename}"
         | 
| 1682 | 
            +
              elsif nick_str =~ /^--import\s+(.*)/
         | 
| 1683 | 
            +
                filename = $1.strip
         | 
| 1684 | 
            +
                return puts "File '#{filename}' not found" unless File.exist?(filename)
         | 
| 1685 | 
            +
                require 'json' unless defined?(JSON)
         | 
| 1686 | 
            +
                imported = JSON.parse(File.read(filename))
         | 
| 1687 | 
            +
                imported.each { |k, v| @nick[k] = v }
         | 
| 1688 | 
            +
                puts "Imported #{imported.length} nicks"
         | 
| 1689 | 
            +
                rshrc
         | 
| 1623 1690 | 
             
              elsif nick_str.match(/^\s*-/)
         | 
| 1624 1691 | 
             
                source = nick_str.sub(/^\s*-/, '')
         | 
| 1625 1692 | 
             
                if @nick.delete(source)
         | 
| @@ -2537,10 +2604,10 @@ def calc(*args) # Inline calculator using Ruby's Math library | |
| 2537 2604 | 
             
              rescue ZeroDivisionError
         | 
| 2538 2605 | 
             
                puts "Error: Division by zero"
         | 
| 2539 2606 | 
             
              rescue NameError => e
         | 
| 2540 | 
            -
                # Extract the undefined name
         | 
| 2541 | 
            -
                if e.message =~ /undefined  | 
| 2607 | 
            +
                # Extract the undefined name (sandbox format)
         | 
| 2608 | 
            +
                if e.message =~ /undefined method `(\w+)'/
         | 
| 2542 2609 | 
             
                  undefined = $1
         | 
| 2543 | 
            -
                  puts "Error: Unknown function  | 
| 2610 | 
            +
                  puts "Error: Unknown function '#{undefined}'"
         | 
| 2544 2611 | 
             
                  puts "Available Math functions: sqrt, sin, cos, tan, log, exp, abs, ceil, floor, round"
         | 
| 2545 2612 | 
             
                  puts "Constants: PI, E"
         | 
| 2546 2613 | 
             
                else
         | 
| @@ -2564,6 +2631,7 @@ def validate(rule_str = nil) # Custom validation rule management | |
| 2564 2631 | 
             
                  puts "\nNo validation rules defined"
         | 
| 2565 2632 | 
             
                  puts "Usage: :validate pattern = action"
         | 
| 2566 2633 | 
             
                  puts "Actions: block, confirm, warn, log"
         | 
| 2634 | 
            +
                  puts "Or try: :validate --templates"
         | 
| 2567 2635 | 
             
                  return
         | 
| 2568 2636 | 
             
                end
         | 
| 2569 2637 | 
             
                puts "\n  Validation Rules:".c(@c_prompt).b
         | 
| @@ -2571,6 +2639,21 @@ def validate(rule_str = nil) # Custom validation rule management | |
| 2571 2639 | 
             
                  puts "  #{i+1}. #{rule[:pattern].inspect} → #{rule[:action]}"
         | 
| 2572 2640 | 
             
                end
         | 
| 2573 2641 | 
             
                puts
         | 
| 2642 | 
            +
              elsif rule_str == '--templates'
         | 
| 2643 | 
            +
                puts "\n  Common Validation Rule Templates:".c(@c_prompt).b
         | 
| 2644 | 
            +
                puts "  Safety:"
         | 
| 2645 | 
            +
                puts "    :validate rm -rf / = block"
         | 
| 2646 | 
            +
                puts "    :validate DROP TABLE = block"
         | 
| 2647 | 
            +
                puts "  Confirmation:"
         | 
| 2648 | 
            +
                puts "    :validate git push --force = confirm"
         | 
| 2649 | 
            +
                puts "    :validate npm publish = confirm"
         | 
| 2650 | 
            +
                puts "  Warnings:"
         | 
| 2651 | 
            +
                puts "    :validate sudo = warn"
         | 
| 2652 | 
            +
                puts "    :validate chmod 777 = warn"
         | 
| 2653 | 
            +
                puts "  Logging:"
         | 
| 2654 | 
            +
                puts "    :validate npm install = log"
         | 
| 2655 | 
            +
                puts "    :validate pip install = log"
         | 
| 2656 | 
            +
                puts
         | 
| 2574 2657 | 
             
              elsif rule_str =~ /^-(\d+)$/
         | 
| 2575 2658 | 
             
                # Delete rule by index
         | 
| 2576 2659 | 
             
                index = $1.to_i - 1
         | 
| @@ -3395,6 +3478,20 @@ loop do | |
| 3395 3478 | 
             
                unless @plugins_loaded
         | 
| 3396 3479 | 
             
                  load_plugins
         | 
| 3397 3480 | 
             
                  @plugins_loaded = true
         | 
| 3481 | 
            +
                  # Show startup tip (30% chance, if enabled)
         | 
| 3482 | 
            +
                  if @show_tips && rand < 0.3
         | 
| 3483 | 
            +
                    tips = [
         | 
| 3484 | 
            +
                      "Tip: Use :nick gp={{branch}} for parametrized aliases!",
         | 
| 3485 | 
            +
                      "Tip: Press Ctrl-G to edit commands in $EDITOR",
         | 
| 3486 | 
            +
                      "Tip: :stats --graph shows visual analytics",
         | 
| 3487 | 
            +
                      "Tip: :record your workflows and :replay them later",
         | 
| 3488 | 
            +
                      "Tip: :validate rm -rf / = block for safety rules",
         | 
| 3489 | 
            +
                      "Tip: :completion_stats shows what you use most",
         | 
| 3490 | 
            +
                      "Tip: Type :help for quick reference",
         | 
| 3491 | 
            +
                      "Tip: Disable tips with: :config show_tips off"
         | 
| 3492 | 
            +
                    ]
         | 
| 3493 | 
            +
                    puts tips.sample.c(244)
         | 
| 3494 | 
            +
                  end
         | 
| 3398 3495 | 
             
                end
         | 
| 3399 3496 | 
             
                # Build display prompt with plugin additions (don't modify @prompt)
         | 
| 3400 3497 | 
             
                plugin_prompts = call_plugin_hook(:on_prompt)
         | 
| @@ -3622,11 +3719,12 @@ loop do | |
| 3622 3719 | 
             
                        puts "Bookmark '#{@cmd}' points to non-existent directory: #{bm_dir}".c(196)
         | 
| 3623 3720 | 
             
                      end
         | 
| 3624 3721 | 
             
                    else
         | 
| 3625 | 
            -
                      puts "#{Time.now.strftime("%H:%M:%S")}: #{@cmd}".c(@c_stamp)
         | 
| 3626 3722 | 
             
                      if @cmd == "f" # fzf integration (https://github.com/junegunn/fzf)
         | 
| 3723 | 
            +
                        puts "#{Time.now.strftime("%H:%M:%S")}: #{@cmd}".c(@c_stamp)
         | 
| 3627 3724 | 
             
                        res = `fzf`.chomp
         | 
| 3628 3725 | 
             
                        Dir.chdir(File.dirname(res))
         | 
| 3629 3726 | 
             
                      elsif File.exist?(@cmd) and not File.executable?(@cmd) and not @cmd.include?(" ")
         | 
| 3727 | 
            +
                        puts "#{Time.now.strftime("%H:%M:%S")}: #{@cmd}".c(@c_stamp)
         | 
| 3630 3728 | 
             
                        # Only auto-open files if it's a single filename (no spaces = no command with args)
         | 
| 3631 3729 | 
             
                        if File.read(@cmd).force_encoding("UTF-8").valid_encoding?
         | 
| 3632 3730 | 
             
                          system("#{ENV['EDITOR']} #{@cmd}") # Try open with user's editor
         | 
| @@ -3644,6 +3742,9 @@ loop do | |
| 3644 3742 | 
             
                          # Apply auto-correct if enabled (before validation)
         | 
| 3645 3743 | 
             
                          @cmd = apply_auto_correct(@cmd)
         | 
| 3646 3744 |  | 
| 3745 | 
            +
                          # Print timestamp AFTER auto-correct (shows what actually executes)
         | 
| 3746 | 
            +
                          puts "#{Time.now.strftime("%H:%M:%S")}: #{@cmd}".c(@c_stamp)
         | 
| 3747 | 
            +
             | 
| 3647 3748 | 
             
                          # Validate command after auto-correction
         | 
| 3648 3749 | 
             
                          warnings = validate_command(@cmd)
         | 
| 3649 3750 | 
             
                          if warnings && !warnings.empty?
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: ruby-shell
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 3. | 
| 4 | 
            +
              version: 3.5.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Geir Isene
         | 
| @@ -12,9 +12,9 @@ date: 2025-10-30 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. | 
| 16 | 
            -
               | 
| 17 | 
            -
               | 
| 15 | 
            +
              v3.5.0: Nick/history export, 9 new tool completions (kubectl, terraform, aws, brew,
         | 
| 16 | 
            +
              etc.), validation templates, startup tips, improved :info, aggressive suggest_command
         | 
| 17 | 
            +
              optimization for huge PATHs (18K+ executables), timestamp shows corrected commands!'
         | 
| 18 18 | 
             
            email: g@isene.com
         | 
| 19 19 | 
             
            executables:
         | 
| 20 20 | 
             
            - rsh
         |