use std::io::{Stdin, Stdout};
use docopt::ArgvMap;
use nix::sys::wait::WaitStatus;
use nix::unistd::Pid;
use crate::process::{Jobs, IO};
#[cfg(feature = "raw")]
use {
termion::cursor::DetectCursorPos,
termion::event::Key,
termion::input::TermRead,
termion::raw::IntoRawMode,
crate::repl::action::{Action, ActionContext},
};
#[cfg(not(feature = "raw"))]
use {
std::io::BufRead,
crate::program::{parse_and_run, Runtime},
};
#[cfg(feature = "history")]
use self::history::History;
#[allow(unused_mut)]
pub fn start(mut stdin: Stdin, mut stdout: Stdout, io: &mut IO, jobs: &mut Jobs, args: &mut ArgvMap)
-> crate::program::Result<WaitStatus>
{
#[cfg(feature = "history")]
let mut history = History::load();
#[cfg(feature = "raw")]
raw_loop(stdin, stdout, io, jobs, args);
#[cfg(not(feature = "raw"))]
buffered_loop(stdin, stdout, io, jobs, args);
Ok(WaitStatus::Exited(Pid::this(), 0))
}
#[cfg(feature = "raw")]
fn raw_loop(stdin: Stdin, stdout: Stdout, io: &mut IO, jobs: &mut Jobs, args: &mut ArgvMap) {
let mut stdout = stdout.into_raw_mode()
.expect("error opening raw mode");
prompt::ps1(&mut stdout);
let prompt_length = stdout.cursor_pos().unwrap().0;
let mut text = String::new();
let mut context = ActionContext {
stdout: &mut stdout,
io: io,
jobs: jobs,
args: args,
prompt_length: prompt_length,
text: &mut text,
#[cfg(feature = "history")]
history: &mut history,
};
for c in stdin.keys() {
match c.unwrap() {
Key::Char('\n') => Action::enter(&mut context),
#[cfg(feature = "completion")]
Key::Char('\t') => Action::complete(&mut context),
Key::Char(c) => Action::insert(&mut context, c),
Key::Left => Action::left(&mut context),
Key::Right => Action::right(&mut context),
Key::Backspace => Action::backspace(&mut context),
Key::Ctrl('a') => Action::home(&mut context),
Key::Ctrl('e') => Action::end(&mut context),
Key::Ctrl('c') => Action::interrupt(&mut context),
Key::Ctrl('d') => Action::eof(&mut context),
Key::Ctrl('l') => Action::clear(&mut context),
#[cfg(feature = "history")]
Key::Up => Action::history_up(&mut context),
#[cfg(feature = "history")]
Key::Down => Action::history_down(&mut context),
_ => {}
}
}
}
#[cfg(not(feature = "raw"))]
fn buffered_loop(stdin: Stdin, mut stdout: Stdout, io: &mut IO, jobs: &mut Jobs, args: &mut ArgvMap) {
prompt::ps1(&mut stdout);
for line in stdin.lock().lines() {
let line = line.unwrap(); let mut runtime = Runtime {
background: false,
io: io.clone(),
jobs: jobs,
args: args,
#[cfg(feature = "history")]
history: history,
};
if parse_and_run(&line, &mut runtime).is_ok() {
#[cfg(feature = "history")]
history.add(&line, 1);
}
#[cfg(feature = "history")]
history.add(&line, 1);
#[cfg(feature = "history")]
history.reset_index();
prompt::ps1(&mut stdout);
}
}
pub mod prompt;
#[cfg(feature = "raw")]
pub mod action;
#[cfg(feature = "completion")]
pub mod completion;
#[cfg(feature = "history")]
pub mod history;