我正在努力使 CLI ruby 工具更加健壮,并对工具的 CLI 组件进行错误处理。我正在使用 optparse 并且文档显示标志可以具有强制和可选参数。我只是看到一些奇怪/烦人的行为。
对于标志的参数是强制性的(使用等号)的一种情况,我试图让它失败但它仍然有效,它只是抓住了下一个标志('-u')作为该标志的参数,而不是导致其余的解析以不太理想的方式失败。我想这还不错,因为'-....' 可能是有效的,但是因为我使用等号来设置开关的值,所以我假设'space' 样式分配不起作用.
op = OptionParser.new do |x|
x.on("-u", "--user=USER", "user flag") do |user| options[:user] = user end
x.on("-d", "--db=DATABASE", "database flag") do |db| options[:db] = db end
end
如果我通过以下 CLI 输入:
myprog -u -d mydb positionalarg
然后在解析过程中,它将 options[:user] 设置为 -d,并且 options[:db] 为 nil,因为它没有遇到并且有 2 个位置参数而不是 1。显然这是一个用户错误,但我想抓住它并显示一个真正的错误,而不仅仅是返回一个错误(在工具的情况下),应该从以下列表中只传递一个位置参数:......真正的问题是 -u 标志缺少它的必需参数所以鉴于 optparse 有一个 ArgumentMissing 异常,我假设这就是 .parse!会扔。
但是,对于具有可选参数(使用等号)的标志,如果您这样做,它实际上是可选的:-a -b=something 但这不起作用:-a something -b=somethingelse。强制该值的唯一方法是使用等号:-a=something -b=somethingelse。鉴于先前带有等号的强制性参数的行为,我认为不会是这种情况。例子:
op = OptionParser.new do |x|
x.on("-u", "--user[=USER]", "user flag") do |user| options[:user] = user unless user.nil? end
x.on("-d", "--db=DATABASE", "database flag") do |db| options[:db] = db end
end
所以通过解析:
myprog -u -d mydb positionalarg
那么 options[:user] 是 nil (ok) 并且 options[:db] 是 mydb 并且剩下一个位置参数。
通过此解析:
myprog -u myuser -d mydb positionalarg
然后 options[:user] 为 nil (不正常), options[:db] 为 mydb 并且剩下两个位置参数:myuser 和 positionalarg (不正常)。我的错误检查再次与位置 arg 计数有关。似乎如果使用强制标志参数,如果空格和 = 都有效,那么对于可选标志参数,它应该是相同的,但事实并非如此。
另一个问题是带有可选参数(使用空格)的标志很好,除非它们位于命令的末尾,然后将位置参数作为标志参数。
例子:
op = OptionParser.new do |x|
x.on("-u", "--user [USER]", "user flag") do |user| options[:user] = user unless user.nil? end
x.on("-d", "--db=DATABASE", "database flag") do |db| options[:db] = db end
end
所以通过解析:
myprog -d mydb -u positionalarg
然后 options[:db] 是 mydb (ok) 并且 options[:user] 是 positionalarg 并且没有剩余的位置参数。请注意, -d mydb 与空间一起使用,即使我用等号指定它也是如此。
似乎很多人通过执行 optparse .parse 来执行 ruby CLI!并将 ARGV 中的剩余条目作为位置参数,但我认为在将 ARGV 传递给 optparse 之前先将位置参数从远端剥离可能会更好(除非在位置参数数量可变的情况下失败。
我相信我可以围绕所有这些进行编程,但如果我不知道在 optparse 中有方法可以做到这一点,我不希望这样做。
也许最好的办法是避免带有可选参数的标志:),但任何建议都会受到赞赏。