简体   繁体   English

命名空间Thor命令在独立的ruby可执行文件中

[英]Namespacing thor commands in a standalone ruby executable

When calling thor commands on the command line, the methods are namespaced by their module/class structure, eg 在命令行上调用thor命令时,这些方法按其模块/类结构命名,例如

class App < Thor
  desc 'hello', 'prints hello'
  def hello
    puts 'hello'
  end
end

would be run with the command 将使用该命令运行

thor app:hello

However, if you make that self executable by putting 但是,如果你通过推杆使自己可执行

App.start

at the bottom you can run the command like: 在底部你可以运行如下命令:

app hello

Is there any way to namespace those commands? 有没有办法命名这些命令? So that you could call, for example 例如,你可以打电话

app say:hello
app say:goodbye

Another way of doing this is to use register: 另一种方法是使用寄存器:

class CLI < Thor
  register(SubTask, 'sub', 'sub <command>', 'Description.')
end

class SubTask < Thor
  desc "bar", "..."
  def bar()
    # ...
  end
end

CLI.start

Now - assuming your executable is called foo - you can call: 现在 - 假设您的可执行文件名为foo - 您可以调用:

$ foo sub bar

In the current thor version (0.15.0.rc2) there is a bug though, which causes the help texts to skip the namespace of sub commands: 在当前的thor版本(0.15.0.rc2)中存在一个错误,导致帮助文本跳过子命令的命名空间:

$ foo sub
Tasks:
   foo help [COMMAND]  # Describe subcommands or one specific subcommand
   foo bar             #

You can fix that by overriding self.banner and explicitly setting the namespace. 您可以通过重写self.banner并显式设置命名空间来解决此问题。

class SubTask < Thor
  namespace :sub

  def bar ...

  def self.banner(task, namespace = true, subcommand = false)
    "#{basename} #{task.formatted_usage(self, true, subcommand)}"
  end
end

The second parameter of formatted_usage is the only difference to the original implemtation of banner. formatted_usage的第二个参数是banner原始实现的唯一区别。 You can also do this once and have other sub command thor classes inherit from SubTask. 您也可以执行此操作,并从SubTask继承其他子命令Thor类。 Now you get: 现在你得到:

$ foo sub
Tasks:
   foo sub help [COMMAND]  # Describe subcommands or one specific subcommand
   foo sub bar             #

Hope that helps. 希望有所帮助。

This is one way with App as the default namespace (quite hacky though): 这是App作为默认命名空间的一种方式(虽然非常hacky):

#!/usr/bin/env ruby
require "rubygems"
require "thor"

class Say < Thor
  # ./app say:hello
  desc 'hello', 'prints hello'
  def hello
    puts 'hello'
  end
end

class App < Thor
  # ./app nothing
  desc 'nothing', 'does nothing'
  def nothing
    puts 'doing nothing'
  end
end

begin
  parts = ARGV[0].split(':')
  namespace = Kernel.const_get(parts[0].capitalize)
  parts.shift
  ARGV[0] = parts.join
  namespace.start
rescue
  App.start
end

Or, also not ideal: 或者,也不理想:

define_method 'say:hello'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM