ruby中Thor用法,MyCLI < Thor详细介绍

作者:小白蒋,个人博客:www.nihao070.cn

ruby中thor详细用法

  • ruby中Thor是什么?
  • 第一点:公共方法变成命令
  • 第二点:你也可以使用Ruby的可选参数使CLI参数可选
  • 第三点:long_desc、\x5
  • 第四点:thor可以更容易指定选项和标签作为元数据
  • 第五点:默认情况下,选项是字符串,但是你可以为任何选项指定另一种类型:
  • 第六点:您还可以指定一个特定的选项是必需的。
  • 第七点:如果只想指定选项的类型,可以使用简写方式一次性指定多个选项。你可以重写前面的例子为:
  • 第八点:您可以使用class_option为整个类指定一个应该存在的选项。类选项采用与单个命令选项完全相同的参数,但应用于一个类的所有命令。
  • 第九点:当您的CLI变得更加复杂时,您可能希望能够指定指向自己的一组子命令的命令。其中一个示例是git remote命令,它公开添加、重命名、rm、修剪、设置头等等。

ruby中Thor是什么?

答:Thor是构建强大命令行接口的工具箱。Bundler, Vagrant, Rails以及其他的一些项目使用了Thor构建其命令行工具。bundler用来处理Ruby项目的版本依赖,Vagrant用来管理虚拟机运行环境,Rails是web开发框架。
Thor is a toolkit for building powerful command-line interfaces. It is used in Bundler, Vagrant, Rails and others.

第一点:公共方法变成命令

一个简单的Thor类公开带有许多子命令的可执行文件,比如git或bundler。在Thor类中,公共方法变成命令。
新建一个MyCLI.rb文件

  1 require "thor"
  2 
  3 class MyCLI < Thor
  4     desc "hello NAME", "say hello to NAME"
  5     def hello(name)
  6         puts "hi #{
       name}"
  7     end
  8 end
  9 
 10 MyCLI.start(ARGV)
~                           

在这里,你想执行,上面定义的hello方法就得在命令中输入,然后hello 命令后面在跟参数name

ruby MyCLI hello mary

输出:

hi Mary

第二点:你也可以使用Ruby的可选参数使CLI参数可选

  1 require "thor"
  2 
  3 class MyCLI < Thor
  4     desc "hello NAME", "say hello to NAME"
  5     def hello(name, from=nil)
  6         puts "from: #{
       from}" if from
  7         puts "hello #{
       name}"
  8     end
  9 end
 10 
 11 MyCLI.start(ARGV)                        

执行ruby MyCLI.rb hello mary bos, from参数如果不传递就是nil(空),如果传递就打印出from:bos

from: bos
hello mary

第三点:long_desc、\x5

①在许多情况下,您需要在较长的使用说明中提供较长的描述。在这种情况下,可以使用long_desc指定更长的使用指令。
②默认情况下,较长的描述以终端的大小包装行,并使用一个换行符将行分组在一起,就像Markdown一样。还可以在行首使用\x5转义序列强制行之间进行一次硬换行。**

  1 require "thor"
  2 
  3 class MyCLI < Thor
  4   desc "hello NAME", "say hello to NAME"
  5   long_desc <<-LONGDESC
  6     `cli hello` will print out a message to a person of your
  7     choosing.
  8 
  9     You can optionally specify a second parameter, which will print
 10     out a from message as well.
 11 
 12     > $ cli hello "Yehuda Katz" "Carl Lerche"
 13 
 14     \x5> from: Carl Lerche
 15   LONGDESC
 16   def hello(name, from=nil)
 17     puts "from: #{
       from}" if from
 18     puts "Hello #{
       name}"
 19   end
 20 end
 21 
 22 MyCLI.start(ARGV)     
 执行跟上面命令一样                     

第四点:thor可以更容易指定选项和标签作为元数据

Thor makes it easy to specify options and flags as metadata about a Thor command:

  1 require "thor"
  2 
  3 class MyCLI < Thor
  4   desc "hello NAME", "say hello to NAME"
  5   option :from
  6   def hello(name)
  7     puts "from: #{
       options[:from]}" if options[:from]
  8     puts "Hello #{
       name}"
  9   end
 10 end
 11 
 12 MyCLI.start(ARGV)

执行:ruby My2.rb hello --from beijing mary或者可以用ruby My2.rb hello beijing --from mary或者ruby My2.rb hello beijing --from=mary
输出:

from: beijing
Hello mary

第五点:默认情况下,选项是字符串,但是你可以为任何选项指定另一种类型:

By default, options are Strings, but you can specify an alternate type for any options:

  1 require 'thor'
  2 
  3 class MyCLI < Thor
  4   option :from
  5   option :yell, :type => :boolean
  6   desc "hello NAME", "say hello to NAME"
  7   def hello(name)
  8     output = []
  9     output << "from: #{
       options[:from]}" if options[:from]
 10     output << "Hello #{
       name}"
 11     output = output.join("\n")
 12     puts options[:yell] ? output.upcase : output
 13   end
 14 end
 15 
 16 MyCLI.start(ARGV)

执行ruby My2.rb hello --from beijing maaa --yell,因为这里yell传递了,所以执行了output.upcase,都输出了大写,如果这里不传递yell,输出全是小写
结果:

FROM: BEIJING
HELLO MAAA

第六点:您还可以指定一个特定的选项是必需的。

