diff --git a/src/cli.rs b/src/cli.rs index 68c652c772..0bc8856195 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -244,6 +244,7 @@ pub async fn cli() -> Result<(), Box> { whole_stream_command(Tags), whole_stream_command(First), whole_stream_command(Last), + whole_stream_command(Env), whole_stream_command(FromCSV), whole_stream_command(FromTSV), whole_stream_command(FromINI), diff --git a/src/commands.rs b/src/commands.rs index c6cc7b7285..af612d5752 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -13,6 +13,7 @@ pub(crate) mod date; pub(crate) mod debug; pub(crate) mod echo; pub(crate) mod enter; +pub(crate) mod env; pub(crate) mod exit; pub(crate) mod fetch; pub(crate) mod first; @@ -78,6 +79,7 @@ pub(crate) use date::Date; pub(crate) use debug::Debug; pub(crate) use echo::Echo; pub(crate) use enter::Enter; +pub(crate) use env::Env; pub(crate) use exit::Exit; pub(crate) use fetch::Fetch; pub(crate) use first::First; diff --git a/src/commands/env.rs b/src/commands/env.rs new file mode 100644 index 0000000000..6fc26507cc --- /dev/null +++ b/src/commands/env.rs @@ -0,0 +1,68 @@ +use crate::data::{Dictionary, Value}; +use crate::errors::ShellError; +use crate::prelude::*; +use crate::TaggedDictBuilder; + +use crate::commands::WholeStreamCommand; +use crate::parser::registry::Signature; +use indexmap::IndexMap; + +pub struct Env; + +impl WholeStreamCommand for Env { + fn name(&self) -> &str { + "env" + } + + fn signature(&self) -> Signature { + Signature::build("env") + } + + fn usage(&self) -> &str { + "Get the current environment." + } + + fn run( + &self, + args: CommandArgs, + registry: &CommandRegistry, + ) -> Result { + env(args, registry) + } +} + +pub fn get_environment(tag: Tag) -> Result, Box> { + let mut indexmap = IndexMap::new(); + + let path = std::env::current_dir()?; + indexmap.insert("cwd".to_string(), Value::path(path).tagged(tag)); + + if let Some(home) = dirs::home_dir() { + indexmap.insert("home".to_string(), Value::path(home).tagged(tag)); + } + + let temp = std::env::temp_dir(); + indexmap.insert("temp".to_string(), Value::path(temp).tagged(tag)); + + let mut dict = TaggedDictBuilder::new(tag); + for v in std::env::vars() { + dict.insert(v.0, Value::string(v.1)); + } + if !dict.is_empty() { + indexmap.insert("vars".to_string(), dict.into_tagged_value()); + } + + Ok(Value::Row(Dictionary::from(indexmap)).tagged(tag)) +} + +pub fn env(args: CommandArgs, registry: &CommandRegistry) -> Result { + let args = args.evaluate_once(registry)?; + + let mut env_out = VecDeque::new(); + let tag = args.call_info.name_tag; + + let value = get_environment(tag)?; + env_out.push_back(value); + + Ok(env_out.to_output_stream()) +} diff --git a/src/data/dict.rs b/src/data/dict.rs index eba68a7f8a..c14c86dd90 100644 --- a/src/data/dict.rs +++ b/src/data/dict.rs @@ -169,6 +169,10 @@ impl TaggedDictBuilder { pub fn into_tagged_dict(self) -> Tagged { Dictionary { entries: self.dict }.tagged(self.tag) } + + pub fn is_empty(&self) -> bool { + self.dict.is_empty() + } } impl From for Tagged {