forked from extern/nushell
* move commands, futures.rs, script.rs, utils * move over maybe_print_errors * add nu_command crate references to nu_cli * in commands.rs open up to pub mod from pub(crate) * nu-cli, nu-command, and nu tests are now passing * cargo fmt * clean up nu-cli/src/prelude.rs * code cleanup * for some reason lex.rs was not formatted, may be causing my error * remove mod completion from lib.rs which was not being used along with quickcheck macros * add in allow unused imports * comment out one failing external test; comment out one failing internal test * revert commenting out failing tests; something else might be going on; someone with a windows machine should check and see what is going on with these failing windows tests * Update Cargo.toml Extend the optional features to nu-command Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
96 lines
2.5 KiB
Rust
96 lines
2.5 KiB
Rust
mod basename;
|
|
mod command;
|
|
mod dirname;
|
|
mod exists;
|
|
mod expand;
|
|
mod extension;
|
|
mod filestem;
|
|
mod r#type;
|
|
|
|
use crate::prelude::*;
|
|
use nu_errors::ShellError;
|
|
use nu_protocol::{ColumnPath, Primitive, ReturnSuccess, ShellTypeName, UntaggedValue, Value};
|
|
use nu_source::Span;
|
|
use std::path::Path;
|
|
use std::sync::Arc;
|
|
|
|
pub use basename::PathBasename;
|
|
pub use command::Path as PathCommand;
|
|
pub use dirname::PathDirname;
|
|
pub use exists::PathExists;
|
|
pub use expand::PathExpand;
|
|
pub use extension::PathExtension;
|
|
pub use filestem::PathFilestem;
|
|
pub use r#type::PathType;
|
|
|
|
#[derive(Deserialize)]
|
|
struct DefaultArguments {
|
|
// used by basename, dirname, extension and filestem
|
|
replace: Option<String>,
|
|
// used by filestem
|
|
prefix: Option<String>,
|
|
suffix: Option<String>,
|
|
// used by dirname
|
|
num_levels: Option<u32>,
|
|
// used by all
|
|
paths: Vec<ColumnPath>,
|
|
}
|
|
|
|
fn handle_value<F>(
|
|
action: &F,
|
|
v: &Value,
|
|
span: Span,
|
|
args: Arc<DefaultArguments>,
|
|
) -> Result<Value, ShellError>
|
|
where
|
|
F: Fn(&Path, Arc<DefaultArguments>) -> UntaggedValue + Send + 'static,
|
|
{
|
|
let v = match &v.value {
|
|
UntaggedValue::Primitive(Primitive::FilePath(buf)) => action(buf, args).into_value(v.tag()),
|
|
UntaggedValue::Primitive(Primitive::String(s)) => {
|
|
action(s.as_ref(), args).into_value(v.tag())
|
|
}
|
|
other => {
|
|
let got = format!("got {}", other.type_name());
|
|
return Err(ShellError::labeled_error_with_secondary(
|
|
"value is not string or path",
|
|
got,
|
|
span,
|
|
"originates from here".to_string(),
|
|
v.tag().span,
|
|
));
|
|
}
|
|
};
|
|
Ok(v)
|
|
}
|
|
|
|
async fn operate<F>(
|
|
input: crate::InputStream,
|
|
action: &'static F,
|
|
span: Span,
|
|
args: Arc<DefaultArguments>,
|
|
) -> Result<OutputStream, ShellError>
|
|
where
|
|
F: Fn(&Path, Arc<DefaultArguments>) -> UntaggedValue + Send + Sync + 'static,
|
|
{
|
|
Ok(input
|
|
.map(move |v| {
|
|
if args.paths.is_empty() {
|
|
ReturnSuccess::value(handle_value(&action, &v, span, Arc::clone(&args))?)
|
|
} else {
|
|
let mut ret = v;
|
|
|
|
for path in &args.paths {
|
|
let cloned_args = Arc::clone(&args);
|
|
ret = ret.swap_data_by_column_path(
|
|
path,
|
|
Box::new(move |old| handle_value(&action, &old, span, cloned_args)),
|
|
)?;
|
|
}
|
|
|
|
ReturnSuccess::value(ret)
|
|
}
|
|
})
|
|
.to_output_stream())
|
|
}
|