diff --git a/src/commands.rs b/src/commands.rs index 9d3f4165f2..c22d85ac10 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,3 +1,4 @@ +crate mod args; crate mod cd; crate mod command; crate mod ls; diff --git a/src/commands/args.rs b/src/commands/args.rs index 51bf37e7e8..183876b584 100644 --- a/src/commands/args.rs +++ b/src/commands/args.rs @@ -1,6 +1,31 @@ -use crate::Value; +use crate::object::Value; +use derive_new::new; +use std::collections::VecDeque; -#[derive(Debug, Clone)] -pub struct Args { - args: Vec, +#[derive(Debug, Default)] +pub struct ObjectStream { + queue: VecDeque, +} + +#[derive(Debug, Default)] +pub struct Streams { + success: ObjectStream, + error: ObjectStream, + warning: ObjectStream, + debug: ObjectStream, + trace: ObjectStream, + verbose: ObjectStream, +} + +#[derive(Debug, new)] +pub struct Args { + argv: Vec, + #[new(default)] + streams: Streams, +} + +impl Args { + crate fn first(&self) -> Option<&Value> { + self.argv.first() + } } diff --git a/src/commands/cd.rs b/src/commands/cd.rs index be05608aa2..3a9cfc1521 100644 --- a/src/commands/cd.rs +++ b/src/commands/cd.rs @@ -1,6 +1,7 @@ use crate::errors::ShellError; use crate::object::process::Process; use crate::object::{DirEntry, ShellObject, Value}; +use crate::Args; use derive_new::new; use std::path::{Path, PathBuf}; use sysinfo::SystemExt; @@ -11,14 +12,20 @@ pub struct CdBlueprint; impl crate::CommandBlueprint for CdBlueprint { fn create( &self, - args: Vec, + args: Args, host: &dyn crate::Host, env: &mut crate::Environment, - ) -> Box { - Box::new(Cd { + ) -> Result, ShellError> { + let target = match args.first() { + // TODO: This needs better infra + None => return Err(ShellError::new(format!("cd must take one arg"))), + Some(v) => v.as_string()?.clone(), + }; + + Ok(Box::new(Cd { cwd: env.cwd().to_path_buf(), - target: args[0].clone(), - }) + target, + })) } } diff --git a/src/commands/command.rs b/src/commands/command.rs index ebbddc4fa6..a62a593eed 100644 --- a/src/commands/command.rs +++ b/src/commands/command.rs @@ -5,10 +5,10 @@ use std::path::PathBuf; pub trait CommandBlueprint { fn create( &self, - args: Vec, + args: crate::Args, host: &dyn crate::Host, env: &mut crate::Environment, - ) -> Box; + ) -> Result, ShellError>; } crate enum CommandAction { diff --git a/src/commands/ls.rs b/src/commands/ls.rs index 5a6461f1c7..4c34874c1b 100644 --- a/src/commands/ls.rs +++ b/src/commands/ls.rs @@ -1,6 +1,7 @@ use crate::errors::ShellError; use crate::object::process::Process; use crate::object::{DirEntry, ShellObject, Value}; +use crate::Args; use crate::{Command, CommandSuccess}; use derive_new::new; use std::path::PathBuf; @@ -12,13 +13,13 @@ pub struct LsBlueprint; impl crate::CommandBlueprint for LsBlueprint { fn create( &self, - args: Vec, + args: Args, host: &dyn crate::Host, env: &mut crate::Environment, - ) -> Box { - Box::new(Ls { + ) -> Result, ShellError> { + Ok(Box::new(Ls { cwd: env.cwd().to_path_buf(), - }) + })) } } diff --git a/src/commands/ps.rs b/src/commands/ps.rs index 2d8dfc9195..faf2687bbb 100644 --- a/src/commands/ps.rs +++ b/src/commands/ps.rs @@ -15,11 +15,11 @@ pub struct PsBlueprint { impl crate::CommandBlueprint for PsBlueprint { fn create( &self, - args: Vec, + args: crate::Args, host: &dyn crate::Host, env: &mut crate::Environment, - ) -> Box { - Box::new(Ps::new(self.system.clone())) + ) -> Result, ShellError> { + Ok(Box::new(Ps::new(self.system.clone()))) } } diff --git a/src/main.rs b/src/main.rs index 6e76bef240..83d892c2ae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,11 +9,14 @@ mod format; mod object; mod parser; +crate use crate::commands::args::{Args, Streams}; crate use crate::commands::command::{Command, CommandAction, CommandBlueprint, CommandSuccess}; crate use crate::env::{Environment, Host}; crate use crate::errors::ShellError; crate use crate::format::RenderView; use crate::object::base::{ToEntriesView, ToGenericView}; +use crate::object::Value; + use ansi_term::Color; use conch_parser::lexer::Lexer; use conch_parser::parse::DefaultParser; @@ -81,14 +84,16 @@ fn main() -> Result<(), Box> { } let command = &parsed[0][0].name(); - let args = parsed[0][1..] + let arg_list = parsed[0][1..] .iter() - .map(|i| i.name().to_string()) + .map(|i| Value::string(i.name().to_string())) .collect(); + let args = Args::new(arg_list); + match commands.get_mut(*command) { Some(command) => { - let mut instance = command.create(args, &mut host, &mut env); + let mut instance = command.create(args, &mut host, &mut env)?; let result = instance.run()?; for action in result.action { diff --git a/src/object/base.rs b/src/object/base.rs index b2d75c234a..4946d89bf5 100644 --- a/src/object/base.rs +++ b/src/object/base.rs @@ -1,3 +1,4 @@ +use crate::errors::ShellError; use crate::format::{EntriesView, GenericView}; use crate::object::desc::DataDescriptor; use chrono::NaiveDateTime; @@ -67,6 +68,15 @@ impl Value { } } + crate fn as_string(&self) -> Result { + match self { + Value::Primitive(Primitive::String(s)) => Ok(s.to_string()), + + // TODO: this should definitely be more general with better errors + other => Err(ShellError::new(format!("Expected string, got {:?}", other))), + } + } + crate fn string(s: impl Into) -> Value { Value::Primitive(Primitive::String(s.into())) }