mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-27 16:51:15 -03:00
Also show case-insensitive prefix matches in completion pager
[ja: made some changes and added commit message] Fixes #7944 Closes #11910
This commit is contained in:
committed by
Johannes Altmanninger
parent
fceb600be5
commit
656b39a0b3
@@ -11,6 +11,7 @@ Interactive improvements
|
||||
------------------------
|
||||
- When typing immediately after starting fish, the first prompt is now rendered correctly.
|
||||
- Completion accuracy was improved for file paths containing ``=`` or ``:`` (:issue:`5363`).
|
||||
- Prefix-matching completions are now shown even if they don't have the case typed by the user (:issue:`7944`).
|
||||
|
||||
Improved terminal support
|
||||
-------------------------
|
||||
|
||||
@@ -110,6 +110,8 @@ pub struct CompleteFlags: u16 {
|
||||
const KEEP_VARIABLE_OVERRIDE_PREFIX = 1 << 8;
|
||||
/// This is a variable name.
|
||||
const VARIABLE_NAME = 1 << 9;
|
||||
/// Suppress showing the pager prefix for this completion.
|
||||
const SUPPRESS_PAGER_PREFIX = 1 << 10;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
37
src/pager.rs
37
src/pager.rs
@@ -6,7 +6,7 @@
|
||||
use crate::common::{
|
||||
EscapeFlags, EscapeStringStyle, escape_string, get_ellipsis_char, get_ellipsis_str,
|
||||
};
|
||||
use crate::complete::Completion;
|
||||
use crate::complete::{CompleteFlags, Completion};
|
||||
use crate::editable_line::EditableLine;
|
||||
use crate::highlight::{HighlightRole, HighlightSpec, highlight_shell};
|
||||
use crate::operation_context::OperationContext;
|
||||
@@ -349,6 +349,11 @@ fn measure_completion_infos(&mut self) {
|
||||
for comp in &mut self.unfiltered_completion_infos {
|
||||
let comp_strings = &mut comp.comp;
|
||||
|
||||
let show_prefix = !comp
|
||||
.representative
|
||||
.flags
|
||||
.contains(CompleteFlags::SUPPRESS_PAGER_PREFIX);
|
||||
|
||||
for (j, comp_string) in comp_strings.iter().enumerate() {
|
||||
// If there's more than one, append the length of ', '.
|
||||
if j >= 1 {
|
||||
@@ -357,7 +362,9 @@ fn measure_completion_infos(&mut self) {
|
||||
|
||||
// This can return -1 if it can't calculate the width. So be cautious.
|
||||
let comp_width = wcswidth_rendered(comp_string);
|
||||
comp.comp_width += usize::try_from(prefix_len).unwrap_or_default();
|
||||
if show_prefix {
|
||||
comp.comp_width += usize::try_from(prefix_len).unwrap_or_default();
|
||||
}
|
||||
comp.comp_width += usize::try_from(comp_width).unwrap_or_default();
|
||||
}
|
||||
|
||||
@@ -432,9 +439,13 @@ fn completion_print(
|
||||
let is_selected = Some(idx) == effective_selected_idx;
|
||||
|
||||
// Print this completion on its own "line".
|
||||
let show_prefix = !el
|
||||
.representative
|
||||
.flags
|
||||
.contains(CompleteFlags::SUPPRESS_PAGER_PREFIX);
|
||||
let mut line = self.completion_print_item(
|
||||
CharOffset::Pager(idx),
|
||||
prefix,
|
||||
show_prefix.then_some(prefix),
|
||||
el,
|
||||
col_width,
|
||||
row % 2 != 0,
|
||||
@@ -459,7 +470,7 @@ fn completion_print(
|
||||
fn completion_print_item(
|
||||
&self,
|
||||
offset_in_cmdline: CharOffset,
|
||||
prefix: &wstr,
|
||||
prefix: Option<&wstr>,
|
||||
c: &PagerComp,
|
||||
width: usize,
|
||||
secondary: bool,
|
||||
@@ -531,14 +542,16 @@ fn completion_print_item(
|
||||
);
|
||||
}
|
||||
|
||||
comp_remaining -= print_max(
|
||||
offset_in_cmdline,
|
||||
prefix,
|
||||
prefix_col,
|
||||
comp_remaining,
|
||||
!comp.is_empty(),
|
||||
&mut line_data,
|
||||
);
|
||||
if let Some(prefix) = prefix {
|
||||
comp_remaining -= print_max(
|
||||
offset_in_cmdline,
|
||||
prefix,
|
||||
prefix_col,
|
||||
comp_remaining,
|
||||
!comp.is_empty(),
|
||||
&mut line_data,
|
||||
);
|
||||
}
|
||||
comp_remaining -= print_max_impl(
|
||||
offset_in_cmdline,
|
||||
comp,
|
||||
|
||||
@@ -6646,8 +6646,16 @@ fn handle_completions(&mut self, token_range: Range<usize>) -> bool {
|
||||
|
||||
// Only use completions that match replace_token.
|
||||
let completion_replaces_token = c.flags.contains(CompleteFlags::REPLACES_TOKEN);
|
||||
let replaces_only_due_to_case_mismatch = {
|
||||
c.flags.contains(CompleteFlags::REPLACES_TOKEN)
|
||||
&& c.r#match.is_exact_or_prefix()
|
||||
&& !matches!(c.r#match.case_fold, CaseSensitivity::Sensitive)
|
||||
};
|
||||
if completion_replaces_token != will_replace_token {
|
||||
continue;
|
||||
// Keep smart/samecase results even if we prefer not to replace the token.
|
||||
if will_replace_token || !replaces_only_due_to_case_mismatch {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't use completions that want to replace, if we cannot replace them.
|
||||
@@ -6655,10 +6663,13 @@ fn handle_completions(&mut self, token_range: Range<usize>) -> bool {
|
||||
continue;
|
||||
}
|
||||
|
||||
// This completion survived.
|
||||
surviving_completions.push(c.clone());
|
||||
all_matches_exact_or_prefix =
|
||||
all_matches_exact_or_prefix && c.r#match.is_exact_or_prefix();
|
||||
all_matches_exact_or_prefix &= c.r#match.is_exact_or_prefix();
|
||||
|
||||
let mut completion = c.clone();
|
||||
if replaces_only_due_to_case_mismatch && !will_replace_token {
|
||||
completion.flags |= CompleteFlags::SUPPRESS_PAGER_PREFIX;
|
||||
}
|
||||
surviving_completions.push(completion);
|
||||
}
|
||||
|
||||
if surviving_completions.len() == 1 {
|
||||
@@ -6735,6 +6746,11 @@ fn handle_completions(&mut self, token_range: Range<usize>) -> bool {
|
||||
|
||||
if use_prefix {
|
||||
for c in &mut surviving_completions {
|
||||
if c.flags.contains(CompleteFlags::SUPPRESS_PAGER_PREFIX) {
|
||||
// Keep replacement semantics and the original prefix so these completions can
|
||||
// fix casing when selected.
|
||||
continue;
|
||||
}
|
||||
c.flags &= !CompleteFlags::REPLACES_TOKEN;
|
||||
c.completion.replace_range(0..common_prefix.len(), L!(""));
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ isolated-tmux send-keys 'HOME=$PWD ls ~/' Tab
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p
|
||||
# Note the contents may or may not have the autosuggestion appended - it is a race.
|
||||
# CHECK: prompt 0> HOME=$PWD ls ~/file-{{1?}}
|
||||
# CHECK: prompt {{\d+}}> HOME=$PWD ls ~/file-{{1?}}
|
||||
# CHECK: ~/file-1 ~/file-2
|
||||
|
||||
# No pager on single smartcase completion (#7738).
|
||||
@@ -21,7 +21,17 @@ isolated-tmux send-keys C-u C-l 'mkdir cmake CMakeFiles' Enter C-l \
|
||||
'cat cmake' Tab
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p
|
||||
# CHECK: prompt 1> cat cmake/
|
||||
# CHECK: prompt {{\d+}}> cat cmake/
|
||||
# CHECK: cmake/ CMakeFiles/
|
||||
|
||||
# Keep mixed-case completions visible when typing lowercase and ignore non-matching prefixes (#7944).
|
||||
isolated-tmux send-keys C-u C-l 'rm -rf dog Dodo Voodo' Enter \
|
||||
'mkdir dog Dodo Voodo docker doc_internal doc_src' Enter C-l \
|
||||
'cd do' Tab
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p
|
||||
# CHECK: prompt {{\d+}}> cd do{{(cker/)?}}
|
||||
# CHECK: docker/ doc_internal/ doc_src/ Dodo/ dog/
|
||||
|
||||
# Correct case in pager when prefixes differ in case (#7743).
|
||||
isolated-tmux send-keys C-u C-l 'complete -c foo2 -a "aabc aaBd" -f' Enter C-l \
|
||||
@@ -29,7 +39,7 @@ isolated-tmux send-keys C-u C-l 'complete -c foo2 -a "aabc aaBd" -f' Enter C-l \
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p
|
||||
# The "bc" part is the autosuggestion - we could use "capture-pane -e" to check colors.
|
||||
# CHECK: prompt 2> foo2 aabc
|
||||
# CHECK: prompt {{\d+}}> foo2 aabc
|
||||
# CHECK: aabc aaBd
|
||||
|
||||
# Check that a larger-than-screen completion list does not stomp a multiline commandline (#8509).
|
||||
@@ -39,7 +49,7 @@ isolated-tmux send-keys C-u 'complete -c foo3 -fa "(seq $LINES)\t(string repeat
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p | sed -n '1p;$p'
|
||||
# Assert that we didn't change the command line.
|
||||
# CHECK: prompt 3> begin
|
||||
# CHECK: prompt {{\d+}}> begin
|
||||
# Also ensure that the pager is actually fully disclosed.
|
||||
# CHECK: rows 1 to {{\d+}} of {{\d+}}
|
||||
|
||||
@@ -50,7 +60,7 @@ tmux-sleep
|
||||
isolated-tmux send-keys C-l foo2 Space BTab b BSpace b Escape
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p
|
||||
# CHECK: prompt 3> foo2 aa
|
||||
# CHECK: prompt {{\d+}}> foo2 aa
|
||||
|
||||
# Check that down-or-search works even when the pager is not selected.
|
||||
isolated-tmux send-keys C-u foo2 Space Tab
|
||||
@@ -59,7 +69,7 @@ isolated-tmux send-keys Down
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p
|
||||
# Also check that we show an autosuggestion.
|
||||
# CHECK: prompt 3> foo2 aabc aabc
|
||||
# CHECK: prompt {{\d+}}> foo2 aabc aabc
|
||||
# CHECK: aabc{{ *}}aaBd
|
||||
|
||||
# Check that a larger-than-screen completion does not break down-or-search.
|
||||
@@ -76,14 +86,14 @@ isolated-tmux capture-pane -p | head -1
|
||||
isolated-tmux send-keys C-u echo Space old-arg Enter C-l foo2 Space Tab Tab M-.
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p
|
||||
# CHECK: prompt 5> foo2 aabc old-arg
|
||||
# CHECK: prompt {{\d+}}> foo2 aabc old-arg
|
||||
|
||||
isolated-tmux send-keys C-u 'echo suggest this' Enter C-l
|
||||
tmux-sleep
|
||||
isolated-tmux send-keys 'echo sug' C-w C-z
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p
|
||||
# CHECK: prompt 6> echo suggest this
|
||||
# CHECK: prompt {{\d+}}> echo suggest this
|
||||
|
||||
isolated-tmux send-keys C-u 'bind ctrl-s forward-single-char' Enter C-l
|
||||
isolated-tmux send-keys 'echo suggest thi'
|
||||
@@ -93,7 +103,7 @@ tmux-sleep
|
||||
isolated-tmux send-keys C-s
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p
|
||||
# CHECK: prompt 7> echo suggest this
|
||||
# CHECK: prompt {{\d+}}> echo suggest this
|
||||
|
||||
isolated-tmux send-keys C-u
|
||||
isolated-tmux send-keys 'echo sugg' C-a
|
||||
@@ -101,7 +111,7 @@ tmux-sleep
|
||||
isolated-tmux send-keys C-e M-f Space nothing
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p
|
||||
# CHECK: prompt 7> echo suggest nothing
|
||||
# CHECK: prompt {{\d+}}> echo suggest nothing
|
||||
|
||||
isolated-tmux send-keys C-u 'bind \cs forward-char-passive' Enter C-l
|
||||
isolated-tmux send-keys C-u 'bind \cb backward-char-passive' Enter C-l
|
||||
@@ -111,8 +121,8 @@ isolated-tmux send-keys 'echo do not accept thi' C-b C-b DC C-b C-s 'h'
|
||||
tmux-sleep
|
||||
isolated-tmux send-keys C-s C-s C-s 'x'
|
||||
isolated-tmux capture-pane -p
|
||||
# CHECK: prompt 10> echo do not accept thix
|
||||
# CHECK: prompt {{\d+}}> echo do not accept thix
|
||||
isolated-tmux send-keys C-u C-l ': {*,' Tab Tab Space ,
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p
|
||||
# CHECK: prompt 10> : {*,cmake/ ,{{.*}}
|
||||
# CHECK: prompt {{\d+}}> : {*,cmake/ ,{{.*}}
|
||||
|
||||
Reference in New Issue
Block a user