require 'hammer_cli/abstract' require 'readline' module HammerCLI class ShellMainCommand < AbstractCommand class HelpCommand < AbstractCommand command_name "help" desc _("Print help for commands") parameter "[COMMAND] ...", "command" def execute ShellMainCommand.run('', command_list << '-h') HammerCLI::EX_OK end end class ExitCommand < AbstractCommand command_name "exit" desc _("Exit interactive shell") def execute exit HammerCLI::EX_OK end end def self.load_commands(main_cls) cmds = main_cls.recognised_subcommands.select do |sub_cmd| !sub_cmd.is_called?("shell") end self.recognised_subcommands.push(*cmds) end autoload_subcommands end class ShellHistory def initialize(history_file_path) @file_path = history_file_path load end def push(line) line.strip! return if line.empty? or ingonred_commands.include?(line) Readline::HISTORY.push(line) File.open(file_path, "a") do |f| f.puts(line) end end def ingonred_commands ["exit"] end protected def file_path File.expand_path(@file_path) end def load if File.exist?(file_path) File.readlines(file_path).each do |line| Readline::HISTORY.push(line.strip) end end end end class ShellCommand < AbstractCommand DEFAULT_HISTORY_FILE = "~/.hammer_history" def execute ShellMainCommand.load_commands(HammerCLI::MainCommand) if RUBY_VERSION >= "1.9" Readline.completion_append_character = '' Readline.completer_word_break_characters = ' =' Readline.completion_proc = complete_proc else Readline.completion_proc = lambda {} end stty_save = `stty -g`.chomp history = ShellHistory.new(Settings.get(:ui, :history_file) || DEFAULT_HISTORY_FILE) begin print_welcome_message while line = Readline.readline(prompt) history.push(line) line = HammerCLI::CompleterLine.new(line) ShellMainCommand.run('', line, context) unless line.empty? end rescue Interrupt; end puts system('stty', stty_save) # Restore HammerCLI::EX_OK end private def prompt 'hammer> ' end def print_welcome_message print_message(_("Welcome to the hammer interactive shell")) print_message(_("Type 'help' for usage information")) print_message(_("Command completion is disabled on ruby < 1.9 due to compatibility problems.")) if RUBY_VERSION < "1.9" end def common_prefix(results) results.delete_if{ |r| !r[0].start_with?(results[0][0][0]) }.length == results.length end def complete_proc completer = Completer.new(ShellMainCommand) Proc.new do |last_word| completer.complete(Readline.line_buffer) end end end HammerCLI::MainCommand.subcommand "shell", _("Interactive shell"), HammerCLI::ShellCommand end