#!/usr/bin/ruby # Seafaring Drydock Examples # # This is a functioning script so you can copy it, run it, # and just generally be a longshoreman about things. This is # a drydock after all. # # If you're reading this via the Rdocs you won't see the code. See: # # http://github.com/delano/drydock/blob/master/bin/example # # For an example of a complex command-line application using # Drydock, see: # # http://github.com/solutious/rudy/blob/master/bin/rudy # $:.unshift File.expand_path(File.join(File.dirname(__FILE__), '..')), 'lib' require 'drydock' module Example extend Drydock # Tell Drydock you want its methods! default :welcome # The welcome command will be run if no command is given capture :stderr # Drydock will capture STDERR and keep it in the hold. # You can use this to suppress errors. about "A friendly welcome to the Drydock" command :welcome do puts "Welcome to Drydock.", $/ puts "For available commands: #{$0} show-commands" end usage "USAGE: #{$0} laugh [-f]" about "The captain commands his crew to laugh" option :f, :faster, "A boolean value. Go even faster!" command :laugh do |obj| # +obj+ is an instance of Drydock::Command. The options you define are available # via obj.option.name answer = !obj.option.faster ? "Sort of" : "Yes! I'm literally laughing as fast as possible." puts "Captain Stubing: Are you laughing?" puts "Dr. Bricker: " << answer end global_usage "USAGE: #{File.basename($0)} [global options] command [command options]" global :s, :seconds, "Display values in seconds" global :v, :verbose, "Verbosity level (i.e. -vvv is greater than -v)" do |v| # Use instance variables to maintain values between option blocks. # This will increment for every -v found (i.e. -vvv) @val ||= 0 @val += 1 end before do |obj| # You can execute a block before the requests command is executed. Instance # variables defined here will be available to all commands. # +obj+ is a reference to the command object, just like in command blocks. end after do |obj| # And this will be called after the command. end usage "#{$0} [-s] [-vv] date" about "Display the current date" command :date do |obj| require 'time' now = Time.now puts "(Not verbose enough. Try adding a -v.)" if (obj.global.verbose || 0) == 1 puts "More verbosely, the date is now: " if (obj.global.verbose || 0) >= 2 puts (obj.global.seconds) ? now.to_i : now.to_s end ignore :options about "This command ignores options" command :rogue do |obj| # You can use ignore :options to tell Drydock to not process the # command-specific options. # Unnamed arguments are available from obj.argv if obj.argv.empty? puts "Had you supplied some arguments, I would have ignored them." else puts "Hi! You supplied some arguments but I ignored them." puts "They're all still here in this array: %s" % obj.argv.join(', ') end end class JohnWestSmokedOysters < Drydock::Command # You can write your own command classes by inheriting from Drydock::Command # and referencing it in the command definition. def ahoy!; p "matey"; end end about "Do something with John West's Smoked Oysters" command :oysters => JohnWestSmokedOysters do |obj| p obj # => # end about "My way of saying hello!" command [:ahoy!, :hello!] => JohnWestSmokedOysters # If you don't provide a block, Drydock will call JohnWestSmokedOysters#ahoy! require 'yaml' usage 'ruby bin/example uri -c -d " " -t 15 http://solutious.com/' usage 'echo "http://solutious.com/" | ruby bin/example uri -c -d " " -t 15' about "Check for broken URIs" option :c, :check, "Check response codes for each URI" option :d, :delim, String, "Output delimiter" option :t, :timeout, Float, "Timeout value for HTTP request" do |v| # You can provide an block to process the option value. # This block must return the final value. v = 10 if (v > 10) v end argv :uris command :uri do |obj| # This command processes the output of the stdin block (below this definition). # The output of that block is available as obj.stdin. If there is no stdin block # obj.stdin will be STDIN's IO object. require 'net/http' require 'uri' require 'timeout' uris = [] uris += obj.stdin if obj.stdin uris += obj.argv.uris if obj.argv.uris delim = obj.option.delim || ',' timeout = obj.option.timeout || 5 code = :notchecked # The default code when :check is false if uris.empty? puts "Frylock: You didn't provide any URIs. " puts "Master Shake: Ya, see #{$0} #{obj.alias} -h" exit 0 end uris.each_with_index do |uri, index| code = response_code(uri, timeout) if (obj.option.check) puts [index+1, uri, code].join(delim) end end about "Prints the alias used to access the command" # We can define command aliases by providing a list of command # names. The first name is still consider to be the main name. command :printalias, :reveal do |obj| puts "This is printalias!" if (obj.alias == obj.cmd) puts "You did not use an alias" else puts "You used the alias " << obj.alias end end stdin do |stdin, output| # Pre-process STDIN for all commands. This example returns an array of lines. # The command processuris uses this array. # We only want piped data. If this is not included # execution will wait for input from the user. unless stdin.tty? while !stdin.eof? do line = stdin.readline line.chomp! (output ||= []) << line end end output end # And one final feature for the intrepid swabbies like myself. # Drydock can handle unknown commands by catching them with a # trawler. It's like the captain of all aliases. Just specify # the command name to direct all unknown commands to. Simple! trawler :printalias # Return the HTTP response code for the given URI. Used by # uri command. # # +uri+ A valid HTTP URI # +duration+ The timeout threshold (in seconds) for the request. def response_code(uri_str, duration=5) #:nodoc: response = :unavailable begin uri = (uri_str.kind_of? URI::HTTP) ? uri_str : URI.parse(uri_str) timeout(duration) do response = Net::HTTP.get_response(uri).code end rescue Exception => ex end response end end Drydock.run!