module TreasureData module Command module List class CommandOption < OptionParser def initialize(name, args, description) super() @name = name @description = description.to_s if args.last.to_s =~ /_$/ @varlen = true args.push args.pop.to_s[0..-2]+'...' elsif args.last.to_s =~ /_\?$/ @varlen = true args.push args.pop.to_s[0..-3]+'...?' end @req_args, opt_args = args.partition {|a| a.to_s !~ /\?$/ } @opt_args = opt_args.map {|a| a.to_s[0..-2].to_sym } @args = @req_args + @opt_args @usage_args = "#{@name}" @req_args.each {|a| @usage_args << " <#{a}>" } @opt_args.each {|a| @usage_args << " [#{a}]" } @has_options = false self.summary_indent = " " banner = "usage:\n" banner << " $ #{File.basename($0)} #{@usage_args}\n" banner << "\n" banner << "description:\n" @description.split("\n").each {|l| banner << " #{l}\n" } self.banner = banner @message = nil @argv = nil end attr_accessor :message, :argv def message @message || to_s end def banner s = super.dup if @has_options s << "\n" s << "options:\n" end s << "\n" s end def usage "%-40s # %s" % [@usage_args, @description] end def cmd_parse(argv=@argv||ARGV) parse!(argv) if argv.length < @req_args.length || (!@varlen && argv.length > @argv.length) cmd_usage nil end if argv.length <= 1 return argv[0] else return argv end rescue cmd_usage $! end def cmd_usage(msg=nil) puts self.message if msg puts "" puts "error: #{msg}" end exit 1 end def group name.split(':', 2).first end def on(*argv) @has_options = true super end def with_args(argv) d = dup d.argv = argv d end attr_reader :name attr_reader :description end LIST = [] COMMAND = {} GUESS = {} HELP_EXCLUDE = ['help', 'account'] def self.add_list(name, args, description) LIST << COMMAND[name] = CommandOption.new(name, args, description) end def self.add_alias(new_cmd, old_cmd) COMMAND[new_cmd] = COMMAND[old_cmd] end def self.add_guess(wrong, correct) GUESS[wrong] = correct end def self.get_method(name) if op = COMMAND[name] name = op.name group, action = op.group require 'td/command/common' require "td/command/#{group}" cmd = name.gsub(':', '_') m = Object.new.extend(Command).method(cmd) return Proc.new {|args| m.call(op.with_args(args)) } end nil end def self.show_guess(wrong) if correct = GUESS[wrong] $stderr.puts "Did you mean this?: #{correct}" end end def self.get_option(name) COMMAND[name] end def self.show_help(indent=' ') before_group = nil LIST.each {|op| next if HELP_EXCLUDE.include?(op.name) if before_group != op.group before_group = op.group puts "" end puts "#{indent}#{op.usage}" } end def self.get_group(group) LIST.map {|op| op.group == group } end def self.finishup groups = {} LIST.each {|op| (groups[op.group] ||= []) << op } groups.each_pair {|group,ops| if ops.size > 1 && xop = COMMAND[group].dup msg = %[Additional commands, type "#{File.basename($0)} help COMMAND" for more details:\n\n] ops.each {|op| msg << %[ #{op.usage}\n] } msg << %[\n] xop.message = msg COMMAND[group] = xop end } end add_list 'db:list', %w[], 'Show list of tables in a database' add_list 'db:show', %w[db], 'Describe a information of a database' add_list 'db:create', %w[db], 'Create a database' add_list 'db:delete', %w[db], 'Delete a database' add_list 'table:list', %w[db?], 'Show list of tables' add_list 'table:show', %w[db table], 'Describe a information of a table' add_list 'table:create', %w[db table], 'Create a table' add_list 'table:delete', %w[db table], 'Delete a table' add_list 'table:import', %w[db table files_], 'Parse and import files to a table' #add_list 'table:tail', %w[db table], 'Get recently imported logs' add_list 'schema:show', %w[db table], 'Show schema of a table' add_list 'schema:set', %w[db table columns_?], 'Set new schema on a table' add_list 'schema:add', %w[db table columns_], 'Add new columns to a table' add_list 'schema:remove', %w[db table columns_], 'Remove columns from a table' add_list 'sched:list', %w[], 'Show list of schedules' add_list 'sched:create', %w[name cron sql], 'Create a schedule' add_list 'sched:delete', %w[name], 'Delete a schedule' add_list 'sched:history', %w[name max?], 'Show history of scheduled queries' add_list 'query', %w[sql], 'Issue a query' add_list 'job:show', %w[job_id], 'Show status and result of a job' add_list 'job:list', %w[max?], 'Show list of jobs' add_list 'job:kill', %w[job_id], 'Kill or cancel a job' add_list 'account', %w[user_name?], 'Setup a Treasure Data account' add_list 'apikey:show', %w[], 'Show Treasure Data API key' add_list 'apikey:set', %w[apikey], 'Set Treasure Data API key' add_list 'server:status', %w[], 'Show status of the Treasure Data server' add_list 'help', %w[command], 'Show usage of a command' # aliases add_alias 'db', 'db:show' add_alias 'dbs', 'db:list' add_alias 'database:show', 'db:show' add_alias 'database:list', 'db:list' add_alias 'database:create', 'db:create' add_alias 'database:delete', 'db:delete' add_alias 'database', 'db:show' add_alias 'databases', 'db:list' add_alias 'table', 'table:show' add_alias 'tables', 'table:list' add_alias 'schema', 'schema:show' add_alias 'schedule:list', 'sched:list' add_alias 'schedule:create', 'sched:create' add_alias 'schedule:delete', 'sched:delete' add_alias 'schedule:history', 'sched:history' add_alias 'schedule:hist', 'sched:history' add_alias 'sched:hist', 'sched:history' add_alias 'sched', 'sched:history' add_alias 'scheds', 'sched:list' add_alias 'schedules', 'sched:list' add_alias 'job', 'job:show' add_alias 'jobs', 'job:list' add_alias 'kill', 'job:kill' add_alias 'apikey', 'apikey:show' # backward compatibility add_alias 'show-databases', 'db:list' add_alias 'show-dbs', 'db:list' add_alias 'create-database', 'db:create' add_alias 'create-db', 'db:create' add_alias 'drop-database', 'db:delete' add_alias 'drop-db', 'db:delete' add_alias 'delete-database', 'db:delete' add_alias 'delete-db', 'db:delete' add_alias 'show-tables', 'table:list' add_alias 'show-table', 'table:show' add_alias 'create-log-table', 'table:create' add_alias 'create-table', 'table:create' add_alias 'drop-log-table', 'table:delete' add_alias 'drop-table', 'table:delete' add_alias 'delete-log-table', 'table:delete' add_alias 'delete-table', 'table:delete' add_guess 'show-job', 'job:show' add_guess 'show-jobs', 'job:list' add_guess 'server-status', 'server:status' add_alias 'import', 'table:import' finishup end end end