7

我在 Ruby (test.rb) 中有这样一个简单的代码:

#! /usr/bin/env ruby

require 'optparse'

OptionParser.new do |option|
  option.on("--sort", "Sort data") do 
    puts "--sort passed"
  end
end.parse!

然后我运行它:./test.rb -s并得到:

--sort passed

我错过了什么吗?

我想要唯一的--sort(长)选项,而不是短选项。

我如何得到它?

4

5 回答 5

3

optparse.rb我在第 1378-1380 行中找到了导致此行为的代码:

# if no short options match, try completion with long
# options.
sw, = complete(:long, opt)

如果您不喜欢这种行为,似乎最好的选择是optparse.rb在您的项目中创建一个副本,删除副本中的违规rescue InvalidOption子句load,而不是标准库的版本。

于 2013-12-18T09:40:14.527 回答
2

有趣的行为是,如果您定义以相同字母开头的相似长选项,在示例中是s. 它不允许使用-skey with exception OptionParser::AmbiguousOption,但似乎没有办法在OptionParser不侵入其代码的情况下禁用 short 选项:

#! /usr/bin/env ruby

require 'optparse'

OptionParser.new do |option|
  option.on("--sport", "Sport data") do
    puts "--sport passed"
  end
  option.on("--sort", "Sort data") do
    puts "--sort passed"
  end
end.parse!

这是on方法的扩展版本:

OptionParser.new do |option|
  opts = [ "--sort", "Sort data" ]
  sw = option.make_switch(opts) 
  block = proc { puts "--sort passed" }
  sw[0].instance_variable_set :@block, block
  option.top.append *sw
  p sw
  # => [#<OptionParser::Switch::NoArgument:0x806c770 @pattern=/.*/m, @conv=#<Proc:0x806dd8c@/home/malo/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/optparse.rb:1617>, @short=[], @long=["--sort"], @arg=nil, @desc=["Sort data"], @block=#<Proc:0x806c70c@./1.rb:8>>, [], ["sort"], nil, []]
end.parse!
# => --sort passed when  ./1.rb --sort and ./1.rb -s

有趣的是,@short变量是空的,但应用程序会对-s键做出反应。

我更喜欢使用micro-optparsegem。按如下方式使用它:

宝石文件

gem 'micro-optparse', :git => 'https://github.com/3aHyga/micro-optparse.git', :branch => 'no-short' # for now it is available only from git repo

ruby_script.rb

require 'micro-optparse'

options = Parser.new do |p|
   p.banner = "This is a fancy script, for usage see below"
   p.option :sport, "sport", :default => "Sport", :short => "p"
   p.option :sort, "sort", :default => "Sort", :short => false
end.process!

p options

模拟:

$ bundle exec ./1.rb --sort 111
{:sport=>"Sport", :sort=>"111"}

$ bundle exec ./1.rb -s 111
ambiguous option: -s

$ bundle exec ./1.rb -p 111
{:sport=>"111", :sort=>"Sort"}
于 2013-12-18T10:17:02.797 回答
2

您可以重新打开 OptionParser::OptionMap 以禁用完成:

class OptionParser::OptionMap
  def complete(key, icase = false, pat = nil)
    # disable completions
    nil
  end
end

这将禁用搜索要完成的内容的预定义行为。

于 2021-07-14T06:04:22.303 回答
1

我的程序有一个参数'--sort',它可以接受'-s'、's'、'+s'等参数

在这种情况下,您可以将一组有效参数传递给您的选项:

require 'optparse'

OptionParser.new do |option|
  option.on("--sort TYPE", %w(-s s +s), "Sort data") do |type|
    puts "--sort passed with argument #{type}"
  end
end.parse!

用法:

$ ./test.rb --sort -s
--sort passed with argument -s
$ ./test.rb --sort s
--sort passed with argument s
$ ./test.rb --sort +s
--sort passed with argument +s

请注意,您仍然可以使用简写-s

$ ./test.rb -s -s
--sort passed with argument -s
$ ./test.rb -s s
--sort passed with argument s
$ ./test.rb -s +s
--sort passed with argument +s
于 2013-12-18T10:58:03.270 回答
0

从文档来看,这似乎是不可能的。

#on方法使用 的语法,此处#make_switch对其进行了描述。整个文档没有提到能够打开或关闭长变量或短变量。

然而,这真的是个问题吗?约定是可以通过长名称和短名称访问选项,并且强制更改该行为可能会使您的用户感到沮丧。

如果您真的不想允许使用短名称,最好的选择是查看其他一些库(例如 highline、slop、trollop)或滚动您自己的库。

于 2013-12-18T09:39:24.417 回答