模块 Bundler::Thor::Util

此模块包含多个实用程序

1) 将 thor 命名空间转换为常量以及反之的方法。

Bundler::Thor::Util.namespace_from_thor_class(Foo::Bar::Baz) #=> "foo:bar:baz"

2) 加载 thor 文件和沙箱处理

Bundler::Thor::Util.load_thorfile("~/.thor/foo")

公共类方法

camel_case(str) 点击以切换源代码

接收一个字符串并将其转换为驼峰式大小写。camel_case 返回 CamelCase。

参数

字符串

返回

字符串

# File bundler/vendor/thor/lib/thor/util.rb, line 104
def camel_case(str)
  return str if str !~ /_/ && str =~ /[A-Z]+.*/
  str.split("_").map(&:capitalize).join
end
escape_globs(path) 点击以切换源代码

返回一个字符串,该字符串已转义任何 glob 字符。 glob 字符是 ‘* ? { } [ ]`。

示例

Bundler::Thor::Util.escape_globs('[apps]')   # => '\[apps\]'

参数

字符串

返回

字符串

# File bundler/vendor/thor/lib/thor/util.rb, line 264
def escape_globs(path)
  path.to_s.gsub(/[*?{}\[\]]/, '\\\\\\&')
end
escape_html(string) 点击以切换源代码

返回一个字符串,该字符串已转义任何 HTML 字符。

示例

Bundler::Thor::Util.escape_html('<div>')   # => "&lt;div&gt;"

参数

字符串

返回

字符串

# File bundler/vendor/thor/lib/thor/util.rb, line 280
def escape_html(string)
  CGI.escapeHTML(string)
end
find_by_namespace(namespace) 点击以切换源代码

接收一个命名空间并在 Bundler::Thor::Base 子类中搜索它。

参数

命名空间<字符串>

要搜索的命名空间。

# File 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) 点击以切换源代码

接收一个命名空间并尝试从中检索一个 Bundler::Thor 或 Bundler::Thor::Group 类。 它首先使用给定的所有命名空间搜索类,如果未找到,则删除最高的条目并再次搜索类。 如果找到,则返回最高条目作为类名。

示例

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"

参数

命名空间<字符串>

# File 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, command  = namespace.split(":")
    namespace = pieces.join(":")
    namespace = "default" if namespace.empty?
    klass = Bundler::Thor::Base.subclasses.detect { |thor| thor.namespace == namespace && thor.command_exists?(command) }
  end
  unless klass # look for a Bundler::Thor::Group with the right name
    klass = Bundler::Thor::Util.find_by_namespace(namespace)
    command = 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
find_class_and_task_by_namespace(namespace, fallback = true)
globs_for(path) 点击以切换源代码

在何处查找 Bundler::Thor 文件。

# File bundler/vendor/thor/lib/thor/util.rb, line 213
def globs_for(path)
  path = escape_globs(path)
  ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/**/*.thor"]
end
load_thorfile(path, content = nil, debug = false) 点击以切换源代码

接收一个路径并加载该路径中的 thor 文件。 该文件在沙箱内求值,以避免命名空间冲突。

# File bundler/vendor/thor/lib/thor/util.rb, line 153
def load_thorfile(path, content = nil, debug = false)
  content ||= File.read(path)

  begin
    Bundler::Thor::Sandbox.class_eval(content, path)
  rescue StandardError => e
    $stderr.puts("WARNING: unable to load thorfile #{path.inspect}: #{e.message}")
    if debug
      $stderr.puts(*e.backtrace)
    else
      $stderr.puts(e.backtrace.first)
    end
  end
end
namespace_from_thor_class(constant) 点击以切换源代码

接收一个常量并将其转换为 Bundler::Thor 命名空间。 由于可以将 Bundler::Thor 命令添加到沙箱中,因此此方法还负责删除沙箱命名空间。

通常不应使用此方法,因为它用于处理较旧版本的 Bundler::Thor。 在当前版本中,如果需要从类中获取命名空间,只需调用其 namespace 即可。

参数

常量<对象>

要转换为 thor 路径的常量。

返回

字符串

如果我们收到 Foo::Bar::Baz,它会返回 “foo:bar:baz”

# File 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__) 点击以切换源代码

给定内容,在沙箱内对其求值并返回沙箱中定义的命名空间。

参数

内容<字符串>

返回

数组

# File 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!(&:namespace)
  new_constants.compact!
  new_constants
end
ruby_command() 点击以切换源代码

返回 ruby 解释器的路径,其中考虑了多个安装和 windows 扩展名。

# File bundler/vendor/thor/lib/thor/util.rb, line 221
def ruby_command
  @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 Lint/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) 点击以切换源代码

接收一个字符串并将其转换为蛇形大小写。SnakeCase 返回 snake_case。

参数

字符串

返回

字符串

# File 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("_") =~ /_*(.*)/
  Regexp.last_match(-1).downcase
end
thor_classes_in(klass) 点击以切换源代码

返回给定类中声明的 thor 类。

# File bundler/vendor/thor/lib/thor/util.rb, line 74
def thor_classes_in(klass)
  stringfied_constants = klass.constants.map(&: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() 点击以切换源代码

返回 thor 文件所在的根目录,具体取决于操作系统。

# File bundler/vendor/thor/lib/thor/util.rb, line 192
def thor_root
  File.join(user_home, ".thor").tr("\\", "/")
end
thor_root_glob() 点击以切换源代码

返回 thor 根目录中的文件。在 Windows 上,thor_root 将类似于这样

C:\Documents and Settings\james\.thor

如果我们不 gsub \ 字符,Dir.glob 将失败。

# File bundler/vendor/thor/lib/thor/util.rb, line 203
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() 点击以切换源代码
# File bundler/vendor/thor/lib/thor/util.rb, line 168
def 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.expand_path("~")
    rescue
      if File::ALT_SEPARATOR
        "C:/"
      else
        "/"
      end
    end
  end
end