【Ruby】optparseの使い方

Rubyを学習する過程で使用した`optparse`の使い方を解説したいと思います。
本記事に間違った内容が含まれている場合、ご指摘いただけますと幸いです。

## `optparse`とは
[公式リファレンス](https://docs.ruby-lang.org/ja/latest/library/optparse.html)を見ていただければわかりますが、要するに**コマンド実行時のオプションを自分で作るためのライブラリ**です。
オプションというのは、コマンドを実行するときにその後に`-`や`--`をつけて指定できるものです。
たとえばGitの`branch`コマンドでは、以下のように`-d`(`--delete`)オプションの後にブランチ名を指定することでそのブランチを削除できます。`-d`がショートオプション、`--delete`がロングオプションです。
```
git branch -d ブランチ名
git branch --delete ブランチ名
```

上の例ではオプションのあとにブランチ名を指定していますが、これは引数となるものです。引数は省略できる場合もあります。`オプション(+引数)`で色々な操作が実現可能になります。`optparse`で自分の好きなオプションを作成可能です。


## `optparse`の使ったオプションの作成方法
`require`します。

```diff_ruby:optparse.rb
+ require 'optparse'
```

`OptionParser.new`ブロック内に必要なオプションを定義します。
引数なしのオプションを作成する場合はオプション名のみ、引数ありのオプションを作成する場合はオプション名と引数名を指定します。
下記の例は、引数に指定した値を`x`にプラスする処理です。`-a`オプションのあとに引数の`number`を書いています。

```diff_ruby:optparse.rb
require 'optparse'

+ x = 10
+ options = {} # 引数の値を入れるための空の配列を作成
+ OptionParser.new do |opts|
+   opts.on('-a number') do |number|
+     options[:number] = number.to_i
+     x += options[:number]
+   end
+ end.parse!

+ puts x
```

```:実行結果
$ ruby optparse.rb -a 10
20
```

### コードの役割
```ruby
options = {}
```
引数を入れるための空の配列を作成しています。

```ruby
options[:number] = number.to_i
```
引数は文字列として扱われるので、`number.to_i`で数値型に変換しています。もしこの行を以下のように書くとエラーになります。
```ruby
x += number
```

```:実行結果
$ ruby optparse.rb -a 10
optparse.rb:10:in `+': String can't be coerced into Integer (TypeError)
```

ただし、以下のように引数の型を指定しておけばまた別です。
- [Ruby の OptionParser チートシート #Ruby - Qiita](https://qiita.com/sonots/items/1b44ed3a770ef790a63d#%E6%95%B4%E6%95%B0%E5%BC%95%E6%95%B0%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3)
```ruby
opts.on('-a number', Integer) do |number|
  options[:number] = number
  x += options[:number]
end
```

```ruby
end.parse!
```
この行はARGV(オプションと引数の配列)から引数だけを取り出します。この行まで来たらブロック内の処理が行われます。もし`.parse!`の部分がなかったら以下のようにブロック内の処理が行われません。

```diff_ruby
require 'optparse'

x = 10
options = {} # 引数の値を入れるための空の配列を作成
OptionParser.new do |opts|
  opts.on('-a number') do |number|
    options[:number] = number.to_i
    x += options[:number]
  end
- end.parse!
+ end
puts x
```

```:実行結果
$ ruby optparse.rb -a 10
10
```


### 補足
#### ロングオプション
指定する場合は以下のようになります。
```diff_ruby:optparse.rb
- opts.on('-a number') do |number|
+ opts.on('-a', '--add number') do |number|
```
```:実行結果
$ ruby optparse.rb --add 10
20
```

#### 引数なしの場合
本記事では引数必須のオプションを作成したので、引数を指定しないとエラーになります。
```:実行結果
$ ruby optparse.rb -a
optparse.rb:16:in `<main>': missing argument: -a (OptionParser::MissingArgument)
$ ruby optparse.rb --add
optparse.rb:16:in `<main>': missing argument: --add (OptionParser::MissingArgument)
```

本記事では解説しませんが、省略可の引数ありのオプションを作成する場合は、引数を`[]`で囲みます。
- [ruby コマンドライン引数 optparseの利用 スクリプトの書き方 | バイオインフォ 道場 [bioinfo-Dojo]](https://bioinfo-dojo.net/2017/07/18/ruby_optparse/)


#### ヘルプ
オプションの説明を加えておくことで、`-h`(`--help`)でコマンドの説明を出力できます。
```ruby:optparse.rb
opts.on('-a', '--add number', 'add') do |number|
```

```:実行結果
$ ruby optparse.rb -h
Usage: optparse [options]
    -a, --add number                 add
$ ruby optparse.rb --help
Usage: optparse [options]
    -a, --add number                 add
```

以上になります。


## 参考記事
- [コマンドライン引数によるオプションに対応する (optparse) - まくまくRubyノート](https://maku77.github.io/ruby/io/optparse.html)
- [Rubyのoptparseについて掘り下げてみる - あきろぐ](https://akng-engineer.hatenablog.com/entry/2021/12/02/225959)
- [Ruby実行時のオプションをよろしく解析してくれるoptparseを使ってみる - kk_Atakaの日記](https://note.gosyujin.com/2011/12/21/1324477125/#%E3%81%82%E3%82%89%E3%81%99%E3%81%98)
- [OptionParser | Ruby API (v3.2)](https://rubyapi.org/3.2/o/optionparser)
- [ruby で ARGV をうけるコマンドっぽいものを作ってみる | DriftwoodJP](https://www.d-wood.com/blog/2014/05/15_6221.html)
- [ruby コマンドライン引数 optparseの利用 スクリプトの書き方 | バイオインフォ 道場 [bioinfo-Dojo]](https://bioinfo-dojo.net/2017/07/18/ruby_optparse/)
- [optparseライブラリを使う(in Ruby) | 雑記帳](https://cosmo0920.wordpress.com/2011/06/13/optparse%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%82%92%E4%BD%BF%E3%81%86in-ruby/)
- [RubyのOptionParserの底力を知る - ザリガニが見ていた...。](https://zariganitosh.hatenablog.jp/entry/20140819/ruby_optparser_true_power)
- [初心者でもわかるRubyのコマンドラインオプション - すずかのプログラミング勉強記](https://suzuka-hk.hatenablog.com/entry/2023/11/20/105820)