nushell/src/main.rs

192 lines
5.3 KiB
Rust
Raw Normal View History

2019-05-10 18:59:12 +02:00
#![feature(crate_visibility_modifier)]
#![feature(in_band_lifetimes)]
#![allow(unused)]
mod commands;
mod env;
mod errors;
mod format;
mod object;
2019-05-11 06:45:57 +02:00
mod parser;
mod prelude;
2019-05-10 18:59:12 +02:00
2019-05-12 00:59:57 +02:00
crate use crate::commands::args::{Args, Streams};
use crate::commands::command::ReturnValue;
crate use crate::commands::command::{Command, CommandAction, CommandBlueprint};
2019-05-10 18:59:12 +02:00
crate use crate::env::{Environment, Host};
2019-05-11 06:45:57 +02:00
crate use crate::errors::ShellError;
2019-05-11 09:00:33 +02:00
crate use crate::format::RenderView;
2019-05-10 18:59:12 +02:00
use crate::object::base::{ToEntriesView, ToGenericView};
2019-05-12 00:59:57 +02:00
use crate::object::Value;
2019-05-11 09:00:33 +02:00
use ansi_term::Color;
use conch_parser::lexer::Lexer;
use conch_parser::parse::DefaultParser;
2019-05-10 18:59:12 +02:00
use rustyline::error::ReadlineError;
use rustyline::Editor;
2019-05-11 10:08:21 +02:00
use std::cell::RefCell;
2019-05-10 18:59:12 +02:00
use std::collections::BTreeMap;
use std::collections::VecDeque;
2019-05-10 18:59:12 +02:00
use std::error::Error;
2019-05-11 10:08:21 +02:00
use std::rc::Rc;
2019-05-11 09:00:33 +02:00
use subprocess::Exec;
2019-05-10 18:59:12 +02:00
use sysinfo::{self, SystemExt};
#[derive(Debug)]
pub enum MaybeOwned<'a, T> {
Owned(T),
Borrowed(&'a T),
}
impl<T> MaybeOwned<'a, T> {
crate fn borrow(&self) -> &T {
match self {
MaybeOwned::Owned(v) => v,
MaybeOwned::Borrowed(v) => v,
}
}
}
2019-05-13 23:00:25 +02:00
type Commands = BTreeMap<String, Box<dyn crate::CommandBlueprint>>;
struct Context {
commands: BTreeMap<String, Box<dyn crate::CommandBlueprint>>,
host: Box<dyn crate::Host>,
env: Environment,
}
impl Context {
fn basic() -> Result<Context, Box<Error>> {
Ok(Context {
commands: BTreeMap::new(),
host: Box::new(crate::env::host::BasicHost),
env: crate::Environment::basic()?,
})
}
}
2019-05-10 18:59:12 +02:00
fn main() -> Result<(), Box<Error>> {
let mut rl = Editor::<()>::new();
if rl.load_history("history.txt").is_err() {
println!("No previous history.");
}
2019-05-13 23:00:25 +02:00
let mut context = Context::basic()?;
2019-05-10 18:59:12 +02:00
2019-05-13 23:00:25 +02:00
// let mut commands = BTreeMap::<String, Box<dyn crate::CommandBlueprint>>::new();
2019-05-10 18:59:12 +02:00
2019-05-11 10:08:21 +02:00
let mut system = Rc::new(RefCell::new(sysinfo::System::new()));
let mut ps = crate::commands::ps::PsBlueprint::new(system);
let mut ls = crate::commands::ls::LsBlueprint;
let mut cd = crate::commands::cd::CdBlueprint;
2019-05-13 23:00:25 +02:00
let mut to_array = crate::commands::to_array::ToArrayBlueprint;
2019-05-10 18:59:12 +02:00
2019-05-13 23:00:25 +02:00
context.commands.insert("ps".to_string(), Box::new(ps));
context.commands.insert("ls".to_string(), Box::new(ls));
context.commands.insert("cd".to_string(), Box::new(cd));
context
.commands
.insert("to-array".to_string(), Box::new(to_array));
2019-05-10 18:59:12 +02:00
loop {
2019-05-11 09:00:33 +02:00
let readline = rl.readline(&format!(
"{}> ",
2019-05-13 23:00:25 +02:00
Color::Green.paint(context.env.cwd().display().to_string())
2019-05-11 09:00:33 +02:00
));
2019-05-11 06:45:57 +02:00
2019-05-10 18:59:12 +02:00
match readline {
Ok(line) => {
2019-05-11 09:00:33 +02:00
let result = crate::parser::shell_parser(&line)
.map_err(|e| ShellError::string(format!("{:?}", e)))?;
2019-05-11 06:45:57 +02:00
let parsed = result.1;
2019-05-10 18:59:12 +02:00
rl.add_history_entry(line.as_ref());
2019-05-13 23:00:25 +02:00
let mut input = VecDeque::new();
2019-05-13 23:00:25 +02:00
for item in parsed {
// println!("Processing {:?}", item);
input = process_command(
crate::parser::print_items(&item),
item.clone(),
input,
&mut context,
)?;
2019-05-10 18:59:12 +02:00
2019-05-13 23:00:25 +02:00
// println!("OUTPUT: {:?}", input);
2019-05-10 18:59:12 +02:00
}
}
Err(ReadlineError::Interrupted) => {
println!("CTRL-C");
break;
}
Err(ReadlineError::Eof) => {
println!("CTRL-D");
break;
}
Err(err) => {
println!("Error: {:?}", err);
break;
}
}
}
rl.save_history("history.txt").unwrap();
Ok(())
}
2019-05-13 23:00:25 +02:00
fn process_command(
line: String,
parsed: Vec<crate::parser::Item>,
input: VecDeque<Value>,
context: &mut Context,
) -> Result<VecDeque<Value>, ShellError> {
let command = &parsed[0].name();
let arg_list = parsed[1..]
.iter()
.map(|i| Value::string(i.name().to_string()))
.collect();
let streams = Streams::new();
// let args = Args::new(arg_list);
match *command {
"format" => {
for item in input {
let view = item.to_generic_view();
crate::format::print_rendered(&view.render_view(&context.host), &mut context.host);
}
Ok(VecDeque::new())
}
command => match context.commands.get_mut(command) {
Some(command) => {
let mut instance = command.create(arg_list, &context.host, &mut context.env)?;
let mut result = instance.run(input)?;
let mut next = VecDeque::new();
for v in result {
match v {
ReturnValue::Action(action) => match action {
crate::CommandAction::ChangeCwd(cwd) => context.env.cwd = cwd,
},
ReturnValue::Value(v) => next.push_back(v),
}
}
Ok(next)
}
other => {
Exec::shell(line).cwd(context.env.cwd()).join().unwrap();
Ok(VecDeque::new())
}
},
}
}