diff --git a/src/cli.rs b/src/cli.rs index 24e654da3..4c631a619 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -113,7 +113,7 @@ pub async fn cli() -> Result<(), Box> { let (obj, cwd) = { let env = context.env.lock().unwrap(); - let last = env.last().unwrap(); + let last = env.back().unwrap(); (last.obj().clone(), last.path().display().to_string()) }; let readline = match obj { diff --git a/src/commands/cd.rs b/src/commands/cd.rs index d69f71e2b..8716a4362 100644 --- a/src/commands/cd.rs +++ b/src/commands/cd.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; pub fn cd(args: CommandArgs) -> Result { let env = args.env.lock().unwrap(); - let latest = env.last().unwrap(); + let latest = env.back().unwrap(); match latest.obj { Value::Filesystem => { diff --git a/src/commands/classified.rs b/src/commands/classified.rs index fcd9586f2..a83a384f9 100644 --- a/src/commands/classified.rs +++ b/src/commands/classified.rs @@ -4,6 +4,7 @@ use crate::parser::lexer::Span; use crate::parser::registry::Args; use crate::prelude::*; use bytes::{BufMut, BytesMut}; +use futures::stream::StreamExt; use futures_codec::{Decoder, Encoder, Framed}; use std::io::{Error, ErrorKind}; use std::path::PathBuf; @@ -109,15 +110,50 @@ impl InternalCommand { context: &mut Context, input: ClassifiedInputStream, ) -> Result { - let result = context.run_command( + let mut result = context.run_command( self.command, self.name_span.clone(), self.args, input.objects, )?; - let env = context.env.clone(); + let mut stream = VecDeque::new(); + while let Some(item) = result.next().await { + match item { + ReturnValue::Value(Value::Error(err)) => { + return Err(*err); + } + ReturnValue::Action(action) => match action { + CommandAction::ChangePath(path) => { + context.env.lock().unwrap().back_mut().map(|x| { + x.path = path; + x + }); + } + CommandAction::Enter(obj) => { + let new_env = Environment { + obj: obj, + path: PathBuf::from("/"), + }; + context.env.lock().unwrap().push_back(new_env); + } + CommandAction::Exit => match context.env.lock().unwrap().pop_back() { + Some(Environment { + obj: Value::Filesystem, + .. + }) => std::process::exit(0), + None => std::process::exit(-1), + _ => {} + }, + }, + ReturnValue::Value(v) => { + stream.push_back(v); + } + } + } + /* let stream = result.filter_map(move |v| match v { + //ReturnValue::Value(Value::Error(err)) => futures::future::err(Err(err)), ReturnValue::Action(action) => match action { CommandAction::ChangePath(path) => { env.lock().unwrap().last_mut().map(|x| { @@ -146,7 +182,7 @@ impl InternalCommand { ReturnValue::Value(v) => futures::future::ready(Some(v)), }); - + */ Ok(stream.boxed() as InputStream) } } @@ -229,7 +265,7 @@ impl ExternalCommand { } process = Exec::shell(new_arg_string); } - process = process.cwd(context.env.lock().unwrap().first().unwrap().path()); + process = process.cwd(context.env.lock().unwrap().front().unwrap().path()); let mut process = match stream_next { StreamNext::Last => process, diff --git a/src/commands/command.rs b/src/commands/command.rs index 2d9faff09..ff2046206 100644 --- a/src/commands/command.rs +++ b/src/commands/command.rs @@ -8,7 +8,7 @@ use std::path::PathBuf; pub struct CommandArgs { pub host: Arc>, - pub env: Arc>>, + pub env: Arc>>, pub name_span: Option, pub positional: Vec>, pub named: indexmap::IndexMap, diff --git a/src/commands/enter.rs b/src/commands/enter.rs index d1bbef5da..972225823 100644 --- a/src/commands/enter.rs +++ b/src/commands/enter.rs @@ -14,7 +14,7 @@ pub fn enter(args: CommandArgs) -> Result { .env .lock() .unwrap() - .first() + .front() .unwrap() .path() .to_path_buf(); diff --git a/src/commands/exit.rs b/src/commands/exit.rs index 0669adee7..27438f665 100644 --- a/src/commands/exit.rs +++ b/src/commands/exit.rs @@ -1,11 +1,8 @@ use crate::commands::command::CommandAction; use crate::errors::ShellError; -use crate::object::{Primitive, Value}; -use crate::parser::lexer::Spanned; use crate::prelude::*; -use std::path::{Path, PathBuf}; -pub fn exit(args: CommandArgs) -> Result { +pub fn exit(_args: CommandArgs) -> Result { let mut stream = VecDeque::new(); stream.push_back(ReturnValue::Action(CommandAction::Exit)); Ok(stream.boxed()) diff --git a/src/commands/get.rs b/src/commands/get.rs index b3869d97a..3939e9fde 100644 --- a/src/commands/get.rs +++ b/src/commands/get.rs @@ -1,17 +1,19 @@ use crate::errors::ShellError; use crate::object::Value; +use crate::parser::lexer::Span; use crate::prelude::*; -fn get_member(path: &str, obj: &Value) -> Option { +fn get_member(path: &str, span: Span, obj: &Value) -> Option { let mut current = obj; for p in path.split(".") { match current.get_data_by_key(p) { Some(v) => current = v, None => { - return Some(Value::Error(Box::new(ShellError::string(format!( - "Object field name not found: {}", - p - ))))) + return Some(Value::Error(Box::new(ShellError::labeled_error( + "Unknown field", + "unknown field", + span, + )))); } } } @@ -44,7 +46,11 @@ pub fn get(args: CommandArgs) -> Result { .boxed()); } - let fields: Result, _> = args.positional.iter().map(|a| a.as_string()).collect(); + let fields: Result, _> = args + .positional + .iter() + .map(|a| (a.as_string().map(|x| (x, a.span)))) + .collect(); let fields = fields?; let stream = args @@ -52,7 +58,7 @@ pub fn get(args: CommandArgs) -> Result { .map(move |item| { let mut result = VecDeque::new(); for field in &fields { - match get_member(field, &item) { + match get_member(&field.0, field.1, &item) { Some(Value::List(l)) => { for item in l { result.push_back(ReturnValue::Value(item.copy())); diff --git a/src/commands/ls.rs b/src/commands/ls.rs index 70cbf9d53..bfa86218e 100644 --- a/src/commands/ls.rs +++ b/src/commands/ls.rs @@ -7,8 +7,8 @@ use std::path::{Path, PathBuf}; pub fn ls(args: CommandArgs) -> Result { let env = args.env.lock().unwrap(); - let path = env.last().unwrap().path.to_path_buf(); - let obj = &env.last().unwrap().obj; + let path = env.back().unwrap().path.to_path_buf(); + let obj = &env.back().unwrap().obj; let mut full_path = PathBuf::from(path); match &args.positional.get(0) { Some(Spanned { diff --git a/src/commands/open.rs b/src/commands/open.rs index 15392e48d..18b8e242d 100644 --- a/src/commands/open.rs +++ b/src/commands/open.rs @@ -13,7 +13,7 @@ pub fn open(args: CommandArgs) -> Result { .env .lock() .unwrap() - .first() + .front() .unwrap() .path() .to_path_buf(); diff --git a/src/commands/save.rs b/src/commands/save.rs index 5d94496cf..ea16f5f0b 100644 --- a/src/commands/save.rs +++ b/src/commands/save.rs @@ -14,7 +14,7 @@ pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> { .env .lock() .unwrap() - .first() + .front() .unwrap() .path() .to_path_buf(); diff --git a/src/commands/size.rs b/src/commands/size.rs index 4fe90e25f..fb9ff767e 100644 --- a/src/commands/size.rs +++ b/src/commands/size.rs @@ -13,7 +13,7 @@ pub fn size(args: CommandArgs) -> Result { .env .lock() .unwrap() - .first() + .front() .unwrap() .path() .to_path_buf(); diff --git a/src/commands/view.rs b/src/commands/view.rs index 30dce91d8..043b30f6a 100644 --- a/src/commands/view.rs +++ b/src/commands/view.rs @@ -34,7 +34,7 @@ pub fn view(args: CommandArgs) -> Result { .env .lock() .unwrap() - .first() + .front() .unwrap() .path() .to_path_buf(); diff --git a/src/context.rs b/src/context.rs index ff571369d..931190aca 100644 --- a/src/context.rs +++ b/src/context.rs @@ -13,16 +13,18 @@ pub struct Context { commands: IndexMap>, sinks: IndexMap>, crate host: Arc>, - crate env: Arc>>, + crate env: Arc>>, } impl Context { crate fn basic() -> Result> { + let mut env = VecDeque::new(); + env.push_back(Environment::basic()?); Ok(Context { commands: indexmap::IndexMap::new(), sinks: indexmap::IndexMap::new(), host: Arc::new(Mutex::new(crate::env::host::BasicHost)), - env: Arc::new(Mutex::new(vec![Environment::basic()?])), + env: Arc::new(Mutex::new(env)), }) }