解析 docopt 参数类型(任何语言)

huangapple go评论83阅读模式
英文:

Parsing docopt argument types (any language)

问题

我有一个使用情况,用户提供一个docopt字符串,我根据它生成一些代码。所以我事先不知道我的docopt字符串。

对于某些“参数类型”(而不是数据类型),我希望生成各种代码。

在接下来的内容中,我将区分“类型”和“数据类型”。对于docopt参数--arg=DEGREES和argv输入--arg=10--arg的“类型”是DEGREES,而数据类型是integer。值是10

用户可能给我以下docopt字符串:

Naval Fate.

Usage:
  naval_fate --dir=FILE [--speed=ABC]

Options:
  --dir=FILE   Moored (anchored) mine.
  --speed=ABC  Speed in knots [default: 10]。

除了像往常一样解析这个docopt字符串,我还试图弄清楚dirspeed参数所要求的“类型”。我想知道dir的类型是FILEspeed的类型是ABC

示例:

给定上述docopt字符串和argv字符串naval_fate --dir=/tmp --speed 1234,我希望不仅可以访问值和数据类型(<key> => <value,datatype>),还可以访问“配置类型”(<key> => <value,datatype,argtype>),即类似以下内容:

dir => val: /tmp,数据类型:String类型:FILE
speed => val: 1234,数据类型:Integer类型:ABC

任何(可管理的)docopt实现都可以接受,包括Python的实现,但最好是在编译语言中找到解决方案,比如C、Go、Rust等。

英文:

I have a use case where users provide a docopt string, and based on it, I generate some code. So I do not know my docopt string up front.

For certain "argument types" (not datatypes), I wish to generate various code.

In the following, I will distinguish between "types" and "datatypes". For the docopt argument --arg=DEGREES and the argv input --arg=10, the "type" of --arg is DEGREES, while the datatype is integer. The value is 10.

A user may give me the following docopt string:

Naval Fate.

Usage:
  naval_fate --dir=FILE [--speed=ABC]

Options:
  --dir=FILE   Moored (anchored) mine.
  --speed=ABC  Speed in knots [default: 10].

Besides parsing this docopt string as usual, I'm trying to also figure out what "type" of argument dir and speed asks for. I want to know that dir is of type FILE and speed is of type ABC.

Example:

Given the above docopt string, and an argv string naval_fate --dir=/tmp --speed 1234, I hope to access not just the value and datatype (&lt;key&gt; =&gt; &lt;value,datatype&gt;), but also the "config type" (&lt;key&gt; =&gt; &lt;value,datatype,argtype&gt;, i.e. something along the lines of:

dir => val: /tmp, datatype: String, type: FILE
speed => val: 1234, datatype: Integer, type: ABC

Any (managed) implementation of docopt is acceptable, including Python's, though preferably I'm looking for a solution in a compiled language, be it C, Go, Rust etc.

答案1

得分: 1

这在Rust的Docopt中非常简单:

#![allow(unstable)]

extern crate docopt;

use docopt::Docopt;

static USAGE: &amp;'static str = "
Naval Fate.

Usage:
    naval_fate ship --dir=FILE [--speed <kn>]
    naval_fate (-h | --help)

Options:
    -h --help     Show this screen.
    --speed <kn>  Speed in knots [default: 10].
    --dir=FILE    Moored (anchored) mine.
";

fn main() {
    let args = Docopt::new(USAGE)
                      .and_then(|d| d.parse())
                      .unwrap_or_else(|e| e.exit());
    println!("Type of 'ship': {:?}", args.find("ship"));
    println!("Type of '--dir': {:?}", args.find("--dir"));
    println!("Type of '--speed': {:?}", args.find("--speed"));
}

输出结果为:

$ ./target/scratch ship --dir /tmp --speed 1234                                      
Type of 'ship': Some(Switch(true))                                                                       
Type of '--dir': Some(Plain(Some("/tmp")))                                                               
Type of '--speed': Some(Plain(Some("1234"))) 

关键是find的返回类型是Value,它是一个代数数据类型:http://burntsushi.net/rustdoc/docopt/enum.Value.html --- 因此,通过构造,你可以免费获得参数的“类型”。

请注意,这适用于Docopt使用字符串中的任何“参数”,即使它没有传递到参数列表中。

英文:

This is pretty easy with Rust's Docopt:

#![allow(unstable)]

extern crate docopt;

use docopt::Docopt;

static USAGE: &amp;&#39;static str = &quot;
Naval Fate.

Usage:
    naval_fate ship --dir=FILE [--speed &lt;kn&gt;]
    naval_fate (-h | --help)

Options:
    -h --help     Show this screen.
    --speed &lt;kn&gt;  Speed in knots [default: 10].
    --dir=FILE    Moored (anchored) mine.
&quot;;

fn main() {
    let args = Docopt::new(USAGE)
                      .and_then(|d| d.parse())
                      .unwrap_or_else(|e| e.exit());
    println!(&quot;Type of &#39;ship&#39;: {:?}&quot;, args.find(&quot;ship&quot;));
    println!(&quot;Type of &#39;--dir&#39;: {:?}&quot;, args.find(&quot;--dir&quot;));
    println!(&quot;Type of &#39;--speed&#39;: {:?}&quot;, args.find(&quot;--speed&quot;));
}

Which outputs:

$ ./target/scratch ship --dir /tmp --speed 1234                                        
Type of &#39;ship&#39;: Some(Switch(true))                                                                       
Type of &#39;--dir&#39;: Some(Plain(Some(&quot;/tmp&quot;)))                                                               
Type of &#39;--speed&#39;: Some(Plain(Some(&quot;1234&quot;))) 

The key is that the return type of find is Value, which is an algebraic data type: http://burntsushi.net/rustdoc/docopt/enum.Value.html --- So by construction, you get the "type" of the argument for free.

Note that this will work for any "argument" in the Docopt usage string, even if it isn't passed into the argument list.

huangapple
  • 本文由 发表于 2015年1月29日 16:39:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/28210260.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定