bin/restfully in restfully-0.8.8 vs bin/restfully in restfully-1.0.0.rc1

- old
+ new

@@ -3,122 +3,172 @@ require 'restfully' require 'optparse' require 'logger' require 'pp' +require 'ripl' +require 'ripl/multi_line' # Behaviour of pp in IRB is different on ruby1.9: # * pp(object) returns object#inspect. # * we prefer the behaviour of ruby1.8 where pp returns nil. -alias :old_pp :pp +alias :old_pp :pp def pp(*args) old_pp(*args); nil end logger = Logger.new(STDERR) logger.level = Logger::WARN -@options = {"logger" => logger} +OPTIONS = {"logger" => logger, "shell" => false} + +Ripl.config[:play_quiet] = true +Ripl.config[:play_input] = false + option_parser = OptionParser.new do |opts| opts.banner = <<BANNER * Description Restfully #{Restfully::VERSION} - Access REST APIs effortlessly * Usage - restfully [uri] [options] -* Options + restfully [options] [FILE] + + If FILE is given and is an HTTP URI or a local file, the content of that file will be executed in the context of the Restfully session. It can also be read from STDIN. + If no FILE is given, then an interactive shell will be launched in the context of the Restfully session. BANNER - opts.on("-u=", "--username=", "Sets the username") do |u| - @options["username"] = u + opts.separator "" + opts.separator "* Common options" + opts.on("--uri=", "Sets the base URI") do |v| + OPTIONS["uri"] = v end - opts.on("-p=", "--password=", "Sets the user password") do |p| - @options["password"] = p + opts.on("-u=", "--username=", "Sets the username (Basic Authentication)") do |u| + OPTIONS["username"] = u end - opts.on("-c=", "--config=", "Sets the various options based on a custom YAML configuration file") do |v| - @options["configuration_file"] = v + opts.on("-p=", "--password=", "Sets the password (Basic Authentication)") do |p| + OPTIONS["password"] = p end + opts.on("-c=", "--config=", "Load options from a custom YAML configuration file") do |v| + OPTIONS["configuration_file"] = v + end opts.on("-r=", "--require=", "Require an additional media-type") do |v| - @options["require"] ||= [] - @options["require"].push(v) + OPTIONS["require"] ||= [] + OPTIONS["require"].push(v) end - opts.on("--log=", "Outputs log messages to the given file. Defaults to stdout") do |v| + opts.on("--log=", "Outputs log messages to the given file. Defaults to STDERR") do |v| original_logger_level = logger.level - logger = Logger.new(File.expand_path(v)) + @log_file = File.open(File.expand_path(v), "w+") + STDERR.sync = true + STDERR.reopen(@log_file) + logger = Logger.new(@log_file) logger.level = original_logger_level - @options["logger"] = logger + OPTIONS["logger"] = logger end opts.on("--no-cache", "Disable client-side caching") do |v| - @options["cache"] = false + OPTIONS["cache"] = false end + opts.on("--color", "Color output") do |v| + require 'ripl/color_streams' + require 'ripl/color_result' + end + opts.on("--record [SESSION_FILE]", "Record interactive session into SESSION_FILE (default=#{Restfully::DEFAULT_TAPE}), to be replayed later. This option is ignored if FILE is given.") do |v| + OPTIONS["record"] = v || Restfully::DEFAULT_TAPE + end opts.on("-v", "--verbose", "Run verbosely") do |v| - @options["logger"].level = Logger::INFO + OPTIONS["logger"].level = Logger::INFO end opts.on("--debug", "Run in debug mode") do |v| - @options["logger"].level = Logger::DEBUG + OPTIONS["logger"].level = Logger::DEBUG end + + opts.separator "" + opts.separator "* Options specific to FILE" + opts.on("--replay", "Display the FILE input line by line, and the result of each command") do |v| + Ripl.config[:play_input] = true + Ripl.config[:play_quiet] = false + end + opts.on("--shell", "Start an interactive session even after FILE content has been executed") do |v| + OPTIONS["shell"] = true + end + opts.on("-i", "--install", "Ask to install any gem that might be required in FILE") do |v| + Ripl.config[:play_install] = true + end + + opts.separator "" + opts.separator "* Other" opts.on_tail("-h", "--help", "Show this message") do puts opts exit end - -end + opts.on_tail("--version", "Show version") do + puts Restfully::VERSION + exit + end +end.parse! -option_parser.parse! +# Declare original Restfully::Session +@session = Restfully::Session.new(OPTIONS) -if given_uri = ARGV.shift - @options["uri"] = given_uri -end +if $stdin.tty? && !ARGV[0] + # Interactive session + puts "Restfully/#{Restfully::VERSION} - The root resource is available in the 'root' variable." + if OPTIONS["record"] + # Recording requested + require 'ripl/record' + Ripl.config[:play] = OPTIONS["record"] + end +else + # Replayed session + @session.logger.warn "--record option valid only with interactive session. Ignoring." if OPTIONS["record"] + require 'ripl/play' -@session = Restfully::Session.new(@options) - -def session; @session; end - -def root - @root ||= session.root + module Ripl::Play + # Overwrite #get_input so that it does not display the input if not + # required. + def get_input + puts(prompt + @play_input) if Ripl.config[:play_input] + @play_input + end + end + + module Ripl::PlayWithoutWhitespace + # Remove empty lines when replaying + def play_back_string(str) + str.gsub!(/^\s*\n+/, '') + super(str) + end + end + Ripl::Shell.include Ripl::PlayWithoutWhitespace + + unless OPTIONS["shell"] + # Use readline-rb to avoid error message 'Bond has detected EditLine and + # may not work with it. See the README's Limitations section.' when no + # shell is requested after execution of FILE. + Ripl.config[:readline] = 'readline-rb' + Ripl.config[:completion] = {:readline => :ruby } + module Ripl::Exit + def before_loop; super; exit; end + end + Ripl::Shell.include Ripl::Exit + end + + Ripl.config[:play] = ARGV[0].dup if ARGV[0] end -puts "Restfully/#{Restfully::VERSION} - The root resource is available in the 'root' variable." - -require 'irb' -require 'irb/completion' -require 'irb/ext/save-history' - -HOME = ENV['HOME'] || ENV['HOMEPATH'] -# Keep history of your last commands. -# Taken from <http://blog.nicksieger.com/articles/2006/04/23/tweaking-irb> -IRB.conf[:SAVE_HISTORY] = 100 -IRB.conf[:HISTORY_FILE] = "#{HOME}/.irb-save-history" - -# Raises an error on Windows, so disabling it. -if RUBY_PLATFORM !~ /(win|w)32$/ - module Readline - module History - LOG = "#{HOME}/.irb-history" - - def self.write_log(line) - File.open(LOG, 'ab') {|f| - f << "#{line}\n" - } - end - - def self.start_session_log - write_log("\n") - end +module Restfully + class Session + alias :old_initialize :initialize + # Overwrite Restfully::Session.new calls that might occur in replayed + # scripts, so that they preferably take the configuration given with the + # restfully command-line tool. + def initialize(options = {}, &block) + old_opts = Configuration.new(options).expand + new_opts = Configuration.new(OPTIONS).expand + old_initialize(old_opts.merge(new_opts).to_hash, &block) end - - alias :old_readline :readline - def readline(*args) - ln = old_readline(*args) - begin - History.write_log(ln) - rescue - end - ln - end end - Readline::History.start_session_log end +# Ensure to close the log file, if any, when exiting. +at_exit{ @log_file && @log_file.close } + ARGV.clear -ARGV.concat [ "--readline", "--prompt-mode", "simple" ] -IRB.start -exit! \ No newline at end of file +Ripl.start :binding => @session.instance_eval{ binding }