Module: Thor::Util
- Defined in:
- lib/thor/util.rb
Overview
This module holds several utilities:
- Methods to convert thor namespaces to constants and vice-versa.
Thor::Utils.namespace_from_thor_class(Foo::Bar::Baz) #=> "foo:bar:baz"
- Loading thor files and sandboxing:
Thor::Utils.load_thorfile("~/.thor/foo")
Class Method Summary collapse
-
.camel_case(str) ⇒ Object
Receives a string and convert it to camel case.
-
.convert_constants_to_namespaces(yaml) ⇒ Object
Receives a yaml (hash) and updates all constants entries to namespace.
-
.find_by_namespace(namespace) ⇒ Object
Receives a namespace and search for it in the Thor::Base subclasses.
-
.globs_for(path) ⇒ Object
Where to look for Thor files.
-
.load_thorfile(path, content = nil) ⇒ Object
Receives a path and load the thor file in the path.
-
.namespace_from_thor_class(constant, remove_default = true) ⇒ Object
Receives a constant and converts it to a Thor namespace.
-
.namespace_to_thor_class_and_task(namespace, raise_if_nil = true) ⇒ Object
Receives a namespace and tries to retrieve a Thor or Thor::Group class from it.
-
.namespaces_in_content(contents, file = __FILE__) ⇒ Object
Given the contents, evaluate it inside the sandbox and returns the namespaces defined in the sandbox.
-
.ruby_command ⇒ Object
Return the path to the ruby interpreter taking into account multiple installations and windows extensions.
-
.snake_case(str) ⇒ Object
Receives a string and convert it to snake case.
-
.thor_classes_in(klass) ⇒ Object
Returns the thor classes declared inside the given class.
-
.thor_root ⇒ Object
Returns the root where thor files are located, dependending on the OS.
-
.thor_root_glob ⇒ Object
Returns the files in the thor root.
- .user_home ⇒ Object
Class Method Details
.camel_case(str) ⇒ Object
Receives a string and convert it to camel case. camel_case returns CamelCase.
Parameters
String
Returns
String
106 107 108 109 |
# File 'lib/thor/util.rb', line 106 def self.camel_case(str) return str if str !~ /_/ && str =~ /[A-Z]+.*/ str.split('_').map { |i| i.capitalize }.join end |
.convert_constants_to_namespaces(yaml) ⇒ Object
Receives a yaml (hash) and updates all constants entries to namespace. This was added to deal with deprecated versions of Thor.
TODO Deprecate this method in the future.
Returns
- TrueClass|FalseClass
Returns true if any change to the yaml file was made.
174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/thor/util.rb', line 174 def self.convert_constants_to_namespaces(yaml) yaml_changed = false yaml.each do |k, v| next unless v[:constants] && v[:namespaces].nil? yaml_changed = true yaml[k][:namespaces] = v[:constants].map{|c| Thor::Util.namespace_from_thor_class(c)} end yaml_changed end |
.find_by_namespace(namespace) ⇒ Object
Receives a namespace and search for it in the Thor::Base subclasses.
Parameters
- namespace
The namespace to search for.
24 25 26 27 28 29 30 |
# File 'lib/thor/util.rb', line 24 def self.find_by_namespace(namespace) namespace = 'default' if namespace.empty? Thor::Base.subclasses.find do |klass| klass.namespace == namespace end end |
.globs_for(path) ⇒ Object
Where to look for Thor files.
231 232 233 |
# File 'lib/thor/util.rb', line 231 def self.globs_for(path) ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"] end |
.load_thorfile(path, content = nil) ⇒ Object
Receives a path and load the thor file in the path. The file is evaluated inside the sandbox to avoid namespacing conflicts.
156 157 158 159 160 161 162 163 164 |
# File 'lib/thor/util.rb', line 156 def self.load_thorfile(path, content=nil) content ||= File.read(path) begin Thor::Sandbox.class_eval(content, path) rescue Exception => e $stderr.puts "WARNING: unable to load thorfile #{path.inspect}: #{e.message}" end end |
.namespace_from_thor_class(constant, remove_default = true) ⇒ Object
Receives a constant and converts it to a Thor namespace. Since Thor tasks can be added to a sandbox, this method is also responsable for removing the sandbox namespace.
This method should not be used in general because it's used to deal with older versions of Thor. On current versions, if you need to get the namespace from a class, just call namespace on it.
Parameters
- constant
The constant to be converted to the thor path.
Returns
- String
If we receive Foo::Bar::Baz it returns "foo:bar:baz"
46 47 48 49 50 51 |
# File 'lib/thor/util.rb', line 46 def self.namespace_from_thor_class(constant, remove_default=true) constant = constant.to_s.gsub(/^Thor::Sandbox::/, "") constant = snake_case(constant).squeeze(":") constant.gsub!(/^default/, '') if remove_default constant end |
.namespace_to_thor_class_and_task(namespace, raise_if_nil = true) ⇒ Object
Receives a namespace and tries to retrieve a Thor or Thor::Group class from it. It first searches for a class using the all the given namespace, if it's not found, removes the highest entry and searches for the class again. If found, returns the highest entry as the class name.
Examples
class Foo::Bar < Thor
def baz
end
end
class Baz::Foo < Thor::Group
end
Thor::Util.namespace_to_thor_class("foo:bar") #=> Foo::Bar, nil # will invoke default task
Thor::Util.namespace_to_thor_class("baz:foo") #=> Baz::Foo, nil
Thor::Util.namespace_to_thor_class("foo:bar:baz") #=> Foo::Bar, "baz"
Parameters
namespace
Errors
Thor::Error:: raised if the namespace cannot be found.
Thor::Error:: raised if the namespace evals to a class which does not inherit from Thor or Thor::Group.
139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/thor/util.rb', line 139 def self.namespace_to_thor_class_and_task(namespace, raise_if_nil=true) klass, task_name = Thor::Util.find_by_namespace(namespace), nil if klass.nil? && namespace.include?(?:) namespace = namespace.split(":") task_name = namespace.pop klass = Thor::Util.find_by_namespace(namespace.join(":")) end raise Error, "could not find Thor class or task '#{namespace}'" if raise_if_nil && klass.nil? return klass, task_name end |
.namespaces_in_content(contents, file = __FILE__) ⇒ Object
Given the contents, evaluate it inside the sandbox and returns the namespaces defined in the sandbox.
Parameters
contents
Returns
62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/thor/util.rb', line 62 def self.namespaces_in_content(contents, file=__FILE__) old_constants = Thor::Base.subclasses.dup Thor::Base.subclasses.clear load_thorfile(file, contents) new_constants = Thor::Base.subclasses.dup Thor::Base.subclasses.replace(old_constants) new_constants.map!{ |c| c.namespace } new_constants.compact! new_constants end |
.ruby_command ⇒ Object
Return the path to the ruby interpreter taking into account multiple installations and windows extensions.
238 239 240 241 242 243 244 245 246 247 |
# File 'lib/thor/util.rb', line 238 def self.ruby_command @ruby_command ||= begin ruby = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']) ruby << Config::CONFIG['EXEEXT'] # escape string in case path to ruby executable contain spaces. ruby.sub!(/.*\s.*/m, '"\&"') ruby end end |
.snake_case(str) ⇒ Object
Receives a string and convert it to snake case. SnakeCase returns snake_case.
Parameters
String
Returns
String
92 93 94 95 96 |
# File 'lib/thor/util.rb', line 92 def self.snake_case(str) return str.downcase if str =~ /^[A-Z_]+$/ str.gsub(/\B[A-Z]/, '_\&').squeeze('_') =~ /_*(.*)/ return $+.downcase end |
.thor_classes_in(klass) ⇒ Object
Returns the thor classes declared inside the given class.
78 79 80 81 82 |
# File 'lib/thor/util.rb', line 78 def self.thor_classes_in(klass) Thor::Base.subclasses.select do |subclass| klass.constants.include?(subclass.name.gsub("#{klass.name}::", '')) end end |
.thor_root ⇒ Object
Returns the root where thor files are located, dependending on the OS.
210 211 212 |
# File 'lib/thor/util.rb', line 210 def self.thor_root File.join(user_home, ".thor") end |
.thor_root_glob ⇒ Object
Returns the files in the thor root. On Windows thor_root will be something like this:
C:\Documents and Settings\james\.thor
If we don't #gsub the \ character, Dir.glob will fail.
221 222 223 224 225 226 227 |
# File 'lib/thor/util.rb', line 221 def self.thor_root_glob files = Dir["#{thor_root.gsub(/\\/, '/')}/*"] files.map! do |file| File.directory?(file) ? File.join(file, "main.thor") : file end end |
.user_home ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/thor/util.rb', line 186 def self.user_home @@user_home ||= if ENV["HOME"] ENV["HOME"] elsif ENV["USERPROFILE"] ENV["USERPROFILE"] elsif ENV["HOMEDRIVE"] && ENV["HOMEPATH"] File.join(ENV["HOMEDRIVE"], ENV["HOMEPATH"]) elsif ENV["APPDATA"] ENV["APPDATA"] else begin File.("~") rescue if File::ALT_SEPARATOR "C:/" else "/" end end end end |