Help us understand the problem. What is going on with this article?

Ruby の CLI ツールの作成を支援する、 thor gem の基本について。 #thor #ruby

More than 5 years have passed since last update.

Ruby の CLI ツールの作成を支援する、 thor gem の基本について。

概要

Ruby の CLI ツールの作成を支援する、 thor gem の基本について。

Thor 関連資料

CLI のクラス作成

Thor クラスを継承し、 public メソッドを定義すると
該当メソッドがコマンドになります。

require 'thor'
class SampleCLI < Thor
  desc "command1 usage", "command1 desc"
  def command1(name)
    puts "command1 #{name}"
  end

  desc "command2 usage", "command2 desc"
  def command2(name)
    puts "command2 #{name}"
  end
end

SampleCLI.start(ARGV)
  • 出力
$ ruby thor_class_define.rb help
Commands:
  thor_class_define.rb command1 usage  # command1 desc
  thor_class_define.rb command2 usage  # command2 desc
  thor_class_define.rb help [COMMAND]  # Describe available commands or one specific command

$ ruby thor_class_define.rb help command1
Usage:
  thor_class_define.rb command1 usage

command1 desc
$ ruby thor_class_define.rb help command2
Usage:
  thor_class_define.rb command2 usage

command2 desc

$ ruby thor_class_define.rb command1 hoge
command1 hoge

各種設定

package_name(name, options = {})

パッケージ名を指定する。
help コマンドを実行した際に表示される。

require 'thor'
class SampleCLI < Thor
  package_name "package_name"
end

SampleCLI.start(ARGV)
  • 出力
$ ruby thor_class_package_name.rb help
package_name commands:
  thor_class_package_name.rb help [COMMAND]  # Describe available commands or one specific command

各種設定

default_command(meth = nil)

デフォルトのコマンドを指定する。
コマンド名を省略した際に実行されるコマンドを決定する。
default_command を指定しなかった場合は、 help コマンドが実行される。

require 'thor'
class SampleCLI < Thor
  default_command :command1
  desc "command1 usage", "command1 desc"
  def command1(name = 'default')
    puts "command1 #{name}"
  end

  desc "command2 usage", "command2 desc"
  def command2(name)
    puts "command2 #{name}"
  end
end

SampleCLI.start(ARGV)
  • 出力
$ ruby thor_class_default_command.rb
command1 default
$ ruby thor_class_default_command.rb command1
command1 default
$ ruby thor_class_default_command.rb command1 hoge
command1 hoge
  • default_command を無効化
require 'thor'
class SampleCLI < Thor
  # default_command :command1
  desc "command1 usage", "command1 desc"
  def command1(name = 'default')
    puts "command1 #{name}"
  end

  desc "command2 usage", "command2 desc"
  def command2(name)
    puts "command2 #{name}"
  end
end

SampleCLI.start(ARGV)
  • 出力
$ ruby thor_class_default_command.rb
Commands:
thor_class_default_command.rb command1 usage  # command1 desc
thor_class_default_command.rb command2 usage  # command2 desc
thor_class_default_command.rb help [COMMAND]  # Describe available commands or one specific command

register(klass, subcommand_name, usage, description, options = {})

外部コマンドの登録

  • thor_class_register_main.rb
require 'thor'
require './thor_class_register_sub'
class SampleCLI < Thor
  register(SubCommand, "sub", "command2 usage override", "command2 desc override")
  register(GroupPlugin, "group", "group usage override", "group desc override")

  desc "command1 usage", "command1 desc"
  def command1(name = 'default')
    puts "command1 #{name}"
  end
end

SampleCLI.start(ARGV)
  • thor_class_register_sub.rb
require 'thor'
class SubCommand < Thor
  desc "command2 usage", "command2 desc"
  def command2(name)
    puts "command2 #{name}"
  end

  desc "command3 usage", "command3 desc"
  def command3(name)
    puts "command3 #{name}"
  end
end

# Thor::Group は定義したコマンドを上から順にすべて実行する
class GroupPlugin < Thor::Group
  desc "hoge1"
  def hoge1
    puts "hoge1"
  end

  desc "hoge2"
  def hoge2
    puts "hoge2"
  end
