Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

Ruby | CLI | Be Helpful | Documenting a Command Suit

概要

書籍 Build Awesome Command-Line Applications in Ruby2

Be Helpful

詳細

Command suit は各コマンドごとのドキュメントが必要になる。
これは2段階のヘルプシステムで提供する。

まず、1段階目として

command -h

で、globalなオプション・コマンドリスト・各コマンドが何をするかの概要を表示します。

そして、2段階目として

command -h subcommand

で、サブコマンドの内容を表示します。

サンプル仕様

下記記事のサンプルをベースに設定を追加します。

Ruby | CLI | Be Easy to Use | Ruby | CLI | Thorを利用した使いやすいCommand suitインターフェース
http://d.hatena.ne.jp/tbpg/20140526/1401109675

サンプルコード

require 'csv'
require 'thor'
require 'pp'

class PersonViewer < Thor
  package_name "person_viewer"
  VERSION = "0.0.1"
  PERSONALS = './personals.csv'
  UP_OPTIONS = {type: :boolean, aliases: '-u', desc: "文字を大文字にする"}
  DOWN_OPTIONS = {type: :boolean, aliases: '-d', desc: "文字を小文字にする"}
  class_option :help, type: :boolean, aliases: '-h', desc: 'ヘルプを表示します'
  class_option :version, type: :boolean, desc: 'バージョンを表示します'

  desc "名前を表示します", "名前を表示します"
  option :upcase, UP_OPTIONS
  option :downcase, DOWN_OPTIONS
  def firstname
    read_csv.each do |row|
      row[:firstname] = row[:firstname].upcase if options[:upcase]
      row[:firstname] = row[:firstname].downcase if options[:downcase]
      puts row[:firstname]
    end
  end

  desc "find by firstname [FIRSTNAME]", "find by firstname [FIRSTNAME]"
  def find_by_firstname(text = '')
    target = read_csv.select { |row|row[:firstname] =~ /#{text}/ }
    pp target
  end

  desc "名字を表示します", "名字を表示します"
  option :upcase, UP_OPTIONS
  option :downcase, DOWN_OPTIONS
  def lastname
    read_csv.each do |row|
      row[:lastname] = row[:lastname].upcase if options[:upcase]
      row[:lastname] = row[:lastname].downcase if options[:downcase]
      puts row[:lastname]
    end
  end

  desc "フルネームを表示します", "フルネームを表示します"
  option :upcase, UP_OPTIONS
  option :downcase, DOWN_OPTIONS
  def fullname
    read_csv.each do |row|
      tmp_fullname = "#{row[:firstname]} #{row[:lastname]}"
      tmp_fullname = tmp_fullname.upcase if options[:upcase]
      tmp_fullname = tmp_fullname.downcase if options[:downcase]
      puts tmp_fullname
    end
  end

  desc "年齢を表示します", "年齢を表示します"
  option :upcase, UP_OPTIONS
  option :downcase, DOWN_OPTIONS
  def age
    read_csv.each { |row|puts row[:age] }
  end

  desc 'バージョンを表示します', 'バージョンを表示します'
  def version
    puts VERSION
  end

  def self.banner(task, namespace = false, subcommand = true)
      super
  end

  private
    def read_csv
      CSV.table(PERSONALS)
    end
end
PersonViewer.start(ARGV)

出力

globalなヘルプ
$ ruby personal.rb -h
person_viewer commands:
  personal.rb find by firstname [FIRSTNAME]  # find by firstname [FIRSTNAME]
  personal.rb help [COMMAND]                 # Describe available commands or...
  personal.rb バージョンを表示します                    # バージョンを表示します
  personal.rb フルネームを表示します                    # フルネームを表示します
  personal.rb 名前を表示します                       # 名前を表示します
  personal.rb 名字を表示します                       # 名字を表示します
  personal.rb 年齢を表示します                       # 年齢を表示します

Options:
  -h, [--help], [--no-help]        # ヘルプを表示します
      [--version], [--no-version]  # バージョンを表示します
SubCommandsのヘルプ
$ ruby personal.rb -h fir
Usage:
  personal.rb person_viewer 名前を表示します

Options:
  -u, [--upcase], [--no-upcase]      # 文字を大文字にする
  -d, [--downcase], [--no-downcase]  # 文字を小文字にする
  -h, [--help], [--no-help]          # ヘルプを表示します
      [--version], [--no-version]    # バージョンを表示します

名前を表示します