Refactor/config commands (#3265)
* Use ctx.configs in all config commands * Remove all setting/accessing of vars.("config-path") * Add tests * Add comment * Reload cfg on remove * Hypocratic ws change * Use history_path in hist_or_default * Make clippy happy * Fix rebase stuff * Fix clippy lint
This commit is contained in:
parent
111ad868a7
commit
ac070ae942
|
@ -173,7 +173,7 @@ pub fn cli(context: EvaluationContext, options: Options) -> Result<(), Box<dyn E
|
||||||
let _ = configure_rustyline_editor(&mut rl, cfg);
|
let _ = configure_rustyline_editor(&mut rl, cfg);
|
||||||
let helper = Some(nu_line_editor_helper(&context, cfg));
|
let helper = Some(nu_line_editor_helper(&context, cfg));
|
||||||
rl.set_helper(helper);
|
rl.set_helper(helper);
|
||||||
nu_data::config::path::history_path(cfg)
|
nu_data::config::path::history_path_or_default(cfg)
|
||||||
} else {
|
} else {
|
||||||
nu_data::config::path::default_history_path()
|
nu_data::config::path::default_history_path()
|
||||||
};
|
};
|
||||||
|
@ -420,15 +420,8 @@ pub fn load_local_cfg_if_present(context: &EvaluationContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_cfg_as_global_cfg(context: &EvaluationContext, path: PathBuf) {
|
fn load_cfg_as_global_cfg(context: &EvaluationContext, path: PathBuf) {
|
||||||
if let Err(err) = context.load_config(&ConfigPath::Global(path.clone())) {
|
if let Err(err) = context.load_config(&ConfigPath::Global(path)) {
|
||||||
context.host.lock().print_err(err, &Text::from(""));
|
context.host.lock().print_err(err, &Text::from(""));
|
||||||
} else {
|
|
||||||
//TODO current commands assume to find path to global cfg file under config-path
|
|
||||||
//TODO use newly introduced nuconfig::file_path instead
|
|
||||||
context.scope.add_var(
|
|
||||||
"config-path",
|
|
||||||
UntaggedValue::filepath(path).into_untagged_value(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub struct SubCommand;
|
||||||
|
|
||||||
|
@ -32,23 +32,22 @@ impl WholeStreamCommand for SubCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn clear(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let name_span = args.call_info.name_tag.clone();
|
let ctx = EvaluationContext::from_args(&args);
|
||||||
|
|
||||||
let path = match args.scope.get_var("config-path") {
|
let result = if let Some(global_cfg) = &mut args.configs.lock().global_config {
|
||||||
Some(Value {
|
global_cfg.vars.clear();
|
||||||
value: UntaggedValue::Primitive(Primitive::FilePath(path)),
|
global_cfg.write()?;
|
||||||
..
|
ctx.reload_config(global_cfg)?;
|
||||||
}) => Some(path),
|
Ok(OutputStream::one(ReturnSuccess::value(
|
||||||
_ => nu_data::config::default_path().ok(),
|
UntaggedValue::Row(global_cfg.vars.clone().into()).into_value(args.call_info.name_tag),
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
Ok(vec![ReturnSuccess::value(UntaggedValue::Error(
|
||||||
|
crate::commands::config::err_no_global_cfg_present(),
|
||||||
|
))]
|
||||||
|
.into_iter()
|
||||||
|
.to_output_stream())
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = nu_data::config::read(name_span, &path)?;
|
result
|
||||||
|
|
||||||
result.clear();
|
|
||||||
|
|
||||||
config::write(&result, &path)?;
|
|
||||||
|
|
||||||
Ok(OutputStream::one(ReturnSuccess::value(
|
|
||||||
UntaggedValue::Row(result.into()).into_value(args.call_info.name_tag),
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ impl WholeStreamCommand for Command {
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
} else {
|
} else {
|
||||||
Ok(vec![ReturnSuccess::value(UntaggedValue::Error(
|
Ok(vec![ReturnSuccess::value(UntaggedValue::Error(
|
||||||
ShellError::untagged_runtime_error("No global config found!"),
|
crate::commands::config::err_no_global_cfg_present(),
|
||||||
))]
|
))]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{
|
use nu_protocol::{ColumnPath, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
ColumnPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub struct SubCommand;
|
||||||
|
|
||||||
|
@ -44,33 +42,27 @@ impl WholeStreamCommand for SubCommand {
|
||||||
|
|
||||||
pub fn get(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn get(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let name = args.call_info.name_tag.clone();
|
let name = args.call_info.name_tag.clone();
|
||||||
let scope = args.scope.clone();
|
let ctx = EvaluationContext::from_args(&args);
|
||||||
|
|
||||||
let (Arguments { column_path }, _) = args.process()?;
|
let (Arguments { column_path }, _) = args.process()?;
|
||||||
|
|
||||||
let path = match scope.get_var("config-path") {
|
let result = if let Some(global_cfg) = &ctx.configs.lock().global_config {
|
||||||
Some(Value {
|
let result = UntaggedValue::row(global_cfg.vars.clone()).into_value(&name);
|
||||||
value: UntaggedValue::Primitive(Primitive::FilePath(path)),
|
|
||||||
..
|
|
||||||
}) => Some(path),
|
|
||||||
_ => nu_data::config::default_path().ok(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = UntaggedValue::row(nu_data::config::read(&name, &path)?).into_value(&name);
|
|
||||||
|
|
||||||
let value = crate::commands::get::get_column_path(&column_path, &result)?;
|
let value = crate::commands::get::get_column_path(&column_path, &result)?;
|
||||||
|
|
||||||
Ok(match value {
|
Ok(match value {
|
||||||
Value {
|
Value {
|
||||||
value: UntaggedValue::Table(list),
|
value: UntaggedValue::Table(list),
|
||||||
..
|
..
|
||||||
} => {
|
} => list.into_iter().to_output_stream(),
|
||||||
let list: Vec<_> = list
|
|
||||||
.iter()
|
|
||||||
.map(|x| ReturnSuccess::value(x.clone()))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
list.into_iter().to_output_stream()
|
|
||||||
}
|
|
||||||
x => OutputStream::one(ReturnSuccess::value(x)),
|
x => OutputStream::one(ReturnSuccess::value(x)),
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
Ok(vec![ReturnSuccess::value(UntaggedValue::Error(
|
||||||
|
crate::commands::config::err_no_global_cfg_present(),
|
||||||
|
))]
|
||||||
|
.into_iter()
|
||||||
|
.to_output_stream())
|
||||||
|
};
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,3 +13,9 @@ pub use path::SubCommand as ConfigPath;
|
||||||
pub use remove::SubCommand as ConfigRemove;
|
pub use remove::SubCommand as ConfigRemove;
|
||||||
pub use set::SubCommand as ConfigSet;
|
pub use set::SubCommand as ConfigSet;
|
||||||
pub use set_into::SubCommand as ConfigSetInto;
|
pub use set_into::SubCommand as ConfigSetInto;
|
||||||
|
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
|
||||||
|
pub fn err_no_global_cfg_present() -> ShellError {
|
||||||
|
ShellError::untagged_runtime_error("No global config found!")
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue};
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub struct SubCommand;
|
||||||
|
|
||||||
|
@ -32,18 +32,15 @@ impl WholeStreamCommand for SubCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn path(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
if let Some(global_cfg) = &mut args.configs.lock().global_config {
|
||||||
Ok(OutputStream::one(ReturnSuccess::value(
|
Ok(OutputStream::one(ReturnSuccess::value(
|
||||||
match args.scope.get_var("config-path") {
|
UntaggedValue::Primitive(Primitive::FilePath(global_cfg.file_path.clone())),
|
||||||
Some(
|
|
||||||
path
|
|
||||||
@
|
|
||||||
Value {
|
|
||||||
value: UntaggedValue::Primitive(Primitive::FilePath(_)),
|
|
||||||
..
|
|
||||||
},
|
|
||||||
) => path,
|
|
||||||
_ => UntaggedValue::Primitive(Primitive::FilePath(nu_data::config::default_path()?))
|
|
||||||
.into_value(args.call_info.name_tag),
|
|
||||||
},
|
|
||||||
)))
|
)))
|
||||||
|
} else {
|
||||||
|
Ok(vec![ReturnSuccess::value(UntaggedValue::Error(
|
||||||
|
crate::commands::config::err_no_global_cfg_present(),
|
||||||
|
))]
|
||||||
|
.into_iter()
|
||||||
|
.to_output_stream())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub struct SubCommand;
|
||||||
|
@ -42,27 +42,18 @@ impl WholeStreamCommand for SubCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn remove(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let name_span = args.call_info.name_tag.clone();
|
let ctx = EvaluationContext::from_args(&args);
|
||||||
let scope = args.scope.clone();
|
|
||||||
let (Arguments { remove }, _) = args.process()?;
|
let (Arguments { remove }, _) = args.process()?;
|
||||||
|
|
||||||
let path = match scope.get_var("config-path") {
|
|
||||||
Some(Value {
|
|
||||||
value: UntaggedValue::Primitive(Primitive::FilePath(path)),
|
|
||||||
..
|
|
||||||
}) => Some(path),
|
|
||||||
_ => nu_data::config::default_path().ok(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut result = nu_data::config::read(name_span, &path)?;
|
|
||||||
|
|
||||||
let key = remove.to_string();
|
let key = remove.to_string();
|
||||||
|
|
||||||
if result.contains_key(&key) {
|
let result = if let Some(global_cfg) = &mut ctx.configs.lock().global_config {
|
||||||
result.swap_remove(&key);
|
if global_cfg.vars.contains_key(&key) {
|
||||||
config::write(&result, &path)?;
|
global_cfg.vars.swap_remove(&key);
|
||||||
|
global_cfg.write()?;
|
||||||
|
ctx.reload_config(global_cfg)?;
|
||||||
Ok(vec![ReturnSuccess::value(
|
Ok(vec![ReturnSuccess::value(
|
||||||
UntaggedValue::Row(result.into()).into_value(remove.tag()),
|
UntaggedValue::row(global_cfg.vars.clone()).into_value(remove.tag()),
|
||||||
)]
|
)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
|
@ -73,4 +64,13 @@ pub fn remove(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
remove.tag(),
|
remove.tag(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Ok(vec![ReturnSuccess::value(UntaggedValue::Error(
|
||||||
|
crate::commands::config::err_no_global_cfg_present(),
|
||||||
|
))]
|
||||||
|
.into_iter()
|
||||||
|
.to_output_stream())
|
||||||
|
};
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{
|
use nu_protocol::{ColumnPath, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
ColumnPath, ConfigPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub struct SubCommand;
|
||||||
|
|
||||||
|
@ -61,7 +59,6 @@ impl WholeStreamCommand for SubCommand {
|
||||||
pub fn set(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn set(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let name = args.call_info.name_tag.clone();
|
let name = args.call_info.name_tag.clone();
|
||||||
let ctx = EvaluationContext::from_args(&args);
|
let ctx = EvaluationContext::from_args(&args);
|
||||||
let scope = args.scope.clone();
|
|
||||||
let (
|
let (
|
||||||
Arguments {
|
Arguments {
|
||||||
column_path,
|
column_path,
|
||||||
|
@ -70,16 +67,8 @@ pub fn set(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
_,
|
_,
|
||||||
) = args.process()?;
|
) = args.process()?;
|
||||||
|
|
||||||
let path = match scope.get_var("config-path") {
|
let result = if let Some(global_cfg) = &mut ctx.configs.lock().global_config {
|
||||||
Some(Value {
|
let configuration = UntaggedValue::row(global_cfg.vars.clone()).into_value(&name);
|
||||||
value: UntaggedValue::Primitive(Primitive::FilePath(path)),
|
|
||||||
..
|
|
||||||
}) => Some(path),
|
|
||||||
_ => nu_data::config::default_path().ok(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let raw_entries = nu_data::config::read(&name, &path)?;
|
|
||||||
let configuration = UntaggedValue::row(raw_entries).into_value(&name);
|
|
||||||
|
|
||||||
if let UntaggedValue::Table(rows) = &value.value {
|
if let UntaggedValue::Table(rows) = &value.value {
|
||||||
if rows.len() == 1 && rows[0].is_row() {
|
if rows.len() == 1 && rows[0].is_row() {
|
||||||
|
@ -92,16 +81,24 @@ pub fn set(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
value: UntaggedValue::Row(changes),
|
value: UntaggedValue::Row(changes),
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
config::write(&changes.entries, &path)?;
|
global_cfg.vars = changes.entries;
|
||||||
ctx.reload_config(&ConfigPath::Global(
|
global_cfg.write()?;
|
||||||
path.expect("Global config path is always some"),
|
ctx.reload_config(global_cfg)?;
|
||||||
))?;
|
|
||||||
|
|
||||||
Ok(OutputStream::one(ReturnSuccess::value(
|
Ok(OutputStream::one(ReturnSuccess::value(
|
||||||
UntaggedValue::Row(changes).into_value(name),
|
UntaggedValue::row(global_cfg.vars.clone()).into_value(name),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
Ok(_) => Ok(OutputStream::empty()),
|
Ok(_) => Ok(OutputStream::empty()),
|
||||||
Err(reason) => Err(reason),
|
Err(reason) => Err(reason),
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Ok(vec![ReturnSuccess::value(UntaggedValue::Error(
|
||||||
|
crate::commands::config::err_no_global_cfg_present(),
|
||||||
|
))]
|
||||||
|
.into_iter()
|
||||||
|
.to_output_stream())
|
||||||
|
};
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
ConfigPath, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
|
|
||||||
};
|
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub struct SubCommand;
|
||||||
|
@ -46,23 +44,13 @@ impl WholeStreamCommand for SubCommand {
|
||||||
pub fn set_into(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn set_into(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let name = args.call_info.name_tag.clone();
|
let name = args.call_info.name_tag.clone();
|
||||||
let ctx = EvaluationContext::from_args(&args);
|
let ctx = EvaluationContext::from_args(&args);
|
||||||
let scope = args.scope.clone();
|
|
||||||
let (Arguments { set_into: v }, input) = args.process()?;
|
let (Arguments { set_into: v }, input) = args.process()?;
|
||||||
|
|
||||||
let path = match scope.get_var("config-path") {
|
|
||||||
Some(Value {
|
|
||||||
value: UntaggedValue::Primitive(Primitive::FilePath(path)),
|
|
||||||
..
|
|
||||||
}) => Some(path),
|
|
||||||
_ => nu_data::config::default_path().ok(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut result = nu_data::config::read(&name, &path)?;
|
|
||||||
|
|
||||||
let rows: Vec<Value> = input.collect();
|
let rows: Vec<Value> = input.collect();
|
||||||
let key = v.to_string();
|
let key = v.to_string();
|
||||||
|
|
||||||
Ok(if rows.is_empty() {
|
let result = if let Some(global_cfg) = &mut ctx.configs.lock().global_config {
|
||||||
|
if rows.is_empty() {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"No values given for set_into",
|
"No values given for set_into",
|
||||||
"needs value(s) from pipeline",
|
"needs value(s) from pipeline",
|
||||||
|
@ -72,29 +60,27 @@ pub fn set_into(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
// A single value
|
// A single value
|
||||||
let value = &rows[0];
|
let value = &rows[0];
|
||||||
|
|
||||||
result.insert(key, value.clone());
|
global_cfg.vars.insert(key, value.clone());
|
||||||
|
|
||||||
config::write(&result, &path)?;
|
|
||||||
ctx.reload_config(&ConfigPath::Global(
|
|
||||||
path.expect("Global config path is always some"),
|
|
||||||
))?;
|
|
||||||
|
|
||||||
OutputStream::one(ReturnSuccess::value(
|
|
||||||
UntaggedValue::Row(result.into()).into_value(name),
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
// Take in the pipeline as a table
|
// Take in the pipeline as a table
|
||||||
let value = UntaggedValue::Table(rows).into_value(name.clone());
|
let value = UntaggedValue::Table(rows).into_value(name.clone());
|
||||||
|
|
||||||
result.insert(key, value);
|
global_cfg.vars.insert(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
config::write(&result, &path)?;
|
global_cfg.write()?;
|
||||||
ctx.reload_config(&ConfigPath::Global(
|
ctx.reload_config(global_cfg)?;
|
||||||
path.expect("Global config path is always some"),
|
|
||||||
))?;
|
|
||||||
|
|
||||||
OutputStream::one(ReturnSuccess::value(
|
Ok(OutputStream::one(ReturnSuccess::value(
|
||||||
UntaggedValue::Row(result.into()).into_value(name),
|
UntaggedValue::row(global_cfg.vars.clone()).into_value(name),
|
||||||
))
|
)))
|
||||||
})
|
} else {
|
||||||
|
Ok(vec![ReturnSuccess::value(UntaggedValue::Error(
|
||||||
|
crate::commands::config::err_no_global_cfg_present(),
|
||||||
|
))]
|
||||||
|
.into_iter()
|
||||||
|
.to_output_stream())
|
||||||
|
};
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_data::config::{Conf, NuConfig};
|
|
||||||
use nu_engine::WholeStreamCommand;
|
use nu_engine::WholeStreamCommand;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
|
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue};
|
||||||
|
@ -32,11 +31,15 @@ impl WholeStreamCommand for History {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn history(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
fn history(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let config: Box<dyn Conf> = Box::new(NuConfig::new());
|
|
||||||
let tag = args.call_info.name_tag.clone();
|
let tag = args.call_info.name_tag.clone();
|
||||||
|
let ctx = EvaluationContext::from_args(&args);
|
||||||
let (Arguments { clear }, _) = args.process()?;
|
let (Arguments { clear }, _) = args.process()?;
|
||||||
|
|
||||||
let path = nu_data::config::path::history_path(&config);
|
let path = if let Some(global_cfg) = &ctx.configs.lock().global_config {
|
||||||
|
nu_data::config::path::history_path_or_default(global_cfg)
|
||||||
|
} else {
|
||||||
|
nu_data::config::path::default_history_path()
|
||||||
|
};
|
||||||
|
|
||||||
match clear {
|
match clear {
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
|
|
138
crates/nu-command/tests/commands/config.rs
Normal file
138
crates/nu-command/tests/commands/config.rs
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
use nu_test_support::fs::AbsolutePath;
|
||||||
|
use nu_test_support::fs::Stub::FileWithContent;
|
||||||
|
use nu_test_support::playground::{says, Playground};
|
||||||
|
|
||||||
|
use hamcrest2::assert_that;
|
||||||
|
use hamcrest2::prelude::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn clearing_config_clears_config() {
|
||||||
|
Playground::setup("environment_syncing_test_1", |dirs, nu| {
|
||||||
|
let file = AbsolutePath::new(dirs.test().join("config.toml"));
|
||||||
|
|
||||||
|
nu.with_config(&file);
|
||||||
|
nu.with_files(vec![FileWithContent(
|
||||||
|
"config.toml",
|
||||||
|
r#"
|
||||||
|
skip_welcome_message = true
|
||||||
|
"#,
|
||||||
|
)]);
|
||||||
|
|
||||||
|
assert_that!(
|
||||||
|
nu.pipeline("config clear; config get skip_welcome_message"),
|
||||||
|
says().to_stdout("")
|
||||||
|
);
|
||||||
|
let config_contents = std::fs::read_to_string(file).expect("Could not read file");
|
||||||
|
assert!(config_contents.is_empty());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_get_returns_value() {
|
||||||
|
Playground::setup("environment_syncing_test_1", |dirs, nu| {
|
||||||
|
let file = AbsolutePath::new(dirs.test().join("config.toml"));
|
||||||
|
|
||||||
|
nu.with_config(&file);
|
||||||
|
nu.with_files(vec![FileWithContent(
|
||||||
|
"config.toml",
|
||||||
|
r#"
|
||||||
|
skip_welcome_message = true
|
||||||
|
"#,
|
||||||
|
)]);
|
||||||
|
|
||||||
|
assert_that!(
|
||||||
|
//Clears config
|
||||||
|
nu.pipeline("config get skip_welcome_message"),
|
||||||
|
says().to_stdout("true")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_set_sets_value() {
|
||||||
|
Playground::setup("environment_syncing_test_1", |dirs, nu| {
|
||||||
|
let file = AbsolutePath::new(dirs.test().join("config.toml"));
|
||||||
|
|
||||||
|
nu.with_config(&file);
|
||||||
|
nu.with_files(vec![FileWithContent(
|
||||||
|
"config.toml",
|
||||||
|
r#"
|
||||||
|
skip_welcome_message = true
|
||||||
|
"#,
|
||||||
|
)]);
|
||||||
|
|
||||||
|
assert_that!(
|
||||||
|
//Clears config
|
||||||
|
nu.pipeline("config set key value; config get key"),
|
||||||
|
says().to_stdout("value")
|
||||||
|
);
|
||||||
|
let config_contents = std::fs::read_to_string(file).expect("Could not read file");
|
||||||
|
assert!(config_contents.contains("key = \"value\""));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_set_into_sets_value() {
|
||||||
|
Playground::setup("environment_syncing_test_1", |dirs, nu| {
|
||||||
|
let file = AbsolutePath::new(dirs.test().join("config.toml"));
|
||||||
|
|
||||||
|
nu.with_config(&file);
|
||||||
|
nu.with_files(vec![FileWithContent(
|
||||||
|
"config.toml",
|
||||||
|
r#"
|
||||||
|
skip_welcome_message = true
|
||||||
|
"#,
|
||||||
|
)]);
|
||||||
|
|
||||||
|
assert_that!(
|
||||||
|
//Clears config
|
||||||
|
nu.pipeline("echo value | config set_into key; config get key"),
|
||||||
|
says().to_stdout("value")
|
||||||
|
);
|
||||||
|
let config_contents = std::fs::read_to_string(file).expect("Could not read file");
|
||||||
|
assert!(config_contents.contains("key = \"value\""));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_rm_removes_value() {
|
||||||
|
Playground::setup("environment_syncing_test_1", |dirs, nu| {
|
||||||
|
let file = AbsolutePath::new(dirs.test().join("config.toml"));
|
||||||
|
|
||||||
|
nu.with_config(&file);
|
||||||
|
nu.with_files(vec![FileWithContent(
|
||||||
|
"config.toml",
|
||||||
|
r#"
|
||||||
|
key = "value"
|
||||||
|
skip_welcome_message = true
|
||||||
|
"#,
|
||||||
|
)]);
|
||||||
|
|
||||||
|
assert_that!(
|
||||||
|
nu.pipeline("config remove key; config get key"),
|
||||||
|
says().to_stdout("")
|
||||||
|
);
|
||||||
|
let config_contents = std::fs::read_to_string(file).expect("Could not read file");
|
||||||
|
assert!(!config_contents.contains("key = \"value\""));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn config_path_returns_correct_path() {
|
||||||
|
Playground::setup("environment_syncing_test_1", |dirs, nu| {
|
||||||
|
let file = AbsolutePath::new(dirs.test().join("config.toml"));
|
||||||
|
|
||||||
|
nu.with_config(&file);
|
||||||
|
nu.with_files(vec![FileWithContent(
|
||||||
|
"config.toml",
|
||||||
|
r#"
|
||||||
|
skip_welcome_message = true
|
||||||
|
"#,
|
||||||
|
)]);
|
||||||
|
|
||||||
|
assert_that!(
|
||||||
|
nu.pipeline("config path"),
|
||||||
|
says().to_stdout(&file.inner.to_string_lossy().to_string())
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ mod append;
|
||||||
mod cal;
|
mod cal;
|
||||||
mod cd;
|
mod cd;
|
||||||
mod compact;
|
mod compact;
|
||||||
|
mod config;
|
||||||
mod cp;
|
mod cp;
|
||||||
mod def;
|
mod def;
|
||||||
mod default;
|
mod default;
|
||||||
|
|
|
@ -16,8 +16,8 @@ use indexmap::IndexMap;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_errors::{CoerceInto, ShellError};
|
use nu_errors::{CoerceInto, ShellError};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ConfigPath, Dictionary, Primitive, ShellTypeName, TaggedDictBuilder, UnspannedPathMember,
|
Dictionary, Primitive, ShellTypeName, TaggedDictBuilder, UnspannedPathMember, UntaggedValue,
|
||||||
UntaggedValue, Value,
|
Value,
|
||||||
};
|
};
|
||||||
use nu_source::{SpannedItem, Tag, TaggedItem};
|
use nu_source::{SpannedItem, Tag, TaggedItem};
|
||||||
use std::fs::{self, OpenOptions};
|
use std::fs::{self, OpenOptions};
|
||||||
|
@ -328,6 +328,6 @@ fn touch(path: &Path) -> io::Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cfg_path_to_scope_tag(cfg_path: &ConfigPath) -> String {
|
pub fn cfg_path_to_scope_tag(cfg_path: &Path) -> String {
|
||||||
cfg_path.get_path().to_string_lossy().to_string()
|
cfg_path.to_string_lossy().to_string()
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ use nu_protocol::Value;
|
||||||
use nu_source::Tag;
|
use nu_source::Tag;
|
||||||
use std::{fmt::Debug, path::PathBuf};
|
use std::{fmt::Debug, path::PathBuf};
|
||||||
|
|
||||||
|
use super::write;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct NuConfig {
|
pub struct NuConfig {
|
||||||
pub vars: IndexMap<String, Value>,
|
pub vars: IndexMap<String, Value>,
|
||||||
|
@ -63,6 +65,11 @@ impl NuConfig {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Writes self.values under self.file_path
|
||||||
|
pub fn write(&self) -> Result<(), ShellError> {
|
||||||
|
write(&self.vars, &Some(self.file_path.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new() -> NuConfig {
|
pub fn new() -> NuConfig {
|
||||||
let vars = if let Ok(variables) = read(Tag::unknown(), &None) {
|
let vars = if let Ok(variables) = read(Tag::unknown(), &None) {
|
||||||
variables
|
variables
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::config::Conf;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use super::NuConfig;
|
||||||
|
|
||||||
const DEFAULT_LOCATION: &str = "history.txt";
|
const DEFAULT_LOCATION: &str = "history.txt";
|
||||||
|
|
||||||
pub fn default_history_path() -> PathBuf {
|
pub fn default_history_path() -> PathBuf {
|
||||||
|
@ -12,14 +13,18 @@ pub fn default_history_path() -> PathBuf {
|
||||||
.unwrap_or_else(|_| PathBuf::from(DEFAULT_LOCATION))
|
.unwrap_or_else(|_| PathBuf::from(DEFAULT_LOCATION))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn history_path(config: &dyn Conf) -> PathBuf {
|
/// Get history path of config, if present
|
||||||
let default_history_path = default_history_path();
|
pub fn history_path(config: &NuConfig) -> Option<PathBuf> {
|
||||||
|
config
|
||||||
config.var("history-path").map_or(
|
.var("history-path")
|
||||||
default_history_path.clone(),
|
.map(|custom_path| match custom_path.as_string() {
|
||||||
|custom_path| match custom_path.as_string() {
|
Ok(path) => Some(PathBuf::from(path)),
|
||||||
Ok(path) => PathBuf::from(path),
|
Err(_) => None,
|
||||||
Err(_) => default_history_path,
|
})
|
||||||
},
|
.flatten()
|
||||||
)
|
}
|
||||||
|
|
||||||
|
/// Get history path in config or default
|
||||||
|
pub fn history_path_or_default(config: &NuConfig) -> PathBuf {
|
||||||
|
history_path(config).unwrap_or_else(default_history_path)
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,7 +227,7 @@ fn evaluate_literal(literal: &hir::Literal, span: Span) -> Value {
|
||||||
|
|
||||||
fn evaluate_reference(name: &str, ctx: &EvaluationContext, tag: Tag) -> Result<Value, ShellError> {
|
fn evaluate_reference(name: &str, ctx: &EvaluationContext, tag: Tag) -> Result<Value, ShellError> {
|
||||||
match name {
|
match name {
|
||||||
"$nu" => crate::evaluate::variables::nu(&ctx.scope, tag),
|
"$nu" => crate::evaluate::variables::nu(&ctx.scope, tag, ctx),
|
||||||
|
|
||||||
"$scope" => crate::evaluate::variables::scope(&ctx.scope.get_aliases(), tag),
|
"$scope" => crate::evaluate::variables::scope(&ctx.scope.get_aliases(), tag),
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
use crate::evaluate::scope::Scope;
|
use crate::{evaluate::scope::Scope, EvaluationContext};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu_data::config::path::history_path;
|
use nu_data::config::path::{default_history_path, history_path};
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Primitive, TaggedDictBuilder, UntaggedValue, Value};
|
use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value};
|
||||||
use nu_source::{Spanned, Tag};
|
use nu_source::{Spanned, Tag};
|
||||||
|
|
||||||
pub fn nu(scope: &Scope, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
pub fn nu(
|
||||||
|
scope: &Scope,
|
||||||
|
tag: impl Into<Tag>,
|
||||||
|
ctx: &EvaluationContext,
|
||||||
|
) -> Result<Value, ShellError> {
|
||||||
let env = &scope.get_env_vars();
|
let env = &scope.get_env_vars();
|
||||||
let tag = tag.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
|
@ -17,18 +21,33 @@ pub fn nu(scope: &Scope, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
||||||
dict.insert_untagged(v.0, UntaggedValue::string(v.1));
|
dict.insert_untagged(v.0, UntaggedValue::string(v.1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nu_dict.insert_value("env", dict.into_value());
|
nu_dict.insert_value("env", dict.into_value());
|
||||||
|
|
||||||
let config_file = match scope.get_var("config-path") {
|
nu_dict.insert_value(
|
||||||
Some(Value {
|
"history-path",
|
||||||
value: UntaggedValue::Primitive(Primitive::FilePath(path)),
|
UntaggedValue::filepath(default_history_path()).into_value(&tag),
|
||||||
..
|
);
|
||||||
}) => Some(path),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let config = nu_data::config::read(&tag, &config_file)?;
|
if let Some(global_cfg) = &ctx.configs.lock().global_config {
|
||||||
nu_dict.insert_value("config", UntaggedValue::row(config).into_value(&tag));
|
nu_dict.insert_value(
|
||||||
|
"config",
|
||||||
|
UntaggedValue::row(global_cfg.vars.clone()).into_value(&tag),
|
||||||
|
);
|
||||||
|
|
||||||
|
nu_dict.insert_value(
|
||||||
|
"config-path",
|
||||||
|
UntaggedValue::filepath(global_cfg.file_path.clone()).into_value(&tag),
|
||||||
|
);
|
||||||
|
|
||||||
|
// overwrite hist-path if present
|
||||||
|
if let Some(hist_path) = history_path(global_cfg) {
|
||||||
|
nu_dict.insert_value(
|
||||||
|
"history-path",
|
||||||
|
UntaggedValue::filepath(hist_path).into_value(&tag),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut table = vec![];
|
let mut table = vec![];
|
||||||
for v in env.iter() {
|
for v in env.iter() {
|
||||||
|
@ -50,17 +69,6 @@ pub fn nu(scope: &Scope, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
||||||
let temp = std::env::temp_dir();
|
let temp = std::env::temp_dir();
|
||||||
nu_dict.insert_value("temp-dir", UntaggedValue::filepath(temp).into_value(&tag));
|
nu_dict.insert_value("temp-dir", UntaggedValue::filepath(temp).into_value(&tag));
|
||||||
|
|
||||||
let config = if let Some(path) = config_file {
|
|
||||||
path
|
|
||||||
} else {
|
|
||||||
nu_data::config::default_path()?
|
|
||||||
};
|
|
||||||
|
|
||||||
nu_dict.insert_value(
|
|
||||||
"config-path",
|
|
||||||
UntaggedValue::filepath(config).into_value(&tag),
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(feature = "rustyline-support")]
|
#[cfg(feature = "rustyline-support")]
|
||||||
{
|
{
|
||||||
let keybinding_path = nu_data::keybinding::keybinding_path()?;
|
let keybinding_path = nu_data::keybinding::keybinding_path()?;
|
||||||
|
@ -70,13 +78,6 @@ pub fn nu(scope: &Scope, tag: impl Into<Tag>) -> Result<Value, ShellError> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let config: Box<dyn nu_data::config::Conf> = Box::new(nu_data::config::NuConfig::new());
|
|
||||||
let history = history_path(&config);
|
|
||||||
nu_dict.insert_value(
|
|
||||||
"history-path",
|
|
||||||
UntaggedValue::filepath(history).into_value(&tag),
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(nu_dict.into_value())
|
Ok(nu_dict.into_value())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,7 +161,7 @@ impl EvaluationContext {
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
let tag = config::cfg_path_to_scope_tag(cfg_path);
|
let tag = config::cfg_path_to_scope_tag(cfg_path.get_path());
|
||||||
|
|
||||||
self.scope.enter_scope_with_tag(tag);
|
self.scope.enter_scope_with_tag(tag);
|
||||||
self.scope.add_env(cfg.env_map());
|
self.scope.add_env(cfg.env_map());
|
||||||
|
@ -188,30 +188,8 @@ impl EvaluationContext {
|
||||||
/// If an error occurs while reloading the config:
|
/// If an error occurs while reloading the config:
|
||||||
/// The config is not reloaded
|
/// The config is not reloaded
|
||||||
/// The error is returned
|
/// The error is returned
|
||||||
pub fn reload_config(&self, cfg_path: &ConfigPath) -> Result<(), ShellError> {
|
pub fn reload_config(&self, cfg: &mut NuConfig) -> Result<(), ShellError> {
|
||||||
trace!("Reloading cfg {:?}", cfg_path);
|
trace!("Reloading cfg {:?}", cfg.file_path);
|
||||||
|
|
||||||
let mut configs = self.configs.lock();
|
|
||||||
let cfg = match cfg_path {
|
|
||||||
ConfigPath::Global(path) => {
|
|
||||||
configs.global_config.iter_mut().find(|cfg| &cfg.file_path == path).ok_or_else(||
|
|
||||||
ShellError::labeled_error(
|
|
||||||
&format!("Error reloading global config with path of {}. No such global config present.", path.display()),
|
|
||||||
"Config path error",
|
|
||||||
Span::unknown(),
|
|
||||||
)
|
|
||||||
)?
|
|
||||||
}
|
|
||||||
ConfigPath::Local(path) => {
|
|
||||||
configs.local_configs.iter_mut().find(|cfg| &cfg.file_path == path).ok_or_else(||
|
|
||||||
ShellError::labeled_error(
|
|
||||||
&format!("Error reloading local config with path of {}. No such local config present.", path.display()),
|
|
||||||
"Config path error",
|
|
||||||
Span::unknown(),
|
|
||||||
)
|
|
||||||
)?
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
cfg.reload();
|
cfg.reload();
|
||||||
|
|
||||||
|
@ -244,7 +222,7 @@ impl EvaluationContext {
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
let tag = config::cfg_path_to_scope_tag(cfg_path);
|
let tag = config::cfg_path_to_scope_tag(&cfg.file_path);
|
||||||
let mut frame = ScopeFrame::with_tag(tag.clone());
|
let mut frame = ScopeFrame::with_tag(tag.clone());
|
||||||
|
|
||||||
frame.env = cfg.env_map();
|
frame.env = cfg.env_map();
|
||||||
|
@ -265,7 +243,7 @@ impl EvaluationContext {
|
||||||
pub fn unload_config(&self, cfg_path: &ConfigPath) {
|
pub fn unload_config(&self, cfg_path: &ConfigPath) {
|
||||||
trace!("UnLoading cfg {:?}", cfg_path);
|
trace!("UnLoading cfg {:?}", cfg_path);
|
||||||
|
|
||||||
let tag = config::cfg_path_to_scope_tag(cfg_path);
|
let tag = config::cfg_path_to_scope_tag(cfg_path.get_path());
|
||||||
|
|
||||||
//Run exitscripts with scope frame and cfg still applied
|
//Run exitscripts with scope frame and cfg still applied
|
||||||
if let Some(scripts) = self.scope.get_exitscripts_of_frame_with_tag(&tag) {
|
if let Some(scripts) = self.scope.get_exitscripts_of_frame_with_tag(&tag) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ impl From<AbsoluteFile> for PathBuf {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AbsolutePath {
|
pub struct AbsolutePath {
|
||||||
inner: PathBuf,
|
pub inner: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbsolutePath {
|
impl AbsolutePath {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user