我试图编写一个可以从标准输入或作为命令行选项提供的文件中读取的nim程序。我使用docopt来解析命令行。
import docopt
const doc = """
This program takes input from a file or from stdin.
Usage:
testinput [-i <filename> | --input <filename>]
-h --help Show this help message and exit.
-i --input <filename> File to use as input.
"""
when isMainModule:
let args = docopt(doc)
var inFilename: string
for opt, val in args.pairs():
case opt
of "-i", "--input":
inFilename = $args[opt]
else:
echo "Unknown option" & opt
quit(QuitFailure)
let inputSource =
if inFilename.isNil:
stdin
else:
echo "We have inFilename: " & inFilename
open(inFilename)
该程序编译。
当我在命令行上给它一个文件时,它不会崩溃:
$ ./testinput -i testinput.nim
We have inFilename: testinput.nim
但是如果我试图从它的stdin中提取它,我会得到一个IOError:
$ ./testinput < testinput.nim
We have inFilename: nil
testinput.nim(28) testinput
system.nim(2833) sysFatal
Error: unhandled exception: cannot open: nil [IOError]
为什么inFilename.isNil
是假的,但else
分支的执行告诉我inFilename
&#34;是&#34; nil
?
有没有一种正确而优雅的方法来使用docopt?
答案 0 :(得分:1)
我不熟悉docopt,但它似乎为文档中的每个选项创建了一个条目,而不是为用户指定的选项创建条目,因此您的代码已获得args == {"--input": nil}
并且字符串化nil
。
以下内容将正常运行:
import docopt
const doc = """
This program takes input from a file or from stdin.
Usage:
testinput [-i <filename> | --input <filename>]
-h --help Show this help message and exit.
-i --input <filename> File to use as input.
"""
when isMainModule:
let args = docopt(doc)
var inFilename: string
if args["--input"]:
inFilename = $args["--input"]
if not inFilename.isNil:
echo "We have inFilename: " & inFilename
let inputSource =
if inFilename.isNil:
stdin
else:
open(inFilename)
另请注意,您不必检查"-i"
选项,因为docopt知道它是"--input"
的别名。
答案 1 :(得分:0)
不是将选项的值转换为$
的字符串,而是将其保留为Value
,这是docopt
返回的类型。
vkNone
(无价值)当存在尚未设置且没有默认值的选项时,会出现此类值。转换
时为falsetoBool
显然可以在布尔表达式中使用选项的值,它似乎自动解释为bool
:
import docopt
const doc = """
This program takes input from a file or from stdin.
Usage:
testinput [-i <filename> | --input <filename>]
-h --help Show this help message and exit.
-i --input <filename> File to use as input.
"""
when isMainModule:
let args = docopt(doc)
var inFilename: Value
for opt, val in args.pairs():
case opt
of "-i", "--input":
inFilename = val
else:
echo "Unknown option" & opt
quit(QuitFailure)
let inputSource =
if not bool(inFilename):
stdin
else:
echo "We have inFilename: " & $inFilename
open($inFilename)
this other anwser中给出了此行为的另一种用法,并避免设置变量,因此保留变量nil
。