mirror of
https://github.com/nushell/nushell
synced 2025-01-15 06:34:15 +00:00
Add pathvar
command (#3670)
* Add pathvar command Signed-off-by: nathom <nathanthomas707@gmail.com> * Add pathvar command to context Signed-off-by: nathom <nathanthomas707@gmail.com> * Add pathvar reset command Signed-off-by: nathom <nathanthomas707@gmail.com> * Update help message Signed-off-by: nathom <nathanthomas707@gmail.com> * Remove insert command Signed-off-by: nathom <nathanthomas707@gmail.com> * Remove unused import Signed-off-by: nathom <nathanthomas707@gmail.com> * Remove insert mod Signed-off-by: nathom <nathanthomas707@gmail.com> * Support for windows path separator Signed-off-by: nathom <nathanthomas707@gmail.com> * Clear clippy errors Signed-off-by: nathom <nathanthomas707@gmail.com> * Remove empty file Signed-off-by: nathom <nathanthomas707@gmail.com> * Formatting Signed-off-by: nathom <nathanthomas707@gmail.com>
This commit is contained in:
parent
6ba40773bb
commit
a3f119e0bd
10 changed files with 376 additions and 0 deletions
|
@ -12,6 +12,7 @@ mod generators;
|
||||||
mod math;
|
mod math;
|
||||||
mod network;
|
mod network;
|
||||||
mod path;
|
mod path;
|
||||||
|
mod pathvar;
|
||||||
mod platform;
|
mod platform;
|
||||||
mod random;
|
mod random;
|
||||||
mod shells;
|
mod shells;
|
||||||
|
@ -43,6 +44,7 @@ pub use generators::*;
|
||||||
pub use math::*;
|
pub use math::*;
|
||||||
pub use network::*;
|
pub use network::*;
|
||||||
pub use path::*;
|
pub use path::*;
|
||||||
|
pub use pathvar::*;
|
||||||
pub use platform::*;
|
pub use platform::*;
|
||||||
pub use random::*;
|
pub use random::*;
|
||||||
pub use shells::*;
|
pub use shells::*;
|
||||||
|
|
59
crates/nu-command/src/commands/pathvar/add.rs
Normal file
59
crates/nu-command/src/commands/pathvar/add.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use nu_engine::WholeStreamCommand;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{Signature, SyntaxShape};
|
||||||
|
use nu_source::Tagged;
|
||||||
|
use nu_test_support::{NATIVE_PATH_ENV_SEPARATOR, NATIVE_PATH_ENV_VAR};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
pub struct SubCommand;
|
||||||
|
|
||||||
|
impl WholeStreamCommand for SubCommand {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"pathvar add"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("pathvar add").required("path", SyntaxShape::FilePath, "path to add")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Add a filepath to the start of the pathvar"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
add(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![Example {
|
||||||
|
description: "Add /usr/local/bin to the pathvar",
|
||||||
|
example: "pathvar add /usr/local/bin",
|
||||||
|
result: None,
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
let ctx = &args.context;
|
||||||
|
|
||||||
|
let path_to_add: Tagged<PathBuf> = args.req(0)?;
|
||||||
|
let path = path_to_add.item.into_os_string().into_string();
|
||||||
|
|
||||||
|
if let Ok(mut path) = path {
|
||||||
|
path.push(NATIVE_PATH_ENV_SEPARATOR);
|
||||||
|
if let Some(old_pathvar) = ctx.scope.get_env(NATIVE_PATH_ENV_VAR) {
|
||||||
|
path.push_str(&old_pathvar);
|
||||||
|
ctx.scope.add_env_var(NATIVE_PATH_ENV_VAR, path);
|
||||||
|
Ok(OutputStream::empty())
|
||||||
|
} else {
|
||||||
|
Err(ShellError::unexpected("PATH not set"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(ShellError::labeled_error(
|
||||||
|
"Invalid path.",
|
||||||
|
"cannot convert to string",
|
||||||
|
path_to_add.tag,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
58
crates/nu-command/src/commands/pathvar/append.rs
Normal file
58
crates/nu-command/src/commands/pathvar/append.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use nu_engine::WholeStreamCommand;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{Signature, SyntaxShape};
|
||||||
|
use nu_source::Tagged;
|
||||||
|
use nu_test_support::{NATIVE_PATH_ENV_SEPARATOR, NATIVE_PATH_ENV_VAR};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
pub struct SubCommand;
|
||||||
|
|
||||||
|
impl WholeStreamCommand for SubCommand {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"pathvar append"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("pathvar append").required("path", SyntaxShape::FilePath, "path to append")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Add a path to the end of the pathvar"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
add(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![Example {
|
||||||
|
description: "Append /bin to the pathvar",
|
||||||
|
example: "pathvar append /bin",
|
||||||
|
result: None,
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
let ctx = &args.context;
|
||||||
|
let path_to_append_arg: Tagged<PathBuf> = args.req(0)?;
|
||||||
|
let path_to_append = path_to_append_arg.item.into_os_string().into_string();
|
||||||
|
|
||||||
|
if let Ok(path) = path_to_append {
|
||||||
|
if let Some(mut pathvar) = ctx.scope.get_env(NATIVE_PATH_ENV_VAR) {
|
||||||
|
pathvar.push(NATIVE_PATH_ENV_SEPARATOR);
|
||||||
|
pathvar.push_str(&path);
|
||||||
|
ctx.scope.add_env_var(NATIVE_PATH_ENV_VAR, pathvar);
|
||||||
|
Ok(OutputStream::empty())
|
||||||
|
} else {
|
||||||
|
Err(ShellError::unexpected("PATH not set"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(ShellError::labeled_error(
|
||||||
|
"Invalid path.",
|
||||||
|
"cannot convert to string",
|
||||||
|
path_to_append_arg.tag,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
58
crates/nu-command/src/commands/pathvar/command.rs
Normal file
58
crates/nu-command/src/commands/pathvar/command.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use nu_engine::WholeStreamCommand;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{Signature, Value};
|
||||||
|
use nu_test_support::{NATIVE_PATH_ENV_SEPARATOR, NATIVE_PATH_ENV_VAR};
|
||||||
|
|
||||||
|
pub struct Command;
|
||||||
|
|
||||||
|
impl WholeStreamCommand for Command {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"pathvar"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("pathvar")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Manipulate the PATH variable (or pathvar)."
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
get_pathvar(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![
|
||||||
|
Example {
|
||||||
|
description: "Display the current session's pathvar",
|
||||||
|
example: "pathvar",
|
||||||
|
result: None,
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Add /usr/bin to the pathvar",
|
||||||
|
example: "pathvar add /usr/bin",
|
||||||
|
result: None,
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Remove the 3rd path in the pathvar",
|
||||||
|
example: "pathvar remove 2",
|
||||||
|
result: None,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_pathvar(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
if let Some(pathvar) = args.context.scope.get_env(NATIVE_PATH_ENV_VAR) {
|
||||||
|
let pathvar: Vec<Value> = pathvar
|
||||||
|
.split(NATIVE_PATH_ENV_SEPARATOR)
|
||||||
|
.map(Value::from)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(OutputStream::from(pathvar))
|
||||||
|
} else {
|
||||||
|
Err(ShellError::unexpected("PATH not set"))
|
||||||
|
}
|
||||||
|
}
|
13
crates/nu-command/src/commands/pathvar/mod.rs
Normal file
13
crates/nu-command/src/commands/pathvar/mod.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
pub mod add;
|
||||||
|
pub mod append;
|
||||||
|
pub mod command;
|
||||||
|
pub mod remove;
|
||||||
|
pub mod reset;
|
||||||
|
pub mod save;
|
||||||
|
|
||||||
|
pub use add::SubCommand as PathvarAdd;
|
||||||
|
pub use append::SubCommand as PathvarAppend;
|
||||||
|
pub use command::Command as Pathvar;
|
||||||
|
pub use remove::SubCommand as PathvarRemove;
|
||||||
|
pub use reset::SubCommand as PathvarReset;
|
||||||
|
pub use save::SubCommand as PathvarSave;
|
66
crates/nu-command/src/commands/pathvar/remove.rs
Normal file
66
crates/nu-command/src/commands/pathvar/remove.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use nu_engine::WholeStreamCommand;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{Signature, SyntaxShape};
|
||||||
|
use nu_source::Tagged;
|
||||||
|
use nu_test_support::{NATIVE_PATH_ENV_SEPARATOR, NATIVE_PATH_ENV_VAR};
|
||||||
|
|
||||||
|
pub struct SubCommand;
|
||||||
|
|
||||||
|
impl WholeStreamCommand for SubCommand {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"pathvar remove"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("pathvar remove").required(
|
||||||
|
"index",
|
||||||
|
SyntaxShape::Int,
|
||||||
|
"index of the path to remove (starting at 0)",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Remove a path from the pathvar"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
remove(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![Example {
|
||||||
|
description: "Remove the second path from the pathvar",
|
||||||
|
example: "pathvar remove 1",
|
||||||
|
result: None,
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
let ctx = &args.context;
|
||||||
|
let index_to_remove_arg: Tagged<u64> = args.req(0)?;
|
||||||
|
let index_to_remove = index_to_remove_arg.item as usize;
|
||||||
|
|
||||||
|
if let Some(old_pathvar) = ctx.scope.get_env(NATIVE_PATH_ENV_VAR) {
|
||||||
|
let mut paths: Vec<&str> = old_pathvar.split(NATIVE_PATH_ENV_SEPARATOR).collect();
|
||||||
|
|
||||||
|
if index_to_remove >= paths.len() {
|
||||||
|
return Err(ShellError::labeled_error(
|
||||||
|
"Index out of bounds",
|
||||||
|
format!("the index must be between 0 and {}", paths.len() - 1),
|
||||||
|
index_to_remove_arg.tag,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
paths.remove(index_to_remove);
|
||||||
|
ctx.scope.add_env_var(
|
||||||
|
NATIVE_PATH_ENV_VAR,
|
||||||
|
paths.join(&NATIVE_PATH_ENV_SEPARATOR.to_string()),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(OutputStream::empty())
|
||||||
|
} else {
|
||||||
|
Err(ShellError::unexpected("PATH not set"))
|
||||||
|
}
|
||||||
|
}
|
52
crates/nu-command/src/commands/pathvar/reset.rs
Normal file
52
crates/nu-command/src/commands/pathvar/reset.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use nu_engine::WholeStreamCommand;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{Signature, UntaggedValue};
|
||||||
|
use nu_test_support::{NATIVE_PATH_ENV_SEPARATOR, NATIVE_PATH_ENV_VAR};
|
||||||
|
|
||||||
|
pub struct SubCommand;
|
||||||
|
|
||||||
|
impl WholeStreamCommand for SubCommand {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"pathvar reset"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("pathvar reset")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Reset the pathvar to the one specified in the config"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
reset(args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn reset(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
|
let ctx = &args.context;
|
||||||
|
|
||||||
|
if let Some(global_cfg) = &mut ctx.configs().lock().global_config {
|
||||||
|
let default_pathvar = global_cfg.vars.get("path");
|
||||||
|
if let Some(pathvar) = default_pathvar {
|
||||||
|
if let UntaggedValue::Table(paths) = &pathvar.value {
|
||||||
|
let pathvar_str = paths
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.as_string().expect("Error converting path to string"))
|
||||||
|
.join(&NATIVE_PATH_ENV_SEPARATOR.to_string());
|
||||||
|
ctx.scope.add_env_var(NATIVE_PATH_ENV_VAR, pathvar_str);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(ShellError::untagged_runtime_error(
|
||||||
|
"Default path is not set in config file.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(OutputStream::empty())
|
||||||
|
} else {
|
||||||
|
let value = UntaggedValue::Error(crate::commands::config::err_no_global_cfg_present())
|
||||||
|
.into_value(name);
|
||||||
|
|
||||||
|
Ok(OutputStream::one(value))
|
||||||
|
}
|
||||||
|
}
|
57
crates/nu-command/src/commands/pathvar/save.rs
Normal file
57
crates/nu-command/src/commands/pathvar/save.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use nu_engine::WholeStreamCommand;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{Signature, UntaggedValue, Value};
|
||||||
|
use nu_test_support::{NATIVE_PATH_ENV_SEPARATOR, NATIVE_PATH_ENV_VAR};
|
||||||
|
|
||||||
|
pub struct SubCommand;
|
||||||
|
|
||||||
|
impl WholeStreamCommand for SubCommand {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"pathvar save"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("pathvar save")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Save the current pathvar to the config file"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
save(args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn save(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
let name = args.call_info.name_tag.clone();
|
||||||
|
let ctx = &args.context;
|
||||||
|
|
||||||
|
if let Some(global_cfg) = &mut ctx.configs().lock().global_config {
|
||||||
|
if let Some(pathvar) = ctx.scope.get_env(NATIVE_PATH_ENV_VAR) {
|
||||||
|
let paths: Vec<Value> = pathvar
|
||||||
|
.split(NATIVE_PATH_ENV_SEPARATOR)
|
||||||
|
.map(Value::from)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let span_range = 0..paths.len();
|
||||||
|
let row = Value::new(
|
||||||
|
UntaggedValue::Table(paths),
|
||||||
|
Tag::from(Span::from(&span_range)),
|
||||||
|
);
|
||||||
|
|
||||||
|
global_cfg.vars.insert("path".to_string(), row);
|
||||||
|
global_cfg.write()?;
|
||||||
|
ctx.reload_config(global_cfg)?;
|
||||||
|
|
||||||
|
Ok(OutputStream::empty())
|
||||||
|
} else {
|
||||||
|
Err(ShellError::unexpected("PATH not set"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let value = UntaggedValue::Error(crate::commands::config::err_no_global_cfg_present())
|
||||||
|
.into_value(name);
|
||||||
|
|
||||||
|
Ok(OutputStream::one(value))
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,6 +27,12 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
|
||||||
whole_stream_command(Cd),
|
whole_stream_command(Cd),
|
||||||
whole_stream_command(Remove),
|
whole_stream_command(Remove),
|
||||||
whole_stream_command(Open),
|
whole_stream_command(Open),
|
||||||
|
whole_stream_command(Pathvar),
|
||||||
|
whole_stream_command(PathvarAdd),
|
||||||
|
whole_stream_command(PathvarRemove),
|
||||||
|
whole_stream_command(PathvarReset),
|
||||||
|
whole_stream_command(PathvarAppend),
|
||||||
|
whole_stream_command(PathvarSave),
|
||||||
whole_stream_command(Config),
|
whole_stream_command(Config),
|
||||||
whole_stream_command(ConfigGet),
|
whole_stream_command(ConfigGet),
|
||||||
whole_stream_command(ConfigSet),
|
whole_stream_command(ConfigSet),
|
||||||
|
|
|
@ -14,6 +14,11 @@ pub const NATIVE_PATH_ENV_VAR: &str = "Path";
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
pub const NATIVE_PATH_ENV_VAR: &str = "PATH";
|
pub const NATIVE_PATH_ENV_VAR: &str = "PATH";
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub const NATIVE_PATH_ENV_SEPARATOR: char = ':';
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
pub const NATIVE_PATH_ENV_SEPARATOR: char = ';';
|
||||||
|
|
||||||
impl Outcome {
|
impl Outcome {
|
||||||
pub fn new(out: String, err: String) -> Outcome {
|
pub fn new(out: String, err: String) -> Outcome {
|
||||||
Outcome { out, err }
|
Outcome { out, err }
|
||||||
|
|
Loading…
Reference in a new issue