`您还可以指定一个特定的选项是必需的。

  1 require 'thor'
  2 
  3 class MyCLI < Thor
  4   option :from, :required => true
  5   option :yell, :type => :boolean
  6   desc "hello NAME", "say hello to NAME"
  7   def hello(name)
  8     output = []
  9     output << "from: #{
       options[:from]}" if options[:from]
 10     output << "Hello #{
       name}"
 11     output = output.join("\n")
 12     puts options[:yell] ? output.upcase : output
 13   end
 14 end
 15 
 16 MyCLI.start(ARGV)

意思就是这里from参数必须要传递,否则报错,下面试一下
执行命令ruby My2.rb hello beijing --yell
结果:

No value provided for required options '--from'

执行ruby My2.rb hello mary --from beijing --yell
结果:

FROM: BEIJING
HELLO MARY

第七点:如果只想指定选项的类型,可以使用简写方式一次性指定多个选项。你可以重写前面的例子为:

You can use a shorthand to specify a number of options at once if you just want to specify the type of the options. You could rewrite the previous example as:

  1 require "thor"
  2 
  3 class MyCLI < Thor
  4     desc "hello NAME", "say hello to NAME"
  5     options :from => :required, :yell => :boolean
  6     def hello(name)
  7         output = []
  8         output << "from: #{
       options[:from]}" if options[:from]
  9         output << "Hello #{
       name}"
 10         output = output.join("\n")
 11         puts options[:yell] ? output.upcase : output
 12     end
 13 end
 14 
 15 MyCLI.start

输出ruby My3.rb hello --from beijing jack --yell
结果:

FROM: BEIJING
HELLO JACK

第八点:您可以使用class_option为整个类指定一个应该存在的选项。类选项采用与单个命令选项完全相同的参数,但应用于一个类的所有命令。

You can specify an option that should exist for the entire class by using class_option. Class options take exactly the same parameters as options for individual commands, but apply across all commands for a class.

  1 require "thor"
  2 
  3 class MyCLI < Thor
  4     class_option :verbose, :type => :boolean
  5 
  6     desc "hello NAME", "say hello to NAME"
  7     options :from => :required, :yell => :boolean
  8 
  9     def hello(name)
 10         puts "> saying hello" if options[:verbose]
 11         output = []
 12         output << "from: #{
       options[:from]}" if options[:from]
 13         output << "Hello #{
       name}"
 14         output = output.join("\n")
 15         puts options[:yell] ? output.upcase : output
 16         puts "> done saying hello" if options[:verbose]
 17     end
 18 
 19     desc "goodbye", "say goodbye to the world"
 20     def goodbye
 21         puts "> saying goodbye" if options[:verbose]
 22         puts "Goodbye World"
 23         puts "> done saying goodbye" if options[:verbose]
 24     end
 25 end
 26 
 27 MyCLI.start

执行: ruby My4.rb goodbye --verbose
结果:

> saying goodbye
Goodbye World
> done saying goodbye

第九点:当您的CLI变得更加复杂时,您可能希望能够指定指向自己的一组子命令的命令。其中一个示例是git remote命令,它公开添加、重命名、rm、修剪、设置头等等。

As your CLI becomes more complex, you might want to be able to specify a command that points at its own set of subcommands. One example of this is the git remote command, which exposes add, rename, rm, prune, set-head, and so on.

在Thor中,您可以通过创建一个新的Thor类来表示子命令,并从父类指向它来轻松实现这一点。让我们看看如何实现git remote。这个示例是有意简化的。

In Thor, you can achieve this easily by creating a new Thor class to represent the subcommand, and point to it from the parent class. Let’s take a look at how you would implement git remote. The example is intentionally simplified.

1 require 'thor'
  2 
  3 module GitCLI
  4   class Remote < Thor
  5     desc "add  ", "Adds a remote named  for the repository at "
  6     long_desc <<-LONGDESC
  7       Adds a remote named <name> for the repository at <url>. The command git fetch <name> can then be     used to create and update
  8       remote-tracking branches <name>/<branch>.
  9 
 10       With -f option, git fetch <name> is run immediately after the remote information is set up.
 11 
 12       With --tags option, git fetch <name> imports every tag from the remote repository.
 13 
 14       With --no-tags option, git fetch <name> does not import tags from the remote repository.
 15 
 16       With -t <branch> option, instead of the default glob refspec for the remote to track all branche    s under $GIT_DIR/remotes//, a
 17       refspec to track only <branch> is created. You can give more than one -t <branch> to track multi    ple branches without grabbing all
 18       branches.
 19 
 20       With -m <master> option, $GIT_DIR/remotes/<name>/HEAD is set up to point at remote's <master> br    anch. See also the set-head
 21       command.
 22 
 23       When a fetch mirror is created with --mirror=fetch, the refs will not be stored in the refs/remo    tes/ namespace, but rather
 24       everything in refs/ on the remote will be directly mirrored into refs/ in the local repository.     This option only makes sense in
 25       bare repositories, because a fetch would overwrite any local commits.
 26 
 27       When a push mirror is created with --mirror=push, then git push will always behave as if --mirro    r was passed.
 28     LONGDESC
 29     option :t, :banner => ""
 30     option :m, :banner => ""
 31     options :f => :boolean, :tags => :boolean, :mirror => :string
 32     def add(name, url)
 33       # implement git remote add
 34     end
 35 
 36     desc "rename  ", "Rename the remote named  to "
 37     def rename(old, new)
 38     end
 39   end
 40 
 41   class Git < Thor
 42     desc "fetch  [...]", "Download objects and refs from another repository"
 43     options :all => :boolean, :multiple => :boolean
 44     option :append, :type => :boolean, :aliases => :a
 45     def fetch(respository, *refspec)
 46       # implement git fetch here
 47     end
 48 
 49     desc "remote SUBCOMMAND ...ARGS", "manage set of tracked repositories"
 50     subcommand "remote", Remote
 51   end
 52 
 53 
 54 
 55 end

你可能感兴趣的:(ruby学习,ruby,thor)