這是一篇使用ruby和commander來構(gòu)建一個命令行交互app(command line interface,CLI).
Gemfile
創(chuàng)建一個工程目錄,創(chuàng)建一個Gemfile.
mkdir ruby-cli
cd ruby-cli
touch Gemfile
這個Gemfile只包含一個gem,即commander:
備注:commander的github已經(jīng)從作者寫文章時候的https://github.com/tj/commander 遷移到了 https://github.com/commander-rb/commander
source "http://rubygems.org"
gem "commander"
運行bundle install.如果你電腦上沒有bundler,首先你需要用gem install bundler來安裝它.
? bundle install
Fetching gem metadata from http://rubygems.org/...
Resolving dependencies...
Using bundler 2.0.1
Using highline 2.0.2
Using commander 4.4.7
Bundle complete! 1 Gemfile dependency, 3 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
翻譯補充: gem可以安裝一個包的很多個版本,那么對于多個版本所產(chǎn)生的問題,怎么解決呢?
Bundler https://bundler.io 就是為了解決這個問題的, 它提供了兩個命令
bundle install :根據(jù)Gemfile中申明的gem全部安裝,并將版本號等寫入Gemfile.lock文件,保證不同的機器執(zhí)行的時候,獲取到的都是相同的依賴包
bundle exec:替我們解決了多版本環(huán)境不隔離的問題。當你執(zhí)行 bundle exec的時候,Bundler 會把 LOAD_PATH中不相干的那些 gem 的路徑全都去掉拥诡,然后讀取 Gemfile.lock 中的 gem 版本(如果沒有 Gemfile.lock 會決議版本后創(chuàng)建一個 Gemfile.lock),保證 $LOAD_PATH中只存在 Gemfile.lock 中已經(jīng)固定版本的 gem 的路徑
代碼
下面是我們創(chuàng)建的的文件名為rbuy-cli.rb的示例代碼:
#!/usr/bin/env ruby
require 'rubygems'
require "bundler/setup"
require 'commander/import'
program :name, "Ruby CLI"
program :version, '1.0.0'
program :description, 'A simple cli that does nothing'
command :extract do |c|
c.syntax = 'ruby-cli extract foo -bar=123'
c.description = 'Extract foo and bar'
c.option '--bar STRING', String, 'Option bar with a string'
c.action do |args, options|
options.default :bar => 'BAR'
puts 'Extracting..'
puts "Args: #{args}"
puts "Option Bar: #{options.bar}"
end
end
我們現(xiàn)在可以運行ruby ruby-cli.rb extract.當然了,由于這個文件頭部添加了使用ruby來解釋的聲明,還可以簡單地使用./ruby-cli.rb來運行.(當然,首先還是得使用chmod a+x ruby-cli.rb來讓這個文件具有可執(zhí)行權(quán)限,否則是不可以直接調(diào)用的).
譯者注
當你運行上面的命令的時候,你可能會遇到和我一樣的問題
You must use Bundler 2 or greater with this lockfile.
當你檢查
? bundle -v
Bundler version 2.0.1
明明bundle已經(jīng)是2.x的版本了,怎么還提示這個錯誤呢?
我們可以通過 gem list來查看本地的bundle
看到
? gem list
*** LOCAL GEMS ***
activesupport (4.2.11.1)
addressable (2.6.0)
atomos (0.1.3)
aws-sdk (1.67.0)
aws-sdk-v1 (1.67.0)
babosa (1.0.2)
bigdecimal (default: 1.4.1)
bundler (2.0.1, default: 1.17.3)
.......
從上面我們可以看到,對于我們這個版本的ruby(我的是2.6.0),它默認裝載的是bundle1.17.3.
解決的辦法很簡單,就是在
ruby-cli.rb文件的
require "bundler/setup"的上面添加require 'bundler'.
繼續(xù)
從上面的示例,可以看到,通過commander,我們可以很容易的描述我們的CLI.運行
./ruby-cli.rb --help
,將會展示一個非常友好的關(guān)于所有支持的命令的幫助信息.在我們上面的rb文件中,只定義了一個名字為extract的命令.
在我們的extract命令中,我們打印了所有的參數(shù)和選項.
這里,只要一個選項 --bar,它帶有一個默認的字符串"BAR".
Ruby Gem
直到現(xiàn)在為止,我們都是用 ruby ./ruby-cli.rb ... 來運行的.
其實我們可以將其制作成一個gem包,然后直接像其它命令那樣,運行 ruby-cli ...
為了實現(xiàn)制作一個gem包,
我們創(chuàng)建一個bin目錄,將腳本移動到bin目錄下,并且去掉.rb后綴.
mkdir bin
mv ruby-cli.rb bin/ruby-cli
移動后,我們的目錄應(yīng)該是這樣
.
├── Gemfile
├── Gemfile.lock
└── bin
└── ruby-cli
現(xiàn)在,我們創(chuàng)建一個文件 ruby-cli.gemspec
添加內(nèi)容
Gem::Specification.new do |s|
s.name = 'ruby-cli'
s.version = '1.0.0'
s.date = '2015-12-25'
s.summary = "Our simple CLI"
s.description = "Our very very simple CLI"
s.authors = [ "Luke Skywalker" ]
s.email = 'lukeskywalker@gmail.com'
s.executables << 'ruby-cli'
s.add_dependency 'commander'
end
現(xiàn)在,編譯這個gem:
gem build ruby-cli.gemset
沒有錯誤的話,會在目錄下生成文件 ruby-cli-1.0.0.gem
現(xiàn)在,我們已經(jīng)得到了一個gem的安裝文件
通過如下命令來安裝它:
gem install ruby-cli-1.0.0.gem
現(xiàn)在,你可以直接運行這個命令了
? ruby-cli gem install ruby-cli-1.0.0.gem
Successfully installed ruby-cli-1.0.0
Parsing documentation for ruby-cli-1.0.0
Installing ri documentation for ruby-cli-1.0.0
Done installing documentation for ruby-cli after 0 seconds
1 gem installed
? ruby-cli ruby-cli extract foo -bar=1213
Extracting..
Args: ["foo"]
Option Bar: ar=1213
PS:這是我寫的第一個Ruby教程.對于使用Ruby,我內(nèi)心已經(jīng)掙扎過很多次了,因為像Python和Go這樣的語言已經(jīng)很棒了,并且,我也確信,有一天可以使用Apple的Swift語言來編寫腳本.
我不得不使用Ruby的最主要原因是,有很多現(xiàn)有的工具都是用Ruby構(gòu)建的,例如,我最愛的諸多工具中的Jekyll和Fastlane.
譯者添加
我們可以卸載它,卸載的時候,是不帶版本號的!!
? ruby-cli gem uninstall ruby-cli
Remove executables:
ruby-cli
in addition to the gem? [Yn] Y
Removing ruby-cli
Successfully uninstalled ruby-cli-1.0.0