Fixing the flag issue (#5447)

* Fixing the flag issue

* whoops, forgot the original point of the function

* Update deparse.rs

* Update deparse.rs

* Update deparse.rs

* maybe this might work

* fmt

* quotation marks works now due to a rigorous check for args.

* fmt and clippy

* kept the original escape_quote_string(), escaped " and \

* removed script.nu

* Added appropriate comments.
This commit is contained in:
pwygab 2022-05-09 20:01:58 +08:00 committed by GitHub
parent 7ee22603ac
commit 8d8f25b210
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 98 additions and 3 deletions

View File

@ -1,3 +1,6 @@
use std::fs::File;
use std::io::{BufRead, BufReader};
pub fn escape_quote_string(input: &str) -> String {
let mut output = String::with_capacity(input.len() + 2);
output.push('"');
@ -12,3 +15,95 @@ pub fn escape_quote_string(input: &str) -> String {
output.push('"');
output
}
fn looks_like_flag(input: &str) -> bool {
if !input.starts_with('-') {
false
// it does not start with '-'
} else if !input.starts_with("--") {
if input.len() > 2
&& input.chars().nth(2).expect("this should never trigger") != '='
&& input.chars().nth(2).expect("this should never trigger") != ' '
{
false
// while it start with '-', it is not of the form '-x=y' or '-x y'
} else {
input.len() >= 2
}
} else {
input.len() > 2
// it is either a flag --x or a '--'
}
}
fn escape_quote_string_when_flags_are_unclear(input: &str) -> String {
// internal use only. When reading the file for flags goes wrong, revert back to a manual check
// for flags.
let mut output = String::new();
if !looks_like_flag(input) {
output.push('"');
for c in input.chars() {
if c == '"' || c == '\\' {
output.push('\\');
}
output.push(c);
}
output.push('"');
output
} else if input.contains(' ') || input.contains('=') {
// this is a flag that requires delicate handling
let mut flag_tripped = false;
for c in input.chars() {
if c == '"' || c == '\\' {
output.push('\\');
}
output.push(c);
if (c == ' ' || c == '=') && !flag_tripped {
flag_tripped = true;
output.push('"');
}
}
output.push('"');
output
} else {
// this is a normal flag, aka "--x"
String::from(input)
}
}
pub fn escape_quote_string_with_file(input: &str, file: &str) -> String {
// use when you want to cross-compare to a file to ensure flags are checked properly
let file = File::open(file);
match file {
Ok(f) => {
let lines = BufReader::new(f).lines();
for line in lines {
let mut flag_start = false;
let mut word = String::new();
let line_or = line.unwrap_or_else(|_| String::from(" "));
if line_or.contains('-') {
for n in line_or.chars() {
if n == '-' {
flag_start = true;
}
if n == ' ' || n == ':' || n == ')' {
flag_start = false;
}
if flag_start {
word.push(n);
}
}
}
if word == input {
return word;
}
}
let mut final_word = String::new();
final_word.push('"');
final_word.push_str(input);
final_word.push('"');
final_word
}
_ => escape_quote_string_when_flags_are_unclear(input),
}
}

View File

@ -8,7 +8,7 @@ mod parse_keywords;
mod parser;
mod type_check;
pub use deparse::escape_quote_string;
pub use deparse::{escape_quote_string, escape_quote_string_with_file};
pub use errors::ParseError;
pub use flatten::{flatten_block, flatten_expression, flatten_pipeline, FlatShape};
pub use known_external::KnownExternal;

View File

@ -17,7 +17,7 @@ use nu_cli::{
};
use nu_command::{create_default_context, BufferedReader};
use nu_engine::{get_full_help, CallExt};
use nu_parser::{escape_quote_string, parse};
use nu_parser::{escape_quote_string, escape_quote_string_with_file, parse};
use nu_protocol::{
ast::{Call, Expr, Expression},
engine::{Command, EngineState, Stack, StateWorkingSet},
@ -82,7 +82,7 @@ fn main() -> Result<()> {
let mut args = std::env::args().skip(1);
while let Some(arg) = args.next() {
if !script_name.is_empty() {
args_to_script.push(escape_quote_string(&arg));
args_to_script.push(escape_quote_string_with_file(&arg, &script_name));
} else if arg.starts_with('-') {
// Cool, it's a flag
let flag_value = match arg.as_ref() {