Implement reedline
This commit is contained in:
parent
ac29f0210f
commit
784e4b309d
49
src/main.rs
49
src/main.rs
@ -4,8 +4,8 @@ use clap::{Parser, Subcommand};
|
|||||||
use crossterm::event::{KeyCode, KeyModifiers};
|
use crossterm::event::{KeyCode, KeyModifiers};
|
||||||
use nu_ansi_term::Style;
|
use nu_ansi_term::Style;
|
||||||
use reedline::{
|
use reedline::{
|
||||||
default_emacs_keybindings, ColumnarMenu, DefaultCompleter, DefaultPrompt, EditCommand, Emacs,
|
default_emacs_keybindings, DefaultPrompt, EditCommand, Emacs, Highlighter, Reedline,
|
||||||
Highlighter, Reedline, ReedlineEvent, ReedlineMenu, Signal, SqliteBackedHistory, StyledText,
|
ReedlineEvent, Signal, SqliteBackedHistory, StyledText,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::{fs::read_to_string, path::PathBuf};
|
use std::{fs::read_to_string, path::PathBuf};
|
||||||
@ -126,7 +126,7 @@ impl Highlighter for DustHighlighter {
|
|||||||
fn highlight(&self, line: &str, _cursor: usize) -> reedline::StyledText {
|
fn highlight(&self, line: &str, _cursor: usize) -> reedline::StyledText {
|
||||||
fn highlight_identifier(styled: &mut StyledText, word: &str, map: &Map) -> bool {
|
fn highlight_identifier(styled: &mut StyledText, word: &str, map: &Map) -> bool {
|
||||||
for (key, (value, _type)) in map.variables().unwrap().iter() {
|
for (key, (value, _type)) in map.variables().unwrap().iter() {
|
||||||
if key == &word[0..word.len() - 1] {
|
if key == &word {
|
||||||
styled.push((Style::new().bold(), word.to_string()));
|
styled.push((Style::new().bold(), word.to_string()));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -138,8 +138,10 @@ impl Highlighter for DustHighlighter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for built_in_value in built_in_values() {
|
for built_in_value in built_in_values() {
|
||||||
if built_in_value.name() == &word[0..word.len() - 1] {
|
if built_in_value.name() == word {
|
||||||
styled.push((Style::new().bold(), word.to_string()));
|
styled.push((Style::new().bold(), word.to_string()));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,11 +149,19 @@ impl Highlighter for DustHighlighter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut styled = StyledText::new();
|
let mut styled = StyledText::new();
|
||||||
|
let terminators = [' ', ':', '(', ')', '{', '}', '[', ']'];
|
||||||
|
|
||||||
for word in line.split_inclusive(&[' ', ':', '(', ')', '{', '}', '[', ']']) {
|
for word in line.split_inclusive(&terminators) {
|
||||||
let word_is_highlighted = highlight_identifier(&mut styled, word, &self.context);
|
let word_is_highlighted =
|
||||||
|
highlight_identifier(&mut styled, &word[0..word.len() - 1], &self.context);
|
||||||
|
|
||||||
if !word_is_highlighted {
|
if word_is_highlighted {
|
||||||
|
let final_char = word.chars().last().unwrap();
|
||||||
|
|
||||||
|
if terminators.contains(&final_char) {
|
||||||
|
styled.push((Style::new(), final_char.to_string()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
styled.push((Style::new(), word.to_string()));
|
styled.push((Style::new(), word.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,9 +176,14 @@ fn run_shell(context: Map) -> Result<()> {
|
|||||||
let mut keybindings = default_emacs_keybindings();
|
let mut keybindings = default_emacs_keybindings();
|
||||||
|
|
||||||
keybindings.add_binding(
|
keybindings.add_binding(
|
||||||
KeyModifiers::ALT,
|
KeyModifiers::NONE,
|
||||||
KeyCode::Char('m'),
|
KeyCode::Enter,
|
||||||
ReedlineEvent::Edit(vec![EditCommand::BackspaceWord]),
|
ReedlineEvent::Edit(vec![EditCommand::InsertNewline]),
|
||||||
|
);
|
||||||
|
keybindings.add_binding(
|
||||||
|
KeyModifiers::CONTROL,
|
||||||
|
KeyCode::Char(' '),
|
||||||
|
ReedlineEvent::Submit,
|
||||||
);
|
);
|
||||||
keybindings.add_binding(
|
keybindings.add_binding(
|
||||||
KeyModifiers::NONE,
|
KeyModifiers::NONE,
|
||||||
@ -184,26 +199,16 @@ fn run_shell(context: Map) -> Result<()> {
|
|||||||
SqliteBackedHistory::with_file(PathBuf::from("target/history"), None, None)
|
SqliteBackedHistory::with_file(PathBuf::from("target/history"), None, None)
|
||||||
.expect("Error loading history."),
|
.expect("Error loading history."),
|
||||||
);
|
);
|
||||||
let mut commands = Vec::new();
|
|
||||||
|
|
||||||
for built_in_value in built_in_values() {
|
|
||||||
commands.push(built_in_value.name().to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
let completer = Box::new(DefaultCompleter::new_with_wordlen(commands.clone(), 0));
|
|
||||||
let completion_menu = Box::new(ColumnarMenu::default().with_name("completion_menu"));
|
|
||||||
let mut line_editor = Reedline::create()
|
let mut line_editor = Reedline::create()
|
||||||
.with_edit_mode(edit_mode)
|
.with_edit_mode(edit_mode)
|
||||||
.with_history(history)
|
.with_history(history)
|
||||||
.with_highlighter(Box::new(DustHighlighter::new(context)))
|
.with_highlighter(Box::new(DustHighlighter::new(context)));
|
||||||
.with_completer(completer)
|
|
||||||
.with_menu(ReedlineMenu::EngineCompleter(completion_menu));
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let sig = line_editor.read_line(&prompt);
|
let sig = line_editor.read_line(&prompt);
|
||||||
match sig {
|
match sig {
|
||||||
Ok(Signal::Success(buffer)) => {
|
Ok(Signal::Success(buffer)) => {
|
||||||
if buffer.is_empty() {
|
if buffer.trim().is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user