lib/guard/interactors/readline.rb in guard-1.1.1 vs lib/guard/interactors/readline.rb in guard-1.2.0

- old
+ new

@@ -1,110 +1,88 @@ module Guard + autoload :TerminalHelper, 'guard/interactors/helpers/terminal' + autoload :CompletionHelper, 'guard/interactors/helpers/completion' + autoload :UI, 'guard/ui' + # Interactor that used readline for getting the user input. # This enables history support and auto-completion, but is # broken on OS X without installing `rb-readline` or using JRuby. # # @see http://bugs.ruby-lang.org/issues/5539 # class ReadlineInteractor < Interactor + include ::Guard::CompletionHelper + include ::Guard::TerminalHelper - COMPLETION_ACTIONS = %w[help reload exit pause notification] + # Test if the Interactor is + # available in the current environment? + # + # @param [Boolean] silent true if no error messages should be shown + # @return [Boolean] the availability status + # + def self.available?(silent = false) + require 'readline' + if defined?(RbReadline) || defined?(JRUBY_VERSION) || RbConfig::CONFIG['target_os'] =~ /linux/i + true + else + ::Guard::UI.error 'The :readline interactor runs only fine on JRuby, Linux or with the gem \'rb-readline\' installed.' unless silent + false + end + end + # Initialize the interactor. # def initialize require 'readline' - unless defined?(RbReadline) || defined?(JRUBY_VERSION) || RbConfig::CONFIG['target_os'] =~ /linux/i - ::Guard::UI.info 'Please add rb-readline for proper Readline support.' - end - Readline.completion_proc = proc { |word| auto_complete(word) } begin Readline.completion_append_character = ' ' rescue NotImplementedError # Ignore, we just don't support it then end end - # Start the interactor. - # - def start - store_terminal_settings if stty_exists? - super - end - # Stop the interactor. # def stop + # Erase the current line for Ruby Readline + if Readline.respond_to?(:refresh_line) + Readline.refresh_line + end + + # Erase the current line for Rb-Readline + if defined?(RbReadline) && RbReadline.rl_outstream + RbReadline._rl_erase_entire_line + end + super - restore_terminal_settings if stty_exists? end - + # Read a line from stdin with Readline. # def read_line + require 'readline' + while line = Readline.readline(prompt, true) line.gsub!(/^\W*/, '') if line =~ /^\s*$/ or Readline::HISTORY.to_a[-2] == line Readline::HISTORY.pop end process_input(line) end end - # Auto complete the given word. - # - # @param [String] word the partial word - # @return [Array<String>] the matching words - # - def auto_complete(word) - completion_list.grep(/^#{ Regexp.escape(word) }/) - end - - # Get the auto completion list. - # - # @return [Array<String>] the list of words - # - def completion_list - groups = ::Guard.groups.map { |group| group.name.to_s } - guards = ::Guard.guards.map { |guard| guard.class.to_s.downcase.sub('guard::', '') } - - COMPLETION_ACTIONS + groups + guards - ['default'] - end - # The current interactor prompt # # @return [String] the prompt to show # def prompt ::Guard.listener.paused? ? 'p> ' : '> ' end - private - - # Detects whether or not the stty command exists - # on the user machine. - # - # @return [Boolean] the status of stty - # - def stty_exists? - system('hash', 'stty') - end - - # Stores the terminal settings so we can resore them - # when stopping. - # - def store_terminal_settings - @stty_save = `stty -g 2>/dev/null`.chomp - end - - # Restore terminal settings - # - def restore_terminal_settings - system('stty', @stty_save, '2>/dev/null') - end end end