Hiroto's diary

プログラミング関連とイベントの感想を書くかもしれない

RubyのThorで設定出来ないコマンド名を無理矢理設定する

Rubyで簡単にCLIツールを作れるThor。

github.com

Thorを使って、runshellなどのコマンド名でコマンドを作ろうとすると怒られます。

test-run.rb

require 'thor'

class Cli < Thor

  desc 'run', 'Run command.'
  def run
    puts 'Running "run" command.'
  end

  desc 'shell', 'Shell command.'
  def shell
    puts 'Running "shell" command.'
  end

end

Cli.start(ARGV)

実行すると…

$ ruby test-run.rb
/path/to/ruby/2.4.0/gems/thor-0.20.0/lib/thor/base.rb:557:in `is_thor_reserved_word?': "run" is a Thor reserved word and cannot be defined as command (RuntimeError)
    from /path/to/ruby/2.4.0/gems/thor-0.20.0/lib/thor/base.rb:620:in `method_added'
    from test-run.rb:6:in `<class:Cli>'
    from test-run.rb:3:in `<main>'

と怒られる。

設定出来ないメソッド名

Thor::THOR_RESERVED_WORDSで定義されているワードが使えません。

具体的には

invoke
shell
options
behavior
root
destination_root
relative_root
action
add_file
create_file
in_root
inside
run
run_ruby_script

です。

runshellは割りと使うので普通に困る。(startconsoleなどの別のコマンド名にすれば回避出来るとかは無しで…)

解決策

適当なメソッド名で書いた上で mapを使って紐付け

どうせ紐付けるのでメソッド名は何でも良いんですが、後ろに_commandとでも付けておくのがベタ。

require 'thor'

class Cli < Thor

  desc 'run', 'Run command.'
  def run_command
    puts 'Running "run" command.'
  end

  # runコマンドをrun_commandに紐付け
  map 'run' => 'run_command'

  desc 'shell', 'Shell command.'
  def shell_command
    puts 'Running "shell" command.'
  end

  # shellコマンドをshell_commandに紐付け
  map 'shell' => 'shell_command'

end

Cli.start(ARGV)

実行してみる。

$ ruby test-run.rb
Commands:
  test-run.rb help [COMMAND]  # Describe available commands or one specific com...
  test-run.rb run             # Run command.
  test-run.rb shell           # Shell command.

$ ruby test-run.rb run
Running "run" command.

$ ruby test-run.rb shell
Running "shell" command.

これで怒られずにrunshellコマンドを作成出来ます。

© 2015-2018 Hiroto-K