require "fileutils" require "transcriptic/auth" require "transcriptic/command" class Transcriptic::Command::Base include Transcriptic::Helpers def self.namespace self.to_s.split("::").last.downcase end attr_reader :args attr_reader :options def initialize(args=[], options={}) @args = args @options = options end def transcriptic Transcriptic::Auth.client end protected def self.inherited(klass) unless klass == Transcriptic::Command::Base help = extract_help_from_caller(caller.first) Transcriptic::Command.register_namespace( :name => klass.namespace, :description => help.first ) end end def self.method_added(method) return if self == Transcriptic::Command::Base return if private_method_defined?(method) return if protected_method_defined?(method) help = extract_help_from_caller(caller.first) resolved_method = (method.to_s == "index") ? nil : method.to_s command = [ self.namespace, resolved_method ].compact.join(":") banner = extract_banner(help) || command Transcriptic::Command.register_command( :klass => self, :method => method, :namespace => self.namespace, :command => command, :banner => banner.strip, :help => help.join("\n"), :summary => extract_summary(help), :description => extract_description(help), :options => extract_options(help) ) end def self.alias_command(new, old) raise "no such command: #{old}" unless Transcriptic::Command.commands[old] Transcriptic::Command.command_aliases[new] = old end def self.extract_help_from_caller(line) # pull out of the caller the information for the file path and line number if line =~ /^(.+?):(\d+)/ extract_help($1, $2) else raise("unable to extract help from caller: #{line}") end end def self.extract_help(file, line_number) buffer = [] lines = Transcriptic::Command.files[file] (line_number.to_i-2).downto(0) do |i| line = lines[i] case line[0..0] when "" when "#" buffer.unshift(line[1..-1]) else break end end buffer end def self.extract_command(help) extract_banner(help).to_s.split(" ").first end def self.extract_banner(help) help.first end def self.extract_summary(help) extract_description(help).split("\n").first end def self.extract_description(help) help.reject do |line| line =~ /^\s+-(.+)#(.+)/ end.join("\n") end def self.extract_options(help) help.select do |line| line =~ /^\s+-(.+)#(.+)/ end.inject({}) do |hash, line| description = line.split("#", 2).last long = line.match(/--([A-Za-z\- ]+)/)[1].strip short = line.match(/-([A-Za-z ])/)[1].strip hash.update(long.split(" ").first => { :desc => description, :short => short, :long => long }) end end def current_command Transcriptic::Command.current_command end def extract_option(name, default=true) key = name.gsub("--", "").to_sym return unless options[key] value = options[key] || default block_given? ? yield(value) : value end def invalid_arguments Transcriptic::Command.invalid_arguments end def shift_argument Transcriptic::Command.shift_argument end def validate_arguments! Transcriptic::Command.validate_arguments! end def confirm_mismatch? options[:confirm] && (options[:confirm] != options[:app]) end def extract_app_in_dir(dir) return unless remotes = git_remotes(dir) if remote = options[:remote] remotes[remote] elsif remote = extract_app_from_git_config remotes[remote] else apps = remotes.values.uniq if apps.size == 1 apps.first else raise(Transcriptic::Command::CommandFailed, "Multiple apps in folder and no app specified.\nSpecify which app to use with --app ") end end end def extract_app_from_git_config remote = git("config transcriptic.remote") remote == "" ? nil : remote end def git_remotes(base_dir=Dir.pwd) remotes = {} original_dir = Dir.pwd Dir.chdir(base_dir) git("remote -v").split("\n").each do |remote| name, url, method = remote.split(/\s/) if url =~ /^git@#{transcriptic.host}:([\w\d-]+)\.git$/ remotes[name] = $1 end end Dir.chdir(original_dir) remotes end def escape(value) transcriptic.escape(value) end end module Transcriptic::Command unless const_defined?(:BaseWithApp) BaseWithApp = Base end end