+3
-2
src/cmd/ls.rs
+3
-2
src/cmd/ls.rs
···
98
98
} else {
99
99
// Non-glob path: check if it's a directory and list its contents
100
100
let normalized_path = path_str.trim_start_matches('/').trim_end_matches('/');
101
-
let target_path = base_path.join(normalized_path)
101
+
let target_path = base_path
102
+
.join(normalized_path)
102
103
.map_err(to_shell_err(call.arguments_span()))?;
103
-
104
+
104
105
let metadata = target_path.metadata().map_err(to_shell_err(span))?;
105
106
match metadata.file_type {
106
107
vfs::VfsFileType::Directory => {
+147
-84
src/completion/context.rs
+147
-84
src/completion/context.rs
···
1
1
use crate::completion::helpers::*;
2
-
use crate::completion::types::CompletionContext;
2
+
use crate::completion::types::{CompletionContext, CompletionKind};
3
3
use crate::console_log;
4
4
use nu_parser::FlatShape;
5
5
use nu_protocol::engine::{EngineState, StateWorkingSet};
···
122
122
if let Some((cmd_name, _)) =
123
123
find_command_and_arg_index(input, shapes, idx, local_span, global_offset)
124
124
{
125
-
CompletionContext::Flag {
125
+
CompletionContext {
126
+
kind: CompletionKind::Flag {
127
+
command_name: cmd_name,
128
+
},
126
129
prefix: trimmed_prefix.to_string(),
127
130
span,
128
-
command_name: cmd_name,
129
131
}
130
132
} else {
131
-
CompletionContext::Argument {
133
+
CompletionContext {
134
+
kind: CompletionKind::Argument,
132
135
prefix: prefix.to_string(),
133
136
span,
134
137
}
···
138
141
if let Some((cmd_name, arg_index)) =
139
142
find_command_and_arg_index(input, shapes, idx, local_span, global_offset)
140
143
{
141
-
CompletionContext::CommandArgument {
144
+
CompletionContext {
145
+
kind: CompletionKind::CommandArgument {
146
+
command_name: cmd_name,
147
+
arg_index,
148
+
},
142
149
prefix: trimmed_prefix.to_string(),
143
150
span,
144
-
command_name: cmd_name,
145
-
arg_index,
146
151
}
147
152
} else {
148
-
CompletionContext::Argument {
153
+
CompletionContext {
154
+
kind: CompletionKind::Argument,
149
155
prefix: prefix.to_string(),
150
156
span,
151
157
}
···
227
233
console_log!(
228
234
"[completion] {shape_name} is empty, showing subcommands of {cmd_name:?}"
229
235
);
230
-
Some(CompletionContext::Command {
236
+
Some(CompletionContext {
237
+
kind: CompletionKind::Command {
238
+
parent_command: Some(cmd_name),
239
+
},
231
240
prefix: String::new(),
232
241
span: adjusted_span,
233
-
parent_command: Some(cmd_name),
234
242
})
235
243
} else {
236
244
// Truly empty - show all commands
237
245
console_log!("[completion] {shape_name} is empty, setting Command context");
238
-
Some(CompletionContext::Command {
246
+
Some(CompletionContext {
247
+
kind: CompletionKind::Command {
248
+
parent_command: None,
249
+
},
239
250
prefix: String::new(),
240
251
span: adjusted_span,
241
-
parent_command: None,
242
252
})
243
253
}
244
254
} else if let Some(last_sep_pos) = last_sep_pos_in_prefix {
···
247
257
console_log!(
248
258
"[completion] {shape_name} has separator at {last_sep_pos}, after_sep={after_sep:?}, setting Command context"
249
259
);
250
-
Some(CompletionContext::Command {
260
+
Some(CompletionContext {
261
+
kind: CompletionKind::Command {
262
+
parent_command: None,
263
+
},
251
264
prefix: after_sep.to_string(),
252
265
span: Span::new(span.start + last_sep_pos, span.end),
253
-
parent_command: None,
254
266
})
255
267
} else {
256
268
console_log!(
···
270
282
console_log!(
271
283
"[completion] {shape_name}: Setting CellPath context with var {var_name:?}, prefix {cell_prefix:?}"
272
284
);
273
-
Some(CompletionContext::CellPath {
285
+
Some(CompletionContext {
286
+
kind: CompletionKind::CellPath {
287
+
var_id,
288
+
path_so_far: path_so_far.iter().map(|s| s.to_string()).collect(),
289
+
},
274
290
prefix: cell_prefix.to_string(),
275
291
span: Span::new(cell_span_start, adjusted_span.end),
276
-
var_id,
277
-
path_so_far: path_so_far.iter().map(|s| s.to_string()).collect(),
278
292
})
279
293
} else {
280
294
// Unknown variable, fall back to variable completion
···
282
296
console_log!(
283
297
"[completion] {shape_name}: Unknown var, setting Variable context with prefix {var_prefix:?}"
284
298
);
285
-
Some(CompletionContext::Variable {
299
+
Some(CompletionContext {
300
+
kind: CompletionKind::Variable,
286
301
prefix: var_prefix,
287
302
span: adjusted_span,
288
303
})
···
297
312
console_log!(
298
313
"[completion] {shape_name}: Setting Variable context with prefix {var_prefix:?}"
299
314
);
300
-
Some(CompletionContext::Variable {
315
+
Some(CompletionContext {
316
+
kind: CompletionKind::Variable,
301
317
prefix: var_prefix,
302
318
span: adjusted_span,
303
319
})
···
314
330
console_log!(
315
331
"[completion] {shape_name}: Found command {cmd_name:?} for flag completion"
316
332
);
317
-
Some(CompletionContext::Flag {
333
+
Some(CompletionContext {
334
+
kind: CompletionKind::Flag {
335
+
command_name: cmd_name,
336
+
},
318
337
prefix: trimmed.to_string(),
319
338
span: adjusted_span,
320
-
command_name: cmd_name,
321
339
})
322
340
} else {
323
-
Some(CompletionContext::Argument {
341
+
Some(CompletionContext {
342
+
kind: CompletionKind::Argument,
324
343
prefix: trimmed_prefix.to_string(),
325
344
span: adjusted_span,
326
345
})
···
337
356
console_log!(
338
357
"[completion] {shape_name}: Found command {cmd_name:?} with arg_index {arg_index} for argument completion"
339
358
);
340
-
Some(CompletionContext::CommandArgument {
359
+
Some(CompletionContext {
360
+
kind: CompletionKind::CommandArgument {
361
+
command_name: cmd_name,
362
+
arg_index,
363
+
},
341
364
prefix: trimmed.to_string(),
342
365
span: adjusted_span,
343
-
command_name: cmd_name,
344
-
arg_index,
345
366
})
346
367
} else {
347
368
// No command found, treat as regular argument
348
369
console_log!(
349
370
"[completion] {shape_name}: No command found, using Argument context"
350
371
);
351
-
Some(CompletionContext::Argument {
372
+
Some(CompletionContext {
373
+
kind: CompletionKind::Argument,
352
374
prefix: trimmed_prefix.to_string(),
353
375
span: adjusted_span,
354
376
})
···
392
414
console_log!(
393
415
"[completion] Detected cell path from Variable+String shapes, var_id={var_id:?}, prefix={cell_prefix:?}, path={path_so_far:?}"
394
416
);
395
-
Some(CompletionContext::CellPath {
417
+
Some(CompletionContext {
418
+
kind: CompletionKind::CellPath {
419
+
var_id,
420
+
path_so_far: path_so_far.iter().map(|s| s.to_string()).collect(),
421
+
},
396
422
prefix: cell_prefix.to_string(),
397
423
span: Span::new(cell_span_start, span.end),
398
-
var_id,
399
-
path_so_far: path_so_far.iter().map(|s| s.to_string()).collect(),
400
424
})
401
425
} else {
402
426
// Gap between shapes, use helper to determine context
···
434
458
global_offset: usize,
435
459
) -> Option<CompletionContext> {
436
460
if idx == 0 {
437
-
return Some(CompletionContext::Argument {
461
+
return Some(CompletionContext {
462
+
kind: CompletionKind::Argument,
438
463
prefix: prefix.to_string(),
439
464
span,
440
465
});
···
460
485
console_log!(
461
486
"[completion] Detected cell path from adjacent Variable shape, var_id={var_id:?}, prefix={cell_prefix:?}"
462
487
);
463
-
Some(CompletionContext::CellPath {
488
+
Some(CompletionContext {
489
+
kind: CompletionKind::CellPath {
490
+
var_id,
491
+
path_so_far: path_so_far.iter().map(|s| s.to_string()).collect(),
492
+
},
464
493
prefix: cell_prefix.to_string(),
465
494
span: Span::new(cell_span_start, span.end),
466
-
var_id,
467
-
path_so_far: path_so_far.iter().map(|s| s.to_string()).collect(),
468
495
})
469
496
} else {
470
497
// Gap between shapes, fall through to default handling
471
-
Some(CompletionContext::Argument {
498
+
Some(CompletionContext {
499
+
kind: CompletionKind::Argument,
472
500
prefix: prefix.to_string(),
473
501
span,
474
502
})
475
503
}
476
504
} else {
477
505
// Previous shape is not a Variable, this is likely a file path starting with .
478
-
Some(CompletionContext::Argument {
506
+
Some(CompletionContext {
507
+
kind: CompletionKind::Argument,
479
508
prefix: prefix.to_string(),
480
509
span,
481
510
})
···
518
547
if trimmed_prefix == "{" {
519
548
// We're right after '{' - command context
520
549
if let Some((_, adjusted_span, _)) = handle_block_prefix(&prefix, span) {
521
-
return Some(CompletionContext::Command {
550
+
return Some(CompletionContext {
551
+
kind: CompletionKind::Command {
552
+
parent_command: None,
553
+
},
522
554
prefix: String::new(),
523
555
span: adjusted_span,
524
-
parent_command: None,
525
556
});
526
557
}
527
558
} else {
···
577
608
// Calculate span for the cell path member being completed
578
609
let prefix_byte_len = cell_prefix.len();
579
610
let cell_span_start = span.end.saturating_sub(prefix_byte_len);
580
-
return Some(CompletionContext::CellPath {
611
+
return Some(CompletionContext {
612
+
kind: CompletionKind::CellPath {
613
+
var_id,
614
+
path_so_far: path_so_far
615
+
.iter()
616
+
.map(|s| s.to_string())
617
+
.collect(),
618
+
},
581
619
prefix: cell_prefix.to_string(),
582
620
span: Span::new(cell_span_start, span.end),
583
-
var_id,
584
-
path_so_far: path_so_far
585
-
.iter()
586
-
.map(|s| s.to_string())
587
-
.collect(),
588
621
});
589
622
} else {
590
623
// Unknown variable, fall back to variable completion
591
624
let var_prefix = trimmed_prefix[1..].to_string();
592
-
return Some(CompletionContext::Variable {
625
+
return Some(CompletionContext {
626
+
kind: CompletionKind::Variable,
593
627
prefix: var_prefix,
594
628
span,
595
629
});
···
601
635
} else {
602
636
String::new()
603
637
};
604
-
return Some(CompletionContext::Variable {
638
+
return Some(CompletionContext {
639
+
kind: CompletionKind::Variable,
605
640
prefix: var_prefix,
606
641
span,
607
642
});
···
610
645
_ if is_command_shape(input, shape, local_span) => {
611
646
let (full_prefix, full_span) =
612
647
build_command_prefix(input, shapes, idx, span, &prefix, global_offset);
613
-
return Some(CompletionContext::Command {
648
+
return Some(CompletionContext {
649
+
kind: CompletionKind::Command {
650
+
parent_command: None,
651
+
},
614
652
prefix: full_prefix,
615
653
span: full_span,
616
-
parent_command: None,
617
654
});
618
655
}
619
656
FlatShape::Block | FlatShape::Closure => {
···
641
678
{
642
679
let prefix_byte_len = cell_prefix.len();
643
680
let cell_span_start = span.end.saturating_sub(prefix_byte_len);
644
-
return Some(CompletionContext::CellPath {
681
+
return Some(CompletionContext {
682
+
kind: CompletionKind::CellPath {
683
+
var_id: *var_id,
684
+
path_so_far: path_so_far
685
+
.iter()
686
+
.map(|s| s.to_string())
687
+
.collect(),
688
+
},
645
689
prefix: cell_prefix.to_string(),
646
690
span: Span::new(cell_span_start, span.end),
647
-
var_id: *var_id,
648
-
path_so_far: path_so_far
649
-
.iter()
650
-
.map(|s| s.to_string())
651
-
.collect(),
652
691
});
653
692
} else {
654
693
// Simple variable completion
655
694
let var_prefix = trimmed_prefix[1..].to_string();
656
-
return Some(CompletionContext::Variable {
695
+
return Some(CompletionContext {
696
+
kind: CompletionKind::Variable,
657
697
prefix: var_prefix,
658
698
span,
659
699
});
660
700
}
661
701
} else {
662
702
// Fallback to argument context if no $ found
663
-
return Some(CompletionContext::Argument {
703
+
return Some(CompletionContext {
704
+
kind: CompletionKind::Argument,
664
705
prefix: prefix.to_string(),
665
706
span,
666
707
});
···
678
719
if let Some(var_id) = var_id {
679
720
let prefix_byte_len = cell_prefix.len();
680
721
let cell_span_start = span.end.saturating_sub(prefix_byte_len);
681
-
return Some(CompletionContext::CellPath {
722
+
return Some(CompletionContext {
723
+
kind: CompletionKind::CellPath {
724
+
var_id,
725
+
path_so_far: path_so_far
726
+
.iter()
727
+
.map(|s| s.to_string())
728
+
.collect(),
729
+
},
682
730
prefix: cell_prefix.to_string(),
683
731
span: Span::new(cell_span_start, span.end),
684
-
var_id,
685
-
path_so_far: path_so_far
686
-
.iter()
687
-
.map(|s| s.to_string())
688
-
.collect(),
689
732
});
690
733
} else {
691
734
let var_prefix = trimmed_prefix[1..].to_string();
692
-
return Some(CompletionContext::Variable {
735
+
return Some(CompletionContext {
736
+
kind: CompletionKind::Variable,
693
737
prefix: var_prefix,
694
738
span,
695
739
});
···
701
745
} else {
702
746
String::new()
703
747
};
704
-
return Some(CompletionContext::Variable {
748
+
return Some(CompletionContext {
749
+
kind: CompletionKind::Variable,
705
750
prefix: var_prefix,
706
751
span,
707
752
});
···
810
855
"[completion] Right after command {cmd_name:?}, setting CommandArgument context with arg_index: {arg_count}"
811
856
);
812
857
813
-
context.push(CompletionContext::CommandArgument {
858
+
context.push(CompletionContext {
859
+
kind: CompletionKind::CommandArgument {
860
+
command_name: cmd_name.clone(),
861
+
arg_index: arg_count,
862
+
},
814
863
prefix: String::new(),
815
864
span: Span::new(byte_pos, byte_pos),
816
-
command_name: cmd_name.clone(),
817
-
arg_index: arg_count,
818
865
});
819
866
}
820
867
}
···
830
877
console_log!(
831
878
"[completion] Command {cmd_name:?} has no positional args, showing subcommands"
832
879
);
833
-
context.push(CompletionContext::Command {
880
+
context.push(CompletionContext {
881
+
kind: CompletionKind::Command {
882
+
parent_command: Some(cmd_first_word),
883
+
},
834
884
prefix: String::new(),
835
885
span: Span::new(byte_pos, byte_pos),
836
-
parent_command: Some(cmd_first_word),
837
886
});
838
887
}
839
888
// reverse to put subcommands in the beginning
···
842
891
} else {
843
892
// Not right after command, complete the command itself
844
893
console_log!("[completion] Set Command context with prefix: {cmd:?}");
845
-
return vec![CompletionContext::Command {
894
+
return vec![CompletionContext {
895
+
kind: CompletionKind::Command {
896
+
parent_command: None,
897
+
},
846
898
prefix: cmd.to_string(),
847
899
span: local_span,
848
-
parent_command: None,
849
900
}];
850
901
}
851
902
}
···
902
953
console_log!("[completion] last_word_start={last_word_start}, last_word={last_word:?}");
903
954
904
955
if is_cmd_context {
905
-
vec![CompletionContext::Command {
956
+
vec![CompletionContext {
957
+
kind: CompletionKind::Command {
958
+
parent_command: None,
959
+
},
906
960
prefix: last_word.to_string(),
907
961
span: Span::new(last_word_start, byte_pos),
908
-
parent_command: None,
909
962
}]
910
963
} else {
911
964
// Check if this is a variable or cell path (starts with $)
···
918
971
if let Some(var_id) = var_id {
919
972
let prefix_byte_len = cell_prefix.len();
920
973
let cell_span_start = byte_pos.saturating_sub(prefix_byte_len);
921
-
vec![CompletionContext::CellPath {
974
+
vec![CompletionContext {
975
+
kind: CompletionKind::CellPath {
976
+
var_id,
977
+
path_so_far: path_so_far.iter().map(|s| s.to_string()).collect(),
978
+
},
922
979
prefix: cell_prefix.to_string(),
923
980
span: Span::new(cell_span_start, byte_pos),
924
-
var_id,
925
-
path_so_far: path_so_far.iter().map(|s| s.to_string()).collect(),
926
981
}]
927
982
} else {
928
983
let var_prefix = trimmed_word[1..].to_string();
929
-
vec![CompletionContext::Variable {
984
+
vec![CompletionContext {
985
+
kind: CompletionKind::Variable,
930
986
prefix: var_prefix,
931
987
span: Span::new(last_word_start, byte_pos),
932
988
}]
···
934
990
} else {
935
991
// Simple variable completion
936
992
let var_prefix = trimmed_word[1..].to_string();
937
-
vec![CompletionContext::Variable {
993
+
vec![CompletionContext {
994
+
kind: CompletionKind::Variable,
938
995
prefix: var_prefix,
939
996
span: Span::new(last_word_start, byte_pos),
940
997
}]
···
952
1009
}
953
1010
}
954
1011
if let Some(cmd_name) = found_cmd {
955
-
vec![CompletionContext::Flag {
1012
+
vec![CompletionContext {
1013
+
kind: CompletionKind::Flag {
1014
+
command_name: cmd_name,
1015
+
},
956
1016
prefix: trimmed_word.to_string(),
957
1017
span: Span::new(last_word_start, byte_pos),
958
-
command_name: cmd_name,
959
1018
}]
960
1019
} else {
961
-
vec![CompletionContext::Argument {
1020
+
vec![CompletionContext {
1021
+
kind: CompletionKind::Argument,
962
1022
prefix: last_word.to_string(),
963
1023
span: Span::new(last_word_start, byte_pos),
964
1024
}]
···
985
1045
}
986
1046
}
987
1047
if let Some(cmd_name) = found_cmd {
988
-
vec![CompletionContext::CommandArgument {
1048
+
vec![CompletionContext {
1049
+
kind: CompletionKind::CommandArgument {
1050
+
command_name: cmd_name,
1051
+
arg_index: arg_count,
1052
+
},
989
1053
prefix: trimmed_word.to_string(),
990
1054
span: Span::new(last_word_start, byte_pos),
991
-
command_name: cmd_name,
992
-
arg_index: arg_count,
993
1055
}]
994
1056
} else {
995
-
vec![CompletionContext::Argument {
1057
+
vec![CompletionContext {
1058
+
kind: CompletionKind::Argument,
996
1059
prefix: last_word.to_string(),
997
1060
span: Span::new(last_word_start, byte_pos),
998
1061
}]
+5
-1
src/completion/mod.rs
+5
-1
src/completion/mod.rs
···
73
73
global_offset,
74
74
);
75
75
76
+
// Convert Vec to HashSet
77
+
use std::collections::HashSet;
78
+
let context_set: HashSet<CompletionContext> = context.into_iter().collect();
79
+
76
80
// Generate suggestions based on context
77
81
let suggestions = generate_suggestions(
78
82
&input,
79
-
context,
83
+
context_set,
80
84
&working_set,
81
85
&engine_guard,
82
86
&stack_guard,
+54
-38
src/completion/suggestions.rs
+54
-38
src/completion/suggestions.rs
···
1
1
use crate::completion::context::get_command_signature;
2
2
use crate::completion::helpers::to_char_span;
3
-
use crate::completion::types::{CompletionContext, Suggestion};
3
+
use crate::completion::types::{CompletionContext, CompletionKind, Suggestion};
4
4
use crate::completion::variables::*;
5
5
use crate::console_log;
6
6
use nu_protocol::Span;
7
7
use nu_protocol::engine::{EngineState, Stack, StateWorkingSet};
8
+
use std::collections::HashSet;
8
9
9
10
pub fn generate_command_suggestions(
10
11
input: &str,
···
205
206
);
206
207
207
208
let mut suggestions = Vec::new();
208
-
209
+
209
210
// If we're at argument index 0, check if the command has subcommands and add them
210
211
if arg_index == 0 {
211
212
let parent_prefix = format!("{} ", command_name);
···
214
215
} else {
215
216
format!("{}{}", parent_prefix, prefix)
216
217
};
217
-
218
+
218
219
let subcommands = working_set
219
220
.find_commands_by_predicate(|value| value.starts_with(search_prefix.as_bytes()), true);
220
-
221
+
221
222
if !subcommands.is_empty() {
222
223
// Command has subcommands - add them to suggestions
223
224
console_log!(
···
229
230
if let Some(subcommand_name) = name_str.strip_prefix(&parent_prefix) {
230
231
suggestions.push(Suggestion {
231
232
rendered: {
232
-
let name_colored = ansi_term::Color::Green.bold().paint(subcommand_name);
233
+
let name_colored =
234
+
ansi_term::Color::Green.bold().paint(subcommand_name);
233
235
let desc_str = desc.as_deref().unwrap_or("<no description>");
234
236
format!("{name_colored} {desc_str}")
235
237
},
···
242
244
}
243
245
}
244
246
}
245
-
247
+
246
248
if let Some(signature) = get_command_signature(engine_guard, &command_name) {
247
249
// First, check if we're completing an argument for a flag
248
250
// Look backwards from the current position to find the previous flag
···
558
560
559
561
pub fn generate_suggestions(
560
562
input: &str,
561
-
contexts: Vec<CompletionContext>,
563
+
contexts: HashSet<CompletionContext>,
562
564
working_set: &StateWorkingSet,
563
565
engine_guard: &EngineState,
564
566
stack_guard: &Stack,
···
567
569
) -> Vec<Suggestion> {
568
570
console_log!("contexts: {contexts:?}");
569
571
572
+
let mut context_vec: Vec<_> = contexts.into_iter().collect();
573
+
context_vec.sort_by_key(|ctx| match &ctx.kind {
574
+
CompletionKind::Command { .. } => 0,
575
+
CompletionKind::Flag { .. } => 1,
576
+
CompletionKind::Variable => 2,
577
+
CompletionKind::CellPath { .. } => 3,
578
+
CompletionKind::CommandArgument { .. } => 4,
579
+
CompletionKind::Argument => 5,
580
+
});
581
+
570
582
let mut suggestions = Vec::new();
571
-
for context in contexts {
572
-
let mut sug = match context {
573
-
CompletionContext::Command {
574
-
prefix,
575
-
span,
576
-
parent_command,
577
-
} => generate_command_suggestions(input, working_set, prefix, span, parent_command),
578
-
CompletionContext::Argument { prefix, span } => {
579
-
generate_argument_suggestions(input, prefix, span, root)
583
+
for context in context_vec.iter() {
584
+
let mut sug = match &context.kind {
585
+
CompletionKind::Command { parent_command } => generate_command_suggestions(
586
+
input,
587
+
working_set,
588
+
context.prefix.clone(),
589
+
context.span,
590
+
parent_command.clone(),
591
+
),
592
+
CompletionKind::Argument => {
593
+
generate_argument_suggestions(input, context.prefix.clone(), context.span, root)
580
594
}
581
-
CompletionContext::Flag {
582
-
prefix,
583
-
span,
584
-
command_name,
585
-
} => generate_flag_suggestions(input, engine_guard, prefix, span, command_name),
586
-
CompletionContext::CommandArgument {
587
-
prefix,
588
-
span,
595
+
CompletionKind::Flag { command_name } => generate_flag_suggestions(
596
+
input,
597
+
engine_guard,
598
+
context.prefix.clone(),
599
+
context.span,
600
+
command_name.clone(),
601
+
),
602
+
CompletionKind::CommandArgument {
589
603
command_name,
590
604
arg_index,
591
605
} => generate_command_argument_suggestions(
592
606
input,
593
607
engine_guard,
594
608
working_set,
595
-
prefix,
596
-
span,
597
-
command_name,
598
-
arg_index,
609
+
context.prefix.clone(),
610
+
context.span,
611
+
command_name.clone(),
612
+
*arg_index,
599
613
root,
600
614
),
601
-
CompletionContext::Variable { prefix, span } => {
602
-
generate_variable_suggestions(input, working_set, prefix, span, byte_pos)
603
-
}
604
-
CompletionContext::CellPath {
605
-
prefix,
606
-
span,
615
+
CompletionKind::Variable => generate_variable_suggestions(
616
+
input,
617
+
working_set,
618
+
context.prefix.clone(),
619
+
context.span,
620
+
byte_pos,
621
+
),
622
+
CompletionKind::CellPath {
607
623
var_id,
608
624
path_so_far,
609
625
} => generate_cell_path_suggestions(
···
611
627
working_set,
612
628
engine_guard,
613
629
stack_guard,
614
-
prefix,
615
-
span,
616
-
var_id,
617
-
path_so_far,
630
+
context.prefix.clone(),
631
+
context.span,
632
+
*var_id,
633
+
path_so_far.clone(),
618
634
),
619
635
};
620
636
suggestions.append(&mut sug);
+44
-18
src/completion/types.rs
+44
-18
src/completion/types.rs
···
27
27
}
28
28
}
29
29
30
-
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
31
-
pub enum CompletionContext {
30
+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
31
+
pub enum CompletionKind {
32
32
Command {
33
-
prefix: String,
34
-
span: Span,
35
33
parent_command: Option<String>, // If Some, only show subcommands of this command
36
34
},
37
-
Argument {
38
-
prefix: String,
39
-
span: Span,
40
-
},
35
+
Argument,
41
36
Flag {
42
-
prefix: String,
43
-
span: Span,
44
37
command_name: String,
45
38
},
46
39
CommandArgument {
47
-
prefix: String,
48
-
span: Span,
49
40
command_name: String,
50
41
arg_index: usize,
51
42
},
52
-
Variable {
53
-
prefix: String, // without the $ prefix
54
-
span: Span,
55
-
},
43
+
Variable, // prefix is without the $ prefix
56
44
CellPath {
57
-
prefix: String, // the partial field name being typed (after the last dot)
58
-
span: Span, // replacement span
59
45
var_id: nu_protocol::VarId, // variable ID for evaluation
60
46
path_so_far: Vec<String>, // path members accessed before current one
61
47
},
62
48
}
49
+
50
+
#[derive(Debug)]
51
+
pub struct CompletionContext {
52
+
pub kind: CompletionKind,
53
+
pub prefix: String, // the partial text being completed
54
+
pub span: Span,
55
+
}
56
+
57
+
impl PartialEq for CompletionContext {
58
+
fn eq(&self, other: &Self) -> bool {
59
+
self.kind == other.kind && self.prefix == other.prefix
60
+
}
61
+
}
62
+
63
+
impl Eq for CompletionContext {}
64
+
65
+
impl PartialOrd for CompletionContext {
66
+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
67
+
match self.kind.partial_cmp(&other.kind) {
68
+
Some(std::cmp::Ordering::Equal) => self.prefix.partial_cmp(&other.prefix),
69
+
other => other,
70
+
}
71
+
}
72
+
}
73
+
74
+
impl Ord for CompletionContext {
75
+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
76
+
match self.kind.cmp(&other.kind) {
77
+
std::cmp::Ordering::Equal => self.prefix.cmp(&other.prefix),
78
+
other => other,
79
+
}
80
+
}
81
+
}
82
+
83
+
impl std::hash::Hash for CompletionContext {
84
+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
85
+
self.kind.hash(state);
86
+
self.prefix.hash(state);
87
+
}
88
+
}