77 lines
1.6 KiB
Rust
77 lines
1.6 KiB
Rust
use rustyline::{completion::{Candidate, Completer, FilenameCompleter}, hint::{Hint, Hinter}, history::{History, SearchDirection}, Helper};
|
|
|
|
use crate::prelude::*;
|
|
|
|
pub struct SynHelper<'a> {
|
|
pub file_comp: FilenameCompleter,
|
|
pub shenv: &'a mut ShEnv,
|
|
}
|
|
|
|
impl<'a> Helper for SynHelper<'a> {}
|
|
|
|
impl<'a> SynHelper<'a> {
|
|
pub fn new(shenv: &'a mut ShEnv) -> Self {
|
|
Self {
|
|
file_comp: FilenameCompleter::new(),
|
|
shenv,
|
|
}
|
|
}
|
|
|
|
pub fn hist_search(&self, term: &str, hist: &dyn History) -> Option<String> {
|
|
let limit = hist.len();
|
|
let mut latest_match = None;
|
|
for i in 0..limit {
|
|
if let Some(hist_entry) = hist.get(i, SearchDirection::Forward).ok()? {
|
|
if hist_entry.entry.starts_with(term) {
|
|
latest_match = Some(hist_entry.entry.into_owned())
|
|
}
|
|
}
|
|
}
|
|
latest_match
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct SynHint {
|
|
text: String,
|
|
styled: String
|
|
}
|
|
|
|
impl SynHint {
|
|
pub fn new(text: String) -> Self {
|
|
let styled = (&text).styled(Style::BrightBlack);
|
|
Self { text, styled }
|
|
}
|
|
pub fn empty() -> Self {
|
|
Self { text: String::new(), styled: String::new() }
|
|
}
|
|
}
|
|
|
|
impl Hint for SynHint {
|
|
fn display(&self) -> &str {
|
|
&self.styled
|
|
}
|
|
fn completion(&self) -> Option<&str> {
|
|
if !self.text.is_empty() {
|
|
Some(&self.text)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> Hinter for SynHelper<'a> {
|
|
type Hint = SynHint;
|
|
fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<Self::Hint> {
|
|
if line.is_empty() {
|
|
return None
|
|
}
|
|
let history = ctx.history();
|
|
let result = self.hist_search(line, history)?;
|
|
let window = result[line.len()..].trim_end().to_string();
|
|
Some(SynHint::new(window))
|
|
}
|
|
}
|