mirror of
https://github.com/nushell/nushell
synced 2024-12-30 15:03:25 +00:00
Merge pull request #236 from nushell/select_completions
Try out select completions from dialoguer
This commit is contained in:
commit
2be26127c9
4 changed files with 118 additions and 20 deletions
71
Cargo.lock
generated
71
Cargo.lock
generated
|
@ -170,10 +170,25 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation-sys"
|
name = "console"
|
||||||
version = "0.8.2"
|
version = "0.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
|
@ -261,7 +276,20 @@ version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c9dd058f8b65922819fabb4a41e7d1964e56344042c26efbccd465202c23fa0c"
|
checksum = "c9dd058f8b65922819fabb4a41e7d1964e56344042c26efbccd465202c23fa0c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"console",
|
"console 0.14.1",
|
||||||
|
"lazy_static",
|
||||||
|
"tempfile",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dialoguer"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61579ada4ec0c6031cfac3f86fdba0d195a7ebeb5e36693bd53cb5999a25beeb"
|
||||||
|
dependencies = [
|
||||||
|
"console 0.15.0",
|
||||||
|
"fuzzy-matcher",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
|
@ -330,6 +358,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
|
"dialoguer 0.9.0",
|
||||||
"miette",
|
"miette",
|
||||||
"nu-cli",
|
"nu-cli",
|
||||||
"nu-command",
|
"nu-command",
|
||||||
|
@ -345,6 +374,15 @@ dependencies = [
|
||||||
"tempfile",
|
"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]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
|
@ -574,7 +612,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytesize",
|
"bytesize",
|
||||||
"chrono",
|
"chrono",
|
||||||
"dialoguer",
|
"dialoguer 0.8.0",
|
||||||
"glob",
|
"glob",
|
||||||
"lscolors",
|
"lscolors",
|
||||||
"nu-engine",
|
"nu-engine",
|
||||||
|
@ -752,9 +790,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.10"
|
version = "0.2.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "predicates"
|
name = "predicates"
|
||||||
|
@ -797,9 +835,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.29"
|
version = "1.0.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
|
checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
@ -900,7 +938,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reedline"
|
name = "reedline"
|
||||||
version = "0.2.0"
|
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 = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
|
@ -1092,9 +1130,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sysinfo"
|
name = "sysinfo"
|
||||||
version = "0.20.4"
|
version = "0.20.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ffff4a02fa61eee51f95210fc9c98ea6eeb46bb071adeafd61e1a0b9b22c6a6d"
|
checksum = "e223c65cd36b485a34c2ce6e38efa40777d31c4166d9076030c74cdcf971679f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
|
@ -1176,6 +1214,15 @@ dependencies = [
|
||||||
"syn",
|
"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]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.44"
|
version = "0.1.44"
|
||||||
|
|
|
@ -11,6 +11,7 @@ members = ["crates/nu-cli", "crates/nu-engine", "crates/nu-parser", "crates/nu-c
|
||||||
[dependencies]
|
[dependencies]
|
||||||
reedline = { git = "https://github.com/nushell/reedline", branch = "main" }
|
reedline = { git = "https://github.com/nushell/reedline", branch = "main" }
|
||||||
crossterm = "0.21.*"
|
crossterm = "0.21.*"
|
||||||
|
dialoguer = { version = "0.9.0", features = ["fuzzy-select"] }
|
||||||
nu-cli = { path="./crates/nu-cli" }
|
nu-cli = { path="./crates/nu-cli" }
|
||||||
nu-command = { path="./crates/nu-command" }
|
nu-command = { path="./crates/nu-command" }
|
||||||
nu-engine = { path="./crates/nu-engine" }
|
nu-engine = { path="./crates/nu-engine" }
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use nu_protocol::ast::Call;
|
use nu_protocol::ast::Call;
|
||||||
use nu_protocol::engine::{Command, EvaluationContext};
|
use nu_protocol::engine::{Command, EvaluationContext};
|
||||||
use nu_protocol::{ShellError, Signature, Span, Value, ValueStream};
|
use nu_protocol::{ShellError, Signature, Value, ValueStream};
|
||||||
|
|
||||||
pub struct Lines;
|
pub struct Lines;
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ impl Command for Lines {
|
||||||
call: &Call,
|
call: &Call,
|
||||||
input: Value,
|
input: Value,
|
||||||
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
) -> Result<nu_protocol::Value, nu_protocol::ShellError> {
|
||||||
|
let span = call.head;
|
||||||
match input {
|
match input {
|
||||||
#[allow(clippy::needless_collect)]
|
#[allow(clippy::needless_collect)]
|
||||||
// Collect is needed because the string may not live long enough for
|
// Collect is needed because the string may not live long enough for
|
||||||
|
@ -49,7 +50,7 @@ impl Command for Lines {
|
||||||
|
|
||||||
Ok(Value::Stream {
|
Ok(Value::Stream {
|
||||||
stream: ValueStream(Rc::new(RefCell::new(iter))),
|
stream: ValueStream(Rc::new(RefCell::new(iter))),
|
||||||
span: Span::unknown(),
|
span,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Value::Stream { stream, span: _ } => {
|
Value::Stream { stream, span: _ } => {
|
||||||
|
@ -80,7 +81,7 @@ impl Command for Lines {
|
||||||
|
|
||||||
Ok(Value::Stream {
|
Ok(Value::Stream {
|
||||||
stream: ValueStream(Rc::new(RefCell::new(iter))),
|
stream: ValueStream(Rc::new(RefCell::new(iter))),
|
||||||
span: Span::unknown(),
|
span,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
val => Err(ShellError::UnsupportedInput(
|
val => Err(ShellError::UnsupportedInput(
|
||||||
|
|
59
src/main.rs
59
src/main.rs
|
@ -1,5 +1,6 @@
|
||||||
use std::{cell::RefCell, io::Write, rc::Rc};
|
use std::{cell::RefCell, io::Write, rc::Rc};
|
||||||
|
|
||||||
|
use dialoguer::{theme::ColorfulTheme, Select};
|
||||||
use miette::{IntoDiagnostic, Result};
|
use miette::{IntoDiagnostic, Result};
|
||||||
use nu_cli::{report_error, NuCompleter, NuHighlighter, NuValidator, NushellPrompt};
|
use nu_cli::{report_error, NuCompleter, NuHighlighter, NuValidator, NushellPrompt};
|
||||||
use nu_command::create_default_context;
|
use nu_command::create_default_context;
|
||||||
|
@ -10,7 +11,7 @@ use nu_protocol::{
|
||||||
engine::{EngineState, EvaluationContext, Stack, StateWorkingSet},
|
engine::{EngineState, EvaluationContext, Stack, StateWorkingSet},
|
||||||
ShellError, Value,
|
ShellError, Value,
|
||||||
};
|
};
|
||||||
use reedline::{DefaultPrompt, Prompt};
|
use reedline::{Completer, CompletionActionHandler, DefaultPrompt, LineBuffer, Prompt};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
@ -18,6 +19,51 @@ mod tests;
|
||||||
// Name of environment variable where the prompt could be stored
|
// Name of environment variable where the prompt could be stored
|
||||||
const PROMPT_COMMAND: &str = "PROMPT_COMMAND";
|
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<()> {
|
fn main() -> Result<()> {
|
||||||
miette::set_panic_hook();
|
miette::set_panic_hook();
|
||||||
let miette_hook = std::panic::take_hook();
|
let miette_hook = std::panic::take_hook();
|
||||||
|
@ -66,7 +112,7 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
use reedline::{FileBackedHistory, ListCompletionHandler, Reedline, Signal};
|
use reedline::{FileBackedHistory, Reedline, Signal};
|
||||||
|
|
||||||
let completer = NuCompleter::new(engine_state.clone());
|
let completer = NuCompleter::new(engine_state.clone());
|
||||||
let mut entry_num = 0;
|
let mut entry_num = 0;
|
||||||
|
@ -80,9 +126,12 @@ fn main() -> Result<()> {
|
||||||
.with_highlighter(Box::new(NuHighlighter {
|
.with_highlighter(Box::new(NuHighlighter {
|
||||||
engine_state: engine_state.clone(),
|
engine_state: engine_state.clone(),
|
||||||
}))
|
}))
|
||||||
.with_completion_action_handler(Box::new(
|
.with_completion_action_handler(Box::new(FuzzyCompletion {
|
||||||
ListCompletionHandler::default().with_completer(Box::new(completer)),
|
completer: Box::new(completer),
|
||||||
))
|
}))
|
||||||
|
// .with_completion_action_handler(Box::new(
|
||||||
|
// ListCompletionHandler::default().with_completer(Box::new(completer)),
|
||||||
|
// ))
|
||||||
.with_validator(Box::new(NuValidator {
|
.with_validator(Box::new(NuValidator {
|
||||||
engine_state: engine_state.clone(),
|
engine_state: engine_state.clone(),
|
||||||
}));
|
}));
|
||||||
|
|
Loading…
Reference in a new issue