# encoding: UTF-8 require 'set' module Earthquake module Input def input_filters @input_filters ||= [] end def input_filter(&block) input_filters << block end def commands @commands ||= [] end def command_names @command_names ||= Set.new end def completions @completions ||= [] end def completion(&block) completions << block end def input(text) begin reload rescue Exception => e error e end return if text.empty? begin input_filters.each { |f| text = f.call(text) } if command = command(text) command[:block].call(command[:pattern].match(text)) elsif !text.empty? puts "Command not found".c(43) end store_history rescue Exception => e error e end end def command(pattern, options = {}, &block) if block if pattern.is_a?(String) || pattern.is_a?(Symbol) command_name = ":#{pattern}" command_names << command_name if block.arity > 0 pattern = %r|^#{command_name}\s+(.*)$| else pattern = %r|^#{command_name}$| end end command_names << ":#{options[:as]}" if options[:as] commands << {:pattern => pattern, :block => block} else commands.detect {|c| c[:pattern] =~ pattern} end end def confirm(message, type = :y) case type when :y print "#{message} [Yn] ".u return !(gets.strip =~ /^n$/i) when :n print "#{message} [yN] ".u return !!(gets.strip =~ /^y$/i) else raise "type must be :y or :n" end end def async_e(&block) async { handle_api_error(&block) } end def handle_api_error(&block) result = block.call if result["error"] notify "[ERROR] #{result["error"]}" end end end init do commands.clear command_names.clear completions.clear input_filters.clear Readline.basic_word_break_characters = " \t\n\"\\'`$><=;|&{(@" Readline.completion_proc = lambda do |text| completions.inject([]) do |results, completion| begin results + (completion.call(text) || []) rescue Exception => e error e results end end end completion do |text| results = [] regexp = /^#{Regexp.quote(text)}/ results += command_names.grep(regexp) range = Readline::HISTORY.count >= 100 ? -100..-1 : 0..-1 results += Readline::HISTORY.to_a[range].map { |line| line.split(/\s+/) }.flatten.grep(regexp) results end input_filter do |text| if text =~ %r|^:| text.gsub(/\$\w+/) { |var| var2id(var) || var } else text end end end extend Input end