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 = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"accesskit_consumer",
|
"accesskit_consumer",
|
||||||
"arrayvec 0.7.4",
|
"arrayvec",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"paste",
|
"paste",
|
||||||
"windows 0.48.0",
|
"windows 0.48.0",
|
||||||
@ -233,12 +233,6 @@ version = "0.3.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
|
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arrayvec"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.7.4"
|
version = "0.7.4"
|
||||||
@ -710,8 +704,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "9ab77dbd8adecaf3f0db40581631b995f312a8a5ae3aa9993188bb8f23d83a5b"
|
checksum = "9ab77dbd8adecaf3f0db40581631b995f312a8a5ae3aa9993188bb8f23d83a5b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"strum 0.24.1",
|
"strum",
|
||||||
"strum_macros 0.24.3",
|
"strum_macros",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -836,7 +830,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"serde",
|
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"signal-hook-mio",
|
"signal-hook-mio",
|
||||||
"winapi",
|
"winapi",
|
||||||
@ -936,11 +929,10 @@ dependencies = [
|
|||||||
"egui_extras",
|
"egui_extras",
|
||||||
"git2",
|
"git2",
|
||||||
"json",
|
"json",
|
||||||
"nu-ansi-term",
|
|
||||||
"rand",
|
"rand",
|
||||||
"rayon",
|
"rayon",
|
||||||
"reedline",
|
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
"rustyline",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
@ -1065,6 +1057,12 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "endian-type"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "enumflags2"
|
name = "enumflags2"
|
||||||
version = "0.7.7"
|
version = "0.7.7"
|
||||||
@ -1649,15 +1647,6 @@ version = "2.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
|
checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itertools"
|
|
||||||
version = "0.10.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
|
||||||
dependencies = [
|
|
||||||
"either",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.9"
|
version = "1.0.9"
|
||||||
@ -1948,6 +1937,15 @@ dependencies = [
|
|||||||
"jni-sys",
|
"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]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.24.3"
|
version = "0.24.3"
|
||||||
@ -2010,15 +2008,6 @@ dependencies = [
|
|||||||
"winapi",
|
"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]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.45"
|
version = "0.1.45"
|
||||||
@ -2365,6 +2354,16 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"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]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@ -2432,26 +2431,6 @@ dependencies = [
|
|||||||
"bitflags 1.3.2",
|
"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]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.9.4"
|
version = "1.9.4"
|
||||||
@ -2557,6 +2536,41 @@ version = "1.0.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
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]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
@ -2830,15 +2844,6 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
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]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@ -2851,12 +2856,6 @@ version = "0.24.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strum"
|
|
||||||
version = "0.25.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strum_macros"
|
name = "strum_macros"
|
||||||
version = "0.24.3"
|
version = "0.24.3"
|
||||||
@ -2870,19 +2869,6 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"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]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.109"
|
version = "1.0.109"
|
||||||
@ -2971,7 +2957,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "df8493a203431061e901613751931f047d1971337153f96d0e5e363d6dbf6a67"
|
checksum = "df8493a203431061e901613751931f047d1971337153f96d0e5e363d6dbf6a67"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayref",
|
"arrayref",
|
||||||
"arrayvec 0.7.4",
|
"arrayvec",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"png",
|
"png",
|
||||||
@ -3228,27 +3214,6 @@ version = "0.9.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
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]]
|
[[package]]
|
||||||
name = "waker-fn"
|
name = "waker-fn"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -27,12 +27,11 @@ sysinfo = "0.29.6"
|
|||||||
toml = "0.7.6"
|
toml = "0.7.6"
|
||||||
toml_edit = "0.19.14"
|
toml_edit = "0.19.14"
|
||||||
comfy-table = "7.0.1"
|
comfy-table = "7.0.1"
|
||||||
reedline = "0.22.0"
|
|
||||||
clap = { version = "4.3.19", features = ["derive"] }
|
clap = { version = "4.3.19", features = ["derive"] }
|
||||||
nu-ansi-term = "0.49"
|
|
||||||
git2 = "0.17.2"
|
git2 = "0.17.2"
|
||||||
csv = "1.2.2"
|
csv = "1.2.2"
|
||||||
json = "0.12.4"
|
json = "0.12.4"
|
||||||
reqwest = { version = "0.11.18", features = ["blocking", "json"] }
|
reqwest = { version = "0.11.18", features = ["blocking", "json"] }
|
||||||
serde_json = "1.0.104"
|
serde_json = "1.0.104"
|
||||||
egui_extras = "0.22.0"
|
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.
|
//! Command line interface for the whale programming language.
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use nu_ansi_term::{Color, Style};
|
use eframe::epaint::ahash::HashSet;
|
||||||
use reedline::{
|
use rustyline::{
|
||||||
default_emacs_keybindings, ColumnarMenu, Completer, DefaultHinter, DefaultPrompt,
|
completion::FilenameCompleter,
|
||||||
DefaultPromptSegment, EditCommand, Emacs, FileBackedHistory, KeyCode, KeyModifiers, Reedline,
|
error::ReadlineError,
|
||||||
ReedlineEvent, ReedlineMenu, Signal, Span, Suggestion,
|
highlight::Highlighter,
|
||||||
|
hint::{Hint, Hinter, HistoryHinter},
|
||||||
|
history::DefaultHistory,
|
||||||
|
validate::MatchingBracketValidator,
|
||||||
|
Completer, Context, DefaultEditor, Editor, Helper, Hinter, Validator,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
collections::BTreeSet,
|
||||||
fs::{self, read_to_string},
|
fs::{self, read_to_string},
|
||||||
path::PathBuf,
|
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() {
|
fn run_cli_shell() {
|
||||||
let mut context = VariableMap::new();
|
let mut context = VariableMap::new();
|
||||||
let mut line_editor = setup_reedline();
|
let mut rl: Editor<DustReadline, DefaultHistory> = Editor::new().unwrap();
|
||||||
let prompt = DefaultPrompt {
|
|
||||||
left_prompt: DefaultPromptSegment::WorkingDirectory,
|
rl.set_helper(Some(DustReadline::new()));
|
||||||
right_prompt: DefaultPromptSegment::CurrentDateTime,
|
|
||||||
};
|
if rl.load_history("target/history.txt").is_err() {
|
||||||
|
println!("No previous history.");
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let sig = line_editor.read_line(&prompt);
|
let readline = rl.readline(">> ");
|
||||||
|
match readline {
|
||||||
|
Ok(line) => {
|
||||||
|
let line = line.as_str();
|
||||||
|
|
||||||
match sig {
|
rl.add_history_entry(line).unwrap();
|
||||||
Ok(Signal::Success(buffer)) => {
|
|
||||||
let eval_result = eval_with_context(&buffer, &mut context);
|
let eval_result = eval_with_context(line, &mut context);
|
||||||
|
|
||||||
match eval_result {
|
match eval_result {
|
||||||
Ok(value) => println!("{value}"),
|
Ok(value) => println!("{value}"),
|
||||||
Err(error) => eprintln!("{error}"),
|
Err(error) => eprintln!("{error}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Signal::CtrlD) | Ok(Signal::CtrlC) => {
|
Err(ReadlineError::Interrupted) => {
|
||||||
println!("\nExit");
|
println!("CTRL-C");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
signal => {
|
Err(ReadlineError::Eof) => {
|
||||||
println!("Unhandled signal: {:?}", signal);
|
println!("CTRL-D");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
println!("Error: {:?}", err);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
rl.save_history("target/history.txt").unwrap();
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user