From cc6e5a4ded0af8b65e1a7555bc8a641ebb580293 Mon Sep 17 00:00:00 2001 From: Paul Seyfert Date: Fri, 8 Oct 2021 09:46:41 +0200 Subject: [PATCH] Brute force attempt at https://github.com/clap-rs/clap/issues/1596 * This escapes everything that comes up in the reproducer from the above issue. NB: this means possible_value only. missing: * possible_value(...).about * Arg(...).value_name[s] * Arg(...).about * Arg(...).long --- clap_generate/src/generators/shells/zsh.rs | 39 +++++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/clap_generate/src/generators/shells/zsh.rs b/clap_generate/src/generators/shells/zsh.rs index 17a21d10a8aa..a967019145a6 100644 --- a/clap_generate/src/generators/shells/zsh.rs +++ b/clap_generate/src/generators/shells/zsh.rs @@ -358,7 +358,7 @@ fn value_completion(arg: &Arg) -> Option { } else { Some(format!( r#"{name}\:"{about}""#, - name = escape_value(value.get_name()), + name = escape_value(value.get_name(), true), about = value.get_about().map(escape_help).unwrap_or_default() )) } @@ -371,7 +371,15 @@ fn value_completion(arg: &Arg) -> Option { "({})", values .iter() - .filter_map(ArgValue::get_visible_name) + // .filter_map(ArgValue::get_visible_name) + .filter_map(|value| { + if value.is_hidden() { + None + } else { + Some(format!("{}", escape_value(value.get_name(), false) + )) + } + }) .collect::>() .join(" ") )) @@ -411,13 +419,34 @@ fn escape_help(string: &str) -> String { } /// Escape value string inside single quotes and parentheses -fn escape_value(string: &str) -> String { +fn escape_value(string: &str, for_about: bool) -> String { string - .replace("\\", "\\\\") - .replace("'", "'\\''") + // .replace("\\", "\\\\") + // .replace("\\", "\\\\\\\\") // ':: :((\\\\\:"some descr"))' \ + .replace("\\", if for_about {"\\\\\\\\"} else {"\\\\"}) + .replace("'", "'\\\\\\''") .replace("(", "\\(") .replace(")", "\\)") + .replace("[", "\\[") + .replace("]", "\\]") .replace(" ", "\\ ") + .replace("$", "\\$") + .replace("`", "\\`") + .replace("\"", "\\\"") + .replace("&", "\\&") + .replace("#", "\\#") + .replace("{", "\\{") + .replace("|", "\\|") + .replace("}", "\\}") + .replace("~", "\\~") + .replace("?", "\\?") + .replace("^", "\\^") + .replace("*", "\\*") + .replace(";", "\\;") + .replace("<", "\\<") + .replace(">", "\\>") + .replace("=", "\\=") // ':: :((\=\:"some descr"))' \ + .replace(":", if for_about {"\\\\\\:"} else {":"}) // ':: :((\\\:\:"some descr"))' \ } fn write_opts_of(p: &App, p_global: Option<&App>) -> String {