lib/birdwatcher/console.rb in birdwatcher-0.3.1 vs lib/birdwatcher/console.rb in birdwatcher-0.4.0

- old
+ new

@@ -1,36 +1,43 @@ module Birdwatcher class Console include Singleton DEFAULT_AUTO_COMPLETION_STRINGS = [].freeze - DB_MIGRATIONS_PATH = File.expand_path("../../../db/migrations", __FILE__).freeze - LINE_SEPARATOR = ("=" * 80).freeze + DB_MIGRATIONS_PATH = File.expand_path("../../../db/migrations", __FILE__).freeze + LINE_SEPARATOR = ("=" * 80).freeze + HISTORY_FILE_NAME = ".birdwatcher_history".freeze + HISTORY_FILE_LOCATION = File.join(Dir.home, HISTORY_FILE_NAME).freeze - attr_accessor :current_workspace, :current_module + attr_accessor :current_workspace, :current_module, :spool attr_reader :database def initialize @output_mutex = Mutex.new + @spool_mutex = Mutex.new end def start! print_banner bootstrap! Readline.completion_proc = proc do |s| expanded_s = File.expand_path(s) Birdwatcher::Console.instance.auto_completion_strings.grep(/\A#{Regexp.escape(s)}/) + Dir["#{expanded_s}*"].grep(/^#{Regexp.escape(expanded_s)}/) end Readline.completion_append_character = "" + load_command_history while input = Readline.readline(prompt_line, true) + save_to_spool(prompt_line) input = input.to_s.strip handle_input(input) unless input.empty? end end def handle_input(input) input.strip! + save_command_to_history(input) + save_to_spool("#{input}\n") command_name, argument_line = input.split(" ", 2).map(&:strip) command_name.downcase commands.each do |command| next unless command.has_name?(command_name) command.new.execute(argument_line) @@ -50,18 +57,19 @@ end def output(data, newline = true) data = "#{data}\n" if newline with_output_mutex { print data } + save_to_spool(data) end def output_formatted(*args) - with_output_mutex { printf(*args) } + output(sprintf(*args), false) end def newline - with_output_mutex { puts } + output "" end def line_separator output LINE_SEPARATOR end @@ -75,10 +83,11 @@ yield block output " done".bold.light_green rescue => e output " failed".bold.light_red error "#{e.class}: ".bold + e.message + e.backtrace.each { |l| error l } if debugging_enabled? exit(1) if fatal end def error(message) output "[-] ".bold.light_red + message @@ -90,10 +99,28 @@ def fatal(message) output "[-]".white.bold.on_red + " #{message}" end + def confirm(question) + question = "#{question} (y/n) " + save_to_spool(question) + if HighLine.agree("#{question}") + save_to_spool("y\n") + true + else + save_to_spool("n\n") + false + end + end + + def page_text(text) + save_to_spool(text) + ::TTY::Pager::SystemPager.new.page(text) + rescue Errno::EPIPE + end + def twitter_client if !@twitter_clients @twitter_clients = create_twitter_clients! end @twitter_clients.sample @@ -177,10 +204,14 @@ def with_output_mutex @output_mutex.synchronize { yield } end + def with_spool_mutex + @spool_mutex.synchronize { yield } + end + def create_twitter_clients! clients = [] configuration.get!(:twitter).each do |keypair| clients << Twitter::REST::Client.new do |config| config.consumer_key = keypair["consumer_key"] @@ -194,8 +225,44 @@ clients = [] configuration.get(:klout).each do |key| clients << Birdwatcher::KloutClient.new(key) end clients + end + + def load_command_history + if File.exist?(HISTORY_FILE_LOCATION) + if File.readable?(HISTORY_FILE_LOCATION) + File.open(HISTORY_FILE_LOCATION).each_line do |command| + Readline::HISTORY << command.strip + end + else + warn("Cannot load command history: #{HISTORY_FILE_LOCATION} is not readable") + end + end + end + + def save_command_to_history(command) + if File.exist?(HISTORY_FILE_LOCATION) && !File.writable?(HISTORY_FILE_LOCATION) + warn("Cannot save command to history: #{HISTORY_FILE_LOCATION} is not writable") + return + end + File.open(HISTORY_FILE_LOCATION, "a") do |file| + file.puts(command) + end + end + + def save_to_spool(string) + return unless spool_enabled? + string = string.to_s.uncolorize + with_spool_mutex { self.spool.write(string) } + end + + def spool_enabled? + self.spool && self.spool.is_a?(File) + end + + def debugging_enabled? + ENV.key?("BIRDWATCHER_DEBUG") end end end