Replace reedline with rustyline
This commit is contained in:
parent
3cc62129c7
commit
e528c09623
165
Cargo.lock
generated
165
Cargo.lock
generated
@ -68,7 +68,7 @@ checksum = "9eac0a7f2d7cd7a93b938af401d3d8e8b7094217989a7c25c55a953023436e31"
|
||||
dependencies = [
|
||||
"accesskit",
|
||||
"accesskit_consumer",
|
||||
"arrayvec 0.7.4",
|
||||
"arrayvec",
|
||||
"once_cell",
|
||||
"paste",
|
||||
"windows 0.48.0",
|
||||
@ -233,12 +233,6 @@ version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.4"
|
||||
@ -710,8 +704,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ab77dbd8adecaf3f0db40581631b995f312a8a5ae3aa9993188bb8f23d83a5b"
|
||||
dependencies = [
|
||||
"crossterm",
|
||||
"strum 0.24.1",
|
||||
"strum_macros 0.24.3",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
@ -836,7 +830,6 @@ dependencies = [
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"serde",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
"winapi",
|
||||
@ -936,11 +929,10 @@ dependencies = [
|
||||
"egui_extras",
|
||||
"git2",
|
||||
"json",
|
||||
"nu-ansi-term",
|
||||
"rand",
|
||||
"rayon",
|
||||
"reedline",
|
||||
"reqwest",
|
||||
"rustyline",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sysinfo",
|
||||
@ -1065,6 +1057,12 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "endian-type"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
|
||||
|
||||
[[package]]
|
||||
name = "enumflags2"
|
||||
version = "0.7.7"
|
||||
@ -1649,15 +1647,6 @@ version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.9"
|
||||
@ -1948,6 +1937,15 @@ dependencies = [
|
||||
"jni-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nibble_vec"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43"
|
||||
dependencies = [
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.24.3"
|
||||
@ -2010,15 +2008,6 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.49.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
@ -2365,6 +2354,16 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radix_trie"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd"
|
||||
dependencies = [
|
||||
"endian-type",
|
||||
"nibble_vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
@ -2432,26 +2431,6 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reedline"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2fde955d11817fdcb79d703932fb6b473192cb36b6a92ba21f7f4ac0513374e"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"crossterm",
|
||||
"fd-lock",
|
||||
"itertools",
|
||||
"nu-ansi-term",
|
||||
"serde",
|
||||
"strip-ansi-escapes",
|
||||
"strum 0.25.0",
|
||||
"strum_macros 0.25.2",
|
||||
"thiserror",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.9.4"
|
||||
@ -2557,6 +2536,41 @@ version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "rustyline"
|
||||
version = "12.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "994eca4bca05c87e86e15d90fc7a91d1be64b4482b38cb2d27474568fe7c9db9"
|
||||
dependencies = [
|
||||
"bitflags 2.4.0",
|
||||
"cfg-if",
|
||||
"clipboard-win",
|
||||
"fd-lock",
|
||||
"home",
|
||||
"libc",
|
||||
"log",
|
||||
"memchr",
|
||||
"nix 0.26.3",
|
||||
"radix_trie",
|
||||
"rustyline-derive",
|
||||
"scopeguard",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
"utf8parse",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustyline-derive"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a32af5427251d2e4be14fc151eabe18abb4a7aad5efee7044da9f096c906a43"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.15"
|
||||
@ -2830,15 +2844,6 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
||||
|
||||
[[package]]
|
||||
name = "strip-ansi-escapes"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "011cbb39cf7c1f62871aea3cc46e5817b0937b49e9447370c93cacbe93a766d8"
|
||||
dependencies = [
|
||||
"vte",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
@ -2851,12 +2856,6 @@ version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.24.3"
|
||||
@ -2870,19 +2869,6 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.25.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
@ -2971,7 +2957,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df8493a203431061e901613751931f047d1971337153f96d0e5e363d6dbf6a67"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec 0.7.4",
|
||||
"arrayvec",
|
||||
"bytemuck",
|
||||
"cfg-if",
|
||||
"png",
|
||||
@ -3228,27 +3214,6 @@ version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "vte"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983"
|
||||
dependencies = [
|
||||
"arrayvec 0.5.2",
|
||||
"utf8parse",
|
||||
"vte_generate_state_changes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vte_generate_state_changes"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "waker-fn"
|
||||
version = "1.1.0"
|
||||
|
@ -27,12 +27,11 @@ sysinfo = "0.29.6"
|
||||
toml = "0.7.6"
|
||||
toml_edit = "0.19.14"
|
||||
comfy-table = "7.0.1"
|
||||
reedline = "0.22.0"
|
||||
clap = { version = "4.3.19", features = ["derive"] }
|
||||
nu-ansi-term = "0.49"
|
||||
git2 = "0.17.2"
|
||||
csv = "1.2.2"
|
||||
json = "0.12.4"
|
||||
reqwest = { version = "0.11.18", features = ["blocking", "json"] }
|
||||
serde_json = "1.0.104"
|
||||
egui_extras = "0.22.0"
|
||||
rustyline = { version = "12.0.0", features = ["with-file-history", "derive"] }
|
||||
|
337
src/bin/dust.rs
337
src/bin/dust.rs
@ -1,13 +1,19 @@
|
||||
//! Command line interface for the whale programming language.
|
||||
use clap::Parser;
|
||||
use nu_ansi_term::{Color, Style};
|
||||
use reedline::{
|
||||
default_emacs_keybindings, ColumnarMenu, Completer, DefaultHinter, DefaultPrompt,
|
||||
DefaultPromptSegment, EditCommand, Emacs, FileBackedHistory, KeyCode, KeyModifiers, Reedline,
|
||||
ReedlineEvent, ReedlineMenu, Signal, Span, Suggestion,
|
||||
use eframe::epaint::ahash::HashSet;
|
||||
use rustyline::{
|
||||
completion::FilenameCompleter,
|
||||
error::ReadlineError,
|
||||
highlight::Highlighter,
|
||||
hint::{Hint, Hinter, HistoryHinter},
|
||||
history::DefaultHistory,
|
||||
validate::MatchingBracketValidator,
|
||||
Completer, Context, DefaultEditor, Editor, Helper, Hinter, Validator,
|
||||
};
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::BTreeSet,
|
||||
fs::{self, read_to_string},
|
||||
path::PathBuf,
|
||||
};
|
||||
@ -49,205 +55,156 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Helper, Completer, Validator)]
|
||||
struct DustReadline {
|
||||
#[rustyline(Completer)]
|
||||
completer: FilenameCompleter,
|
||||
|
||||
tool_hints: Vec<ToolHint>,
|
||||
|
||||
#[rustyline(Validator)]
|
||||
validator: MatchingBracketValidator,
|
||||
|
||||
#[rustyline(Hinter)]
|
||||
hinter: HistoryHinter,
|
||||
}
|
||||
|
||||
impl DustReadline {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
completer: FilenameCompleter::new(),
|
||||
validator: MatchingBracketValidator::new(),
|
||||
hinter: HistoryHinter {},
|
||||
tool_hints: TOOL_LIST
|
||||
.iter()
|
||||
.map(|tool| ToolHint {
|
||||
display: tool.info().identifier.to_string(),
|
||||
complete_to: tool.info().identifier.len(),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ToolHint {
|
||||
display: String,
|
||||
complete_to: usize,
|
||||
}
|
||||
|
||||
impl Hint for ToolHint {
|
||||
fn display(&self) -> &str {
|
||||
&self.display
|
||||
}
|
||||
|
||||
fn completion(&self) -> Option<&str> {
|
||||
if self.complete_to > 0 {
|
||||
Some(&self.display[..self.complete_to])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToolHint {
|
||||
fn suffix(&self, strip_chars: usize) -> ToolHint {
|
||||
ToolHint {
|
||||
display: self.display[strip_chars..].to_string(),
|
||||
complete_to: self.complete_to.saturating_sub(strip_chars),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Hinter for DustReadline {
|
||||
type Hint = ToolHint;
|
||||
|
||||
fn hint(&self, line: &str, pos: usize, _ctx: &Context<'_>) -> Option<Self::Hint> {
|
||||
if line.is_empty() || pos < line.len() {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.tool_hints.iter().find_map(|tool_hint| {
|
||||
if tool_hint.display.starts_with(line) {
|
||||
Some(tool_hint.suffix(pos))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Highlighter for DustReadline {
|
||||
fn highlight<'l>(&self, line: &'l str, pos: usize) -> std::borrow::Cow<'l, str> {
|
||||
let _ = pos;
|
||||
Cow::Borrowed(line)
|
||||
}
|
||||
|
||||
fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
|
||||
&'s self,
|
||||
prompt: &'p str,
|
||||
default: bool,
|
||||
) -> std::borrow::Cow<'b, str> {
|
||||
let _ = default;
|
||||
Cow::Borrowed(prompt)
|
||||
}
|
||||
|
||||
fn highlight_hint<'h>(&self, hint: &'h str) -> std::borrow::Cow<'h, str> {
|
||||
Cow::Borrowed(hint)
|
||||
}
|
||||
|
||||
fn highlight_candidate<'c>(
|
||||
&self,
|
||||
candidate: &'c str, // FIXME should be Completer::Candidate
|
||||
completion: rustyline::CompletionType,
|
||||
) -> std::borrow::Cow<'c, str> {
|
||||
let _ = completion;
|
||||
Cow::Borrowed(candidate)
|
||||
}
|
||||
|
||||
fn highlight_char(&self, line: &str, pos: usize) -> bool {
|
||||
let _ = (line, pos);
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn run_cli_shell() {
|
||||
let mut context = VariableMap::new();
|
||||
let mut line_editor = setup_reedline();
|
||||
let prompt = DefaultPrompt {
|
||||
left_prompt: DefaultPromptSegment::WorkingDirectory,
|
||||
right_prompt: DefaultPromptSegment::CurrentDateTime,
|
||||
};
|
||||
let mut rl: Editor<DustReadline, DefaultHistory> = Editor::new().unwrap();
|
||||
|
||||
rl.set_helper(Some(DustReadline::new()));
|
||||
|
||||
if rl.load_history("target/history.txt").is_err() {
|
||||
println!("No previous history.");
|
||||
}
|
||||
|
||||
loop {
|
||||
let sig = line_editor.read_line(&prompt);
|
||||
let readline = rl.readline(">> ");
|
||||
match readline {
|
||||
Ok(line) => {
|
||||
let line = line.as_str();
|
||||
|
||||
match sig {
|
||||
Ok(Signal::Success(buffer)) => {
|
||||
let eval_result = eval_with_context(&buffer, &mut context);
|
||||
rl.add_history_entry(line).unwrap();
|
||||
|
||||
let eval_result = eval_with_context(line, &mut context);
|
||||
|
||||
match eval_result {
|
||||
Ok(value) => println!("{value}"),
|
||||
Err(error) => eprintln!("{error}"),
|
||||
}
|
||||
}
|
||||
Ok(Signal::CtrlD) | Ok(Signal::CtrlC) => {
|
||||
println!("\nExit");
|
||||
Err(ReadlineError::Interrupted) => {
|
||||
println!("CTRL-C");
|
||||
break;
|
||||
}
|
||||
signal => {
|
||||
println!("Unhandled signal: {:?}", signal);
|
||||
Err(ReadlineError::Eof) => {
|
||||
println!("CTRL-D");
|
||||
break;
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct WhaleCompeleter {
|
||||
macro_list: Vec<Suggestion>,
|
||||
files: Vec<Suggestion>,
|
||||
}
|
||||
|
||||
impl WhaleCompeleter {
|
||||
pub fn new() -> Self {
|
||||
WhaleCompeleter {
|
||||
macro_list: Vec::new(),
|
||||
files: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_command_list(&mut self, macro_list: Vec<&'static dyn Tool>) -> &mut Self {
|
||||
self.macro_list = macro_list
|
||||
.iter()
|
||||
.map(|r#macro| {
|
||||
let ToolInfo {
|
||||
identifier,
|
||||
description,
|
||||
group,
|
||||
inputs,
|
||||
} = r#macro.info();
|
||||
|
||||
let description = format!("{description} | {group}");
|
||||
let inputs = inputs
|
||||
.iter()
|
||||
.map(|value_type| value_type.to_string())
|
||||
.collect();
|
||||
|
||||
Suggestion {
|
||||
value: identifier.to_string() + "()",
|
||||
description: Some(description),
|
||||
extra: Some(inputs),
|
||||
..Default::default()
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.macro_list
|
||||
.sort_by_key(|suggestion| suggestion.extra.clone());
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn get_suggestions(&mut self, start: usize, end: usize) -> Vec<Suggestion> {
|
||||
let macro_suggestions = self
|
||||
.macro_list
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|suggestion| Suggestion {
|
||||
span: Span { start, end },
|
||||
..suggestion
|
||||
});
|
||||
let file_suggestions = self.files.iter().cloned().map(|suggestion| Suggestion {
|
||||
span: Span { start, end },
|
||||
..suggestion
|
||||
});
|
||||
|
||||
file_suggestions.chain(macro_suggestions).collect()
|
||||
}
|
||||
|
||||
pub fn update_files(&mut self, mut path: &str) {
|
||||
if path.starts_with('\"') {
|
||||
path = &path[1..];
|
||||
}
|
||||
|
||||
let path = PathBuf::from(path);
|
||||
|
||||
if !path.is_dir() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.files = fs::read_dir(path)
|
||||
.unwrap()
|
||||
.map(|entry| {
|
||||
let path = entry.unwrap().path();
|
||||
let path = path.to_string_lossy();
|
||||
|
||||
Suggestion {
|
||||
value: format!("\"{path}\""),
|
||||
description: None,
|
||||
..Default::default()
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
impl Completer for WhaleCompeleter {
|
||||
fn complete(&mut self, line: &str, pos: usize) -> Vec<Suggestion> {
|
||||
let split = line.split(' ');
|
||||
let current_word = split.last().unwrap_or("");
|
||||
let start = pos.saturating_sub(current_word.len());
|
||||
let end = line.len();
|
||||
|
||||
self.update_files(current_word);
|
||||
self.get_suggestions(start, end)
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_reedline() -> Reedline {
|
||||
let mut completer = Box::new(WhaleCompeleter::new());
|
||||
|
||||
completer.set_command_list(TOOL_LIST.to_vec());
|
||||
|
||||
let completion_menu = Box::new(
|
||||
ColumnarMenu::default()
|
||||
.with_name("completion_menu")
|
||||
.with_columns(1)
|
||||
.with_text_style(Style {
|
||||
foreground: Some(Color::White),
|
||||
is_dimmed: false,
|
||||
..Default::default()
|
||||
})
|
||||
.with_description_text_style(Style {
|
||||
is_dimmed: true,
|
||||
..Default::default()
|
||||
})
|
||||
.with_selected_text_style(Style {
|
||||
is_bold: true,
|
||||
background: Some(Color::Black),
|
||||
foreground: Some(Color::White),
|
||||
..Default::default()
|
||||
}),
|
||||
);
|
||||
|
||||
let mut keybindings = default_emacs_keybindings();
|
||||
keybindings.add_binding(
|
||||
KeyModifiers::NONE,
|
||||
KeyCode::Tab,
|
||||
ReedlineEvent::UntilFound(vec![
|
||||
ReedlineEvent::Menu("completion_menu".to_string()),
|
||||
ReedlineEvent::MenuNext,
|
||||
]),
|
||||
);
|
||||
keybindings.add_binding(
|
||||
KeyModifiers::SHIFT,
|
||||
KeyCode::Tab,
|
||||
ReedlineEvent::UntilFound(vec![
|
||||
ReedlineEvent::Menu("completion_menu".to_string()),
|
||||
ReedlineEvent::MenuPrevious,
|
||||
]),
|
||||
);
|
||||
keybindings.add_binding(
|
||||
KeyModifiers::ALT,
|
||||
KeyCode::Enter,
|
||||
ReedlineEvent::Edit(vec![EditCommand::InsertNewline]),
|
||||
);
|
||||
|
||||
let edit_mode = Box::new(Emacs::new(keybindings));
|
||||
let history = Box::new(
|
||||
FileBackedHistory::with_file(100, "target/history.txt".into())
|
||||
.expect("Error configuring shell history file."),
|
||||
);
|
||||
let mut hinter = DefaultHinter::default();
|
||||
|
||||
hinter = hinter.with_style(Style {
|
||||
foreground: Some(Color::Yellow),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
Reedline::create()
|
||||
.with_completer(completer)
|
||||
.with_menu(ReedlineMenu::EngineCompleter(completion_menu))
|
||||
.with_edit_mode(edit_mode)
|
||||
.with_history(history)
|
||||
.with_hinter(Box::new(hinter))
|
||||
.with_partial_completions(true)
|
||||
.with_quick_completions(true)
|
||||
|
||||
rl.save_history("target/history.txt").unwrap();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user