Module: Bundler::Thor::Util
- Defined in:
- lib/bundler/vendor/thor/lib/thor/util.rb
Overview
This module holds several utilities:
1) Methods to convert thor namespaces to constants and vice-versa.
Bundler::Thor::Util.namespace_from_thor_class(Foo::Bar::Baz) #=> "foo:bar:baz"
2) Loading thor files and sandboxing:
Bundler::Thor::Util.load_thorfile("~/.thor/foo")
Class Method Summary collapse
-
.camel_case(str) ⇒ Object
Receives a string and convert it to camel case.
-
.escape_globs(path) ⇒ Object
Returns a string that has had any glob characters escaped.
-
.find_by_namespace(namespace) ⇒ Object
Receives a namespace and search for it in the Bundler::Thor::Base subclasses.
-
.find_class_and_command_by_namespace(namespace, fallback = true) ⇒ Object
(also: find_class_and_task_by_namespace)
Receives a namespace and tries to retrieve a Bundler::Thor or Bundler::Thor::Group class from it.
-
.globs_for(path) ⇒ Object
Where to look for Bundler::Thor files.
-
.load_thorfile(path, content = nil, debug = false) ⇒ Object
Receives a path and load the thor file in the path.
-
.namespace_from_thor_class(constant) ⇒ Object
Receives a constant and converts it to a Bundler::Thor namespace.
-
.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, depending on the OS.
-
.thor_root_glob ⇒ Object
Returns the files in the thor root.
-
.user_home ⇒ Object
rubocop:disable MethodLength.
Class Method Details
.camel_case(str) ⇒ Object
Receives a string and convert it to camel case. camel_case returns CamelCase.
Parameters
String
Returns
String
104 105 106 107 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 104 def camel_case(str) return str if str !~ /_/ && str =~ /[A-Z]+.*/ str.split("_").map { |i| i.capitalize }.join end |
.escape_globs(path) ⇒ Object
262 263 264 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 262 def escape_globs(path) path.to_s.gsub(/[*?{}\[\]]/, '\\\\\\&') end |
.find_by_namespace(namespace) ⇒ Object
Receives a namespace and search for it in the Bundler::Thor::Base subclasses.
Parameters
- namespace<String>
-
The namespace to search for.
24 25 26 27 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 24 def find_by_namespace(namespace) namespace = "default#{namespace}" if namespace.empty? || namespace =~ /^:/ Bundler::Thor::Base.subclasses.detect { |klass| klass.namespace == namespace } end |
.find_class_and_command_by_namespace(namespace, fallback = true) ⇒ Object Also known as: find_class_and_task_by_namespace
Receives a namespace and tries to retrieve a Bundler::Thor or Bundler::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 < Bundler::Thor
def baz
end
end
class Baz::Foo < Bundler::Thor::Group
end
Bundler::Thor::Util.namespace_to_thor_class("foo:bar") #=> Foo::Bar, nil # will invoke default command
Bundler::Thor::Util.namespace_to_thor_class("baz:foo") #=> Baz::Foo, nil
Bundler::Thor::Util.namespace_to_thor_class("foo:bar:baz") #=> Foo::Bar, "baz"
Parameters
namespace<String>
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 131 def find_class_and_command_by_namespace(namespace, fallback = true) if namespace.include?(":") # look for a namespaced command pieces = namespace.split(":") command = pieces.pop klass = Bundler::Thor::Util.find_by_namespace(pieces.join(":")) end unless klass # look for a Bundler::Thor::Group with the right name klass, command = Bundler::Thor::Util.find_by_namespace(namespace), nil end if !klass && fallback # try a command in the default namespace command = namespace klass = Bundler::Thor::Util.find_by_namespace("") end [klass, command] end |
.globs_for(path) ⇒ Object
Where to look for Bundler::Thor files.
211 212 213 214 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 211 def globs_for(path) path = escape_globs(path) ["#{path}/Bundler::Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"] end |
.load_thorfile(path, content = nil, debug = false) ⇒ Object
Receives a path and load the thor file in the path. The file is evaluated inside the sandbox to avoid namespacing conflicts.
151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 151 def load_thorfile(path, content = nil, debug = false) content ||= File.binread(path) begin Bundler::Thor::Sandbox.class_eval(content, path) rescue StandardError => e $stderr.puts("WARNING: unable to load thorfile #{path.inspect}: #{e.}") if debug $stderr.puts(*e.backtrace) else $stderr.puts(e.backtrace.first) end end end |
.namespace_from_thor_class(constant) ⇒ Object
Receives a constant and converts it to a Bundler::Thor namespace. Since Bundler::Thor commands 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 Bundler::Thor. On current versions, if you need to get the namespace from a class, just call namespace on it.
Parameters
- constant<Object>
-
The constant to be converted to the thor path.
Returns
- String
-
If we receive Foo::Bar::Baz it returns “foo:bar:baz”
43 44 45 46 47 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 43 def namespace_from_thor_class(constant) constant = constant.to_s.gsub(/^Bundler::Thor::Sandbox::/, "") constant = snake_case(constant).squeeze(":") constant 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<String>
Returns
58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 58 def namespaces_in_content(contents, file = __FILE__) old_constants = Bundler::Thor::Base.subclasses.dup Bundler::Thor::Base.subclasses.clear load_thorfile(file, contents) new_constants = Bundler::Thor::Base.subclasses.dup Bundler::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.
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 219 def ruby_command # rubocop:disable MethodLength @ruby_command ||= begin ruby_name = RbConfig::CONFIG["ruby_install_name"] ruby = File.join(RbConfig::CONFIG["bindir"], ruby_name) ruby << RbConfig::CONFIG["EXEEXT"] # avoid using different name than ruby (on platforms supporting links) if ruby_name != "ruby" && File.respond_to?(:readlink) begin alternate_ruby = File.join(RbConfig::CONFIG["bindir"], "ruby") alternate_ruby << RbConfig::CONFIG["EXEEXT"] # ruby is a symlink if File.symlink? alternate_ruby linked_ruby = File.readlink alternate_ruby # symlink points to 'ruby_install_name' ruby = alternate_ruby if linked_ruby == ruby_name || linked_ruby == ruby end rescue NotImplementedError # rubocop:disable HandleExceptions # just ignore on windows end end # 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
90 91 92 93 94 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 90 def snake_case(str) return str.downcase if str =~ /^[A-Z_]+$/ str.gsub(/\B[A-Z]/, '_\&').squeeze("_") =~ /_*(.*)/ $+.downcase end |
.thor_classes_in(klass) ⇒ Object
Returns the thor classes declared inside the given class.
74 75 76 77 78 79 80 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 74 def thor_classes_in(klass) stringfied_constants = klass.constants.map { |c| c.to_s } Bundler::Thor::Base.subclasses.select do |subclass| next unless subclass.name stringfied_constants.include?(subclass.name.gsub("#{klass.name}::", "")) end end |
.thor_root ⇒ Object
Returns the root where thor files are located, depending on the OS.
190 191 192 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 190 def thor_root File.join(user_home, ".thor").gsub(/\\/, "/") 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.
201 202 203 204 205 206 207 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 201 def thor_root_glob files = Dir["#{escape_globs(thor_root)}/*"] files.map! do |file| File.directory?(file) ? File.join(file, "main.thor") : file end end |
.user_home ⇒ Object
rubocop:disable MethodLength
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/bundler/vendor/thor/lib/thor/util.rb', line 166 def user_home # rubocop:disable MethodLength @@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 |