Skip to content

Strings with a backslash before the ending quote results in a quote being included in the final arg value #2791

Closed
@avborup

Description

@avborup

Please complete the following tasks

  • I have searched the discussions
  • I have searched the existing issues

Rust Version

rustc 1.54.0 (a178d0322 2021-07-26)

Clap Version

2.33.3

Minimal reproducible code

use clap::{App, Arg};

fn main() {
    let matches = App::new(r"Minimum Working Example for \'")
        .arg(Arg::with_name("PATH").required(true))
        .get_matches();

    println!("{}", matches.value_of("PATH").unwrap());
}

Steps to reproduce the bug with the above code

cargo run -- '.\foo bar\baz\'

Actual Behaviour

The following is printed:

.\foo bar\baz"

Notice the trailing " - there was not even a direct " in the original input.

Expected Behaviour

Either of the two:

  1. The straight content of the string should be returned: .\foo bar\baz\.
  2. If the trailing ' is meant to be escaped by \, a parse error saying no end ' was found.

Additional Context

This is on Windows and is particularly an issue with paths. Assume you have the following directory tree:

.
└── foo bar
    └── baz

If you autocomplete in PowerShell, the path will be '.\foo bar\baz\' (including the quotes because of the space).

I saw the discussion at #2654, but I'm not sure it's the same issue.

Debug Output

$ cargo run -- '.\foo bar\baz\'
    Blocking waiting for file lock on build directory
   Compiling clap v2.33.3
   Compiling clap-mwe-backslash-quote v0.1.0 (C:\Users\Adrian\coding\testing\clap-mwe-backslash-quote)
    Finished dev [unoptimized + debuginfo] target(s) in 4.57s
     Running `target\debug\clap-mwe-backslash-quote.exe ".\foo bar\baz\""`      
DEBUG:clap:Parser::propagate_settings: self=Minimum Working Example for \', g_settings=AppFlags(
    (empty),
)
DEBUG:clap:Parser::get_matches_with;
DEBUG:clap:Parser::create_help_and_version;
DEBUG:clap:Parser::create_help_and_version: Building --help
DEBUG:clap:Parser::create_help_and_version: Building --version
DEBUG:clap:Parser::get_matches_with: Begin parsing '".\\foo bar\\baz\""' ([46, 92, 102, 111, 111, 32, 98, 97, 114, 92, 98, 97, 122, 34])
DEBUG:clap:Parser::is_new_arg:".\\foo bar\\baz\"":NotFound
DEBUG:clap:Parser::is_new_arg: arg_allows_tac=false
DEBUG:clap:Parser::is_new_arg: probably value
DEBUG:clap:Parser::is_new_arg: starts_new_arg=false
DEBUG:clap:Parser::possible_subcommand: arg=".\\foo bar\\baz\""
DEBUG:clap:Parser::get_matches_with: possible_sc=false, sc=None
DEBUG:clap:Parser::get_matches_with: Positional counter...1
DEBUG:clap:Parser::get_matches_with: Low index multiples...false
DEBUG:clap:ArgMatcher::process_arg_overrides:None;
DEBUG:clap:Parser::add_val_to_arg; arg=PATH, val=".\\foo bar\\baz\""
DEBUG:clap:Parser::add_val_to_arg; trailing_vals=false, DontDelimTrailingVals=false
DEBUG:clap:Parser::add_single_val_to_arg;
DEBUG:clap:Parser::add_single_val_to_arg: adding val...".\\foo bar\\baz\""      
DEBUG:clap:Parser::groups_for_arg: name=PATH
DEBUG:clap:Parser::groups_for_arg: No groups defined
DEBUG:clap:ArgMatcher::needs_more_vals: o=PATH
DEBUG:clap:ArgMatcher::inc_occurrence_of: arg=PATH
DEBUG:clap:Parser::groups_for_arg: name=PATH
DEBUG:clap:Parser::groups_for_arg: No groups defined
DEBUG:clap:ArgMatcher::process_arg_overrides:Some("PATH");
DEBUG:clap:Parser::remove_overrides:[];
DEBUG:clap:Validator::validate;
DEBUG:clap:Parser::add_defaults;
DEBUG:clap:Parser::add_defaults:iter:PATH: doesn't have conditional defaults    
DEBUG:clap:Parser::add_defaults:iter:PATH: doesn't have default vals
DEBUG:clap:Validator::validate_blacklist;
DEBUG:clap:Validator::validate_blacklist:iter:PATH;
DEBUG:clap:Parser::groups_for_arg: name=PATH
DEBUG:clap:Parser::groups_for_arg: No groups defined
DEBUG:clap:Validator::validate_required: required=["PATH"];
DEBUG:clap:Validator::validate_required:iter:PATH:
DEBUG:clap:Validator::validate_matched_args;
DEBUG:clap:Validator::validate_matched_args:iter:PATH: vals=[
    ".\\foo bar\\baz\"",
]
DEBUG:clap:Validator::validate_arg_num_vals:PATH
DEBUG:clap:Validator::validate_arg_num_occurs: a=PATH;
DEBUG:clap:Validator::validate_arg_values: arg="PATH"
DEBUG:clap:Validator::validate_arg_requires:PATH;
DEBUG:clap:usage::create_usage_with_title;
DEBUG:clap:usage::create_usage_no_title;
DEBUG:clap:usage::get_required_usage_from: reqs=["PATH"], extra=None
DEBUG:clap:usage::get_required_usage_from: after init desc_reqs=[]
DEBUG:clap:usage::get_required_usage_from: no more children
DEBUG:clap:usage::get_required_usage_from: final desc_reqs=["PATH"]
DEBUG:clap:usage::get_required_usage_from: args_in_groups=[]
DEBUG:clap:usage::needs_flags_tag;
DEBUG:clap:usage::needs_flags_tag:iter: f=hclap_help;
DEBUG:clap:usage::needs_flags_tag:iter: f=vclap_version;
DEBUG:clap:usage::needs_flags_tag: [FLAGS] not required
DEBUG:clap:usage::create_help_usage: usage=clap-mwe-backslash-quote.exe <PATH>  
DEBUG:clap:ArgMatcher::get_global_values: global_arg_vec=[]
.\foo bar\baz"

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions