This commit is contained in:
Jonathan Turner 2019-08-07 15:42:46 +12:00
parent 52ea14cb25
commit ab8176d4c7
18 changed files with 153 additions and 121 deletions

View File

@ -223,19 +223,11 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
continue;
}
let cwd = {
context
.env
.lock()
.unwrap()
.last()
.unwrap()
.path()
.display()
.to_string()
};
let cwd = context.shell_manager.path();
rl.set_helper(Some(crate::shell::Helper::new(context.env.clone())));
rl.set_helper(Some(crate::shell::Helper::new(
context.shell_manager.clone(),
)));
let readline = rl.readline(&format!(
"{}{}> ",

View File

@ -1,9 +1,6 @@
use crate::errors::ShellError;
use crate::prelude::*;
use crate::shell::shell::Shell;
pub fn cd(args: CommandArgs) -> Result<OutputStream, ShellError> {
let env = args.env.lock().unwrap();
env.last().unwrap().cd(args.call_info, args.input)
args.shell_manager.cd(args.call_info, args.input)
}

View File

@ -145,13 +145,7 @@ impl InternalCommand {
match item? {
ReturnSuccess::Action(action) => match action {
CommandAction::ChangePath(path) => {
let result = context
.env
.lock()
.unwrap()
.last_mut()
.unwrap()
.set_path(path);
context.shell_manager.set_path(&path);
}
CommandAction::AddSpanSource(uuid, span_source) => {
context.add_span_source(uuid, span_source);
@ -159,20 +153,14 @@ impl InternalCommand {
CommandAction::Exit => std::process::exit(0),
CommandAction::Enter(location) => {
context
.env
.lock()
.unwrap()
.push(Box::new(Environment::with_location(location)?));
.shell_manager
.push(Box::new(FilesystemShell::with_location(location)?));
}
CommandAction::PreviousShell => {
let mut x = context.env.lock().unwrap();
let shell = x.pop().unwrap();
x.insert(0, shell);
context.shell_manager.prev();
}
CommandAction::NextShell => {
let mut x = context.env.lock().unwrap();
let shell = x.remove(0);
x.push(shell);
context.shell_manager.next();
}
},
@ -321,7 +309,7 @@ impl ExternalCommand {
process = Exec::shell(new_arg_string);
}
process = process.cwd(context.env.lock().unwrap().last().unwrap().path());
process = process.cwd(context.shell_manager.path());
let mut process = match stream_next {
StreamNext::Last => process,

View File

@ -4,7 +4,6 @@ use crate::errors::ShellError;
use crate::object::Value;
use crate::parser::registry::{self, Args};
use crate::prelude::*;
use crate::shell::shell::Shell;
use getset::Getters;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
@ -21,7 +20,7 @@ pub struct CallInfo {
#[get = "crate"]
pub struct CommandArgs {
pub host: Arc<Mutex<dyn Host + Send>>,
pub env: Arc<Mutex<Vec<Box<dyn Shell>>>>,
pub shell_manager: ShellManager,
pub call_info: CallInfo,
pub input: InputStream,
}

View File

@ -3,7 +3,7 @@ use crate::parser::hir::SyntaxType;
use crate::parser::registry::{CommandConfig, NamedType, PositionalType};
use crate::prelude::*;
use indexmap::IndexMap;
use std::path::Path;
use std::path::{Path, PathBuf};
pub struct Copycp;
@ -32,22 +32,8 @@ impl Command for Copycp {
}
pub fn cp(args: CommandArgs) -> Result<OutputStream, ShellError> {
let mut source = args
.env
.lock()
.unwrap()
.last()
.unwrap()
.path()
.to_path_buf();
let mut destination = args
.env
.lock()
.unwrap()
.last()
.unwrap()
.path()
.to_path_buf();
let mut source = PathBuf::from(args.shell_manager.path());
let mut destination = PathBuf::from(args.shell_manager.path());
let mut dst = String::new();

View File

@ -2,7 +2,5 @@ use crate::errors::ShellError;
use crate::prelude::*;
pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
let env = args.env.lock().unwrap();
env.last().unwrap().ls(args.call_info, args.input)
args.shell_manager.ls(args.call_info, args.input)
}

View File

@ -12,13 +12,7 @@ command! {
let span = args.call_info.name_span;
let cwd = args
.env
.lock()
.unwrap()
.last()
.unwrap()
.path()
.to_path_buf();
.shell_manager.path();
let full_path = PathBuf::from(cwd);

View File

@ -5,6 +5,7 @@ use crate::prelude::*;
use glob::glob;
use indexmap::IndexMap;
use std::path::PathBuf;
pub struct Remove;
@ -33,14 +34,7 @@ impl Command for Remove {
}
pub fn rm(args: CommandArgs) -> Result<OutputStream, ShellError> {
let mut full_path = args
.env
.lock()
.unwrap()
.last()
.unwrap()
.path()
.to_path_buf();
let mut full_path = PathBuf::from(args.shell_manager.path());
match args
.nth(0)

View File

@ -9,15 +9,7 @@ use crate::SpanSource;
use std::path::{Path, PathBuf};
pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
let cwd = args
.ctx
.env
.lock()
.unwrap()
.last()
.unwrap()
.path()
.to_path_buf();
let cwd = args.ctx.shell_manager.path();
let mut full_path = PathBuf::from(cwd);
let save_raw = if args.call_info.args.has("raw") {

View File

@ -38,7 +38,7 @@ pub struct Context {
sinks: IndexMap<String, Arc<dyn Sink>>,
crate source_map: SourceMap,
crate host: Arc<Mutex<dyn Host + Send>>,
crate env: Arc<Mutex<Vec<Box<dyn Shell>>>>,
crate shell_manager: ShellManager,
}
impl Context {
@ -48,7 +48,7 @@ impl Context {
sinks: indexmap::IndexMap::new(),
source_map: SourceMap::new(),
host: Arc::new(Mutex::new(crate::env::host::BasicHost)),
env: Arc::new(Mutex::new(vec![Box::new(Environment::basic()?)])),
shell_manager: ShellManager::basic()?,
})
}
@ -118,7 +118,7 @@ impl Context {
) -> Result<OutputStream, ShellError> {
let command_args = CommandArgs {
host: self.host.clone(),
env: self.env.clone(),
shell_manager: self.shell_manager.clone(),
call_info: CallInfo {
name_span,
source_map,

View File

@ -1,5 +1,3 @@
crate mod environment;
crate mod host;
crate use self::environment::Environment;
crate use self::host::Host;

View File

@ -38,12 +38,13 @@ crate use crate::commands::command::{
};
crate use crate::context::{Context, SpanSource};
crate use crate::env::host::handle_unexpected;
crate use crate::env::{Environment, Host};
crate use crate::env::Host;
crate use crate::errors::ShellError;
crate use crate::object::meta::{Tag, Tagged, TaggedItem};
crate use crate::object::types::ExtractType;
crate use crate::object::{Primitive, Value};
crate use crate::shell::shell::Shell;
crate use crate::shell::filesystem_shell::FilesystemShell;
crate use crate::shell::shell_manager::ShellManager;
crate use crate::stream::{InputStream, OutputStream};
crate use crate::Span;
crate use crate::Text;

View File

@ -1,5 +1,7 @@
crate mod completer;
crate mod filesystem_shell;
crate mod helper;
crate mod shell;
crate mod shell_manager;
crate use helper::Helper;

View File

@ -1,4 +1,3 @@
use crate::prelude::*;
use derive_new::new;
use rustyline::completion::Completer;
use rustyline::completion::{self, FilenameCompleter};

View File

@ -7,15 +7,15 @@ use rustyline::completion::{self, Completer, FilenameCompleter};
use rustyline::error::ReadlineError;
use rustyline::hint::{Hinter, HistoryHinter};
use std::path::{Path, PathBuf};
pub struct Environment {
pub struct FilesystemShell {
crate path: PathBuf,
completer: NuCompleter,
hinter: HistoryHinter,
}
impl Clone for Environment {
impl Clone for FilesystemShell {
fn clone(&self) -> Self {
Environment {
FilesystemShell {
path: self.path.clone(),
completer: NuCompleter {
file_completer: FilenameCompleter::new(),
@ -25,11 +25,11 @@ impl Clone for Environment {
}
}
impl Environment {
pub fn basic() -> Result<Environment, std::io::Error> {
impl FilesystemShell {
pub fn basic() -> Result<FilesystemShell, std::io::Error> {
let path = std::env::current_dir()?;
Ok(Environment {
Ok(FilesystemShell {
path,
completer: NuCompleter {
file_completer: FilenameCompleter::new(),
@ -38,10 +38,10 @@ impl Environment {
})
}
pub fn with_location(location: String) -> Result<Environment, std::io::Error> {
pub fn with_location(location: String) -> Result<FilesystemShell, std::io::Error> {
let path = std::path::PathBuf::from(location);
Ok(Environment {
Ok(FilesystemShell {
path,
completer: NuCompleter {
file_completer: FilenameCompleter::new(),
@ -49,13 +49,9 @@ impl Environment {
hinter: HistoryHinter {},
})
}
pub fn path(&self) -> &Path {
self.path.as_path()
}
}
impl Shell for Environment {
impl Shell for FilesystemShell {
fn ls(&self, call_info: CallInfo, _input: InputStream) -> Result<OutputStream, ShellError> {
let cwd = self.path.clone();
let mut full_path = PathBuf::from(&self.path);
@ -179,12 +175,12 @@ impl Shell for Environment {
self.path.clone()
}
fn set_path(&mut self, path: std::path::PathBuf) {
self.path = path;
fn set_path(&mut self, path: &std::path::PathBuf) {
self.path = path.clone();
}
}
impl Completer for Environment {
impl Completer for FilesystemShell {
type Candidate = completion::Pair;
fn complete(
@ -197,7 +193,7 @@ impl Completer for Environment {
}
}
impl Hinter for Environment {
impl Hinter for FilesystemShell {
fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<String> {
self.hinter.hint(line, pos, ctx)
}

View File

@ -2,7 +2,7 @@ use crate::parser::nom_input;
use crate::parser::parse::token_tree::TokenNode;
use crate::parser::parse::tokens::RawToken;
use crate::parser::{Pipeline, PipelineElement};
use crate::shell::shell::Shell;
use crate::shell::shell_manager::ShellManager;
use crate::Tagged;
use ansi_term::Color;
use rustyline::completion::{self, Completer};
@ -10,14 +10,13 @@ use rustyline::error::ReadlineError;
use rustyline::highlight::Highlighter;
use rustyline::hint::Hinter;
use std::borrow::Cow::{self, Owned};
use std::sync::{Arc, Mutex};
crate struct Helper {
helper: Arc<Mutex<Vec<Box<dyn Shell>>>>,
helper: ShellManager,
}
impl Helper {
crate fn new(helper: Arc<Mutex<Vec<Box<dyn Shell>>>>) -> Helper {
crate fn new(helper: ShellManager) -> Helper {
Helper { helper }
}
}
@ -31,23 +30,13 @@ impl Completer for Helper {
pos: usize,
ctx: &rustyline::Context<'_>,
) -> Result<(usize, Vec<completion::Pair>), ReadlineError> {
self.helper
.lock()
.unwrap()
.last()
.unwrap()
.complete(line, pos, ctx)
self.helper.complete(line, pos, ctx)
}
}
impl Hinter for Helper {
fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<String> {
self.helper
.lock()
.unwrap()
.last()
.unwrap()
.hint(line, pos, ctx)
self.helper.hint(line, pos, ctx)
}
}

15
src/shell/shell.rs Normal file
View File

@ -0,0 +1,15 @@
use crate::commands::command::CallInfo;
use crate::errors::ShellError;
use crate::stream::{InputStream, OutputStream};
use rustyline::{completion::Completer, hint::Hinter};
pub trait Shell
where
Self: Completer<Candidate = rustyline::completion::Pair>,
Self: Hinter,
{
fn ls(&self, call_info: CallInfo, input: InputStream) -> Result<OutputStream, ShellError>;
fn cd(&self, call_info: CallInfo, input: InputStream) -> Result<OutputStream, ShellError>;
fn path(&self) -> std::path::PathBuf;
fn set_path(&mut self, path: &std::path::PathBuf);
}

View File

@ -0,0 +1,92 @@
use crate::commands::command::CallInfo;
use crate::errors::ShellError;
use crate::shell::filesystem_shell::FilesystemShell;
use crate::shell::shell::Shell;
use crate::stream::{InputStream, OutputStream};
use rustyline::completion::{self, Completer};
use rustyline::error::ReadlineError;
use std::error::Error;
use std::sync::{Arc, Mutex};
#[derive(Clone)]
pub struct ShellManager {
crate shells: Arc<Mutex<Vec<Box<dyn Shell>>>>,
}
impl ShellManager {
pub fn basic() -> Result<ShellManager, Box<dyn Error>> {
Ok(ShellManager {
shells: Arc::new(Mutex::new(vec![Box::new(FilesystemShell::basic()?)])),
})
}
pub fn push(&mut self, shell: Box<dyn Shell>) {
self.shells.lock().unwrap().push(shell)
}
pub fn path(&self) -> String {
self.shells
.lock()
.unwrap()
.last()
.unwrap()
.path()
.display()
.to_string()
}
pub fn set_path(&mut self, path: &std::path::PathBuf) {
self.shells
.lock()
.unwrap()
.last_mut()
.unwrap()
.set_path(path)
}
pub fn complete(
&self,
line: &str,
pos: usize,
ctx: &rustyline::Context<'_>,
) -> Result<(usize, Vec<completion::Pair>), ReadlineError> {
self.shells
.lock()
.unwrap()
.last()
.unwrap()
.complete(line, pos, ctx)
}
pub fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<String> {
self.shells
.lock()
.unwrap()
.last()
.unwrap()
.hint(line, pos, ctx)
}
pub fn next(&mut self) {
let mut x = self.shells.lock().unwrap();
let shell = x.pop().unwrap();
x.insert(0, shell);
}
pub fn prev(&mut self) {
let mut x = self.shells.lock().unwrap();
let shell = x.remove(0);
x.push(shell);
}
pub fn ls(&self, call_info: CallInfo, input: InputStream) -> Result<OutputStream, ShellError> {
let env = self.shells.lock().unwrap();
env.last().unwrap().ls(call_info, input)
}
pub fn cd(&self, call_info: CallInfo, input: InputStream) -> Result<OutputStream, ShellError> {
let env = self.shells.lock().unwrap();
env.last().unwrap().cd(call_info, input)
}
}