mirror of
https://github.com/nushell/nushell
synced 2024-12-27 05:23:11 +00:00
Wrap captured env var names into quotes as well (#546)
This commit is contained in:
parent
266fac910a
commit
52dba91e1a
2 changed files with 77 additions and 44 deletions
|
@ -15,7 +15,7 @@ pub use lite_parse::{lite_parse, LiteBlock};
|
||||||
pub use parse_keywords::{
|
pub use parse_keywords::{
|
||||||
parse_alias, parse_def, parse_def_predecl, parse_let, parse_module, parse_use,
|
parse_alias, parse_def, parse_def_predecl, parse_let, parse_module, parse_use,
|
||||||
};
|
};
|
||||||
pub use parser::{find_captures_in_expr, parse, Import};
|
pub use parser::{find_captures_in_expr, parse, trim_quotes, Import};
|
||||||
|
|
||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
pub use parse_keywords::parse_register;
|
pub use parse_keywords::parse_register;
|
||||||
|
|
119
src/main.rs
119
src/main.rs
|
@ -9,7 +9,7 @@ use miette::{IntoDiagnostic, Result};
|
||||||
use nu_cli::{CliError, NuCompleter, NuHighlighter, NuValidator, NushellPrompt};
|
use nu_cli::{CliError, NuCompleter, NuHighlighter, NuValidator, NushellPrompt};
|
||||||
use nu_command::create_default_context;
|
use nu_command::create_default_context;
|
||||||
use nu_engine::{env_to_values, eval_block};
|
use nu_engine::{env_to_values, eval_block};
|
||||||
use nu_parser::{lex, parse, Token, TokenContents};
|
use nu_parser::{lex, parse, trim_quotes, Token, TokenContents};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{EngineState, Stack, StateWorkingSet},
|
engine::{EngineState, Stack, StateWorkingSet},
|
||||||
|
@ -429,44 +429,66 @@ fn main() -> Result<()> {
|
||||||
// This fill collect environment variables from std::env and adds them to a stack.
|
// This fill collect environment variables from std::env and adds them to a stack.
|
||||||
//
|
//
|
||||||
// In order to ensure the values have spans, it first creates a dummy file, writes the collected
|
// In order to ensure the values have spans, it first creates a dummy file, writes the collected
|
||||||
// env vars into it (in a NAME=value format, similar to the output of the Unix 'env' tool), then
|
// env vars into it (in a "NAME"="value" format, quite similar to the output of the Unix 'env'
|
||||||
// uses the file to get the spans. The file stays in memory, no filesystem IO is done.
|
// tool), then uses the file to get the spans. The file stays in memory, no filesystem IO is done.
|
||||||
fn gather_parent_env_vars(engine_state: &mut EngineState, stack: &mut Stack) {
|
fn gather_parent_env_vars(engine_state: &mut EngineState, stack: &mut Stack) {
|
||||||
let mut fake_env_file = String::new();
|
fn get_surround_char(s: &str) -> Option<char> {
|
||||||
for (name, val) in std::env::vars() {
|
if s.contains('"') {
|
||||||
let c = if val.contains('"') {
|
if s.contains('\'') {
|
||||||
if val.contains('\'') {
|
None
|
||||||
// environment variable containing both ' and " is ignored
|
|
||||||
let working_set = StateWorkingSet::new(engine_state);
|
|
||||||
report_error(
|
|
||||||
&working_set,
|
|
||||||
&ShellError::LabeledError(
|
|
||||||
format!("Environment variable was not captured: {}={}", name, val),
|
|
||||||
"Value should not contain both ' and \" at the same time.".into(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
} else {
|
} else {
|
||||||
'\''
|
Some('\'')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
'"'
|
Some('"')
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn report_capture_error(engine_state: &EngineState, env_str: &str, msg: &str) {
|
||||||
|
let working_set = StateWorkingSet::new(engine_state);
|
||||||
|
report_error(
|
||||||
|
&working_set,
|
||||||
|
&ShellError::LabeledError(
|
||||||
|
format!("Environment variable was not captured: {}", env_str),
|
||||||
|
msg.into(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut fake_env_file = String::new();
|
||||||
|
for (name, val) in std::env::vars() {
|
||||||
|
let (c_name, c_val) =
|
||||||
|
if let (Some(cn), Some(cv)) = (get_surround_char(&name), get_surround_char(&val)) {
|
||||||
|
(cn, cv)
|
||||||
|
} else {
|
||||||
|
// environment variable with its name or value containing both ' and " is ignored
|
||||||
|
report_capture_error(
|
||||||
|
engine_state,
|
||||||
|
&format!("{}={}", name, val),
|
||||||
|
"Name or value should not contain both ' and \" at the same time.",
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
fake_env_file.push(c_name);
|
||||||
fake_env_file.push_str(&name);
|
fake_env_file.push_str(&name);
|
||||||
|
fake_env_file.push(c_name);
|
||||||
fake_env_file.push('=');
|
fake_env_file.push('=');
|
||||||
fake_env_file.push(c);
|
fake_env_file.push(c_val);
|
||||||
fake_env_file.push_str(&val);
|
fake_env_file.push_str(&val);
|
||||||
fake_env_file.push(c);
|
fake_env_file.push(c_val);
|
||||||
fake_env_file.push('\n');
|
fake_env_file.push('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
let span_offset = engine_state.next_span_start();
|
let span_offset = engine_state.next_span_start();
|
||||||
|
|
||||||
engine_state.add_file(
|
engine_state.add_file(
|
||||||
"Host Environment Variables".to_string(),
|
"Host Environment Variables".to_string(),
|
||||||
fake_env_file.as_bytes().to_vec(),
|
fake_env_file.as_bytes().to_vec(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let (tokens, _) = lex(fake_env_file.as_bytes(), span_offset, &[], &[], true);
|
let (tokens, _) = lex(fake_env_file.as_bytes(), span_offset, &[], &[], true);
|
||||||
|
|
||||||
for token in tokens {
|
for token in tokens {
|
||||||
if let Token {
|
if let Token {
|
||||||
contents: TokenContents::Item,
|
contents: TokenContents::Item,
|
||||||
|
@ -481,9 +503,27 @@ fn gather_parent_env_vars(engine_state: &mut EngineState, stack: &mut Stack) {
|
||||||
span,
|
span,
|
||||||
}) = parts.get(0)
|
}) = parts.get(0)
|
||||||
{
|
{
|
||||||
String::from_utf8_lossy(engine_state.get_span_contents(span)).to_string()
|
let bytes = engine_state.get_span_contents(span);
|
||||||
|
|
||||||
|
if bytes.len() < 2 {
|
||||||
|
report_capture_error(
|
||||||
|
engine_state,
|
||||||
|
&String::from_utf8_lossy(contents),
|
||||||
|
"Got empty name.",
|
||||||
|
);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let bytes = trim_quotes(bytes);
|
||||||
|
String::from_utf8_lossy(bytes).to_string()
|
||||||
} else {
|
} else {
|
||||||
// Skip this env var if it does not have a name
|
report_capture_error(
|
||||||
|
engine_state,
|
||||||
|
&String::from_utf8_lossy(contents),
|
||||||
|
"Got empty name.",
|
||||||
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -495,36 +535,29 @@ fn gather_parent_env_vars(engine_state: &mut EngineState, stack: &mut Stack) {
|
||||||
let bytes = engine_state.get_span_contents(span);
|
let bytes = engine_state.get_span_contents(span);
|
||||||
|
|
||||||
if bytes.len() < 2 {
|
if bytes.len() < 2 {
|
||||||
let working_set = StateWorkingSet::new(engine_state);
|
report_capture_error(
|
||||||
report_error(
|
engine_state,
|
||||||
&working_set,
|
&String::from_utf8_lossy(contents),
|
||||||
&ShellError::NushellFailed(format!(
|
"Got empty value.",
|
||||||
"Error capturing environment variable {}",
|
|
||||||
name
|
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let bytes = &bytes[1..bytes.len() - 1];
|
let bytes = trim_quotes(bytes);
|
||||||
|
|
||||||
Value::String {
|
Value::String {
|
||||||
val: String::from_utf8_lossy(bytes).to_string(),
|
val: String::from_utf8_lossy(bytes).to_string(),
|
||||||
span: *span,
|
span: *span,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let working_set = StateWorkingSet::new(engine_state);
|
report_capture_error(
|
||||||
report_error(
|
engine_state,
|
||||||
&working_set,
|
&String::from_utf8_lossy(contents),
|
||||||
&ShellError::NushellFailed(format!(
|
"Got empty value.",
|
||||||
"Error capturing environment variable {}",
|
|
||||||
name
|
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Value::String {
|
continue;
|
||||||
val: "".to_string(),
|
|
||||||
span: Span::new(full_span.end, full_span.end),
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
stack.add_env_var(name, value);
|
stack.add_env_var(name, value);
|
||||||
|
|
Loading…
Reference in a new issue