2

I use a YAML file to define my command line interface. I parse the file using Clap's load_yaml! macro, which worked out fine for some time:

#[macro_use]
extern crate clap;
use clap::{App, ArgMatches};

fn main() {
    let yml = load_yaml!("cl_arguments.yml");
    let matches = App::from_yaml(yml).get_matches();
    # some code goes here
}

Without me making any changes to the relevant code, this stopped working and I get the following error:

thread 'main' panicked at 'failed to convert YAML String("1") value to a string',
/home/me/.cargo/registry/src/github.com-1ecc6299db9ec823/clap-2.31.2/src/args/arg.rs:112:28

I am not sure if an update is to blame for this. I updated Rust and removed the Cargo.lock to rule out incompatibility issues, but that did not help.

This is a minimal version of my YAML file that produces the error:

name: "tool"
version: "0.1"
about: "description"
author: "m00am"

subcommands:
  - subcommand1:
      args:
        - path:
            index: "1"
            required: true
            default_value: "/tmp/"
            help: "Dummy Path"
  - subcommand2:
      args:
         - other_path:
             index: "1"
             required: true
             help: "A second dummy path"

Is this a known issue? What went wrong here? Is there anything I can do besides trying out combinations of older versions of Clap and the YAML crate?

Version info

Excerpt from Cargo.toml

[dependencies]
rand = "*"
cute = "0.3.0"
fasthash = "*"
bio = "*"
rulinalg = "*"
serde = "*"
serde_derive = "*"
bincode = "*"
statrs = "*"
separator = "*"
termion = "*"
sysinfo = "*"
clap = { version = "*", features = ["yaml"] }
needletail = "*"
gnuplot = "*"
time = "*"
cue = "*"

Excerpt from Cargo.lock

[[package]]
name = "clap"
version = "2.31.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]

...

[[package]]
name = "yaml-rust"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dtolnay
  • 9,621
  • 5
  • 41
  • 62
m00am
  • 5,910
  • 11
  • 53
  • 69

1 Answers1

5

The index property of an argument specification should be an integer, not a string. One can find an example of a positional argument with an explicit index in the documentation. Remove the quotes from around that value and the configuration file will work again.

name: "tool"
version: "0.1"
about: "description"
author: "m00am"

subcommands:
  - subcommand1:
      args:
        - path:
            index: 1
            required: true
            default_value: "/tmp/"
            help: "Dummy Path"
  - subcommand2:
      args:
         - other_path:
             index: 1
             required: true
             help: "A second dummy path"
$ cargo run -- subcommand1 --help

USAGE:
    tool subcommand1 <path>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

ARGS:
    <path>    Dummy Path [default: /tmp/]

I could not identify the reason why this used to work in previous versions. There is a chance that the implementation allowed it beyond the intended functionality. Otherwise, it could have been a breaking change from an early version of Clap with YAML configuration support. The dependencies in your Cargo.toml file are too flexible for long-term use, and makes these issues more likely to happen. Sticking to the default (caret) version ranges is usually the right thing to do (see specifying dependencies).

E_net4
  • 27,810
  • 13
  • 101
  • 139
  • Thank you for your answer. I already learned a lot here. However, I might have obfuscated the actual error when crafting my minimal example. Initially the error was `thread 'main' panicked at 'failed to convert YAML Integer(1) value to a string`, so I made them strings. With the index values as integers the minimal example works for me, but my actual file doen't. I will change the question title to better suit the error I described here, do some more research and maybe ask a new question with a more detailed description of my problem. – m00am Apr 21 '18 at 07:45
  • Turns out I added a `default_value` with an integer instead of a string, which turned out to be the reason for that error. Thank you for your help. – m00am Apr 23 '18 at 09:13