forked from extern/nushell
Fix quoting for command line args (#5384)
* Fix quoting for command line args * Replace custom quoting with escape_quote_string * Use raw string for now
This commit is contained in:
parent
9da2e142b2
commit
ae9c0fc138
@ -1,7 +1,7 @@
|
|||||||
use crate::CliError;
|
use crate::CliError;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_engine::eval_block;
|
use nu_engine::eval_block;
|
||||||
use nu_parser::{lex, parse, unescape_unquote_string, Token, TokenContents};
|
use nu_parser::{escape_quote_string, lex, parse, unescape_unquote_string, Token, TokenContents};
|
||||||
use nu_protocol::engine::StateWorkingSet;
|
use nu_protocol::engine::StateWorkingSet;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
engine::{EngineState, Stack},
|
engine::{EngineState, Stack},
|
||||||
@ -36,20 +36,9 @@ fn gather_env_vars(vars: impl Iterator<Item = (String, String)>, engine_state: &
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn put_env_to_fake_file(name: &str, val: &str, fake_env_file: &mut String) {
|
fn put_env_to_fake_file(name: &str, val: &str, fake_env_file: &mut String) {
|
||||||
fn push_string_literal(s: &str, fake_env_file: &mut String) {
|
fake_env_file.push_str(&escape_quote_string(name));
|
||||||
fake_env_file.push('"');
|
|
||||||
for c in s.chars() {
|
|
||||||
if c == '\\' || c == '"' {
|
|
||||||
fake_env_file.push('\\');
|
|
||||||
}
|
|
||||||
fake_env_file.push(c);
|
|
||||||
}
|
|
||||||
fake_env_file.push('"');
|
|
||||||
}
|
|
||||||
|
|
||||||
push_string_literal(name, fake_env_file);
|
|
||||||
fake_env_file.push('=');
|
fake_env_file.push('=');
|
||||||
push_string_literal(val, fake_env_file);
|
fake_env_file.push_str(&escape_quote_string(val));
|
||||||
fake_env_file.push('\n');
|
fake_env_file.push('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use nu_engine::get_columns;
|
use nu_engine::get_columns;
|
||||||
|
use nu_parser::escape_quote_string;
|
||||||
use nu_protocol::ast::{Call, RangeInclusion};
|
use nu_protocol::ast::{Call, RangeInclusion};
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
@ -137,15 +138,10 @@ fn value_to_string(v: &Value, span: Span) -> Result<String, ShellError> {
|
|||||||
}
|
}
|
||||||
Ok(format!("{{{}}}", collection.join(", ")))
|
Ok(format!("{{{}}}", collection.join(", ")))
|
||||||
}
|
}
|
||||||
Value::String { val, .. } => Ok(format!("\"{}\"", escape(val))),
|
Value::String { val, .. } => Ok(escape_quote_string(val)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn escape(input: &str) -> String {
|
|
||||||
let output = input.replace('\\', "\\\\");
|
|
||||||
output.replace('"', "\\\"")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_nuon(call: &Call, input: PipelineData) -> Result<String, ShellError> {
|
fn to_nuon(call: &Call, input: PipelineData) -> Result<String, ShellError> {
|
||||||
let v = input.into_value(call.head);
|
let v = input.into_value(call.head);
|
||||||
|
|
||||||
|
14
crates/nu-parser/src/deparse.rs
Normal file
14
crates/nu-parser/src/deparse.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
pub fn escape_quote_string(input: &str) -> String {
|
||||||
|
let mut output = String::with_capacity(input.len() + 2);
|
||||||
|
output.push('"');
|
||||||
|
|
||||||
|
for c in input.chars() {
|
||||||
|
if c == '"' || c == '\\' {
|
||||||
|
output.push('\\');
|
||||||
|
}
|
||||||
|
output.push(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
output.push('"');
|
||||||
|
output
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
mod deparse;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod flatten;
|
mod flatten;
|
||||||
mod known_external;
|
mod known_external;
|
||||||
@ -7,6 +8,7 @@ mod parse_keywords;
|
|||||||
mod parser;
|
mod parser;
|
||||||
mod type_check;
|
mod type_check;
|
||||||
|
|
||||||
|
pub use deparse::escape_quote_string;
|
||||||
pub use errors::ParseError;
|
pub use errors::ParseError;
|
||||||
pub use flatten::{flatten_block, flatten_expression, flatten_pipeline, FlatShape};
|
pub use flatten::{flatten_block, flatten_expression, flatten_pipeline, FlatShape};
|
||||||
pub use known_external::KnownExternal;
|
pub use known_external::KnownExternal;
|
||||||
|
44
src/main.rs
44
src/main.rs
@ -17,7 +17,7 @@ use nu_cli::{
|
|||||||
};
|
};
|
||||||
use nu_command::{create_default_context, BufferedReader};
|
use nu_command::{create_default_context, BufferedReader};
|
||||||
use nu_engine::{get_full_help, CallExt};
|
use nu_engine::{get_full_help, CallExt};
|
||||||
use nu_parser::parse;
|
use nu_parser::{escape_quote_string, parse};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{Call, Expr, Expression},
|
ast::{Call, Expr, Expression},
|
||||||
engine::{Command, EngineState, Stack, StateWorkingSet},
|
engine::{Command, EngineState, Stack, StateWorkingSet},
|
||||||
@ -79,36 +79,28 @@ fn main() -> Result<()> {
|
|||||||
// Would be nice if we had a way to parse this. The first flags we see will be going to nushell
|
// Would be nice if we had a way to parse this. The first flags we see will be going to nushell
|
||||||
// then it'll be the script name
|
// then it'll be the script name
|
||||||
// then the args to the script
|
// then the args to the script
|
||||||
let mut collect_arg_nushell = false;
|
let mut args = std::env::args().skip(1);
|
||||||
for arg in std::env::args().skip(1) {
|
while let Some(arg) = args.next() {
|
||||||
if !script_name.is_empty() {
|
if !script_name.is_empty() {
|
||||||
args_to_script.push(if arg.contains(' ') {
|
args_to_script.push(escape_quote_string(&arg));
|
||||||
format!("`{}`", arg)
|
|
||||||
} else {
|
|
||||||
arg
|
|
||||||
});
|
|
||||||
} else if collect_arg_nushell {
|
|
||||||
args_to_nushell.push(if arg.contains(' ') {
|
|
||||||
format!("`{}`", arg)
|
|
||||||
} else {
|
|
||||||
arg
|
|
||||||
});
|
|
||||||
collect_arg_nushell = false;
|
|
||||||
} else if arg.starts_with('-') {
|
} else if arg.starts_with('-') {
|
||||||
// Cool, it's a flag
|
// Cool, it's a flag
|
||||||
if arg == "-c"
|
let flag_value = match arg.as_ref() {
|
||||||
|| arg == "--commands"
|
"--commands" | "-c" => {
|
||||||
|| arg == "--testbin"
|
// FIXME: Use proper quoting. `escape_quote_string()` can't be used for now due to https://github.com/nushell/nushell/issues/5383.
|
||||||
|| arg == "--log-level"
|
|
||||||
|| arg == "--config"
|
args.next().map(|a| format!("`{}`", a))
|
||||||
|| arg == "--env-config"
|
}
|
||||||
|| arg == "--threads"
|
"--config" | "--env-config" => args.next().map(|a| escape_quote_string(&a)),
|
||||||
|| arg == "-t"
|
"--log-level" | "--testbin" | "--threads" | "-t" => args.next(),
|
||||||
{
|
_ => None,
|
||||||
collect_arg_nushell = true;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
args_to_nushell.push(arg);
|
args_to_nushell.push(arg);
|
||||||
|
|
||||||
|
if let Some(flag_value) = flag_value {
|
||||||
|
args_to_nushell.push(flag_value);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Our script file
|
// Our script file
|
||||||
script_name = arg;
|
script_name = arg;
|
||||||
|
Loading…
Reference in New Issue
Block a user