end
  • 出力
$ ruby thor_class_register_main.rb help
Commands:
  thor_class_register_main.rb command1 usage        # command1 desc
  thor_class_register_main.rb group usage override  # group desc override
  thor_class_register_main.rb help [COMMAND]        # Describe available commands or one specific command
  thor_class_register_main.rb sub usage override    # sub desc override

# サブコマンドの定義を確認
$ ruby thor_class_register_main.rb help sub
Commands:
  thor_class_register_main.rb sub_command command2 usage  # command2 desc
  thor_class_register_main.rb sub_command command3 usage  # command3 desc
  thor_class_register_main.rb sub_command help [COMMAND]  # Describe subcommands or one specific subcommand

$ ruby thor_class_register_main.rb sub command2 hoge
command2 hoge
$ ruby thor_class_register_main.rb sub command3 hige
command3 hige

# Thor::Group を継承したクラスの全メソッドの結果が出力される
$ ruby thor_class_register_main.rb group
hoge1
hoge2

desc(usage, description, options = {})

usage と description を定義する。
設定した内容は、 help で確認可能。

require 'thor'
class SampleCLI < Thor
  desc "command1 usage", "command1 desc"
  def command1(name)
    puts "command1 #{name}"
  end
end

SampleCLI.start(ARGV)
  • 出力
$ ruby thor_class_desc.rb help
Commands:
  thor_class_desc.rb command1 usage  # command1 desc
  thor_class_desc.rb help [COMMAND]  # Describe available commands or one specific command

long_desc(long_description, options = {})

usage と description を定義する。
設定した内容は、 help で確認可能。

require 'thor'
class SampleCLI < Thor
  desc "command1 usage", "command1 desc"
  long_desc "long desc"
  def command1(name)
    puts "command1 #{name}"
  end
end

SampleCLI.start(ARGV)
  • 出力
$ ruby thor_class_long_desc.rb help
Commands:
  thor_class_long_desc.rb command1 usage  # command1 desc
  thor_class_long_desc.rb help [COMMAND]  # Describe available commands or one specific command

$ ruby thor_class_long_desc.rb help command1
Usage:
  thor_class_long_desc.rb command1 usage

Description:
  long desc

map(mappings = nil)

mappings のマップのキーを値に紐付ける

require 'thor'
class SampleCLI < Thor
  map "CM1" => "command1"

  desc "command1 usage", "command1 desc"
  def command1(name)
    puts "command1 #{name}"
  end
end

SampleCLI.start(ARGV)
  • 出力
$ ruby thor_map.rb CM1 test
command1 test
$ ruby thor_map.rb command test
command1 test

method_option(name, options = {})

内部で option エイリアスを定義している

key value
:desc Description for the argument.
:required If the argument is required or not.
:default Default value for this argument. It cannot be required and have default values.
:aliases Aliases for this option.
:type The type of the argument, can be :string, :hash, :array, :numeric or :boolean.
:banner String to show on usage notes.
:hide If you want to hide this option from the help.
require 'thor'
class SampleCLI < Thor
  desc "command1 usage", "command1 desc"
  method_option "opt", desc: 'ops'
  def command1(name)
    print options['opt'], "\n"
    puts "command1 #{name}"
  end

  desc "command2 usage", "command2 desc"
  option "opt", required: true
  def command2(name)
    print options['opt'], "\n"
    puts "command2 #{name}"
  end

  desc "command3 usage", "command3 desc"
  option "opt", aliases: "o"
  def command3(name)
    print options['opt'], "\n"
    puts "command3 #{name}"
  end

  desc "command4 usage", "command4 desc"
  option "opt", type: :string
  def command4(name)
    print options['opt'], "\n"
    puts "command4 #{name}"
  end

  desc "command5 usage", "command5 desc"
  option "opt", type: :array
  def command5(name)
    print options['opt'], "\n"
    puts "command5 #{name}"
  end

  desc "command6 usage", "command6 desc"
  option "opt", banner: "banner"
  def command6(name)
    print options['opt'], "\n"
    puts "command6 #{name}"
  end

  desc "command7 usage", "command7 desc"
  option "opt", hide: true
  def command7(name)
    print options['opt'], "\n"
    puts "command7 #{name}"
  end
