bin/thor in thor-0.9.2 vs bin/thor in thor-0.9.5
- old
+ new
@@ -1,327 +1,7 @@
#!/usr/bin/env ruby
+# -*- mode: ruby -*-
-require "thor"
-require "open-uri"
-require "fileutils"
-require "yaml"
-require "digest/md5"
-require "readline"
+require File.dirname(__FILE__) + "/../lib/thor"
+require 'thor/runner'
-module ObjectSpace
-
- class << self
-
- # ==== Returns
- # Array[Class]:: All the classes in the object space.
- def classes
- klasses = []
- ObjectSpace.each_object(Class) {|o| klasses << o}
- klasses
- end
- end
-
-end
-
-class Thor::Util
-
- # @public
- def self.constant_to_thor_path(str)
- snake_case(str).squeeze(":")
- end
-
- # @public
- def self.constant_from_thor_path(str)
- make_constant(to_constant(str))
- end
-
- def self.to_constant(str)
- str.gsub(/:(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
- end
-
- def self.constants_in_contents(str)
- klasses = self.constants.dup
- eval(str)
- ret = self.constants - klasses
- ret.each {|k| self.send(:remove_const, k)}
- ret
- end
-
- private
- # @private
- def self.make_constant(str)
- list = str.split("::")
- obj = Object
- list.each {|x| obj = obj.const_get(x) }
- obj
- end
-
- # @private
- def self.snake_case(str)
- return str.downcase if str =~ /^[A-Z]+$/
- str.gsub(/([A-Z]+)(?=[A-Z][a-z]?)|\B[A-Z]/, '_\&') =~ /_*(.*)/
- return $+.downcase
- end
-
-end
-
-class Thor::Runner < Thor
-
- def self.globs_for(path)
- ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"]
- end
-
- def initialize_thorfiles(include_system = true)
- thorfiles(include_system).each {|f| load f unless Thor.subclass_files.keys.include?(File.expand_path(f))}
- end
-
- map "-T" => :list, "-i" => :install, "-u" => :update
-
- desc "install NAME", "install a Thor file into your system tasks, optionally named for future updates"
- method_options :as => :optional
- def install(name, opts)
- initialize_thorfiles
- begin
- contents = open(name).read
- rescue OpenURI::HTTPError
- puts "The URI you provided: `#{name}' was invalid"
- return
- rescue Errno::ENOENT
- puts "`#{name}' is not a valid file"
- return
- end
-
- puts "Your Thorfile contains: "
- puts contents
- print "Do you wish to continue [y/N]? "
- response = Readline.readline
-
- return unless response =~ /^\s*y/i
-
- constants = Thor::Util.constants_in_contents(contents)
-
- name = name =~ /\.thor$/ ? name : "#{name}.thor"
-
- as = opts["as"] || begin
- first_line = contents.split("\n")[0]
- (match = first_line.match(/\s*#\s*module:\s*([^\n]*)/)) ? match[1].strip : nil
- end
-
- if !as
- print "Please specify a name for #{name} in the system repository [#{name}]: "
- as = Readline.readline
- as = name if as.empty?
- end
-
- FileUtils.mkdir_p thor_root
-
- yaml_file = File.join(thor_root, "thor.yml")
- FileUtils.touch(yaml_file)
- yaml = thor_yaml
-
- yaml[as] = {:filename => Digest::MD5.hexdigest(name + as), :location => name, :constants => constants}
-
- save_yaml(yaml)
-
- puts "Storing thor file in your system repository"
-
- File.open(File.join(thor_root, yaml[as][:filename] + ".thor"), "w") do |file|
- file.puts contents
- end
- end
-
- desc "uninstall NAME", "uninstall a named Thor module"
- def uninstall(name)
- yaml = thor_yaml
- unless yaml[name]
- puts "There was no module by that name installed"
- return
- end
-
- puts "Uninstalling #{name}."
-
- file = File.join(thor_root, "#{yaml[name][:filename]}.thor")
- File.delete(file)
- yaml.delete(name)
- save_yaml(yaml)
-
- puts "Done."
- end
-
- desc "update NAME", "update a Thor file from its original location"
- def update(name)
- yaml = thor_yaml
- if !yaml[name] || !yaml[name][:location]
- puts "`#{name}' was not found in the system repository"
- else
- puts "Updating `#{name}' from #{yaml[name][:location]}"
- install(yaml[name][:location], "as" => name)
- end
- end
-
- def installed
- Dir["#{ENV["HOME"]}/.thor/**/*.thor"].each do |f|
- load f unless Thor.subclass_files.keys.include?(File.expand_path(f))
- end
- display_klasses(true)
- end
-
- desc "list [SEARCH]", "list the available thor tasks (--substring means SEARCH can be anywhere in the module)"
- method_options :substring => :boolean
- def list(search = "", options = {})
- initialize_thorfiles
- search = ".*#{search}" if options["substring"]
- search = /^#{search}.*/i
-
- display_klasses(false, Thor.subclasses.select {|k|
- Thor::Util.constant_to_thor_path(k.name) =~ search})
- end
-
- def method_missing(meth, *args)
- initialize_thorfiles(false)
- meth = meth.to_s
- unless meth =~ /:/
- puts "Thor tasks must contain a :"
- return
- end
-
- thor_klass = meth.split(":")[0...-1].join(":")
- to_call = meth.split(":").last
-
- yaml = thor_yaml
-
- klass_str = Thor::Util.to_constant(thor_klass)
- files = yaml.inject([]) { |a,(k,v)| a << v[:filename] if v[:constants] && v[:constants].include?(klass_str); a }
-
- unless files.empty?
- files.each do |f|
- load File.join(thor_root, "#{f}.thor")
- end
- klass = Thor::Util.constant_from_thor_path(thor_klass)
- else
- begin
- klass = Thor::Util.constant_from_thor_path(thor_klass)
- rescue
- puts "There was no available namespace `#{thor_klass}'."
- return
- end
- end
-
- unless klass.ancestors.include?(Thor)
- puts "`#{thor_klass}' is not a Thor module"
- return
- end
-
- ARGV.replace [to_call, *(args + ARGV)].compact
- begin
- klass.start
- rescue ArgumentError
- puts "You need to call #{to_call} as `#{klass.usage_for_method(to_call)}'"
- rescue NoMethodError
- puts "`#{to_call}' is not available in #{thor_klass}"
- end
- end
-
- private
- def thor_root
- File.join(ENV["HOME"], ".thor")
- end
-
- def thor_yaml
- yaml_file = File.join(thor_root, "thor.yml")
- yaml = YAML.load_file(yaml_file) if File.exists?(yaml_file)
- yaml || {}
- end
-
- def save_yaml(yaml)
- yaml_file = File.join(thor_root, "thor.yml")
- File.open(yaml_file, "w") {|f| f.puts yaml.to_yaml }
- end
-
- def display_klasses(with_modules = false, klasses = Thor.subclasses)
- klasses = klasses - [Thor::Runner]
-
- if klasses.empty?
- puts "No thorfiles available"
- return
- end
-
- if with_modules
- yaml = thor_yaml
- max_name = yaml.max {|(xk,xv),(yk,yv)| xk.size <=> yk.size }.first.size
-
- print "%-#{max_name + 4}s" % "Name"
- puts "Modules"
- print "%-#{max_name + 4}s" % "----"
- puts "-------"
-
- yaml.each do |name, info|
- print "%-#{max_name + 4}s" % name
- puts info[:constants].map {|c| Thor::Util.constant_to_thor_path(c)}.join(", ")
- end
-
- puts
- end
-
- puts "Tasks"
- puts "-----"
-
- # Calculate the largest base class name
- max_base = klasses.max do |x,y|
- Thor::Util.constant_to_thor_path(x.name).size <=> Thor::Util.constant_to_thor_path(y.name).size
- end.name.size
-
- # Calculate the size of the largest option description
- max_left_item = klasses.max do |x,y|
- (x.help_list && x.help_list.max.usage + x.help_list.max.opt).to_i <=>
- (y.help_list && y.help_list.max.usage + y.help_list.max.opt).to_i
- end
-
- max_left = max_left_item.help_list.max.usage + max_left_item.help_list.max.opt
-
- klasses.map {|k| k.help_list}.compact.each do |item|
- display_tasks(item, max_base, max_left)
- end
- end
-
- def display_tasks(item, max_base, max_left)
- base = Thor::Util.constant_to_thor_path(item.klass.name)
- item.usages.each do |name, usage|
- format_string = "%-#{max_left + max_base + 5}s"
- print format_string %
- "#{base}:#{item.usages.assoc(name).last} #{display_opts(item.opts.assoc(name) && item.opts.assoc(name).last)}"
- puts item.descriptions.assoc(name).last
- end
- end
-
- def display_opts(opts)
- return "" unless opts
- opts.map do |opt, val|
- if val == true || val == "BOOLEAN"
- "[#{opt}]"
- elsif val == "REQUIRED"
- opt + "=" + opt.gsub(/\-/, "").upcase
- elsif val == "OPTIONAL"
- "[" + opt + "=" + opt.gsub(/\-/, "").upcase + "]"
- end
- end.join(" ")
- end
-
- def thorfiles(include_system = true)
- path = Dir.pwd
- system_thorfiles = Dir["#{ENV["HOME"]}/.thor/**/*.thor"]
- thorfiles = []
-
- # Look for Thorfile or *.thor in the current directory or a parent directory, until the root
- while thorfiles.empty?
- thorfiles = Dir[*Thor::Runner.globs_for(path)]
- path = File.dirname(path)
- break if path == "/"
- end
- thorfiles + (include_system ? system_thorfiles : [])
- end
-
-end
-
-unless defined?(Spec)
- Thor::Runner.start
-end
\ No newline at end of file
+Thor::Runner.start