模块 Bundler::Thor::Actions
常量
- 警告
将给定的内容注入到文件中。与
gsub_file
不同,此方法是可逆的。参数¶ ↑
- destination<字符串>
-
目标根目录的相对路径
- data<字符串>
-
要添加到文件中的数据。可以作为代码块给出。
- config<哈希>
-
提供 :verbose => false 以不记录状态和注入标志(:after 或 :before),或 :force => true 以多次插入相同的内容。
示例¶ ↑
insert_into_file "config/environment.rb", "config.gem :thor", :after => "Rails::Initializer.run do |config|\n" insert_into_file "config/environment.rb", :after => "Rails::Initializer.run do |config|\n" do gems = ask "Which gems would you like to add?" gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n") end
属性
公共类方法
扩展初始化器以添加更多配置选项。
配置¶ ↑
- behavior<符号>
-
操作的默认行为。可以是 :invoke 或 :revoke。它也接受 :force、:skip 和 :pretend 来设置行为和相应的选项。
destination_root
<字符串>-
某些操作所需的根目录。
# File bundler/vendor/thor/lib/thor/actions.rb, line 72 def initialize(args = [], options = {}, config = {}) self.behavior = case config[:behavior].to_s when "force", "skip" _cleanup_options_and_set(options, config[:behavior]) :invoke when "revoke" :revoke else :invoke end super self.destination_root = config[:destination_root] end
公共实例方法
将文本附加到文件。由于它依赖于insert_into_file
,因此它是可逆的。
参数¶ ↑
- path<字符串>
-
要更改的文件的路径
- data<字符串>
-
要附加到文件的数据,也可以作为代码块给出。
- config<哈希>
-
提供 :verbose => false 以不记录状态。
示例¶ ↑
append_to_file 'config/environments/test.rb', 'config.gem "rspec"' append_to_file 'config/environments/test.rb' do 'config.gem "rspec"' end
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 192 def append_to_file(path, *args, &block) config = args.last.is_a?(Hash) ? args.pop : {} config[:before] = /\z/ insert_into_file(path, *(args << config), &block) end
加载外部文件并在实例绑定中执行它。
参数¶ ↑
- path<字符串>
-
要执行的文件的路径。可以是 Web 地址或源根目录的相对路径。
示例¶ ↑
apply "http://gist.github.com/103208" apply "recipes/jquery.rb"
# File bundler/vendor/thor/lib/thor/actions.rb, line 216 def apply(path, config = {}) verbose = config.fetch(:verbose, true) is_uri = path =~ %r{^https?\://} path = find_in_source_paths(path) unless is_uri say_status :apply, path, verbose shell.padding += 1 if verbose contents = if is_uri require "open-uri" URI.open(path, "Accept" => "application/x-thor-template", &:read) else File.open(path, &:read) end instance_eval(contents, path) shell.padding -= 1 if verbose end
更改给定文件或目录的模式。
参数¶ ↑
- mode<整数>
-
文件模式
- path<字符串>
-
要更改模式的文件名
- config<哈希>
-
提供 :verbose => false 以不记录状态。
示例¶ ↑
chmod "script/server", 0755
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 145 def chmod(path, mode, config = {}) return unless behavior == :invoke path = File.expand_path(path, destination_root) say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true) unless options[:pretend] require "fileutils" FileUtils.chmod_R(mode, path) end end
注释所有与给定正则表达式匹配的行。它将保留行开始之前的空格,并在注释哈希之后插入一个空格。
参数¶ ↑
- path<字符串>
-
要更改的文件的路径
- flag<正则表达式|字符串>
-
用于决定要注释哪些行的正则表达式或字符串
- config<哈希>
-
提供 :verbose => false 以不记录状态。
示例¶ ↑
comment_lines 'config/initializers/session_store.rb', /cookie_store/
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 308 def comment_lines(path, flag, *args) flag = flag.respond_to?(:source) ? flag.source : flag gsub_file(path, /^(\s*)([^#\n]*#{flag})/, '\1# \2', *args) end
将文件从相对源复制到相对目标。如果未给出目标,则假定它等于源。
参数¶ ↑
- source<字符串>
-
源根目录的相对路径。
- destination<字符串>
-
目标根目录的相对路径。
- config<哈希>
-
提供 :verbose => false 以不记录状态,以及 :mode => :preserve,以保留源文件模式。
示例¶ ↑
copy_file "README", "doc/README" copy_file "doc/README"
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 20 def copy_file(source, *args, &block) config = args.last.is_a?(Hash) ? args.pop : {} destination = args.first || source source = File.expand_path(find_in_source_paths(source.to_s)) resulting_destination = create_file destination, nil, config do content = File.binread(source) content = yield(content) if block content end if config[:mode] == :preserve mode = File.stat(source).mode chmod(resulting_destination, mode, config) end end
使用给定数据(它是代码块的返回值或数据字符串)创建相对于目标根目录的新文件。
参数¶ ↑
- destination<字符串>
-
目标根目录的相对路径。
- data<字符串|NilClass>
-
要附加到文件的数据。
- config<哈希>
-
提供 :verbose => false 以不记录状态。
示例¶ ↑
create_file "lib/fun_party.rb" do hostname = ask("What is the virtual hostname I should use?") "vhost.name = #{hostname}" end create_file "config/apache.conf", "your apache config"
# File bundler/vendor/thor/lib/thor/actions/create_file.rb, line 22 def create_file(destination, *args, &block) config = args.last.is_a?(Hash) ? args.pop : {} data = args.first action CreateFile.new(self, destination, block || data.to_s, config) end
从给定源创建相对于目标根目录的新文件。
参数¶ ↑
- destination<字符串>
-
目标根目录的相对路径。
- source<字符串|NilClass>
-
源根目录的相对路径。
- config<哈希>
-
提供 :verbose => false 以不记录状态。
-
对于硬链接,提供 :symbolic => false。
示例¶ ↑
create_link "config/apache.conf", "/etc/apache.conf"
# File bundler/vendor/thor/lib/thor/actions/create_link.rb, line 17 def create_link(destination, *args) config = args.last.is_a?(Hash) ? args.pop : {} source = args.first action CreateLink.new(self, destination, source, config) end
返回此 thor 类的根目录(也别名为目标根目录)。
# File bundler/vendor/thor/lib/thor/actions.rb, line 99 def destination_root @destination_stack.last end
设置此 thor 类的根目录。相对路径被添加到调用脚本的目录中并展开。
# File bundler/vendor/thor/lib/thor/actions.rb, line 106 def destination_root=(root) @destination_stack ||= [] @destination_stack[0] = File.expand_path(root || "") end
将文件从源目录递归复制到根目录。如果任何文件以 .tt 结尾,则将其视为模板并放置在没有扩展名 .tt 的目标中。如果找到任何空目录,则将其复制,并且所有 .empty_directory 文件都将被忽略。如果任何文件名都用 % 符号括起来,则 % 符号中的文本将作为方法执行,并替换为返回的值。假设一个 doc 目录包含以下文件
doc/ components/.empty_directory README rdoc.rb.tt %app_name%.rb
当调用为
directory "doc"
它将在目标中创建一个 doc 目录,其中包含以下文件(假设 `app_name` 方法返回值为 “blog”)
doc/ components/ README rdoc.rb blog.rb
编码路径注意:由于 Bundler::Thor 内部使用 Object#respond_to? 来检查它是否可以展开 %something%,因此 `something` 应该是调用 directory
的类中的公共方法。如果方法是私有的,则 Bundler::Thor 堆栈会引发 PrivateMethodEncodedError。
参数¶ ↑
- source<字符串>
-
源根目录的相对路径。
- destination<字符串>
-
目标根目录的相对路径。
- config<哈希>
-
提供 :verbose => false 以不记录状态。如果 :recursive => false,则不递归查找路径。如果 :mode => :preserve,则保留源文件模式。如果 :exclude_pattern => /regexp/,则阻止复制与该正则表达式匹配的文件。
示例¶ ↑
directory "doc" directory "doc", "docs", :recursive => false
# File bundler/vendor/thor/lib/thor/actions/directory.rb, line 49 def directory(source, *args, &block) config = args.last.is_a?(Hash) ? args.pop : {} destination = args.first || source action Directory.new(self, source, destination || source, config, &block) end
接收文件或目录并在源路径中搜索它。
# File bundler/vendor/thor/lib/thor/actions.rb, line 133 def find_in_source_paths(file) possible_files = [file, file + TEMPLATE_EXTNAME] relative_root = relative_to_original_destination_root(destination_root, false) source_paths.each do |source| possible_files.each do |f| source_file = File.expand_path(f, File.join(source, relative_root)) return source_file if File.exist?(source_file) end end message = "Could not find #{file.inspect} in any of your source paths. ".dup unless self.class.source_root message << "Please invoke #{self.class.name}.source_root(PATH) with the PATH containing your templates. " end message << if source_paths.empty? "Currently you have no source paths." else "Your current source paths are: \n#{source_paths.join("\n")}" end raise Error, message end
获取给定地址的内容并将其放置在给定的相对目标位置。如果给出了代码块而不是目标,则会生成 URL 的内容并将其用作位置。
get
依赖于 open-uri,因此传递应用程序用户输入将提供命令注入攻击向量。
参数¶ ↑
- source<字符串>
-
给定内容的地址。
- destination<字符串>
-
目标根目录的相对路径。
- config<哈希>
-
提供 :verbose => false 以不记录状态,以及 :http_headers => <哈希> 以将标头添加到 HTTP 请求。
示例¶ ↑
get "http://gist.github.com/103208", "doc/README" get "http://gist.github.com/103208", "doc/README", :http_headers => {"Content-Type" => "application/json"} get "http://gist.github.com/103208" do |content| content.split("\n").first end
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 81 def get(source, *args, &block) config = args.last.is_a?(Hash) ? args.pop : {} destination = args.first render = if source =~ %r{^https?\://} require "open-uri" URI.send(:open, source, config.fetch(:http_headers, {})) { |input| input.binmode.read } else source = File.expand_path(find_in_source_paths(source.to_s)) File.open(source) { |input| input.binmode.read } end destination ||= if block_given? block.arity == 1 ? yield(render) : yield else File.basename(source) end create_file destination, render, config end
在文件上运行正则表达式替换。
参数¶ ↑
- path<字符串>
-
要更改的文件的路径
- flag<正则表达式|字符串>
-
要替换的正则表达式或字符串
- replacement<字符串>
-
替换内容,也可以以代码块的形式给出。
- config<哈希>
-
使用 `:verbose => false` 来不记录状态,使用 `:force => true` 来强制替换,而忽略执行器的行为。
示例¶ ↑
gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1' gsub_file 'README', /rake/, :green do |match| match << " no more. Use thor!" end
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 262 def gsub_file(path, flag, *args, &block) config = args.last.is_a?(Hash) ? args.pop : {} return unless behavior == :invoke || config.fetch(:force, false) path = File.expand_path(path, destination_root) say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true) unless options[:pretend] content = File.binread(path) content.gsub!(flag, *args, &block) File.open(path, "wb") { |file| file.write(content) } end end
进入根目录并执行给定的代码块。
# File bundler/vendor/thor/lib/thor/actions.rb, line 200 def in_root inside(@destination_stack.first) { yield } end
在类定义之后立即注入文本。由于它依赖于 insert_into_file
,因此是可逆的。
参数¶ ↑
- path<字符串>
-
要更改的文件的路径
- klass<String|Class>
-
要操作的类
- data<字符串>
-
要追加到类的数据,也可以以代码块的形式给出。
- config<哈希>
-
提供 :verbose => false 以不记录状态。
示例¶ ↑
inject_into_class "app/controllers/application_controller.rb", "ApplicationController", " filter_parameter :password\n" inject_into_class "app/controllers/application_controller.rb", "ApplicationController" do " filter_parameter :password\n" end
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 216 def inject_into_class(path, klass, *args, &block) config = args.last.is_a?(Hash) ? args.pop : {} config[:after] = /class #{klass}\n|class #{klass} .*\n/ insert_into_file(path, *(args << config), &block) end
在模块定义之后立即注入文本。由于它依赖于 insert_into_file
,因此是可逆的。
参数¶ ↑
- path<字符串>
-
要更改的文件的路径
- module_name<String|Class>
-
要操作的模块
- data<字符串>
-
要追加到类的数据,也可以以代码块的形式给出。
- config<哈希>
-
提供 :verbose => false 以不记录状态。
示例¶ ↑
inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper", " def help; 'help'; end\n" inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper" do " def help; 'help'; end\n" end
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 239 def inject_into_module(path, module_name, *args, &block) config = args.last.is_a?(Hash) ? args.pop : {} config[:after] = /module #{module_name}\n|module #{module_name} .*\n/ insert_into_file(path, *(args << config), &block) end
# File bundler/vendor/thor/lib/thor/actions/inject_into_file.rb, line 26 def insert_into_file(destination, *args, &block) data = block_given? ? block : args.shift config = args.shift || {} config[:after] = /\z/ unless config.key?(:before) || config.key?(:after) action InjectIntoFile.new(self, destination, data, config) end
在根目录或提供的子文件夹中执行某些操作。如果给出了相对路径,则从当前根目录引用。完整路径会传递给您提供的代码块。当方法退出时,路径将设置回先前的路径。
返回代码块产生的值。
参数¶ ↑
- dir<String>
-
要移动到的目录。
- config<哈希>
-
使用 `:verbose => true` 来记录并使用填充。
# File bundler/vendor/thor/lib/thor/actions.rb, line 170 def inside(dir = "", config = {}, &block) verbose = config.fetch(:verbose, false) pretend = options[:pretend] say_status :inside, dir, verbose shell.padding += 1 if verbose @destination_stack.push File.expand_path(dir, destination_root) # If the directory doesn't exist and we're not pretending if !File.exist?(destination_root) && !pretend require "fileutils" FileUtils.mkdir_p(destination_root) end result = nil if pretend # In pretend mode, just yield down to the block result = block.arity == 1 ? yield(destination_root) : yield else require "fileutils" FileUtils.cd(destination_root) { result = block.arity == 1 ? yield(destination_root) : yield } end @destination_stack.pop shell.padding -= 1 if verbose result end
将文件从相对源链接到相对目标。如果未给出目标,则假定其与源相同。
参数¶ ↑
- source<字符串>
-
源根目录的相对路径。
- destination<字符串>
-
目标根目录的相对路径。
- config<哈希>
-
提供 :verbose => false 以不记录状态。
示例¶ ↑
link_file "README", "doc/README" link_file "doc/README"
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 50 def link_file(source, *args) config = args.last.is_a?(Hash) ? args.pop : {} destination = args.first || source source = File.expand_path(find_in_source_paths(source.to_s)) create_link destination, source, config end
将文本前置到文件。由于它依赖于 insert_into_file
,因此是可逆的。
参数¶ ↑
- path<字符串>
-
要更改的文件的路径
- data<字符串>
-
要前置到文件的数据,也可以以代码块的形式给出。
- config<哈希>
-
提供 :verbose => false 以不记录状态。
示例¶ ↑
prepend_to_file 'config/environments/test.rb', 'config.gem "rspec"' prepend_to_file 'config/environments/test.rb' do 'config.gem "rspec"' end
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 170 def prepend_to_file(path, *args, &block) config = args.last.is_a?(Hash) ? args.pop : {} config[:after] = /\A/ insert_into_file(path, *(args << config), &block) end
返回相对于绝对根目录(即脚本启动的根目录)的给定路径。
# File bundler/vendor/thor/lib/thor/actions.rb, line 114 def relative_to_original_destination_root(path, remove_dot = true) root = @destination_stack[0] if path.start_with?(root) && [File::SEPARATOR, File::ALT_SEPARATOR, nil, ""].include?(path[root.size..root.size]) path = path.dup path[0...root.size] = "." remove_dot ? (path[2..-1] || "") : path else path end end
删除给定位置的文件。
参数¶ ↑
- path<字符串>
-
要更改的文件的路径
- config<哈希>
-
提供 :verbose => false 以不记录状态。
示例¶ ↑
remove_file 'README' remove_file 'app/controllers/application_controller.rb'
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 325 def remove_file(path, config = {}) return unless behavior == :invoke path = File.expand_path(path, destination_root) say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true) if !options[:pretend] && (File.exist?(path) || File.symlink?(path)) require "fileutils" ::FileUtils.rm_rf(path) end end
执行命令并返回命令的内容。
参数¶ ↑
- command<String>
-
要执行的命令。
- config<哈希>
-
使用 `:verbose => false` 来不记录状态,`:capture => true` 来隐藏输出。指定 `:with` 来将可执行文件追加到命令执行中。
示例¶ ↑
inside('vendor') do run('ln -s ~/edge rails') end
# File bundler/vendor/thor/lib/thor/actions.rb, line 248 def run(command, config = {}) return unless behavior == :invoke destination = relative_to_original_destination_root(destination_root, false) desc = "#{command} from #{destination.inspect}" if config[:with] desc = "#{File.basename(config[:with].to_s)} #{desc}" command = "#{config[:with]} #{command}" end say_status :run, desc, config.fetch(:verbose, true) return if options[:pretend] env_splat = [config[:env]] if config[:env] if config[:capture] require "open3" result, status = Open3.capture2e(*env_splat, command.to_s) success = status.success? else result = system(*env_splat, command.to_s) success = result end abort if !success && config.fetch(:abort_on_failure, self.class.exit_on_failure?) result end
在实例中保存源路径,以便可以对其进行操作。
# File bundler/vendor/thor/lib/thor/actions.rb, line 127 def source_paths @source_paths ||= self.class.source_paths_for_search end
获取相对源位置的 ERB 模板,执行它并在相对目标位置创建一个副本。如果未给出目标,则假定其与源相同,并从文件名中删除 .tt。
参数¶ ↑
- source<字符串>
-
源根目录的相对路径。
- destination<字符串>
-
目标根目录的相对路径。
- config<哈希>
-
提供 :verbose => false 以不记录状态。
示例¶ ↑
template "README", "doc/README" template "doc/README"
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 117 def template(source, *args, &block) config = args.last.is_a?(Hash) ? args.pop : {} destination = args.first || source.sub(/#{TEMPLATE_EXTNAME}$/, "") source = File.expand_path(find_in_source_paths(source.to_s)) context = config.delete(:context) || instance_eval("binding") create_file destination, nil, config do capturable_erb = CapturableERB.new(::File.binread(source), trim_mode: "-", eoutvar: "@output_buffer") content = capturable_erb.tap do |erb| erb.filename = source end.result(context) content = yield(content) if block content end end
运行 Thor 命令。可以给出选项的哈希,并将其转换为开关。
参数¶ ↑
- command<String>
-
要调用的命令
- args<Array>
-
命令的参数
- config<哈希>
-
使用 `:verbose => false` 来不记录状态,`:capture => true` 来隐藏输出。其他选项作为参数传递给 Bundler::Thor。
示例¶ ↑
thor :install, "http://gist.github.com/103208" #=> thor install http://gist.github.com/103208 thor :list, :all => true, :substring => 'rails' #=> thor list --all --substring=rails
# File bundler/vendor/thor/lib/thor/actions.rb, line 308 def thor(command, *args) config = args.last.is_a?(Hash) ? args.pop : {} verbose = config.key?(:verbose) ? config.delete(:verbose) : true pretend = config.key?(:pretend) ? config.delete(:pretend) : false capture = config.key?(:capture) ? config.delete(:capture) : false args.unshift(command) args.push Bundler::Thor::Options.to_switches(config) command = args.join(" ").strip run command, with: :thor, verbose: verbose, pretend: pretend, capture: capture end
取消注释与给定正则表达式匹配的所有行。保留注释哈希之前的缩进,并删除哈希和任何紧随其后的空格。
参数¶ ↑
- path<字符串>
-
要更改的文件的路径
- flag<正则表达式|字符串>
-
用于确定要取消注释的行的正则表达式或字符串
- config<哈希>
-
提供 :verbose => false 以不记录状态。
示例¶ ↑
uncomment_lines 'config/initializers/session_store.rb', /active_record/
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 289 def uncomment_lines(path, flag, *args) flag = flag.respond_to?(:source) ? flag.source : flag gsub_file(path, /^(\s*)#[[:blank:]]?(.*#{flag})/, '\1\2', *args) end
私有实例方法
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 346 def capture(*args) with_output_buffer { yield(*args) } end
# File bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 342 def concat(string) @output_buffer.concat(string) end