mirror of
https://github.com/nushell/nushell.git
synced 2025-05-07 19:44:25 +02:00
nu-cli/completions: add completion for $env. (#5199)
* nu-cli/completions: add completion for $env. * use stack to avoid showing hidden env vars
This commit is contained in:
parent
583b7b1821
commit
2a3991cfdb
@ -8,6 +8,7 @@ use nu_protocol::{
|
|||||||
Span, Value,
|
Span, Value,
|
||||||
};
|
};
|
||||||
use reedline::{Completer as ReedlineCompleter, Suggestion};
|
use reedline::{Completer as ReedlineCompleter, Suggestion};
|
||||||
|
use std::str;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -69,6 +70,10 @@ impl NuCompleter {
|
|||||||
|
|
||||||
for (flat_idx, flat) in flattened.iter().enumerate() {
|
for (flat_idx, flat) in flattened.iter().enumerate() {
|
||||||
if pos >= flat.0.start && pos < flat.0.end {
|
if pos >= flat.0.start && pos < flat.0.end {
|
||||||
|
// Context variables
|
||||||
|
let mut is_variable_completion = false;
|
||||||
|
let mut previous_expr: Vec<u8> = vec![];
|
||||||
|
|
||||||
// Create a new span
|
// Create a new span
|
||||||
let new_span = Span {
|
let new_span = Span {
|
||||||
start: flat.0.start,
|
start: flat.0.start,
|
||||||
@ -79,9 +84,32 @@ impl NuCompleter {
|
|||||||
let mut prefix = working_set.get_span_contents(flat.0).to_vec();
|
let mut prefix = working_set.get_span_contents(flat.0).to_vec();
|
||||||
prefix.remove(pos - flat.0.start);
|
prefix.remove(pos - flat.0.start);
|
||||||
|
|
||||||
|
// Try to get the previous expression
|
||||||
|
if flat_idx > 0 {
|
||||||
|
match flattened.get(flat_idx - 1) {
|
||||||
|
Some(value) => {
|
||||||
|
let previous_prefix =
|
||||||
|
working_set.get_span_contents(value.0).to_vec();
|
||||||
|
|
||||||
|
// Update the previous expression
|
||||||
|
previous_expr = previous_prefix;
|
||||||
|
|
||||||
|
// Check if should match variable completion
|
||||||
|
if matches!(value.1, FlatShape::Variable) {
|
||||||
|
is_variable_completion = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Variables completion
|
// Variables completion
|
||||||
if prefix.starts_with(b"$") {
|
if prefix.starts_with(b"$") || is_variable_completion {
|
||||||
let mut completer = VariableCompletion::new(self.engine_state.clone());
|
let mut completer = VariableCompletion::new(
|
||||||
|
self.engine_state.clone(),
|
||||||
|
self.stack.clone(),
|
||||||
|
previous_expr,
|
||||||
|
);
|
||||||
|
|
||||||
return self.process_completion(
|
return self.process_completion(
|
||||||
&mut completer,
|
&mut completer,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::completions::{Completer, CompletionOptions};
|
use crate::completions::{Completer, CompletionOptions};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
engine::{EngineState, StateWorkingSet},
|
engine::{EngineState, Stack, StateWorkingSet},
|
||||||
Span,
|
Span,
|
||||||
};
|
};
|
||||||
use reedline::Suggestion;
|
use reedline::Suggestion;
|
||||||
@ -9,11 +9,17 @@ use std::sync::Arc;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct VariableCompletion {
|
pub struct VariableCompletion {
|
||||||
engine_state: Arc<EngineState>,
|
engine_state: Arc<EngineState>,
|
||||||
|
stack: Stack,
|
||||||
|
previous_expr: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VariableCompletion {
|
impl VariableCompletion {
|
||||||
pub fn new(engine_state: Arc<EngineState>) -> Self {
|
pub fn new(engine_state: Arc<EngineState>, stack: Stack, previous_expr: Vec<u8>) -> Self {
|
||||||
Self { engine_state }
|
Self {
|
||||||
|
engine_state,
|
||||||
|
stack,
|
||||||
|
previous_expr,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,10 +33,30 @@ impl Completer for VariableCompletion {
|
|||||||
_: usize,
|
_: usize,
|
||||||
) -> (Vec<Suggestion>, CompletionOptions) {
|
) -> (Vec<Suggestion>, CompletionOptions) {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
|
||||||
let builtins = ["$nu", "$in", "$config", "$env", "$nothing"];
|
let builtins = ["$nu", "$in", "$config", "$env", "$nothing"];
|
||||||
|
let previous_expr_str = std::str::from_utf8(&self.previous_expr)
|
||||||
|
.unwrap_or("")
|
||||||
|
.to_lowercase();
|
||||||
|
|
||||||
|
// Completions for the given variable (e.g: $env.<tab> for completing $env.SOMETHING)
|
||||||
|
if !self.previous_expr.is_empty() && previous_expr_str.as_str() == "$env" {
|
||||||
|
for env_var in self.stack.get_env_vars(&self.engine_state) {
|
||||||
|
output.push(Suggestion {
|
||||||
|
value: env_var.0,
|
||||||
|
description: None,
|
||||||
|
extra: None,
|
||||||
|
span: reedline::Span {
|
||||||
|
start: span.start - offset,
|
||||||
|
end: span.end - offset,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (output, CompletionOptions::default());
|
||||||
|
}
|
||||||
|
|
||||||
for builtin in builtins {
|
for builtin in builtins {
|
||||||
|
// Variable completion (e.g: $en<tab> to complete $env)
|
||||||
if builtin.as_bytes().starts_with(&prefix) {
|
if builtin.as_bytes().starts_with(&prefix) {
|
||||||
output.push(Suggestion {
|
output.push(Suggestion {
|
||||||
value: builtin.to_string(),
|
value: builtin.to_string(),
|
||||||
@ -44,6 +70,7 @@ impl Completer for VariableCompletion {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Working set scope vars
|
||||||
for scope in &working_set.delta.scope {
|
for scope in &working_set.delta.scope {
|
||||||
for v in &scope.vars {
|
for v in &scope.vars {
|
||||||
if v.0.starts_with(&prefix) {
|
if v.0.starts_with(&prefix) {
|
||||||
@ -59,6 +86,8 @@ impl Completer for VariableCompletion {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Permanent state vars
|
||||||
for scope in &self.engine_state.scope {
|
for scope in &self.engine_state.scope {
|
||||||
for v in &scope.vars {
|
for v in &scope.vars {
|
||||||
if v.0.starts_with(&prefix) {
|
if v.0.starts_with(&prefix) {
|
||||||
|
@ -1233,6 +1233,16 @@ impl<'a> StateWorkingSet<'a> {
|
|||||||
self.permanent_state.env_vars.get(name)
|
self.permanent_state.env_vars.get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn list_env(&self) -> Vec<String> {
|
||||||
|
let mut env_vars = vec![];
|
||||||
|
|
||||||
|
for env_var in self.permanent_state.env_vars.clone().into_iter() {
|
||||||
|
env_vars.push(env_var.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
env_vars
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_variable_type(&mut self, var_id: VarId, ty: Type) {
|
pub fn set_variable_type(&mut self, var_id: VarId, ty: Type) {
|
||||||
let num_permanent_vars = self.permanent_state.num_vars();
|
let num_permanent_vars = self.permanent_state.num_vars();
|
||||||
if var_id < num_permanent_vars {
|
if var_id < num_permanent_vars {
|
||||||
|
Loading…
Reference in New Issue
Block a user