end

SampleCLI.start(ARGV)
  • 出力

desc option

$ ruby thor_method_option.rb help command1
Usage:
  thor_method_option.rb command1 usage

Options:
  [--opt=OPT]  # ops

$ ruby thor_method_option.rb command1 hoge --opt="@@@@@"
@@@@@
command1 hoge

require option

$ ruby thor_method_option.rb help command2
Usage:
  thor_method_option.rb command2 usage --opt=OPT

Options:
  --opt=OPT

command2 desc

# require に設定したオプションがないためエラー
$ ruby thor_method_option.rb command2 hoge
No value provided for required options '--opt'

$ ruby thor_method_option.rb command2 hoge --opt=opt_value
opt_value
command2 hoge

aliases option

$ ruby thor_method_option.rb help command3
Usage:
  thor_method_option.rb command3 usage

Options:
  o, [--opt=OPT]

command3 desc

$ ruby thor_method_option.rb command3 hoge -o "@@@@@"
@@@@@
command3 hoge

$ ruby thor_method_option.rb command3 hoge --opt="@@@@@"
@@@@@
command3 hoge

type option

  • String
$ ruby thor_method_option.rb help command4
Usage:
  thor_method_option.rb command4 usage

Options:
  [--opt=OPT]

command4 desc

$ ruby thor_method_option.rb command4 hoge --opt="string"
string
command4 hoge

$ ruby thor_method_option.rb command4 hoge --opt={key1: 1, key2: 2}
ERROR: "thor_method_option.rb command4" was called with arguments ["hoge", "1,", "key2:", "2}"]
Usage: "thor_method_option.rb command4 usage"
  • Array
$ ruby thor_method_option.rb help command5
Usage:
  thor_method_option.rb command5 usage

Options:
  [--opt=one two three]

command5 desc

banner option

$ ruby thor_method_option.rb help command6
Usage:
  thor_method_option.rb command6 usage

Options:
  [--opt=banner]

command6 desc

# 配列で受け取る
$ ruby thor_method_option.rb command5 hoge --opt=hoge hige hage
["hoge", "hige", "hage"]
command5 hoge

# 配列以外は配列に変換
$ ruby thor_method_option.rb command5 hoge --opt=1
["1"]
command5 hoge

# 配列以外は配列に変換
$ ruby thor_method_option.rb command5 hoge --opt={key1: 1, key2: 2}
["{key1:", "1,", "key2:", "2}"]
command5 hoge

hide option

オプションをヘルプには表示しない。
動作上は利用できる。

$ ruby thor_method_option.rb command7 hoge --opt="@@@"
@@@
command7 hoge

method_options(options = nil)

内部で options エイリアスを定義している

キーにオプション名、 値にデータ型(type)を定義する。

require 'thor'
class SampleCLI < Thor
  desc "command1 usage", "command1 desc"
  options opt1: :string, opt2: :array
  def command1(name)
    print options, "\n"
    puts "command1 #{name}"
  end
end

SampleCLI.start(ARGV)
  • 出力
$ ruby thor_method_options.rb command1 hoge --opt1=string --opt2=ary1 ary2 ary3
{"opt1"=>"string", "opt2"=>["ary1", "ary2", "ary3"]}
command1 hoge

参照

tbpgr
Rubyを扱う人事(研修開発、エンジニア採用) Learning Designer。 tbpgr の読み方は(てぃーびー) 個人ブログでも色々と情報を垂れ流してます。 http://tbpgr.hatenablog.com/
http://tbpgr.hatenablog.com/
studist
「伝えることを、もっと簡単に」をミッションにビジュアルSOPマネジメントプラットフォームのBtoB SaaS「Teachme Biz」を開発・運営するスタートアップ
https://medium.com/studist-dev
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした