explicitly |ɪkˈsplɪsɪtli|
adverb
①(clearly, precisely)明确地 míngquè de ‹warn, forbid, tell, deny›
②(openly)坦率地 tǎnshuài de ‹talk, admit›
③(graphically)生动地 shēngdòng de ‹depict, display›
入门
简单说,所有继承自Thor
类的类都是可以执行的, 而且可以带很多子命令和参数.
在这样的类里, 所有的公开方法都是可以作为第一参数的形式来执行各种子命令的.
最后的效果就是能够像 git 或者 bundler 那样灵活使用.
看简单的例子:
我们创建一个文件: touch cli
, 然后编辑这个文件, 创建一个类MyCLI
, 然后继续了Thor
.
class MyCLI < Thor
desc "hello NAME", "say hello to NAME"
def hello(name)
puts "Hello #{name}"
end
end
MyCLI.start(ARGV)
这个时候如果我们使用ruby
来执行这个文件的话, 我们会发现这样的结果:
─> ruby cli
Commands:
cli hello NAME # say hello to NAME
cli help [COMMAND] # Describe available commands or one specific command
这里需要注意的就是在定义完这个类之后, 它会通过MyCLI.start(ARGV)
里的一个start
方法来触发当前文件中所有可以当作子命令来执行的类. 而且它还可以帮助解析从命令行传递的参数作为方法参数使用, 如果当前没有传递任何参数,就会默认输出帮助信息.
如上面的输出:
cli hello NAME # say hello to NAME
我们来把玩一下:
─> ruby cli hello "xiang"
Hello xiang
有点酷? 我们继续
关于命令的描述
默认 Thor 会使用desc
来作为短描述使用, 如果想要使用长描述, 可以通过使用long_desc
来完成.
在 长描述的场合,有时候需要强制换行, 可以通过如 markdown 一样的方式 用\x5
来实现.
class MyCLI < Thor
desc "hello NAME", "say hello to NAME"
long_desc <<-LONGDESC
`cli hello` will print out a message to a person of your
choosing.
You can optionally specify a second parameter, which will print
out a from message as well.
> $ cli hello "Yehuda Katz" "Carl Lerche"
\x5> from: Carl Lerche
LONGDESC
def hello(name, from=nil)
puts "from: #{from}" if from
puts "Hello #{name}"
end
end
命令选修和标识
Thor 已经实现了轻松使用命令的选项和标识:
class MyCLI < Thor
desc "hello NAME", "say hello to NAME"
option :from
def hello(name)
puts "from: #{options[:from]}" if options[:from]
puts "Hello #{name}"
end
end
这个时候,可以这样玩:
$ ruby ./cli hello --from "Carl Lerche" Yehuda
from: Carl Lerche
Hello Yehuda
$ ruby ./cli hello Yehuda --from "Carl Lerche"
from: Carl Lerche
Hello Yehuda
$ ruby ./cli hello Yehuda --from="Carl Lerche"
from: Carl Lerche
Hello Yehuda
但是一般来说,所有的参数都是作为字符串来使用的, 不过也可以这样:
class MyCLI < Thor
option :from
option :yell, :type => :boolean
desc "hello NAME", "say hello to NAME"
def hello(name)
output = []
output << "from: #{options[:from]}" if options[:from]
output << "Hello #{name}"
output = output.join("\n")
puts options[:yell] ? output.upcase : output
end
end
这样玩:
$ ./cli hello --yell Yehuda --from "Carl Lerche"
FROM: CARL LERCHE
HELLO YEHUDA
$ ./cli hello Yehuda --from "Carl Lerche" --yell
FROM: CARL LERCHE
HELLO YEHUDA
同样,还有必选参数选修哦
class MyCLI < Thor
option :from, :required => true
option :yell, :type => :boolean
desc "hello NAME", "say hello to NAME"
def hello(name)
output = []
output << "from: #{options[:from]}" if options[:from]
output << "Hello #{name}"
output = output.join("\n")
puts options[:yell] ? output.upcase : output
end
end
这样的话,如果没有from
选修:
$ ./cli hello Yehuda
No value provided for required options '--from'
下面是对于选修的解释:
:desc: A description for the option. When printing out full usage for a command using cli help hello, this description will appear next to the option.
:banner: The short description of the option, printed out in the usage description. By default, this is the upcase version of the flag (from=FROM).
:required: Indicates that an option is required
:default: The default value of this option if it is not provided. An option cannot be both :required and have a :default.
:type: :string, :hash, :array, :numeric, or :boolean
:aliases: A list of aliases for this option. Typically, you would use aliases to provide short versions of the option.
另外, 可以通过options
这个参数来一次性搞定所有选修参数
class MyCLI < Thor
desc "hello NAME", "say hello to NAME"
options :from => :required, :yell => :boolean
def hello(name)
output = []
output << "from: #{options[:from]}" if options[:from]
output << "Hello #{name}"
output = output.join("\n")
puts options[:yell] ? output.upcase : output
end
end