From 37f10cf273c92ca6d915bf2111f201d5a91d1ec7 Mon Sep 17 00:00:00 2001 From: Matt Hall Date: Mon, 27 Jul 2020 03:12:07 +0100 Subject: [PATCH] Add two further path cmds - type and exists (#2264) * Add two further path cmds - type and exists * Update type.rs Try a more universal directory * Update type.rs Co-authored-by: Jonathan Turner --- crates/nu-cli/src/cli.rs | 2 + crates/nu-cli/src/commands.rs | 2 +- crates/nu-cli/src/commands/path/exists.rs | 44 ++++++++++++++++ crates/nu-cli/src/commands/path/mod.rs | 4 ++ crates/nu-cli/src/commands/path/type.rs | 61 +++++++++++++++++++++++ crates/nu-cli/src/data/files.rs | 2 +- 6 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 crates/nu-cli/src/commands/path/exists.rs create mode 100644 crates/nu-cli/src/commands/path/type.rs diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index f8b2611332..525c12a4f5 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -418,6 +418,8 @@ pub fn create_default_context( whole_stream_command(PathExtension), whole_stream_command(PathBasename), whole_stream_command(PathExpand), + whole_stream_command(PathExists), + whole_stream_command(PathType), ]); #[cfg(feature = "clipboard")] diff --git a/crates/nu-cli/src/commands.rs b/crates/nu-cli/src/commands.rs index 118a402f2a..d211fcd778 100644 --- a/crates/nu-cli/src/commands.rs +++ b/crates/nu-cli/src/commands.rs @@ -204,7 +204,7 @@ pub(crate) use next::Next; pub(crate) use nth::Nth; pub(crate) use open::Open; pub(crate) use parse::Parse; -pub(crate) use path::{PathBasename, PathCommand, PathExpand, PathExtension}; +pub(crate) use path::{PathBasename, PathCommand, PathExists, PathExpand, PathExtension, PathType}; pub(crate) use pivot::Pivot; pub(crate) use prepend::Prepend; pub(crate) use prev::Previous; diff --git a/crates/nu-cli/src/commands/path/exists.rs b/crates/nu-cli/src/commands/path/exists.rs new file mode 100644 index 0000000000..9fb20d74d1 --- /dev/null +++ b/crates/nu-cli/src/commands/path/exists.rs @@ -0,0 +1,44 @@ +use super::{operate, DefaultArguments}; +use crate::commands::WholeStreamCommand; +use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; +use std::path::Path; + +pub struct PathExists; + +#[async_trait] +impl WholeStreamCommand for PathExists { + fn name(&self) -> &str { + "path exists" + } + + fn signature(&self) -> Signature { + Signature::build("path exists").rest(SyntaxShape::ColumnPath, "optionally operate by path") + } + + fn usage(&self) -> &str { + "checks whether the path exists" + } + + async fn run( + &self, + args: CommandArgs, + registry: &CommandRegistry, + ) -> Result { + let (DefaultArguments { rest }, input) = args.process(®istry).await?; + operate(input, rest, &action).await + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Check if file exists", + example: "echo '/home/joe/todo.txt' | path exists", + result: Some(vec![Value::from(UntaggedValue::boolean(false))]), + }] + } +} + +fn action(path: &Path) -> UntaggedValue { + UntaggedValue::boolean(path.exists()) +} diff --git a/crates/nu-cli/src/commands/path/mod.rs b/crates/nu-cli/src/commands/path/mod.rs index 2285e2a4e6..a088cac56e 100644 --- a/crates/nu-cli/src/commands/path/mod.rs +++ b/crates/nu-cli/src/commands/path/mod.rs @@ -1,7 +1,9 @@ mod basename; mod command; +mod exists; mod expand; mod extension; +mod r#type; use crate::prelude::*; use nu_errors::ShellError; @@ -10,8 +12,10 @@ use std::path::Path; pub use basename::PathBasename; pub use command::Path as PathCommand; +pub use exists::PathExists; pub use expand::PathExpand; pub use extension::PathExtension; +pub use r#type::PathType; #[derive(Deserialize)] struct DefaultArguments { diff --git a/crates/nu-cli/src/commands/path/type.rs b/crates/nu-cli/src/commands/path/type.rs new file mode 100644 index 0000000000..8d188abd52 --- /dev/null +++ b/crates/nu-cli/src/commands/path/type.rs @@ -0,0 +1,61 @@ +use super::{operate, DefaultArguments}; +use crate::commands::WholeStreamCommand; +use crate::data::files::get_file_type; +use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; +use std::path::Path; + +pub struct PathType; + +#[async_trait] +impl WholeStreamCommand for PathType { + fn name(&self) -> &str { + "path type" + } + + fn signature(&self) -> Signature { + Signature::build("path type").rest(SyntaxShape::ColumnPath, "optionally operate by path") + } + + fn usage(&self) -> &str { + "gives the type of the object the path refers to (eg file, dir, symlink)" + } + + async fn run( + &self, + args: CommandArgs, + registry: &CommandRegistry, + ) -> Result { + let (DefaultArguments { rest }, input) = args.process(®istry).await?; + operate(input, rest, &action).await + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Show type of a filepath", + example: "echo '.' | path type", + result: Some(vec![Value::from("Dir")]), + }] + } +} + +fn action(path: &Path) -> UntaggedValue { + let meta = std::fs::symlink_metadata(path); + UntaggedValue::string(match &meta { + Ok(md) => get_file_type(md), + Err(_) => "", + }) +} + +#[cfg(test)] +mod tests { + use super::PathType; + + #[test] + fn examples_work_as_expected() { + use crate::examples::test as test_examples; + + test_examples(PathType {}) + } +} diff --git a/crates/nu-cli/src/data/files.rs b/crates/nu-cli/src/data/files.rs index e8ff6f959b..d2eaeda030 100644 --- a/crates/nu-cli/src/data/files.rs +++ b/crates/nu-cli/src/data/files.rs @@ -6,7 +6,7 @@ use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value}; #[cfg(unix)] use std::os::unix::fs::FileTypeExt; -fn get_file_type(md: &std::fs::Metadata) -> &str { +pub(crate) fn get_file_type(md: &std::fs::Metadata) -> &str { let ft = md.file_type(); let mut file_type = "Unknown"; if ft.is_dir() {