Try out select completions from dialoguer

This commit is contained in:
JT 2021-10-16 07:37:58 +13:00
parent 9807b4a484
commit 82b0415d92
4 changed files with 127 additions and 17 deletions

79
Cargo.lock generated
View File

@ -155,10 +155,25 @@ dependencies = [
]
[[package]]
name = "core-foundation-sys"
version = "0.8.2"
name = "console"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31"
dependencies = [
"encode_unicode",
"libc",
"once_cell",
"regex",
"terminal_size",
"unicode-width",
"winapi",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "crossbeam-channel"
@ -240,6 +255,19 @@ dependencies = [
"syn",
]
[[package]]
name = "dialoguer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61579ada4ec0c6031cfac3f86fdba0d195a7ebeb5e36693bd53cb5999a25beeb"
dependencies = [
"console",
"fuzzy-matcher",
"lazy_static",
"tempfile",
"zeroize",
]
[[package]]
name = "diff"
version = "0.1.12"
@ -291,12 +319,19 @@ version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "engine-q"
version = "0.1.0"
dependencies = [
"assert_cmd",
"crossterm",
"dialoguer",
"miette",
"nu-cli",
"nu-command",
@ -312,6 +347,15 @@ dependencies = [
"tempfile",
]
[[package]]
name = "fuzzy-matcher"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94"
dependencies = [
"thread_local",
]
[[package]]
name = "getrandom"
version = "0.2.3"
@ -718,9 +762,9 @@ dependencies = [
[[package]]
name = "ppv-lite86"
version = "0.2.10"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741"
[[package]]
name = "predicates"
@ -763,9 +807,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.29"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70"
dependencies = [
"unicode-xid",
]
@ -866,7 +910,7 @@ dependencies = [
[[package]]
name = "reedline"
version = "0.2.0"
source = "git+https://github.com/nushell/reedline?branch=main#6fedafffb7a783949b5e9a86149286014eddba15"
source = "git+https://github.com/nushell/reedline?branch=main#68a6ab4e5b1ada6d4e0f64bddd305ef1c852fb39"
dependencies = [
"chrono",
"crossterm",
@ -1058,9 +1102,9 @@ dependencies = [
[[package]]
name = "sysinfo"
version = "0.20.4"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffff4a02fa61eee51f95210fc9c98ea6eeb46bb071adeafd61e1a0b9b22c6a6d"
checksum = "e223c65cd36b485a34c2ce6e38efa40777d31c4166d9076030c74cdcf971679f"
dependencies = [
"cfg-if",
"core-foundation-sys",
@ -1142,6 +1186,15 @@ dependencies = [
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
dependencies = [
"once_cell",
]
[[package]]
name = "time"
version = "0.1.44"
@ -1258,3 +1311,9 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "zeroize"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf68b08513768deaa790264a7fac27a58cbf2705cfcdc9448362229217d7e970"

View File

@ -11,6 +11,7 @@ members = ["crates/nu-cli", "crates/nu-engine", "crates/nu-parser", "crates/nu-c
[dependencies]
reedline = { git = "https://github.com/nushell/reedline", branch = "main" }
crossterm = "0.21.*"
dialoguer = { version = "0.9.0", features = ["fuzzy-select"] }
nu-cli = { path="./crates/nu-cli" }
nu-command = { path="./crates/nu-command" }
nu-engine = { path="./crates/nu-engine" }

View File

@ -28,6 +28,7 @@ impl Command for Lines {
call: &Call,
input: Value,
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
let span = call.head;
match input {
#[allow(clippy::needless_collect)]
// Collect is needed because the string may not live long enough for
@ -49,7 +50,7 @@ impl Command for Lines {
Ok(Value::Stream {
stream: ValueStream(Rc::new(RefCell::new(iter))),
span: Span::unknown(),
span,
})
}
Value::Stream { stream, span: _ } => {
@ -80,7 +81,7 @@ impl Command for Lines {
Ok(Value::Stream {
stream: ValueStream(Rc::new(RefCell::new(iter))),
span: Span::unknown(),
span,
})
}
val => Err(ShellError::UnsupportedInput(

View File

@ -1,5 +1,6 @@
use std::{cell::RefCell, io::Write, rc::Rc};
use dialoguer::{theme::ColorfulTheme, Select};
use miette::{IntoDiagnostic, Result};
use nu_cli::{report_error, NuCompleter, NuHighlighter, NuValidator, NushellPrompt};
use nu_command::create_default_context;
@ -10,7 +11,7 @@ use nu_protocol::{
engine::{EngineState, EvaluationContext, Stack, StateWorkingSet},
ShellError, Value,
};
use reedline::{DefaultPrompt, Prompt};
use reedline::{Completer, CompletionActionHandler, DefaultPrompt, LineBuffer, Prompt};
#[cfg(test)]
mod tests;
@ -18,6 +19,51 @@ mod tests;
// Name of environment variable where the prompt could be stored
const PROMPT_COMMAND: &str = "PROMPT_COMMAND";
struct FuzzyCompletion {
completer: Box<dyn Completer>,
}
impl CompletionActionHandler for FuzzyCompletion {
fn handle(&mut self, present_buffer: &mut LineBuffer) {
let completions = self
.completer
.complete(present_buffer.get_buffer(), present_buffer.offset());
if completions.is_empty() {
// do nothing
} else if completions.len() == 1 {
let span = completions[0].0;
let mut offset = present_buffer.offset();
offset += completions[0].1.len() - (span.end - span.start);
// TODO improve the support for multiline replace
present_buffer.replace(span.start..span.end, &completions[0].1);
present_buffer.set_insertion_point(offset);
} else {
let selections: Vec<_> = completions.iter().map(|(_, string)| string).collect();
let _ = crossterm::terminal::disable_raw_mode();
println!();
let result = Select::with_theme(&ColorfulTheme::default())
.default(0)
.items(&selections[..])
.interact()
.unwrap();
let _ = crossterm::terminal::enable_raw_mode();
let span = completions[result].0;
let mut offset = present_buffer.offset();
offset += completions[result].1.len() - (span.end - span.start);
// TODO improve the support for multiline replace
present_buffer.replace(span.start..span.end, &completions[result].1);
present_buffer.set_insertion_point(offset);
}
}
}
fn main() -> Result<()> {
miette::set_panic_hook();
let miette_hook = std::panic::take_hook();
@ -66,7 +112,7 @@ fn main() -> Result<()> {
Ok(())
} else {
use reedline::{FileBackedHistory, ListCompletionHandler, Reedline, Signal};
use reedline::{FileBackedHistory, Reedline, Signal};
let completer = NuCompleter::new(engine_state.clone());
let mut entry_num = 0;
@ -80,9 +126,12 @@ fn main() -> Result<()> {
.with_highlighter(Box::new(NuHighlighter {
engine_state: engine_state.clone(),
}))
.with_completion_action_handler(Box::new(
ListCompletionHandler::default().with_completer(Box::new(completer)),
))
.with_completion_action_handler(Box::new(FuzzyCompletion {
completer: Box::new(completer),
}))
// .with_completion_action_handler(Box::new(
// ListCompletionHandler::default().with_completer(Box::new(completer)),
// ))
.with_validator(Box::new(NuValidator {
engine_state: engine_state.clone(),
}));