2019-06-22 03:36:57 +02:00
|
|
|
use crate::parser::nom_input;
|
2019-06-25 06:33:12 +02:00
|
|
|
use crate::parser::parse::token_tree::TokenNode;
|
|
|
|
use crate::parser::parse::tokens::RawToken;
|
2019-06-23 19:35:43 +02:00
|
|
|
use crate::parser::{Pipeline, PipelineElement};
|
2019-08-07 19:49:11 +02:00
|
|
|
use crate::shell::shell_manager::ShellManager;
|
2019-08-01 03:58:42 +02:00
|
|
|
use crate::Tagged;
|
2019-05-31 02:53:54 +02:00
|
|
|
use ansi_term::Color;
|
2019-08-09 06:51:21 +02:00
|
|
|
use rustyline::completion::Completer;
|
2019-05-16 23:43:36 +02:00
|
|
|
use rustyline::error::ReadlineError;
|
2019-05-31 02:53:54 +02:00
|
|
|
use rustyline::highlight::Highlighter;
|
2019-08-07 19:49:11 +02:00
|
|
|
use rustyline::hint::Hinter;
|
2019-05-16 23:43:36 +02:00
|
|
|
use std::borrow::Cow::{self, Owned};
|
|
|
|
|
|
|
|
crate struct Helper {
|
2019-08-07 19:49:11 +02:00
|
|
|
helper: ShellManager,
|
2019-05-16 23:43:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Helper {
|
2019-08-07 19:49:11 +02:00
|
|
|
crate fn new(helper: ShellManager) -> Helper {
|
|
|
|
Helper { helper }
|
2019-05-16 23:43:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Completer for Helper {
|
2019-08-09 06:51:21 +02:00
|
|
|
type Candidate = rustyline::completion::Pair;
|
|
|
|
fn complete(
|
|
|
|
&self,
|
|
|
|
line: &str,
|
|
|
|
pos: usize,
|
|
|
|
ctx: &rustyline::Context<'_>,
|
|
|
|
) -> Result<(usize, Vec<rustyline::completion::Pair>), ReadlineError> {
|
2019-08-09 21:42:23 +02:00
|
|
|
self.helper.complete(line, pos, ctx)
|
2019-08-09 06:51:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
impl Completer for Helper {
|
|
|
|
type Candidate = rustyline::completion::Pair;
|
2019-05-16 23:43:36 +02:00
|
|
|
|
|
|
|
fn complete(
|
|
|
|
&self,
|
|
|
|
line: &str,
|
|
|
|
pos: usize,
|
|
|
|
ctx: &rustyline::Context<'_>,
|
2019-08-09 06:51:21 +02:00
|
|
|
) -> Result<(usize, Vec<rustyline::completion::Pair>), ReadlineError> {
|
|
|
|
let result = self.helper.complete(line, pos, ctx);
|
|
|
|
|
|
|
|
result.map(|(x, y)| (x, y.iter().map(|z| z.into()).collect()))
|
2019-05-16 23:43:36 +02:00
|
|
|
}
|
|
|
|
}
|
2019-08-09 06:51:21 +02:00
|
|
|
*/
|
2019-05-16 23:43:36 +02:00
|
|
|
|
|
|
|
impl Hinter for Helper {
|
|
|
|
fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<String> {
|
2019-08-07 19:49:11 +02:00
|
|
|
self.helper.hint(line, pos, ctx)
|
2019-05-16 23:43:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Highlighter for Helper {
|
2019-06-22 03:36:57 +02:00
|
|
|
fn highlight_prompt<'b, 's: 'b, 'p: 'b>(&'s self, prompt: &'p str, _: bool) -> Cow<'b, str> {
|
2019-05-16 23:43:36 +02:00
|
|
|
Owned("\x1b[32m".to_owned() + &prompt[0..prompt.len() - 2] + "\x1b[m> ")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
|
|
|
|
Owned("\x1b[1m".to_owned() + hint + "\x1b[m")
|
|
|
|
}
|
|
|
|
|
2019-05-31 02:53:54 +02:00
|
|
|
fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> {
|
2019-06-22 03:36:57 +02:00
|
|
|
let tokens = crate::parser::pipeline(nom_input(line));
|
2019-05-31 02:53:54 +02:00
|
|
|
|
|
|
|
match tokens {
|
2019-06-24 02:55:31 +02:00
|
|
|
Err(_) => Cow::Borrowed(line),
|
2019-06-22 03:36:57 +02:00
|
|
|
Ok((_rest, v)) => {
|
2019-05-31 02:53:54 +02:00
|
|
|
let mut out = String::new();
|
2019-06-23 19:35:43 +02:00
|
|
|
let pipeline = match v.as_pipeline() {
|
2019-06-22 03:36:57 +02:00
|
|
|
Err(_) => return Cow::Borrowed(line),
|
|
|
|
Ok(v) => v,
|
|
|
|
};
|
2019-05-31 02:53:54 +02:00
|
|
|
|
2019-06-23 19:35:43 +02:00
|
|
|
let Pipeline { parts, post_ws } = pipeline;
|
|
|
|
let mut iter = parts.into_iter();
|
2019-05-31 02:53:54 +02:00
|
|
|
|
|
|
|
loop {
|
|
|
|
match iter.next() {
|
2019-06-23 19:35:43 +02:00
|
|
|
None => {
|
|
|
|
if let Some(ws) = post_ws {
|
|
|
|
out.push_str(ws.slice(line));
|
2019-06-22 21:47:29 +02:00
|
|
|
}
|
2019-06-22 03:36:57 +02:00
|
|
|
|
2019-06-23 19:35:43 +02:00
|
|
|
return Cow::Owned(out);
|
|
|
|
}
|
|
|
|
Some(token) => {
|
|
|
|
let styled = paint_pipeline_element(&token, line);
|
2019-05-31 02:53:54 +02:00
|
|
|
out.push_str(&styled.to_string());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn highlight_char(&self, _line: &str, _pos: usize) -> bool {
|
|
|
|
true
|
2019-05-16 23:43:36 +02:00
|
|
|
}
|
2019-05-31 02:53:54 +02:00
|
|
|
}
|
|
|
|
|
2019-06-22 21:47:29 +02:00
|
|
|
fn paint_token_node(token_node: &TokenNode, line: &str) -> String {
|
|
|
|
let styled = match token_node {
|
|
|
|
TokenNode::Call(..) => Color::Cyan.bold().paint(token_node.span().slice(line)),
|
|
|
|
TokenNode::Whitespace(..) => Color::White.normal().paint(token_node.span().slice(line)),
|
|
|
|
TokenNode::Flag(..) => Color::Black.bold().paint(token_node.span().slice(line)),
|
2019-07-15 23:16:27 +02:00
|
|
|
TokenNode::Member(..) => Color::Yellow.bold().paint(token_node.span().slice(line)),
|
2019-06-22 21:47:29 +02:00
|
|
|
TokenNode::Path(..) => Color::Green.bold().paint(token_node.span().slice(line)),
|
|
|
|
TokenNode::Error(..) => Color::Red.bold().paint(token_node.span().slice(line)),
|
|
|
|
TokenNode::Delimited(..) => Color::White.paint(token_node.span().slice(line)),
|
2019-06-24 06:00:16 +02:00
|
|
|
TokenNode::Operator(..) => Color::White.normal().paint(token_node.span().slice(line)),
|
2019-06-22 21:47:29 +02:00
|
|
|
TokenNode::Pipeline(..) => Color::Blue.normal().paint(token_node.span().slice(line)),
|
2019-08-01 03:58:42 +02:00
|
|
|
TokenNode::Token(Tagged {
|
2019-06-23 00:20:13 +02:00
|
|
|
item: RawToken::Integer(..),
|
|
|
|
..
|
|
|
|
}) => Color::Purple.bold().paint(token_node.span().slice(line)),
|
2019-08-01 03:58:42 +02:00
|
|
|
TokenNode::Token(Tagged {
|
2019-06-23 00:20:13 +02:00
|
|
|
item: RawToken::Size(..),
|
|
|
|
..
|
|
|
|
}) => Color::Purple.bold().paint(token_node.span().slice(line)),
|
2019-08-01 03:58:42 +02:00
|
|
|
TokenNode::Token(Tagged {
|
2019-06-23 00:20:13 +02:00
|
|
|
item: RawToken::String(..),
|
|
|
|
..
|
|
|
|
}) => Color::Green.normal().paint(token_node.span().slice(line)),
|
2019-08-01 03:58:42 +02:00
|
|
|
TokenNode::Token(Tagged {
|
2019-06-23 00:20:13 +02:00
|
|
|
item: RawToken::Variable(..),
|
|
|
|
..
|
|
|
|
}) => Color::Yellow.bold().paint(token_node.span().slice(line)),
|
2019-08-01 03:58:42 +02:00
|
|
|
TokenNode::Token(Tagged {
|
2019-06-23 00:20:13 +02:00
|
|
|
item: RawToken::Bare,
|
|
|
|
..
|
|
|
|
}) => Color::Green.normal().paint(token_node.span().slice(line)),
|
2019-08-16 00:18:18 +02:00
|
|
|
TokenNode::Token(Tagged {
|
|
|
|
item: RawToken::External(..),
|
|
|
|
..
|
|
|
|
}) => Color::Cyan.bold().paint(token_node.span().slice(line)),
|
2019-06-22 21:47:29 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
styled.to_string()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn paint_pipeline_element(pipeline_element: &PipelineElement, line: &str) -> String {
|
|
|
|
let mut styled = String::new();
|
|
|
|
|
|
|
|
if let Some(ws) = pipeline_element.pre_ws {
|
|
|
|
styled.push_str(&Color::White.normal().paint(ws.slice(line)));
|
|
|
|
}
|
2019-06-23 19:35:43 +02:00
|
|
|
|
2019-07-15 23:16:27 +02:00
|
|
|
styled.push_str(
|
|
|
|
&Color::Cyan
|
|
|
|
.bold()
|
|
|
|
.paint(pipeline_element.call().head().span().slice(line))
|
|
|
|
.to_string(),
|
|
|
|
);
|
2019-06-22 21:47:29 +02:00
|
|
|
|
|
|
|
if let Some(children) = pipeline_element.call().children() {
|
|
|
|
for child in children {
|
|
|
|
styled.push_str(&paint_token_node(child, line));
|
|
|
|
}
|
|
|
|
}
|
2019-06-23 19:35:43 +02:00
|
|
|
|
2019-06-22 21:47:29 +02:00
|
|
|
if let Some(ws) = pipeline_element.post_ws {
|
|
|
|
styled.push_str(&Color::White.normal().paint(ws.slice(line)));
|
|
|
|
}
|
|
|
|
|
2019-06-23 19:35:43 +02:00
|
|
|
if let Some(_) = pipeline_element.post_pipe {
|
|
|
|
styled.push_str(&Color::Purple.paint("|"));
|
|
|
|
}
|
|
|
|
|
2019-06-22 21:47:29 +02:00
|
|
|
styled.to_string()
|
|
|
|
}
|
|
|
|
|
2019-05-16 23:43:36 +02:00
|
|
|
impl rustyline::Helper for Helper {}
|