11use crate :: completions:: { file_path_completion, Completer , CompletionOptions } ;
2+ use nu_path:: expand_tilde;
23use nu_protocol:: {
34 engine:: { Stack , StateWorkingSet } ,
45 Span ,
@@ -28,7 +29,10 @@ impl Completer for DotNuCompletion {
2829 _pos : usize ,
2930 options : & CompletionOptions ,
3031 ) -> Vec < SemanticSuggestion > {
31- let prefix_str = String :: from_utf8_lossy ( prefix) . replace ( '`' , "" ) ;
32+ let prefix_str = String :: from_utf8_lossy ( prefix) ;
33+ let start_with_backquote = prefix_str. starts_with ( '`' ) ;
34+ let end_with_backquote = prefix_str. ends_with ( '`' ) ;
35+ let prefix_str = prefix_str. replace ( '`' , "" ) ;
3236 let mut search_dirs: Vec < PathBuf > = vec ! [ ] ;
3337
3438 // If prefix_str is only a word we want to search in the current dir
@@ -46,12 +50,8 @@ impl Completer for DotNuCompletion {
4650 lib_dirs
4751 . as_list ( )
4852 . into_iter ( )
49- . flat_map ( |it| {
50- it. iter ( ) . map ( |x| {
51- x. to_path ( )
52- . expect ( "internal error: failed to convert lib path" )
53- } )
54- } )
53+ . flat_map ( |it| it. iter ( ) . filter_map ( |x| x. to_path ( ) . ok ( ) ) )
54+ . map ( expand_tilde)
5555 . collect ( )
5656 } )
5757 . unwrap_or_default ( ) ;
@@ -78,13 +78,12 @@ impl Completer for DotNuCompletion {
7878
7979 // Fetch the files filtering the ones that ends with .nu
8080 // and transform them into suggestions
81-
8281 let completions = file_path_completion (
8382 span,
8483 partial,
8584 & search_dirs
8685 . iter ( )
87- . map ( |d| d. to_str ( ) . unwrap_or_default ( ) )
86+ . filter_map ( |d| d. to_str ( ) )
8887 . collect :: < Vec < _ > > ( ) ,
8988 options,
9089 working_set. permanent_state ,
@@ -93,20 +92,35 @@ impl Completer for DotNuCompletion {
9392 completions
9493 . into_iter ( )
9594 // Different base dir, so we list the .nu files or folders
96- . filter ( |it| it. path . ends_with ( ".nu" ) || it. path . ends_with ( SEP ) )
95+ . filter ( |it| {
96+ // for paths with spaces in them
97+ let path = it. path . trim_end_matches ( '`' ) ;
98+ path. ends_with ( ".nu" ) || path. ends_with ( SEP )
99+ } )
97100 . map ( |x| {
98- let append_whitespace = x. path . ends_with ( ".nu" ) ;
101+ let append_whitespace =
102+ x. path . ends_with ( ".nu" ) && ( !start_with_backquote || end_with_backquote) ;
99103 // Re-calculate the span to replace
100- let span_offset = if base_dir == "." {
101- 0
102- } else {
103- base_dir. len ( ) + 1
104- } + prefix. iter ( ) . take_while ( |c| * * c == b'`' ) . count ( ) ;
104+ let mut span_offset = 0 ;
105+ let mut value = x. path . to_string ( ) ;
106+ // Complete only the last path component
107+ if base_dir != "." {
108+ span_offset = base_dir. len ( ) + 1
109+ }
110+ // Retain only one '`'
111+ if start_with_backquote {
112+ value = value. trim_start_matches ( '`' ) . to_string ( ) ;
113+ span_offset += 1 ;
114+ }
115+ // Add the backquote back
116+ if end_with_backquote && !value. ends_with ( '`' ) {
117+ value. push ( '`' ) ;
118+ }
105119 let end = x. span . end - offset;
106120 let start = std:: cmp:: min ( end, x. span . start - offset + span_offset) ;
107121 SemanticSuggestion {
108122 suggestion : Suggestion {
109- value : x . path ,
123+ value,
110124 style : x. style ,
111125 span : reedline:: Span { start, end } ,
112126 append_whitespace,
0 commit comments