mirror of
https://github.com/nushell/nushell
synced 2024-11-14 00:47:09 +00:00
Extract completions into subcrate. (#3631)
This commit is contained in:
parent
04c0e94349
commit
7c8fb060f1
19 changed files with 160 additions and 110 deletions
19
Cargo.lock
generated
19
Cargo.lock
generated
|
@ -3233,6 +3233,7 @@ dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
"nu-cli",
|
"nu-cli",
|
||||||
"nu-command",
|
"nu-command",
|
||||||
|
"nu-completion",
|
||||||
"nu-data",
|
"nu-data",
|
||||||
"nu-engine",
|
"nu-engine",
|
||||||
"nu-errors",
|
"nu-errors",
|
||||||
|
@ -3318,6 +3319,7 @@ dependencies = [
|
||||||
"meval",
|
"meval",
|
||||||
"nu-ansi-term",
|
"nu-ansi-term",
|
||||||
"nu-command",
|
"nu-command",
|
||||||
|
"nu-completion",
|
||||||
"nu-data",
|
"nu-data",
|
||||||
"nu-engine",
|
"nu-engine",
|
||||||
"nu-errors",
|
"nu-errors",
|
||||||
|
@ -3476,6 +3478,23 @@ dependencies = [
|
||||||
"zip",
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nu-completion"
|
||||||
|
version = "0.32.1"
|
||||||
|
dependencies = [
|
||||||
|
"directories-next",
|
||||||
|
"dirs-next",
|
||||||
|
"indexmap",
|
||||||
|
"nu-data",
|
||||||
|
"nu-engine",
|
||||||
|
"nu-errors",
|
||||||
|
"nu-parser",
|
||||||
|
"nu-protocol",
|
||||||
|
"nu-source",
|
||||||
|
"nu-test-support",
|
||||||
|
"rustyline",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-data"
|
name = "nu-data"
|
||||||
version = "0.32.1"
|
version = "0.32.1"
|
||||||
|
|
|
@ -20,6 +20,7 @@ members = ["crates/*/"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nu-cli = { version = "0.32.1", path = "./crates/nu-cli", default-features = false }
|
nu-cli = { version = "0.32.1", path = "./crates/nu-cli", default-features = false }
|
||||||
nu-command = { version = "0.32.1", path = "./crates/nu-command" }
|
nu-command = { version = "0.32.1", path = "./crates/nu-command" }
|
||||||
|
nu-completion = { version = "0.32.1", path = "./crates/nu-completion" }
|
||||||
nu-data = { version = "0.32.1", path = "./crates/nu-data" }
|
nu-data = { version = "0.32.1", path = "./crates/nu-data" }
|
||||||
nu-engine = { version = "0.32.1", path = "./crates/nu-engine" }
|
nu-engine = { version = "0.32.1", path = "./crates/nu-engine" }
|
||||||
nu-errors = { version = "0.32.1", path = "./crates/nu-errors" }
|
nu-errors = { version = "0.32.1", path = "./crates/nu-errors" }
|
||||||
|
|
|
@ -11,6 +11,7 @@ version = "0.32.1"
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
nu-completion = { version = "0.32.1", path = "../nu-completion" }
|
||||||
nu-command = { version = "0.32.1", path = "../nu-command" }
|
nu-command = { version = "0.32.1", path = "../nu-command" }
|
||||||
nu-data = { version = "0.32.1", path = "../nu-data" }
|
nu-data = { version = "0.32.1", path = "../nu-data" }
|
||||||
nu-engine = { version = "0.32.1", path = "../nu-engine" }
|
nu-engine = { version = "0.32.1", path = "../nu-engine" }
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
pub(crate) mod command;
|
|
||||||
pub(crate) mod engine;
|
|
||||||
pub(crate) mod flag;
|
|
||||||
pub(crate) mod matchers;
|
|
||||||
pub(crate) mod path;
|
|
||||||
|
|
||||||
use matchers::Matcher;
|
|
||||||
use nu_engine::EvaluationContext;
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
|
||||||
pub struct Suggestion {
|
|
||||||
pub display: String,
|
|
||||||
pub replacement: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CompletionContext<'a>(&'a EvaluationContext);
|
|
||||||
|
|
||||||
impl<'a> CompletionContext<'a> {
|
|
||||||
pub fn new(a: &'a EvaluationContext) -> CompletionContext<'a> {
|
|
||||||
CompletionContext(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> AsRef<EvaluationContext> for CompletionContext<'a> {
|
|
||||||
fn as_ref(&self) -> &EvaluationContext {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Completer {
|
|
||||||
fn complete(
|
|
||||||
&self,
|
|
||||||
ctx: &CompletionContext<'_>,
|
|
||||||
partial: &str,
|
|
||||||
matcher: &dyn Matcher,
|
|
||||||
) -> Vec<Suggestion>;
|
|
||||||
}
|
|
|
@ -11,8 +11,6 @@ extern crate quickcheck_macros;
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod cli;
|
mod cli;
|
||||||
#[cfg(feature = "rustyline-support")]
|
|
||||||
mod completion;
|
|
||||||
mod format;
|
mod format;
|
||||||
#[cfg(feature = "rustyline-support")]
|
#[cfg(feature = "rustyline-support")]
|
||||||
mod keybinding;
|
mod keybinding;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#![allow(clippy::module_inception)]
|
#![allow(clippy::module_inception)]
|
||||||
|
|
||||||
#[cfg(feature = "rustyline-support")]
|
|
||||||
pub(crate) mod completer;
|
|
||||||
#[cfg(feature = "rustyline-support")]
|
#[cfg(feature = "rustyline-support")]
|
||||||
pub(crate) mod helper;
|
pub(crate) mod helper;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::completion;
|
|
||||||
use crate::shell::completer::NuCompleter;
|
|
||||||
use nu_ansi_term::Color;
|
use nu_ansi_term::Color;
|
||||||
|
use nu_completion::NuCompleter;
|
||||||
use nu_engine::{DefaultPalette, EvaluationContext, Painter};
|
use nu_engine::{DefaultPalette, EvaluationContext, Painter};
|
||||||
use nu_source::{Tag, Tagged};
|
use nu_source::{Tag, Tagged};
|
||||||
use std::borrow::Cow::{self, Owned};
|
use std::borrow::Cow::{self, Owned};
|
||||||
|
@ -28,18 +27,28 @@ impl Helper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rustyline::completion::Candidate for completion::Suggestion {
|
struct CompletionContext<'a>(&'a EvaluationContext);
|
||||||
|
|
||||||
|
impl<'a> nu_completion::CompletionContext for CompletionContext<'a> {
|
||||||
|
fn signature_registry(&self) -> &dyn nu_parser::ParserScope {
|
||||||
|
&self.0.scope
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CompletionSuggestion(nu_completion::Suggestion);
|
||||||
|
|
||||||
|
impl rustyline::completion::Candidate for CompletionSuggestion {
|
||||||
fn display(&self) -> &str {
|
fn display(&self) -> &str {
|
||||||
&self.display
|
&self.0.display
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replacement(&self) -> &str {
|
fn replacement(&self) -> &str {
|
||||||
&self.replacement
|
&self.0.replacement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rustyline::completion::Completer for Helper {
|
impl rustyline::completion::Completer for Helper {
|
||||||
type Candidate = completion::Suggestion;
|
type Candidate = CompletionSuggestion;
|
||||||
|
|
||||||
fn complete(
|
fn complete(
|
||||||
&self,
|
&self,
|
||||||
|
@ -47,8 +56,10 @@ impl rustyline::completion::Completer for Helper {
|
||||||
pos: usize,
|
pos: usize,
|
||||||
_ctx: &rustyline::Context<'_>,
|
_ctx: &rustyline::Context<'_>,
|
||||||
) -> Result<(usize, Vec<Self::Candidate>), rustyline::error::ReadlineError> {
|
) -> Result<(usize, Vec<Self::Candidate>), rustyline::error::ReadlineError> {
|
||||||
let ctx = completion::CompletionContext::new(&self.context);
|
let ctx = CompletionContext(&self.context);
|
||||||
Ok(self.completer.complete(line, pos, &ctx))
|
let (position, suggestions) = self.completer.complete(line, pos, &ctx);
|
||||||
|
let suggestions = suggestions.into_iter().map(CompletionSuggestion).collect();
|
||||||
|
Ok((position, suggestions))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&self, line: &mut rustyline::line_buffer::LineBuffer, start: usize, elected: &str) {
|
fn update(&self, line: &mut rustyline::line_buffer::LineBuffer, start: usize, elected: &str) {
|
||||||
|
|
29
crates/nu-completion/Cargo.toml
Normal file
29
crates/nu-completion/Cargo.toml
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
[package]
|
||||||
|
authors = ["The Nu Project Contributors"]
|
||||||
|
description = "Completions for nushell"
|
||||||
|
edition = "2018"
|
||||||
|
license = "MIT"
|
||||||
|
name = "nu-completion"
|
||||||
|
version = "0.32.1"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
nu-data = { version = "0.32.1", path = "../nu-data" }
|
||||||
|
nu-engine = { version = "0.32.1", path = "../nu-engine" }
|
||||||
|
nu-errors = { version = "0.32.1", path = "../nu-errors" }
|
||||||
|
nu-parser = { version = "0.32.1", path = "../nu-parser" }
|
||||||
|
nu-protocol = { version = "0.32.1", path = "../nu-protocol" }
|
||||||
|
nu-source = { version = "0.32.1", path = "../nu-source" }
|
||||||
|
nu-test-support = { version = "0.32.1", path = "../nu-test-support" }
|
||||||
|
|
||||||
|
directories-next = { version = "2.0.0", optional = true }
|
||||||
|
dirs-next = { version = "2.0.0", optional = true }
|
||||||
|
indexmap = { version = "1.6.1", features = ["serde-1"] }
|
||||||
|
rustyline = { version = "8.1.0", optional = true }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
rustyline-support = ["rustyline", "nu-engine/rustyline-support"]
|
||||||
|
dirs = ["dirs-next"]
|
||||||
|
directories = ["directories-next"]
|
|
@ -1,24 +1,22 @@
|
||||||
|
use nu_test_support::NATIVE_PATH_ENV_VAR;
|
||||||
|
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use indexmap::set::IndexSet;
|
use indexmap::set::IndexSet;
|
||||||
|
|
||||||
use super::matchers::Matcher;
|
use super::matchers::Matcher;
|
||||||
use crate::completion::{Completer, CompletionContext, Suggestion};
|
use crate::{Completer, CompletionContext, Suggestion};
|
||||||
use nu_engine::EvaluationContext;
|
|
||||||
use nu_test_support::NATIVE_PATH_ENV_VAR;
|
|
||||||
|
|
||||||
pub struct CommandCompleter;
|
pub struct CommandCompleter;
|
||||||
|
|
||||||
impl Completer for CommandCompleter {
|
impl<Context> Completer<Context> for CommandCompleter
|
||||||
fn complete(
|
where
|
||||||
&self,
|
Context: CompletionContext,
|
||||||
ctx: &CompletionContext<'_>,
|
{
|
||||||
partial: &str,
|
fn complete(&self, ctx: &Context, partial: &str, matcher: &dyn Matcher) -> Vec<Suggestion> {
|
||||||
matcher: &dyn Matcher,
|
let registry = ctx.signature_registry();
|
||||||
) -> Vec<Suggestion> {
|
let mut commands: IndexSet<String> = IndexSet::from_iter(registry.get_names());
|
||||||
let context: &EvaluationContext = ctx.as_ref();
|
|
||||||
let mut commands: IndexSet<String> = IndexSet::from_iter(context.scope.get_command_names());
|
|
||||||
|
|
||||||
// Command suggestions can come from three possible sets:
|
// Command suggestions can come from three possible sets:
|
||||||
// 1. internal command names,
|
// 1. internal command names,
|
||||||
|
@ -40,7 +38,7 @@ impl Completer for CommandCompleter {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if !partial.is_empty() {
|
if !partial.is_empty() {
|
||||||
let path_completer = crate::completion::path::PathCompleter;
|
let path_completer = crate::path::PathCompleter;
|
||||||
let path_results = path_completer.path_suggestions(partial, matcher);
|
let path_results = path_completer.path_suggestions(partial, matcher);
|
||||||
let iter = path_results.into_iter().filter_map(|path_suggestion| {
|
let iter = path_results.into_iter().filter_map(|path_suggestion| {
|
||||||
let path = path_suggestion.path;
|
let path = path_suggestion.path;
|
|
@ -1,35 +1,34 @@
|
||||||
use crate::completion::command::CommandCompleter;
|
|
||||||
use crate::completion::flag::FlagCompleter;
|
|
||||||
use crate::completion::matchers;
|
|
||||||
use crate::completion::matchers::Matcher;
|
|
||||||
use crate::completion::path::{PathCompleter, PathSuggestion};
|
|
||||||
use crate::completion::{self, Completer, Suggestion};
|
|
||||||
use nu_engine::EvaluationContext;
|
|
||||||
use nu_parser::ParserScope;
|
|
||||||
use nu_source::{Span, Tag};
|
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
pub(crate) struct NuCompleter {}
|
use nu_source::{Span, Tag};
|
||||||
|
|
||||||
|
use crate::command::CommandCompleter;
|
||||||
|
use crate::engine;
|
||||||
|
use crate::flag::FlagCompleter;
|
||||||
|
use crate::matchers;
|
||||||
|
use crate::matchers::Matcher;
|
||||||
|
use crate::path::{PathCompleter, PathSuggestion};
|
||||||
|
use crate::{Completer, CompletionContext, Suggestion};
|
||||||
|
|
||||||
|
pub struct NuCompleter {}
|
||||||
|
|
||||||
impl NuCompleter {}
|
impl NuCompleter {}
|
||||||
|
|
||||||
impl NuCompleter {
|
impl NuCompleter {
|
||||||
pub fn complete(
|
pub fn complete<Context: CompletionContext>(
|
||||||
&self,
|
&self,
|
||||||
line: &str,
|
line: &str,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
context: &completion::CompletionContext,
|
context: &Context,
|
||||||
) -> (usize, Vec<Suggestion>) {
|
) -> (usize, Vec<Suggestion>) {
|
||||||
use completion::engine::LocationType;
|
use engine::LocationType;
|
||||||
|
|
||||||
let nu_context: &EvaluationContext = context.as_ref();
|
let tokens = nu_parser::lex(line, 0).0;
|
||||||
|
|
||||||
nu_context.scope.enter_scope();
|
let locations = Some(nu_parser::parse_block(tokens).0)
|
||||||
let (block, _) = nu_parser::parse(line, 0, &nu_context.scope);
|
.map(|block| nu_parser::classify_block(&block, context.signature_registry()))
|
||||||
nu_context.scope.exit_scope();
|
.map(|(block, _)| engine::completion_location(line, &block, pos))
|
||||||
|
.unwrap_or_default();
|
||||||
let locations = completion::engine::completion_location(line, &block, pos);
|
|
||||||
|
|
||||||
let matcher = nu_data::config::config(Tag::unknown())
|
let matcher = nu_data::config::config(Tag::unknown())
|
||||||
.ok()
|
.ok()
|
||||||
|
@ -61,7 +60,6 @@ impl NuCompleter {
|
||||||
pos = location.span.start();
|
pos = location.span.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let suggestions = locations
|
let suggestions = locations
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|location| {
|
.flat_map(|location| {
|
||||||
|
@ -147,7 +145,16 @@ fn select_directory_suggestions(completed_paths: Vec<PathSuggestion>) -> Vec<Pat
|
||||||
}
|
}
|
||||||
|
|
||||||
fn requote(orig_value: String, previously_quoted: bool) -> String {
|
fn requote(orig_value: String, previously_quoted: bool) -> String {
|
||||||
let value: Cow<str> = rustyline::completion::unescape(&orig_value, Some('\\'));
|
let value: Cow<str> = {
|
||||||
|
#[cfg(feature = "rustyline-support")]
|
||||||
|
{
|
||||||
|
rustyline::completion::unescape(&orig_value, Some('\\'))
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "rustyline-support"))]
|
||||||
|
{
|
||||||
|
orig_value.into()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut quotes = vec!['"', '\''];
|
let mut quotes = vec!['"', '\''];
|
||||||
let mut should_quote = false;
|
let mut should_quote = false;
|
|
@ -301,6 +301,10 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParserScope for VecRegistry {
|
impl ParserScope for VecRegistry {
|
||||||
|
fn get_names(&self) -> Vec<String> {
|
||||||
|
self.0.iter().cloned().map(|s| s.name).collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn has_signature(&self, name: &str) -> bool {
|
fn has_signature(&self, name: &str) -> bool {
|
||||||
self.0.iter().any(|v| v.name == name)
|
self.0.iter().any(|v| v.name == name)
|
||||||
}
|
}
|
||||||
|
@ -331,8 +335,6 @@ mod tests {
|
||||||
mod completion_location {
|
mod completion_location {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use nu_parser::ParserScope;
|
|
||||||
|
|
||||||
fn completion_location(
|
fn completion_location(
|
||||||
line: &str,
|
line: &str,
|
||||||
scope: &dyn ParserScope,
|
scope: &dyn ParserScope,
|
|
@ -1,22 +1,16 @@
|
||||||
use super::matchers::Matcher;
|
use super::matchers::Matcher;
|
||||||
use crate::completion::{Completer, CompletionContext, Suggestion};
|
use crate::{Completer, CompletionContext, Suggestion};
|
||||||
use nu_engine::EvaluationContext;
|
|
||||||
|
|
||||||
pub struct FlagCompleter {
|
pub struct FlagCompleter {
|
||||||
pub(crate) cmd: String,
|
pub(crate) cmd: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Completer for FlagCompleter {
|
impl<Context> Completer<Context> for FlagCompleter
|
||||||
fn complete(
|
where
|
||||||
&self,
|
Context: CompletionContext,
|
||||||
ctx: &CompletionContext<'_>,
|
{
|
||||||
partial: &str,
|
fn complete(&self, ctx: &Context, partial: &str, matcher: &dyn Matcher) -> Vec<Suggestion> {
|
||||||
matcher: &dyn Matcher,
|
if let Some(sig) = ctx.signature_registry().get_signature(&self.cmd) {
|
||||||
) -> Vec<Suggestion> {
|
|
||||||
let context: &EvaluationContext = ctx.as_ref();
|
|
||||||
|
|
||||||
if let Some(cmd) = context.scope.get_command(&self.cmd) {
|
|
||||||
let sig = cmd.signature();
|
|
||||||
let mut suggestions = Vec::new();
|
let mut suggestions = Vec::new();
|
||||||
for (name, (named_type, _desc)) in sig.named.iter() {
|
for (name, (named_type, _desc)) in sig.named.iter() {
|
||||||
suggestions.push(format!("--{}", name));
|
suggestions.push(format!("--{}", name));
|
24
crates/nu-completion/src/lib.rs
Normal file
24
crates/nu-completion/src/lib.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
pub(crate) mod command;
|
||||||
|
pub(crate) mod completer;
|
||||||
|
pub(crate) mod engine;
|
||||||
|
pub(crate) mod flag;
|
||||||
|
pub(crate) mod matchers;
|
||||||
|
pub(crate) mod path;
|
||||||
|
|
||||||
|
use matchers::Matcher;
|
||||||
|
|
||||||
|
pub use completer::NuCompleter;
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
|
pub struct Suggestion {
|
||||||
|
pub display: String,
|
||||||
|
pub replacement: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait CompletionContext {
|
||||||
|
fn signature_registry(&self) -> &dyn nu_parser::ParserScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Completer<Context: CompletionContext> {
|
||||||
|
fn complete(&self, ctx: &Context, partial: &str, matcher: &dyn Matcher) -> Vec<Suggestion>;
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::completion::matchers;
|
use crate::matchers;
|
||||||
|
|
||||||
pub struct Matcher;
|
pub struct Matcher;
|
||||||
|
|
||||||
impl matchers::Matcher for Matcher {
|
impl matchers::Matcher for Matcher {
|
||||||
|
@ -12,7 +13,7 @@ impl matchers::Matcher for Matcher {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
// TODO: check some Unicode matches if this becomes relevant
|
// TODO: check some unicode matches if this becomes relevant
|
||||||
|
|
||||||
// FIXME: could work exhaustively through ['-', '--'. ''] in a loop for each test
|
// FIXME: could work exhaustively through ['-', '--'. ''] in a loop for each test
|
||||||
#[test]
|
#[test]
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::completion::matchers;
|
use crate::matchers;
|
||||||
|
|
||||||
pub struct Matcher;
|
pub struct Matcher;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use super::matchers::Matcher;
|
use super::matchers::Matcher;
|
||||||
use crate::completion::{Completer, CompletionContext, Suggestion};
|
use crate::{Completer, CompletionContext, Suggestion};
|
||||||
|
|
||||||
const SEP: char = std::path::MAIN_SEPARATOR;
|
const SEP: char = std::path::MAIN_SEPARATOR;
|
||||||
|
|
||||||
|
@ -74,13 +74,11 @@ impl PathCompleter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Completer for PathCompleter {
|
impl<Context> Completer<Context> for PathCompleter
|
||||||
fn complete(
|
where
|
||||||
&self,
|
Context: CompletionContext,
|
||||||
_ctx: &CompletionContext<'_>,
|
{
|
||||||
partial: &str,
|
fn complete(&self, _ctx: &Context, partial: &str, matcher: &dyn Matcher) -> Vec<Suggestion> {
|
||||||
matcher: &dyn Matcher,
|
|
||||||
) -> Vec<Suggestion> {
|
|
||||||
self.path_suggestions(partial, matcher)
|
self.path_suggestions(partial, matcher)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|ps| ps.suggestion)
|
.map(|ps| ps.suggestion)
|
|
@ -319,6 +319,10 @@ impl Scope {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParserScope for Scope {
|
impl ParserScope for Scope {
|
||||||
|
fn get_names(&self) -> Vec<String> {
|
||||||
|
self.get_command_names()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_signature(&self, name: &str) -> Option<nu_protocol::Signature> {
|
fn get_signature(&self, name: &str) -> Option<nu_protocol::Signature> {
|
||||||
self.get_command(name).map(|x| x.signature())
|
self.get_command(name).map(|x| x.signature())
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ use nu_source::Spanned;
|
||||||
use std::{fmt::Debug, sync::Arc};
|
use std::{fmt::Debug, sync::Arc};
|
||||||
|
|
||||||
pub trait ParserScope: Debug {
|
pub trait ParserScope: Debug {
|
||||||
|
fn get_names(&self) -> Vec<String>;
|
||||||
|
|
||||||
fn get_signature(&self, name: &str) -> Option<nu_protocol::Signature>;
|
fn get_signature(&self, name: &str) -> Option<nu_protocol::Signature>;
|
||||||
|
|
||||||
fn has_signature(&self, name: &str) -> bool;
|
fn has_signature(&self, name: &str) -> bool;
|
||||||
|
|
Loading…
Reference in a new issue