Rust: парсить вводимую пользователем строку с хлопком для программирования командной строки

Я хотел бы создать командную строку, которая использует хлопок для анализа ввода. Лучшее, что я могу придумать, - это цикл, который запрашивает у пользователя ввод, разбивает его на регулярное выражение и создает Vec, который он каким-то образом передает

loop {
    // Print command prompt and get command
    print!("> "); io::stdout().flush().expect("Couldn't flush stdout");

    let mut input = String::new(); // Take user input (to be parsed as clap args)
    io::stdin().read_line(&mut input).expect("Error reading input.");
    let args = WORD.captures_iter(&input)
           .map(|cap| cap.get(1).or(cap.get(2)).unwrap().as_str())
           .collect::<Vec<&str>>();

    let matches = App::new("MyApp")
        // ... Process Clap args/subcommands
    .get_matches(args); //match arguments from CLI args variable
}

В принципе, мне интересно, есть ли способ заставить Clap использовать заранее заданный список аргументов?


person Will Nilges    schedule 26.05.2020    source источник
comment
clap, вероятно, не имеет такой функциональности, потому что clap обычно получает командную строку не как отдельную строку, а как список строк, уже проанализированных оболочкой. Можно попросить clap использовать список строк вместо использования аргументов программ.   -  person mcarton    schedule 27.05.2020
comment
Я не уверен, правильно ли понимаю вопрос. Вы спрашиваете, как разобрать все аргументы, переданные как одну строку?   -  person Shiva    schedule 01.05.2021


Ответы (2)


Как говорит @mcarton, программам командной строки аргументы передаются в виде массива, а не строки. Оболочка разделяет исходную командную строку (с учетом кавычек, расширения переменных и т. Д.).

Если ваши требования просты, вы можете просто разделить строку на пробелы и передать их в Clap. Или, если вы хотите уважать строки в кавычках, вы можете использовать shellwords для их анализа. :

let words = shellwords::split(input)?;
let matches = App::new("MyApp")
    // ... command line argument options
    .get_matches_from(words);
person harmic    schedule 26.05.2020

Вот как я закончил работу:

Во-первых, я поместил всю свою основную функцию в loop, чтобы она могла получать команды и, в общем, оставаться в интерфейсе командной строки.

Затем я получил ввод через stdin и разделил аргументы

// Print command prompt and get command
print!("> ");
io::stdout().flush().expect("Couldn't flush stdout");
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Error reading input.");
let args = WORD.captures_iter(&input)
           .map(|cap| cap.get(1).or(cap.get(2)).unwrap().as_str())
           .collect::<Vec<&str>>();

Затем я использовал Clap для синтаксического анализа, вроде того, как предложил @harmic

let matches = App::new("MyApp")
    // ... command line argument options
    .get_matches_from(words);

и использовал subcommands вместо arguments.

eg.

.subcommand(SubCommand::with_name("list")
    .help("Print namespaces currently tracked in the database."))

Для любопытных весь файл находится здесь.

person Will Nilges    schedule 23.06.2020