Implement reedline crate with highlighting
This commit is contained in:
parent
12f82f7bfd
commit
ac29f0210f
306
Cargo.lock
generated
306
Cargo.lock
generated
@ -130,6 +130,12 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
||||
|
||||
[[package]]
|
||||
name = "android-activity"
|
||||
version = "0.4.3"
|
||||
@ -155,12 +161,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -217,7 +229,7 @@ version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aafb29b107435aa276664c1db8954ac27a6e105cdad3c88287a199eb0e313c08"
|
||||
dependencies = [
|
||||
"clipboard-win",
|
||||
"clipboard-win 4.5.0",
|
||||
"log",
|
||||
"objc",
|
||||
"objc-foundation",
|
||||
@ -640,6 +652,19 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41daef31d7a747c5c847246f36de49ced6f7403b4cdabc807a97b5cc184cda7a"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"windows-targets 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.12"
|
||||
@ -680,6 +705,28 @@ version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||
|
||||
[[package]]
|
||||
name = "clipboard"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25a904646c0340239dcf7c51677b33928bf24fdf424b79a57909c0109075b2e7"
|
||||
dependencies = [
|
||||
"clipboard-win 2.2.0",
|
||||
"objc",
|
||||
"objc-foundation",
|
||||
"objc_id",
|
||||
"x11-clipboard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3a093d6fed558e5fe24c3dfc85a68bb68f1c824f440d3ba5aca189e2998786b"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
version = "4.5.0"
|
||||
@ -841,6 +888,32 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"crossterm_winapi",
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"serde",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm_winapi"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
@ -939,9 +1012,9 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||
name = "dust-lang"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"cc",
|
||||
"clap",
|
||||
"crossterm",
|
||||
"csv",
|
||||
"eframe",
|
||||
"egui",
|
||||
@ -951,8 +1024,10 @@ dependencies = [
|
||||
"getrandom",
|
||||
"libc",
|
||||
"log",
|
||||
"nu-ansi-term",
|
||||
"rand",
|
||||
"rayon",
|
||||
"reedline",
|
||||
"reqwest",
|
||||
"rustyline",
|
||||
"serde",
|
||||
@ -1264,6 +1339,18 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
||||
|
||||
[[package]]
|
||||
name = "fallible-streaming-iterator"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.9.0"
|
||||
@ -1566,6 +1653,19 @@ name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"allocator-api2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashlink"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
@ -1671,6 +1771,29 @@ dependencies = [
|
||||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.5.0"
|
||||
@ -1745,6 +1868,15 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.10"
|
||||
@ -1851,6 +1983,17 @@ dependencies = [
|
||||
"redox_syscall 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.8"
|
||||
@ -2067,6 +2210,15 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
|
||||
|
||||
[[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"
|
||||
@ -2533,6 +2685,29 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reedline"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68f4e89a0f80909b3ca4bca9759ed37e4bfddb6f5d2ffb1b4ceb2b1638a3e1eb"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clipboard",
|
||||
"crossterm",
|
||||
"fd-lock",
|
||||
"itertools",
|
||||
"nu-ansi-term",
|
||||
"rusqlite",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"strip-ansi-escapes",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"thiserror",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.2"
|
||||
@ -2612,6 +2787,20 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusqlite"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"fallible-iterator",
|
||||
"fallible-streaming-iterator",
|
||||
"hashlink",
|
||||
"libsqlite3-sys",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
@ -2645,6 +2834,12 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "rustyline"
|
||||
version = "12.0.0"
|
||||
@ -2653,7 +2848,7 @@ checksum = "994eca4bca05c87e86e15d90fc7a91d1be64b4482b38cb2d27474568fe7c9db9"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"cfg-if",
|
||||
"clipboard-win",
|
||||
"clipboard-win 4.5.0",
|
||||
"fd-lock",
|
||||
"home",
|
||||
"libc",
|
||||
@ -2813,6 +3008,27 @@ dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"signal-hook-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-mio"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mio",
|
||||
"signal-hook",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.1"
|
||||
@ -2913,12 +3129,40 @@ version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0"
|
||||
|
||||
[[package]]
|
||||
name = "strip-ansi-escapes"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa"
|
||||
dependencies = [
|
||||
"vte",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[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.25.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 2.0.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
@ -3257,6 +3501,26 @@ version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "vte"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197"
|
||||
dependencies = [
|
||||
"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.1"
|
||||
@ -3527,6 +3791,15 @@ dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.48.0"
|
||||
@ -3800,6 +4073,15 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11-clipboard"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89bd49c06c9eb5d98e6ba6536cf64ac9f7ee3a009b2f53996d405b3944f6bcea"
|
||||
dependencies = [
|
||||
"xcb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11-dl"
|
||||
version = "2.21.0"
|
||||
@ -3833,6 +4115,16 @@ dependencies = [
|
||||
"nix 0.26.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xcb"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e917a3f24142e9ff8be2414e36c649d47d6cc2ba81f16201cdef96e533e02de"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xcursor"
|
||||
version = "0.3.5"
|
||||
|
@ -18,7 +18,6 @@ opt-level = 1
|
||||
opt-level = 3
|
||||
|
||||
[dependencies]
|
||||
ansi_term = "0.12.1"
|
||||
clap = { version = "4.4.4", features = ["derive"] }
|
||||
csv = "1.2.2"
|
||||
egui = "0.24.1"
|
||||
@ -40,6 +39,9 @@ tree-sitter = "0.20.10"
|
||||
egui_extras = "0.24.2"
|
||||
enum-iterator = "1.4.1"
|
||||
env_logger = "0.10"
|
||||
reedline = { version = "0.28.0", features = ["clipboard", "sqlite"] }
|
||||
crossterm = "0.27.0"
|
||||
nu-ansi-term = "0.49.0"
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
env_logger = "0.10"
|
||||
|
@ -31,7 +31,7 @@ pub enum BuiltInValue {
|
||||
}
|
||||
|
||||
impl BuiltInValue {
|
||||
pub fn name(&self) -> &'static str {
|
||||
pub const fn name(&self) -> &'static str {
|
||||
match self {
|
||||
BuiltInValue::Args => "args",
|
||||
BuiltInValue::AssertEqual => "assert_equal",
|
||||
|
246
src/main.rs
246
src/main.rs
@ -1,19 +1,16 @@
|
||||
//! Command line interface for the dust programming language.
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use rustyline::{
|
||||
completion::FilenameCompleter,
|
||||
config::Builder,
|
||||
error::ReadlineError,
|
||||
highlight::Highlighter,
|
||||
hint::{Hint, Hinter, HistoryHinter},
|
||||
history::DefaultHistory,
|
||||
ColorMode, Completer, CompletionType, Context, Editor, Helper, Validator,
|
||||
use crossterm::event::{KeyCode, KeyModifiers};
|
||||
use nu_ansi_term::Style;
|
||||
use reedline::{
|
||||
default_emacs_keybindings, ColumnarMenu, DefaultCompleter, DefaultPrompt, EditCommand, Emacs,
|
||||
Highlighter, Reedline, ReedlineEvent, ReedlineMenu, Signal, SqliteBackedHistory, StyledText,
|
||||
};
|
||||
|
||||
use std::{borrow::Cow, fs::read_to_string};
|
||||
use std::{fs::read_to_string, path::PathBuf};
|
||||
|
||||
use dust_lang::{built_in_values, Interpreter, Map, Value};
|
||||
use dust_lang::{built_in_values, Interpreter, Map, Result, Value};
|
||||
|
||||
/// Command-line arguments to be parsed.
|
||||
#[derive(Parser, Debug)]
|
||||
@ -69,7 +66,14 @@ fn main() {
|
||||
}
|
||||
|
||||
if args.path.is_none() && args.command.is_none() {
|
||||
return run_cli_shell(context);
|
||||
let run_shell_result = run_shell(context);
|
||||
|
||||
match run_shell_result {
|
||||
Ok(_) => {}
|
||||
Err(error) => eprintln!("{error}"),
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let source = if let Some(path) = &args.path {
|
||||
@ -108,157 +112,121 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Helper, Completer, Validator)]
|
||||
struct DustReadline {
|
||||
#[rustyline(Completer)]
|
||||
completer: FilenameCompleter,
|
||||
|
||||
hints: Vec<ToolHint>,
|
||||
|
||||
#[rustyline(Hinter)]
|
||||
_hinter: HistoryHinter,
|
||||
struct DustHighlighter {
|
||||
context: Map,
|
||||
}
|
||||
|
||||
impl DustReadline {
|
||||
fn new() -> Self {
|
||||
let mut hints = Vec::new();
|
||||
impl DustHighlighter {
|
||||
fn new(context: Map) -> Self {
|
||||
Self { context }
|
||||
}
|
||||
}
|
||||
|
||||
for built_in_value in built_in_values() {
|
||||
let mut display = built_in_value.name().to_string();
|
||||
impl Highlighter for DustHighlighter {
|
||||
fn highlight(&self, line: &str, _cursor: usize) -> reedline::StyledText {
|
||||
fn highlight_identifier(styled: &mut StyledText, word: &str, map: &Map) -> bool {
|
||||
for (key, (value, _type)) in map.variables().unwrap().iter() {
|
||||
if key == &word[0..word.len() - 1] {
|
||||
styled.push((Style::new().bold(), word.to_string()));
|
||||
|
||||
if built_in_value.r#type().is_function() {
|
||||
display.push_str("()");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if built_in_value.r#type().is_map() {
|
||||
let value = built_in_value.get();
|
||||
|
||||
if let Value::Map(map) = value {
|
||||
for (key, (value, _)) in map.variables().unwrap().iter() {
|
||||
let display = if value.is_function() {
|
||||
format!("{display}:{key}()")
|
||||
} else {
|
||||
format!("{display}:{key}")
|
||||
};
|
||||
|
||||
hints.push(ToolHint {
|
||||
complete_to: display.len(),
|
||||
display,
|
||||
})
|
||||
}
|
||||
if let Value::Map(nested_map) = value {
|
||||
return highlight_identifier(styled, key, nested_map);
|
||||
}
|
||||
}
|
||||
|
||||
hints.push(ToolHint {
|
||||
complete_to: display.len(),
|
||||
display,
|
||||
})
|
||||
}
|
||||
|
||||
hints.push(ToolHint {
|
||||
display: "output".to_string(),
|
||||
complete_to: 0,
|
||||
});
|
||||
|
||||
Self {
|
||||
completer: FilenameCompleter::new(),
|
||||
_hinter: HistoryHinter {},
|
||||
hints,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.hints.iter().find_map(|tool_hint| {
|
||||
if tool_hint.display.starts_with(line) {
|
||||
Some(tool_hint.suffix(pos))
|
||||
} else {
|
||||
None
|
||||
for built_in_value in built_in_values() {
|
||||
if built_in_value.name() == &word[0..word.len() - 1] {
|
||||
styled.push((Style::new().bold(), word.to_string()));
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
let mut styled = StyledText::new();
|
||||
|
||||
for word in line.split_inclusive(&[' ', ':', '(', ')', '{', '}', '[', ']']) {
|
||||
let word_is_highlighted = highlight_identifier(&mut styled, word, &self.context);
|
||||
|
||||
if !word_is_highlighted {
|
||||
styled.push((Style::new(), word.to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
styled
|
||||
}
|
||||
}
|
||||
|
||||
impl Highlighter for DustReadline {
|
||||
fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
|
||||
let highlighted = ansi_term::Colour::Yellow.paint(hint).to_string();
|
||||
fn run_shell(context: Map) -> Result<()> {
|
||||
let mut interpreter = Interpreter::new(context.clone());
|
||||
let prompt = DefaultPrompt::default();
|
||||
let mut keybindings = default_emacs_keybindings();
|
||||
|
||||
Cow::Owned(highlighted)
|
||||
keybindings.add_binding(
|
||||
KeyModifiers::ALT,
|
||||
KeyCode::Char('m'),
|
||||
ReedlineEvent::Edit(vec![EditCommand::BackspaceWord]),
|
||||
);
|
||||
keybindings.add_binding(
|
||||
KeyModifiers::NONE,
|
||||
KeyCode::Tab,
|
||||
ReedlineEvent::UntilFound(vec![
|
||||
ReedlineEvent::Menu("completion_menu".to_string()),
|
||||
ReedlineEvent::MenuNext,
|
||||
]),
|
||||
);
|
||||
|
||||
let edit_mode = Box::new(Emacs::new(keybindings));
|
||||
let history = Box::new(
|
||||
SqliteBackedHistory::with_file(PathBuf::from("target/history"), None, None)
|
||||
.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());
|
||||
}
|
||||
}
|
||||
|
||||
fn run_cli_shell(context: Map) {
|
||||
let mut interpreter = Interpreter::new(context);
|
||||
let config = Builder::new()
|
||||
.color_mode(ColorMode::Enabled)
|
||||
.completion_type(CompletionType::List)
|
||||
.build();
|
||||
let mut rl: Editor<DustReadline, DefaultHistory> =
|
||||
Editor::with_config(config).expect("Line editor could not be configured properly.");
|
||||
|
||||
rl.set_helper(Some(DustReadline::new()));
|
||||
|
||||
if rl.load_history("target/history.txt").is_err() {
|
||||
println!("No previous history.");
|
||||
}
|
||||
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()
|
||||
.with_edit_mode(edit_mode)
|
||||
.with_history(history)
|
||||
.with_highlighter(Box::new(DustHighlighter::new(context)))
|
||||
.with_completer(completer)
|
||||
.with_menu(ReedlineMenu::EngineCompleter(completion_menu));
|
||||
|
||||
loop {
|
||||
let readline = rl.readline("* ");
|
||||
match readline {
|
||||
Ok(line) => {
|
||||
let input = line.to_string();
|
||||
let sig = line_editor.read_line(&prompt);
|
||||
match sig {
|
||||
Ok(Signal::Success(buffer)) => {
|
||||
if buffer.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
rl.add_history_entry(line).unwrap();
|
||||
let run_result = interpreter.run(&buffer);
|
||||
|
||||
let eval_result = interpreter.run(&input);
|
||||
|
||||
match eval_result {
|
||||
Ok(value) => println!("{value}"),
|
||||
Err(error) => {
|
||||
eprintln!("{error}")
|
||||
match run_result {
|
||||
Ok(value) => {
|
||||
if !value.is_none() {
|
||||
println!("{value}")
|
||||
}
|
||||
}
|
||||
Err(error) => println!("Error: {error}"),
|
||||
}
|
||||
}
|
||||
Err(ReadlineError::Interrupted) => break,
|
||||
Err(ReadlineError::Eof) => break,
|
||||
Err(error) => eprintln!("{error}"),
|
||||
Ok(Signal::CtrlD) | Ok(Signal::CtrlC) => {
|
||||
println!("\nAborted!");
|
||||
break;
|
||||
}
|
||||
x => {
|
||||
println!("Event: {:?}", x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rl.save_history("target/history.txt").unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user