lib/rex/ui/text/dispatcher_shell.rb in librex-0.0.6 vs lib/rex/ui/text/dispatcher_shell.rb in librex-0.0.7

- old
+ new

@@ -1,6 +1,7 @@ require 'rex/ui' +require 'pp' module Rex module Ui module Text @@ -78,23 +79,85 @@ def update_prompt(prompt=nil) shell.update_prompt(prompt) end # + # Displays the help banner. With no arguments, this is just a list of + # all commands grouped by dispatcher. Otherwise, tries to use a method + # named cmd_#{+cmd+}_help for the first dispatcher that has a command + # named +cmd+. + # + def cmd_help(cmd=nil, *ignored) + if cmd + help_found = false + cmd_found = false + shell.dispatcher_stack.each do |dispatcher| + next unless dispatcher.respond_to?(:commands) + next if (dispatcher.commands.nil?) + next if (dispatcher.commands.length == 0) + + if dispatcher.respond_to?("cmd_#{cmd}") + cmd_found = true + break unless dispatcher.respond_to? "cmd_#{cmd}_help" + dispatcher.send("cmd_#{cmd}_help") + help_found = true + break + end + end + print_error("No help for #{cmd}, try -h") if cmd_found and not help_found + print_error("No such command") if not cmd_found + else + print(shell.help_to_s) + end + end + + # + # Tab completion for the help command + # + # By default just returns a list of all commands in all dispatchers. + # + def cmd_help_tabs(str, words) + return [] if words.length > 1 + + tabs = [] + shell.dispatcher_stack.each { |dispatcher| + tabs += dispatcher.commands.keys + } + return tabs + end + + alias cmd_? cmd_help + + + # # No tab completion items by default # attr_accessor :shell, :tab_complete_items + # + # Provide a generic tab completion for file names. + # + # If the only completion is a directory, this descends into that directory + # and continues completions with filenames contained within. + # + def tab_complete_filenames(str, words) + matches = ::Readline::FILENAME_COMPLETION_PROC.call(str) + if matches and matches.length == 1 and File.directory?(matches[0]) + dir = matches[0] + dir += File::SEPARATOR if dir[-1,1] != File::SEPARATOR + matches = ::Readline::FILENAME_COMPLETION_PROC.call(dir) + end + matches + end + end # # DispatcherShell derives from shell. # include Shell - attr_accessor :on_command_proc - # # Initialize the dispatcher shell. # def initialize(prompt, prompt_char = '>', histfile = nil) super @@ -146,24 +209,26 @@ # Enumerate each entry in the dispatcher stack dispatcher_stack.each { |dispatcher| # If no command is set and it supports commands, add them all if (tab_words.empty? and dispatcher.respond_to?('commands')) - items.concat(dispatcher.commands.to_a.map { |x| x[0] }) + items.concat(dispatcher.commands.keys) end # If the dispatcher exports a tab completion function, use it if(dispatcher.respond_to?('tab_complete_helper')) res = dispatcher.tab_complete_helper(str, tab_words) + else + res = tab_complete_helper(dispatcher, str, tab_words) + end - if (res.nil?) - # A nil response indicates no optional arguments - return [''] if items.empty? - else - # Otherwise we add the completion items to the list - items.concat(res) - end + if (res.nil?) + # A nil response indicates no optional arguments + return [''] if items.empty? + else + # Otherwise we add the completion items to the list + items.concat(res) end } # Verify that our search string is a valid regex begin @@ -180,9 +245,29 @@ e =~ /^#{str}/ # Prepend the rest of the command (or it gets replaced!) }.map { |e| tab_words.dup.push(e).join(' ') } + end + + # + # Provide command-specific tab completion + # + def tab_complete_helper(dispatcher, str, words) + items = [] + + tabs_meth = "cmd_#{words[0]}_tabs" + # Is the user trying to tab complete one of our commands? + if (dispatcher.commands.include?(words[0]) and dispatcher.respond_to?(tabs_meth)) + res = dispatcher.send(tabs_meth, str, words) + return [] if res.nil? + items.concat(res) + else + # Avoid the default completion list for known commands + return [] + end + + return items end # # Run a single command line. #