Пространство имен команд thor в автономном исполняемом файле ruby

При вызове команд thor в командной строке имена методов распределяются по их структуре модуля/класса, например.

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

будет запускаться командой

thor app:hello

Однако, если вы сделаете это самоисполняемым, поставив

App.start

внизу вы можете запустить команду, например:

app hello

Есть ли способ указать пространство имен для этих команд? Чтобы можно было позвонить, например

app say:hello
app say:goodbye

person philnash    schedule 14.04.2011    source источник


Ответы (2)


Другой способ сделать это - использовать регистрацию:

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

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

CLI.start

Теперь, если ваш исполняемый файл называется foo, вы можете вызвать:

$ foo sub bar

Однако в текущей версии thor (0.15.0.rc2) есть ошибка, из-за которой тексты справки пропускают пространство имен подкоманд:

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

Вы можете исправить это, переопределив 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

Второй параметр formatted_usage — единственное отличие от оригинальной реализации баннера. Вы также можете сделать это один раз, и другие подкоманды или классы будут наследоваться от SubTask. Теперь вы получаете:

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

Надеюсь, это поможет.

person tfischbach    schedule 31.08.2011
comment
Святое дерьмо! Где ты был 8 часов моей жизни назад? Спасибо за элегантное решение. - person elmt; 23.12.2011
comment
У меня это не сработало (thor 0.18.1), но аналогичная работа описана в github.com/wycats/thor/issues/261#issuecomment-16880836 работал - person Robert J Berger; 09.05.2013

Это один из способов с App в качестве пространства имен по умолчанию (хотя и довольно хакерский):

#!/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

Или тоже не идеально:

define_method 'say:hello'
person Ian Fleeton    schedule 09.05.2011
comment
так что нет чистого способа сделать это? он просто не поддерживается? - person rubiii; 11.05.2011
comment
Я не могу сказать наверняка. Я пытался найти чистый путь и потерпел неудачу. Я думаю, что метод пространства имен работает только при использовании команды thor, а не отдельного исполняемого файла. - person Ian Fleeton; 11.05.2011