RubyでSTDINやSTDOUTを活用できるCLIツールを書く


CLIツールを作るとき、UNIX哲学が好きな人は、
パイプを活用できるように、STDINから入力を取得したいし、STDOUTへ出力したいですよね。

サンプルとして、STDINから取得した文字列をキャメルケースにしたり、スネークケースにしたりしてSTDOUTに出力するコマンドを作ってみます。

こんなイメージのCLIツールを作ってみます。

$ cat 'hello_world' | mycommand camelize
HelloWorld

$ cat 'HelloWorld' | mycommand snake
hello_world

パイプでつなげるので

$ cat 'hello_world' | mycommand camelize | mycommand snake
hello_world

という無駄なこともできます。

bundler gem で雛形を作成する

まずはbundler gemコマンドで雛形を作成します。

$ bundler gem mycommand

CLIツールを簡単に作れるgemのThorを利用するので、mycommand.gemspecファイルにthorを追加します。

spec.add_dependency "thor"

とりあえずbundleを叩いてThorをインストールしておきます。

$ bundle

lib/mycommand.rbを書きます。コマンドはcamelizesnakeを作ります。

require "mycommand/version"
require "thor"

module Mycommand
  class CLI < Thor

    desc "echo 'hello_world' | mycommand camelize", "Camelize STDIN"
    def camelize()
      stdin = stdin_read
      puts stdin.split('_').map{|s| s.capitalize}.join('')
    end

    desc "echo 'HelloWorld' | mycommand snake", "Snakecase STDIN"
    def snake()
      stdin = stdin_read
      puts stdin.split(/(?![a-z])(?=[A-Z])/).map{|s| s.downcase}.join('_')
    end

    private
    def stdin_read()
      return $stdin.read
    end

  end
end

bin/mycommandも書きます。

#!/usr/bin/env ruby

require 'mycommand'
Mycommand::CLI.start

コマンドを試してみる

bin/mycommandに実行権限を与えます。

$ chmod +x bin/mycommand

コマンド実行を試してみます

$ echo 'hello_world' | bundle exec bin/mycommand camelize
HelloWorld

$ echo 'HelloWorld' | bundle exec bin/mycommand snake
hello_world'

$ echo 'hello_world' | bundle exec bin/mycommand camelize | bundle exec bin/mycommand snake
hello_world'

できました!

あとは、必要に応じてmycommand.gemspecファイルのTODOを修正して bundle exec rake install なりしてしまえばSTDINを入力として受け取れるmycommandができます。

というわけで

良いCLIツールライフを!

参考URL