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
4 changes: 2 additions & 2 deletions docs/src/configurations/config-file-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,14 +196,14 @@ The width mode for each graph row image.

### `core.search.ignore_case`

Whether to enable ignore case by default.
Whether to enable ignore case when the application starts. The option can be toggled while the commit list is displayed.

- type: `boolean`
- default: `false`

### `core.search.fuzzy`

Whether to enable fuzzy matching by default.
Whether to enable fuzzy matching when the application starts. The option can be toggled while the commit list is displayed.

- type: `boolean`
- default: `false`
Expand Down
4 changes: 2 additions & 2 deletions docs/src/keybindings/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ The default key bindings can be overridden.
| <kbd>/</kbd> | Start search | `search` |
| <kbd>Esc</kbd> | Cancel search | `cancel` |
| <kbd>n/N</kbd> | Go to next/previous search match | `go_to_next` `go_to_previous` |
| <kbd>Ctrl-g</kbd> | Toggle ignore case (if searching) | `ignore_case_toggle` |
| <kbd>Ctrl-x</kbd> | Toggle fuzzy match (if searching) | `fuzzy_toggle` |
| <kbd>Ctrl-g</kbd> | Toggle ignore case | `ignore_case_toggle` |
| <kbd>Ctrl-x</kbd> | Toggle fuzzy match | `fuzzy_toggle` |
| <kbd>R</kbd> | Refresh | `refresh` |
| <kbd>c/C</kbd> | Copy commit short/full hash | `short_copy` `full_copy` |
| <kbd>d</kbd> | Toggle custom user command view | `user_command_1` |
Expand Down
23 changes: 21 additions & 2 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ enum StatusLine {
#[default]
None,
Input(String, Option<u16>, Option<String>),
Transient(String),
NotificationInfo(String),
NotificationSuccess(String),
NotificationWarn(String),
Expand Down Expand Up @@ -161,7 +162,8 @@ impl App<'_> {
StatusLine::None | StatusLine::Input(_, _, _) => {
// do nothing
}
StatusLine::NotificationInfo(_)
StatusLine::Transient(_)
| StatusLine::NotificationInfo(_)
| StatusLine::NotificationSuccess(_)
| StatusLine::NotificationWarn(_) => {
// Clear message and pass key input as is
Expand Down Expand Up @@ -275,6 +277,9 @@ impl App<'_> {
AppEvent::UpdateStatusInput(msg, cursor_pos, msg_r) => {
self.update_status_input(msg, cursor_pos, msg_r);
}
AppEvent::UpdateStatusTransient(msg) => {
self.update_status_transient(msg);
}
AppEvent::NotifyInfo(msg) => {
self.info_notification(msg);
}
Expand Down Expand Up @@ -348,7 +353,8 @@ impl App<'_> {
let msg_w = console::measure_text_width(msg.as_str());
if let Some(t_msg) = transient_msg {
let t_msg_w = console::measure_text_width(t_msg.as_str());
let pad_w = area.width as usize - msg_w - t_msg_w - 2 /* pad */;
let pad_w =
(area.width as usize).saturating_sub(msg_w + t_msg_w + 2 /* pad */);
Line::from(vec![
msg.as_str().fg(self.ctx.color_theme.status_input_fg),
" ".repeat(pad_w).into(),
Expand All @@ -360,6 +366,15 @@ impl App<'_> {
Line::raw(msg).fg(self.ctx.color_theme.status_input_fg)
}
}
StatusLine::Transient(msg) => {
let msg_w = console::measure_text_width(msg.as_str());
let pad_w = (area.width as usize).saturating_sub(msg_w + 2 /* pad */);
Line::from(vec![
" ".repeat(pad_w).into(),
msg.as_str()
.fg(self.ctx.color_theme.status_input_transient_fg),
])
}
StatusLine::NotificationInfo(msg) => {
Line::raw(msg).fg(self.ctx.color_theme.status_info_fg)
}
Expand Down Expand Up @@ -683,6 +698,10 @@ impl App<'_> {
self.app_status.status_line = StatusLine::Input(msg, cursor_pos, transient_msg);
}

fn update_status_transient(&mut self, msg: String) {
self.app_status.status_line = StatusLine::Transient(msg);
}

fn info_notification(&mut self, msg: String) {
self.app_status.status_line = StatusLine::NotificationInfo(msg);
}
Expand Down
1 change: 1 addition & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub enum AppEvent {
Refresh(RefreshViewContext),
ClearStatusLine,
UpdateStatusInput(String, Option<u16>, Option<String>),
UpdateStatusTransient(String),
NotifyInfo(String),
NotifySuccess(String),
NotifyWarn(String),
Expand Down
27 changes: 18 additions & 9 deletions src/view/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ impl<'a> ListView<'a> {
self.clear_search_query();
}
UserEvent::IgnoreCaseToggle => {
self.as_mut_list_state().toggle_ignore_case();
self.update_search_query();
let message = self.as_mut_list_state().toggle_ignore_case();
self.update_search_status(Some(message));
}
UserEvent::FuzzyToggle => {
self.as_mut_list_state().toggle_fuzzy();
self.update_search_query();
let message = self.as_mut_list_state().toggle_fuzzy();
self.update_search_status(Some(message));
}
_ => {
self.as_mut_list_state().handle_search_input(key);
self.update_search_query();
self.update_search_status(None);
}
}
return;
Expand Down Expand Up @@ -131,7 +131,15 @@ impl<'a> ListView<'a> {
}
UserEvent::Search => {
self.as_mut_list_state().start_search();
self.update_search_query();
self.update_search_status(None);
}
UserEvent::IgnoreCaseToggle => {
let message = self.as_mut_list_state().toggle_ignore_case();
self.tx.send(AppEvent::UpdateStatusTransient(message));
}
UserEvent::FuzzyToggle => {
let message = self.as_mut_list_state().toggle_fuzzy();
self.tx.send(AppEvent::UpdateStatusTransient(message));
}
UserEvent::UserCommand(n) => {
self.tx.send(AppEvent::OpenUserCommand(n));
Expand Down Expand Up @@ -207,16 +215,15 @@ impl<'a> ListView<'a> {
self.as_list_state().graph_image_ids_sorted()
}

fn update_search_query(&self) {
fn update_search_status(&self, transient_message: Option<String>) {
if let SearchState::Searching { .. } = self.as_list_state().search_state() {
let list_state = self.as_list_state();
if let Some(query) = list_state.search_query_string() {
let cursor_pos = list_state.search_query_cursor_position();
let transient_msg = list_state.transient_message_string();
self.tx.send(AppEvent::UpdateStatusInput(
query,
Some(cursor_pos),
transient_msg,
transient_message,
));
}
}
Expand Down Expand Up @@ -265,9 +272,11 @@ impl<'a> ListView<'a> {
selected,
height,
scroll_to_top,
search_options,
search_context,
} = list_context;
let list_state = self.as_mut_list_state();
list_state.restore_search_options(*search_options);
list_state.reset_height(*height);
if *scroll_to_top {
list_state.select_first();
Expand Down
5 changes: 4 additions & 1 deletion src/view/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
detail::DetailView, help::HelpView, list::ListView, refs::RefsView,
user_command::UserCommandView,
},
widget::commit_list::{CommitListState, SearchRefreshContext},
widget::commit_list::{CommitListState, SearchOptions, SearchRefreshContext},
};

#[derive(Debug, Default)]
Expand Down Expand Up @@ -193,6 +193,7 @@ pub struct ListRefreshViewContext {
pub selected: usize,
pub height: usize,
pub scroll_to_top: bool,
pub search_options: SearchOptions,
pub search_context: Option<SearchRefreshContext>,
}

Expand All @@ -203,12 +204,14 @@ impl From<&CommitListState<'_>> for ListRefreshViewContext {
// If the selected commit is the top one and there is no offset, it means the list is already scrolled to the top.
// In this case, we set scroll_to_top to true to indicate that the view should be scrolled to the top after refresh.
let scroll_to_top = selected == 0 && offset == 0;
let search_options = list_state.search_options();
let search_context = list_state.search_refresh_context();
ListRefreshViewContext {
commit_hash,
selected,
height,
scroll_to_top,
search_options,
search_context,
}
}
Expand Down
Loading