11use crate :: completions:: {
2- CommandCompletion , Completer , CompletionOptions , CustomCompletion , DirectoryCompletion ,
3- DotNuCompletion , FileCompletion , FlagCompletion , OperatorCompletion , VariableCompletion ,
2+ CellPathCompletion , CommandCompletion , Completer , CompletionOptions , CustomCompletion ,
3+ DirectoryCompletion , DotNuCompletion , FileCompletion , FlagCompletion , OperatorCompletion ,
4+ VariableNameCompletion ,
45} ;
56use log:: debug;
67use nu_color_config:: { color_record_to_nustyle, lookup_ansi_color_style} ;
@@ -17,6 +18,10 @@ use std::{str, sync::Arc};
1718
1819use super :: base:: { SemanticSuggestion , SuggestionKind } ;
1920
21+ /// Used as the function `f` in find_map Traverse
22+ ///
23+ /// returns the inner-most pipeline_element of interest
24+ /// i.e. the one that contains given position and needs completion
2025fn find_pipeline_element_by_position < ' a > (
2126 expr : & ' a Expression ,
2227 working_set : & ' a StateWorkingSet ,
@@ -62,6 +67,15 @@ fn find_pipeline_element_by_position<'a>(
6267 }
6368}
6469
70+ /// Before completion, an additional character `a` is added to the source as a placeholder for correct parsing results.
71+ /// This function helps to strip it
72+ fn strip_placeholder < ' a > ( working_set : & ' a StateWorkingSet , span : & Span ) -> ( Span , & ' a [ u8 ] ) {
73+ let new_end = std:: cmp:: max ( span. end - 1 , span. start ) ;
74+ let new_span = Span :: new ( span. start , new_end) ;
75+ let prefix = working_set. get_span_contents ( new_span) ;
76+ ( new_span, prefix)
77+ }
78+
6579#[ derive( Clone ) ]
6680pub struct NuCompleter {
6781 engine_state : Arc < EngineState > ,
@@ -80,6 +94,28 @@ impl NuCompleter {
8094 self . completion_helper ( line, pos)
8195 }
8296
97+ fn variable_names_completion_helper (
98+ & self ,
99+ working_set : & StateWorkingSet ,
100+ span : Span ,
101+ offset : usize ,
102+ ) -> Vec < SemanticSuggestion > {
103+ let ( new_span, prefix) = strip_placeholder ( working_set, & span) ;
104+ if !prefix. starts_with ( b"$" ) {
105+ return vec ! [ ] ;
106+ }
107+ let mut variable_names_completer = VariableNameCompletion { } ;
108+ self . process_completion (
109+ & mut variable_names_completer,
110+ working_set,
111+ prefix,
112+ new_span,
113+ offset,
114+ // pos is not required
115+ 0 ,
116+ )
117+ }
118+
83119 // Process the completion for a given completer
84120 fn process_completion < T : Completer > (
85121 & self ,
@@ -193,6 +229,37 @@ impl NuCompleter {
193229 return vec ! [ ] ;
194230 } ;
195231
232+ match & element_expression. expr {
233+ Expr :: Var ( _) => {
234+ return self . variable_names_completion_helper (
235+ & working_set,
236+ element_expression. span ,
237+ fake_offset,
238+ ) ;
239+ }
240+ Expr :: FullCellPath ( full_cell_path) => {
241+ // e.g. `$e<tab>` parsed as FullCellPath
242+ if full_cell_path. tail . is_empty ( ) {
243+ return self . variable_names_completion_helper (
244+ & working_set,
245+ element_expression. span ,
246+ fake_offset,
247+ ) ;
248+ } else {
249+ let mut cell_path_completer = CellPathCompletion { full_cell_path } ;
250+ return self . process_completion (
251+ & mut cell_path_completer,
252+ & working_set,
253+ & [ ] ,
254+ element_expression. span ,
255+ fake_offset,
256+ pos,
257+ ) ;
258+ }
259+ }
260+ _ => ( ) ,
261+ }
262+
196263 let flattened = flatten_expression ( & working_set, element_expression) ;
197264 let mut spans: Vec < String > = vec ! [ ] ;
198265
@@ -223,46 +290,13 @@ impl NuCompleter {
223290
224291 // Complete based on the last span
225292 if is_last_span {
226- // Context variables
227- let most_left_var = most_left_variable ( flat_idx, & working_set, flattened. clone ( ) ) ;
228-
229293 // Create a new span
230294 let new_span = Span :: new ( span. start , span. end - 1 ) ;
231295
232296 // Parses the prefix. Completion should look up to the cursor position, not after.
233297 let index = pos - span. start ;
234298 let prefix = & current_span[ ..index] ;
235299
236- // Variables completion
237- if prefix. starts_with ( b"$" ) || most_left_var. is_some ( ) {
238- let mut variable_names_completer =
239- VariableCompletion :: new ( most_left_var. unwrap_or ( ( vec ! [ ] , vec ! [ ] ) ) ) ;
240-
241- let mut variable_completions = self . process_completion (
242- & mut variable_names_completer,
243- & working_set,
244- prefix,
245- new_span,
246- fake_offset,
247- pos,
248- ) ;
249-
250- let mut variable_operations_completer =
251- OperatorCompletion :: new ( element_expression. clone ( ) ) ;
252-
253- let mut variable_operations_completions = self . process_completion (
254- & mut variable_operations_completer,
255- & working_set,
256- prefix,
257- new_span,
258- fake_offset,
259- pos,
260- ) ;
261-
262- variable_completions. append ( & mut variable_operations_completions) ;
263- return variable_completions;
264- }
265-
266300 // Flags completion
267301 if prefix. starts_with ( b"-" ) {
268302 // Try to complete flag internally
@@ -474,56 +508,6 @@ impl ReedlineCompleter for NuCompleter {
474508 }
475509}
476510
477- // reads the most left variable returning it's name (e.g: $myvar)
478- // and the depth (a.b.c)
479- fn most_left_variable (
480- idx : usize ,
481- working_set : & StateWorkingSet < ' _ > ,
482- flattened : Vec < ( Span , FlatShape ) > ,
483- ) -> Option < ( Vec < u8 > , Vec < Vec < u8 > > ) > {
484- // Reverse items to read the list backwards and truncate
485- // because the only items that matters are the ones before the current index
486- let mut rev = flattened;
487- rev. truncate ( idx) ;
488- rev = rev. into_iter ( ) . rev ( ) . collect ( ) ;
489-
490- // Store the variables and sub levels found and reverse to correct order
491- let mut variables_found: Vec < Vec < u8 > > = vec ! [ ] ;
492- let mut found_var = false ;
493- for item in rev. clone ( ) {
494- let result = working_set. get_span_contents ( item. 0 ) . to_vec ( ) ;
495-
496- match item. 1 {
497- FlatShape :: Variable ( _) => {
498- variables_found. push ( result) ;
499- found_var = true ;
500-
501- break ;
502- }
503- FlatShape :: String => {
504- variables_found. push ( result) ;
505- }
506- _ => {
507- break ;
508- }
509- }
510- }
511-
512- // If most left var was not found
513- if !found_var {
514- return None ;
515- }
516-
517- // Reverse the order back
518- variables_found = variables_found. into_iter ( ) . rev ( ) . collect ( ) ;
519-
520- // Extract the variable and the sublevels
521- let var = variables_found. first ( ) . unwrap_or ( & vec ! [ ] ) . to_vec ( ) ;
522- let sublevels: Vec < Vec < u8 > > = variables_found. into_iter ( ) . skip ( 1 ) . collect ( ) ;
523-
524- Some ( ( var, sublevels) )
525- }
526-
527511pub fn map_value_completions < ' a > (
528512 list : impl Iterator < Item = & ' a Value > ,
529513 span : Span ,
0 commit comments