From 243df639782bec19353e628efc3514a3fe9e3b8a Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Sun, 3 Nov 2019 12:22:30 +1300 Subject: [PATCH 1/2] Move config to async_stream --- src/commands/config.rs | 139 ++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 71 deletions(-) diff --git a/src/commands/config.rs b/src/commands/config.rs index a85920e455..3f2937cb17 100644 --- a/src/commands/config.rs +++ b/src/commands/config.rs @@ -4,7 +4,6 @@ use crate::errors::ShellError; use crate::parser::hir::SyntaxShape; use crate::parser::registry::{self}; use crate::prelude::*; -use std::iter::FromIterator; use std::path::PathBuf; pub struct Config; @@ -64,76 +63,74 @@ pub fn config( ) -> Result { let name_span = name.clone(); - let configuration = if let Some(supplied) = load { - Some(supplied.item().clone()) - } else { - None + let stream = async_stream! { + let configuration = if let Some(supplied) = load { + Some(supplied.item().clone()) + } else { + None + }; + + let mut result = crate::data::config::read(name_span, &configuration)?; + + if let Some(v) = get { + let key = v.to_string(); + let value = result + .get(&key) + .ok_or_else(|| ShellError::labeled_error("Missing key in config", "key", v.tag()))?; + + match value { + Tagged { + item: Value::Table(list), + .. + } => { + for l in list { + yield ReturnSuccess::value(l.clone()); + } + } + x => yield ReturnSuccess::value(x.clone()), + } + } + else if let Some((key, value)) = set { + result.insert(key.to_string(), value.clone()); + + config::write(&result, &configuration)?; + + yield ReturnSuccess::value(Value::Row(result.into()).tagged(value.tag())); + } + else if let Tagged { item: true, tag } = clear { + result.clear(); + + config::write(&result, &configuration)?; + + yield ReturnSuccess::value(Value::Row(result.into()).tagged(tag)); + + return; + } + else if let Tagged { item: true, tag } = path { + let path = config::default_path_for(&configuration)?; + + yield ReturnSuccess::value(Value::Primitive(Primitive::Path(path)).tagged(tag)); + } + else if let Some(v) = remove { + let key = v.to_string(); + + if result.contains_key(&key) { + result.swap_remove(&key); + config::write(&result, &configuration).unwrap(); + } else { + yield Err(ShellError::labeled_error( + "Key does not exist in config", + "key", + v.tag(), + )); + } + + yield ReturnSuccess::value(Value::Row(result.into()).tagged(v.tag())); + } + else { + yield ReturnSuccess::value(Value::Row(result.into()).tagged(name)); + } }; - let mut result = crate::data::config::read(name_span, &configuration)?; - - if let Some(v) = get { - let key = v.to_string(); - let value = result - .get(&key) - .ok_or_else(|| ShellError::labeled_error("Missing key in config", "key", v.tag()))?; - - let mut results = VecDeque::new(); - - match value { - Tagged { - item: Value::Table(list), - .. - } => { - for l in list { - results.push_back(ReturnSuccess::value(l.clone())); - } - } - x => results.push_back(ReturnSuccess::value(x.clone())), - } - - return Ok(results.to_output_stream()); - } - - if let Some((key, value)) = set { - result.insert(key.to_string(), value.clone()); - - config::write(&result, &configuration)?; - - return Ok(stream![Value::Row(result.into()).tagged(value.tag())].from_input_stream()); - } - - if let Tagged { item: true, tag } = clear { - result.clear(); - - config::write(&result, &configuration)?; - - return Ok(stream![Value::Row(result.into()).tagged(tag)].from_input_stream()); - } - - if let Tagged { item: true, tag } = path { - let path = config::default_path_for(&configuration)?; - - return Ok(stream![Value::Primitive(Primitive::Path(path)).tagged(tag)].from_input_stream()); - } - - if let Some(v) = remove { - let key = v.to_string(); - - if result.contains_key(&key) { - result.swap_remove(&key); - config::write(&result, &configuration)?; - } else { - return Err(ShellError::labeled_error( - "Key does not exist in config", - "key", - v.tag(), - )); - } - - let obj = VecDeque::from_iter(vec![Value::Row(result.into()).tagged(v.tag())]); - return Ok(obj.from_input_stream()); - } - - return Ok(vec![Value::Row(result.into()).tagged(name)].into()); + Ok(stream.to_output_stream()) } From c31709494777fb7879507f83170121d8e53c1fef Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Sun, 3 Nov 2019 12:43:15 +1300 Subject: [PATCH 2/2] Add support for config --set_into --- src/commands/config.rs | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/commands/config.rs b/src/commands/config.rs index 3f2937cb17..3c41cceae4 100644 --- a/src/commands/config.rs +++ b/src/commands/config.rs @@ -12,6 +12,7 @@ pub struct Config; pub struct ConfigArgs { load: Option>, set: Option<(Tagged, Tagged)>, + set_into: Option>, get: Option>, clear: Tagged, remove: Option>, @@ -30,7 +31,16 @@ impl WholeStreamCommand for Config { SyntaxShape::Path, "load the config from the path give", ) - .named("set", SyntaxShape::Any, "set a value in the config") + .named( + "set", + SyntaxShape::Any, + "set a value in the config, eg) --set [key value]", + ) + .named( + "set_into", + SyntaxShape::Member, + "sets a variable from values in the pipeline", + ) .named("get", SyntaxShape::Any, "get a value from the config") .named("remove", SyntaxShape::Any, "remove a value from the config") .switch("clear", "clear the config") @@ -54,12 +64,13 @@ pub fn config( ConfigArgs { load, set, + set_into, get, clear, remove, path, }: ConfigArgs, - RunnableContext { name, .. }: RunnableContext, + RunnableContext { name, input, .. }: RunnableContext, ) -> Result { let name_span = name.clone(); @@ -97,6 +108,32 @@ pub fn config( yield ReturnSuccess::value(Value::Row(result.into()).tagged(value.tag())); } + else if let Some(v) = set_into { + let rows: Vec> = input.values.collect().await; + let key = v.to_string(); + + if rows.len() == 0 { + yield Err(ShellError::labeled_error("No values given for set_into", "needs value(s) from pipeline", v.tag())); + } else if rows.len() == 1 { + // A single value + let value = &rows[0]; + + result.insert(key.to_string(), value.clone()); + + config::write(&result, &configuration)?; + + yield ReturnSuccess::value(Value::Row(result.into()).tagged(name)); + } else { + // Take in the pipeline as a table + let value = Value::Table(rows).tagged(name.clone()); + + result.insert(key.to_string(), value.clone()); + + config::write(&result, &configuration)?; + + yield ReturnSuccess::value(Value::Row(result.into()).tagged(name)); + } + } else if let Tagged { item: true, tag } = clear { result.clear();