Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/active_suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2158,6 +2158,15 @@ impl ActiveSuggestions {
idx: usize,
sug: &ProcessedSuggestion,
) -> Option<FilteredItem> {
if self.auto_started && self.comp_type == tab_completion_context::CompType::GlobExpansion {
// Dont fuzzy filter, always show everything
return Some(FilteredItem {
score: 0,
suggestion_idx: idx,
matching_indices: Vec::new(),
});
}

let pattern_with_prefix = &self.word_under_cursor.s;
let pattern = pattern_with_prefix
.strip_prefix(&sug.prefix)
Expand Down
2 changes: 2 additions & 0 deletions src/app/actions/mouse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ impl super::ContextVar for MouseContextVar {
Some(Tag::Suggestion(_))
| Some(Tag::TabSuggestion)
| Some(Tag::TabCompletionScrollBar { .. })
| Some(Tag::AutoCompletionTimeInfo)
),
MouseContextVar::IsOverFuzzyHistory => matches!(
clicked_tag,
Expand Down Expand Up @@ -337,6 +338,7 @@ fn is_pointer_target_tag(tag: Option<Tag>, right_click_popup_active: bool) -> bo
| Tag::TabCompletionScrollBar { .. }
| Tag::FlycompSandboxInfo
| Tag::FlycompInfo
| Tag::AutoCompletionTimeInfo
| Tag::RightClickCopy
| Tag::RightClickCut
| Tag::RightClickPaste
Expand Down
24 changes: 18 additions & 6 deletions src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ use crate::mouse_state::{MouseState, mouse_state};
use crate::palette::{ButtonState, Palette};
use crate::prompt_manager::PromptManager;
use crate::settings::{self, MatrixAnimation, MouseMode, Settings};
use crate::shell;
use crate::shell_integration;
use crate::{command_acceptance, dparser};
use crate::{shell, tab_completion_context};
use flybuffer::{SubString, TextBuffer};

use flash::lexer::TokenKind;
Expand Down Expand Up @@ -2118,8 +2118,12 @@ impl<'a> App<'a> {
Update,
}

let get_action = |app: &Self, new_wuc: &SubString| -> Option<CompletionAction> {
None
let get_action =
|app: &Self,
new_completion_context: &tab_completion_context::CompletionContext<'_>|
-> Option<CompletionAction> {
let new_wuc = &new_completion_context.word_under_cursor;
None
.or_else(|| {
mouse_state(|m| m.is_left_button_dragging())
// If we're dragging the mouse, we dont want to have tab completions
Expand Down Expand Up @@ -2232,6 +2236,12 @@ impl<'a> App<'a> {
new_wuc.s
);
Some(CompletionAction::Restart { carry_over: true })
} else if *new_wuc != *current_wuc && active_suggestions.auto_started && new_completion_context.comp_types().contains(&tab_completion_context::CompType::GlobExpansion) {
log::debug!(
"Word under cursor changed ('{:?}') and new completion context contains glob expansion so lets just restart to pick it up.",
new_wuc
);
Some(CompletionAction::Restart { carry_over: true })
} else if *new_wuc == *current_wuc {
log::debug!(
"Word under cursor unchanged ('{:?}'), keeping existing tab completion suggestions",
Expand Down Expand Up @@ -2272,10 +2282,12 @@ impl<'a> App<'a> {
_ => None,
}
})
};
};

let new_wuc = self.get_completion_context().word_under_cursor;
let action = get_action(self, &new_wuc).unwrap_or(CompletionAction::Keep);
let new_completion_context = self.get_completion_context();
let action =
get_action(self, &new_completion_context).unwrap_or(CompletionAction::Keep);
let new_wuc = new_completion_context.word_under_cursor;

match action {
CompletionAction::Keep => {}
Expand Down
123 changes: 119 additions & 4 deletions src/app/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,7 @@ impl<'a> App<'a> {
self.buffer.buffer(),
self.buffer.cursor_byte_pos(),
scrollbar_style,
terminal_height,
);
} else {
Self::render_user_suggestions(
Expand Down Expand Up @@ -958,6 +959,7 @@ impl<'a> App<'a> {
self.buffer.buffer(),
self.buffer.cursor_byte_pos(),
scrollbar_style,
terminal_height,
);
} else {
Self::render_user_suggestions(
Expand Down Expand Up @@ -1718,6 +1720,7 @@ impl<'a> App<'a> {
buffer: &str,
cursor_byte_pos: usize,
scrollbar_style: Style,
terminal_height: u16,
) {
let original_buf_len = content.buf.len();
content.newline();
Expand Down Expand Up @@ -1785,10 +1788,20 @@ impl<'a> App<'a> {

let source_str = format!(
"{:.1}ms",
// active_suggestions.comp_type.display_name(),
active_suggestions.load_time.as_secs_f32() * 1000.0,
);

let time_hover =
mouse_state(|m| m.last_mouse_over_cell_semantic) == Some(Tag::AutoCompletionTimeInfo);
let source_style = if time_hover {
settings
.colour_palette
.secondary_text()
.add_modifier(Modifier::UNDERLINED)
} else {
settings.colour_palette.secondary_text()
};

let min_box_width = (unicode_width::UnicodeWidthStr::width(status_prefix.as_str())
+ unicode_width::UnicodeWidthStr::width(source_str.as_str())
+ 4)
Expand Down Expand Up @@ -2027,12 +2040,15 @@ impl<'a> App<'a> {

let status_line = TaggedLine::from(vec![
TaggedSpan::new(
Span::styled(status_prefix, settings.colour_palette.secondary_text()),
Span::styled(
status_prefix.clone(),
settings.colour_palette.secondary_text(),
),
Tag::TabSuggestion,
),
TaggedSpan::new(
Span::styled(source_str, settings.colour_palette.secondary_text()),
Tag::TabSuggestion,
Span::styled(source_str, source_style),
Tag::AutoCompletionTimeInfo,
),
]);

Expand Down Expand Up @@ -2071,6 +2087,22 @@ impl<'a> App<'a> {
if content.buf.len() > final_buf_len {
content.buf.truncate(final_buf_len);
}

if time_hover {
let popup_style = settings.colour_palette.normal_text();
let comptype_msg = active_suggestions.comp_type.display_name();
let anchor_col =
(x + 2) + unicode_width::UnicodeWidthStr::width(status_prefix.as_str()) as u16;
let anchor_row = y + total_item_rows as u16 + 1;
content.draw_popup(
comptype_msg,
anchor_row + 1,
anchor_col,
terminal_height,
popup_style,
Tag::Normal,
);
}
}

fn render_auto_suggestions_loading(
Expand Down Expand Up @@ -2427,13 +2459,19 @@ mod tests {
);
}

static TEST_MOUSE_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());

#[test]
fn test_render_auto_suggestions_selected_wrapping_and_ellipsis() {
use crate::active_suggestions::{
ActiveSuggestions, ActiveSuggestionsBuilder, ProcessedSuggestion, SuggestionDescription,
};
use crate::mouse_state::mouse_state;
use crate::settings::Settings;

let _guard = TEST_MOUSE_LOCK.lock().unwrap();
mouse_state(|m| m.last_mouse_over_cell_semantic = None);

let mut settings = Settings::default();
settings.num_suggestion_rows = 5;
let mut content = Contents::new(40);
Expand Down Expand Up @@ -2484,6 +2522,7 @@ mod tests {
"", // buffer
0, // cursor_byte_pos
Style::default(), // scrollbar_style
20, // terminal_height
);

assert_eq!(
Expand Down Expand Up @@ -2517,8 +2556,12 @@ mod tests {
use crate::active_suggestions::{
ActiveSuggestions, ActiveSuggestionsBuilder, ProcessedSuggestion, SuggestionDescription,
};
use crate::mouse_state::mouse_state;
use crate::settings::Settings;

let _guard = TEST_MOUSE_LOCK.lock().unwrap();
mouse_state(|m| m.last_mouse_over_cell_semantic = None);

let settings = Settings::default();
let mut content = Contents::new(40);

Expand Down Expand Up @@ -2566,6 +2609,7 @@ mod tests {
"", // buffer
0, // cursor_byte_pos
Style::default(), // scrollbar_style
20, // terminal_height
);

assert_eq!(
Expand All @@ -2586,8 +2630,12 @@ mod tests {
use crate::active_suggestions::{
ActiveSuggestions, ActiveSuggestionsBuilder, ProcessedSuggestion, SuggestionDescription,
};
use crate::mouse_state::mouse_state;
use crate::settings::Settings;

let _guard = TEST_MOUSE_LOCK.lock().unwrap();
mouse_state(|m| m.last_mouse_over_cell_semantic = None);

let settings = Settings::default();
let mut content = Contents::new(40);

Expand Down Expand Up @@ -2635,6 +2683,7 @@ mod tests {
"", // buffer
0, // cursor_byte_pos
Style::default(), // scrollbar_style
20, // terminal_height
);

assert_eq!(
Expand Down Expand Up @@ -2670,8 +2719,12 @@ mod tests {
use crate::active_suggestions::{
ActiveSuggestions, ActiveSuggestionsBuilder, ProcessedSuggestion,
};
use crate::mouse_state::mouse_state;
use crate::settings::Settings;

let _guard = TEST_MOUSE_LOCK.lock().unwrap();
mouse_state(|m| m.last_mouse_over_cell_semantic = None);

let mut settings = Settings::default();
// Set maximum number of suggestion rows to 5
settings.num_suggestion_rows = 5;
Expand Down Expand Up @@ -2726,6 +2779,7 @@ mod tests {
"", // buffer
0, // cursor_byte_pos
Style::default(), // scrollbar_style
20, // terminal_height
);

assert_eq!(
Expand Down Expand Up @@ -2800,6 +2854,7 @@ mod tests {
"", // buffer
0, // cursor_byte_pos
Style::default(), // scrollbar_style
20, // terminal_height
);

// Nothing was drawn: no popup border on a zero-width terminal.
Expand Down Expand Up @@ -2846,4 +2901,64 @@ mod tests {
"no loading popup should be drawn at zero width",
);
}

#[test]
fn test_render_auto_suggestions_time_hover_shows_comptype_popup() {
use crate::active_suggestions::{
ActiveSuggestions, ActiveSuggestionsBuilder, ProcessedSuggestion,
};
use crate::mouse_state::mouse_state;
use crate::settings::Settings;

let _guard = TEST_MOUSE_LOCK.lock().unwrap();
let settings = Settings::default();
let mut content = Contents::new(40);

let builder = ActiveSuggestionsBuilder {
processed: vec![
ProcessedSuggestion::new("sug1", "", ""),
ProcessedSuggestion::new("sug2", "", ""),
],
unprocessed: std::collections::VecDeque::new(),
common_prefix: None,
auto_accept_if_solo: false,
insert_common_prefix: false,
comp_type: crate::tab_completion_context::CompType::FirstWord,
nosort: false,
compspec_was_useful: Some(true),
should_run_flycomp: false,
};

let mut active = ActiveSuggestions::new(
builder,
flybuffer::SubString::new("", "").unwrap(),
std::time::Duration::from_millis(0),
true, // auto_started
crate::settings::SuggestionSortOrder::default(),
crate::settings::FuzzyMode::default(),
);

// Simulate hovering over the time info tag
mouse_state(|m| m.last_mouse_over_cell_semantic = Some(Tag::AutoCompletionTimeInfo));

App::render_auto_suggestions(
&settings,
&mut active,
&mut content,
40, // width
20, // rows_left_before_end_of_screen
None, // cursor_pos_maybe
"", // buffer
0, // cursor_byte_pos
Style::default(), // scrollbar_style
20, // terminal_height
);

// Reset hover state after test
mouse_state(|m| m.last_mouse_over_cell_semantic = None);

// The popup with "FirstWord" should be drawn below the bottom border!
let lines = content.get_buffer_lines();
assert!(lines.iter().any(|l| l.contains("FirstWord")));
}
}
Loading