mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-04-08 17:05:59 +02:00
feature: Add ctrl-w and ctrl-h support in the search (#409)
Ctrl-w deletes one word backwards from the current cursor location. Ctrl-h is just an alias for backspace.
This commit is contained in:
parent
e437b14922
commit
cf14abe37d
@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
- [#406](https://github.com/ClementTsang/bottom/pull/406): Adds the Nord colour scheme, as well as a light variant.
|
||||
|
||||
- [#409](https://github.com/ClementTsang/bottom/pull/409): Adds `Ctrl-w` and `Ctrl-h` shortcuts in search, to delete a word and delete a character respectively.
|
||||
|
||||
## Changes
|
||||
|
||||
- [#372](https://github.com/ClementTsang/bottom/pull/372): Hides the SWAP graph and legend in normal mode if SWAP is 0.
|
||||
|
@ -333,6 +333,8 @@ Use `btm --help` for more information.
|
||||
| `Ctrl-a` | Skip to the start of the search query |
|
||||
| `Ctrl-e` | Skip to the end of the search query |
|
||||
| `Ctrl-u` | Clear the current search query |
|
||||
| `Ctrl-w` | Delete a word behind the cursor |
|
||||
| `Ctrl-h` | Delete the character behind the cursor |
|
||||
| `Backspace` | Delete the character behind the cursor |
|
||||
| `Delete` | Delete the character at the cursor |
|
||||
| `Alt-c`, `F1` | Toggle matching case |
|
||||
|
94
src/app.rs
94
src/app.rs
@ -725,17 +725,22 @@ impl App {
|
||||
.current_search_query
|
||||
.len()
|
||||
{
|
||||
let current_cursor = proc_widget_state.get_search_cursor_position();
|
||||
proc_widget_state
|
||||
.search_walk_forward(proc_widget_state.get_search_cursor_position());
|
||||
|
||||
let _removed_chars: String = proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
.current_search_query
|
||||
.remove(proc_widget_state.get_search_cursor_position());
|
||||
.drain(current_cursor..proc_widget_state.get_search_cursor_position())
|
||||
.collect();
|
||||
|
||||
proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
.grapheme_cursor = GraphemeCursor::new(
|
||||
proc_widget_state.get_search_cursor_position(),
|
||||
current_cursor,
|
||||
proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
@ -769,14 +774,16 @@ impl App {
|
||||
.is_enabled
|
||||
&& proc_widget_state.get_search_cursor_position() > 0
|
||||
{
|
||||
let current_cursor = proc_widget_state.get_search_cursor_position();
|
||||
proc_widget_state
|
||||
.search_walk_back(proc_widget_state.get_search_cursor_position());
|
||||
|
||||
let removed_char = proc_widget_state
|
||||
let removed_chars: String = proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
.current_search_query
|
||||
.remove(proc_widget_state.get_search_cursor_position());
|
||||
.drain(proc_widget_state.get_search_cursor_position()..current_cursor)
|
||||
.collect();
|
||||
|
||||
proc_widget_state
|
||||
.process_search_state
|
||||
@ -794,7 +801,8 @@ impl App {
|
||||
proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
.char_cursor_position -= UnicodeWidthChar::width(removed_char).unwrap_or(0);
|
||||
.char_cursor_position -= UnicodeWidthStr::width(removed_chars.as_str());
|
||||
|
||||
proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
@ -1167,6 +1175,82 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_previous_word(&mut self) {
|
||||
if let BottomWidgetType::ProcSearch = self.current_widget.widget_type {
|
||||
if let Some(proc_widget_state) = self
|
||||
.proc_state
|
||||
.widget_states
|
||||
.get_mut(&(self.current_widget.widget_id - 1))
|
||||
{
|
||||
// Traverse backwards from the current cursor location until you hit non-whitespace characters,
|
||||
// then continue to traverse (and delete) backwards until you hit a whitespace character. Halt.
|
||||
|
||||
// So... first, let's get our current cursor position using graphemes...
|
||||
let end_index = proc_widget_state.get_char_cursor_position();
|
||||
|
||||
// Then, let's crawl backwards until we hit our location, and store the "head"...
|
||||
let query = proc_widget_state.get_current_search_query();
|
||||
let mut start_index = 0;
|
||||
let mut saw_non_whitespace = false;
|
||||
|
||||
for (itx, c) in query
|
||||
.chars()
|
||||
.rev()
|
||||
.enumerate()
|
||||
.skip(query.len() - end_index)
|
||||
{
|
||||
if c.is_whitespace() {
|
||||
if saw_non_whitespace {
|
||||
start_index = query.len() - itx;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
saw_non_whitespace = true;
|
||||
}
|
||||
}
|
||||
|
||||
let removed_chars: String = proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
.current_search_query
|
||||
.drain(start_index..end_index)
|
||||
.collect();
|
||||
|
||||
proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
.grapheme_cursor = GraphemeCursor::new(
|
||||
start_index,
|
||||
proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
.current_search_query
|
||||
.len(),
|
||||
true,
|
||||
);
|
||||
|
||||
proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
.char_cursor_position -= UnicodeWidthStr::width(removed_chars.as_str());
|
||||
|
||||
proc_widget_state
|
||||
.process_search_state
|
||||
.search_state
|
||||
.cursor_direction = CursorDirection::Left;
|
||||
|
||||
proc_widget_state.update_query();
|
||||
self.proc_state.force_update = Some(self.current_widget.widget_id - 1);
|
||||
|
||||
// Now, convert this range into a String-friendly range and remove it all at once!
|
||||
|
||||
// Now make sure to also update our current cursor positions...
|
||||
|
||||
self.proc_state.force_update = Some(self.current_widget.widget_id - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_dd(&mut self) {
|
||||
self.reset_multi_tap_keys();
|
||||
|
||||
|
@ -549,7 +549,7 @@ impl ProcessTableWidget for Painter {
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if cursor_position >= query.len() {
|
||||
if cursor_position == query.len() {
|
||||
res.push(Span::styled(" ", currently_selected_text_style))
|
||||
}
|
||||
|
||||
@ -558,17 +558,7 @@ impl ProcessTableWidget for Painter {
|
||||
// This is easier - we just need to get a range of graphemes, rather than
|
||||
// dealing with possibly inserting a cursor (as none is shown!)
|
||||
|
||||
grapheme_indices
|
||||
.filter_map(|grapheme| {
|
||||
current_grapheme_posn += UnicodeWidthStr::width(grapheme.1);
|
||||
if current_grapheme_posn <= start_position {
|
||||
None
|
||||
} else {
|
||||
let styled = Span::styled(grapheme.1, text_style);
|
||||
Some(styled)
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
vec![Span::styled(query.to_string(), text_style)]
|
||||
}
|
||||
}
|
||||
|
||||
@ -622,6 +612,7 @@ impl ProcessTableWidget for Painter {
|
||||
},
|
||||
)];
|
||||
search_vec.extend(query_with_cursor);
|
||||
|
||||
search_vec
|
||||
})];
|
||||
|
||||
|
@ -271,13 +271,15 @@ pub const PROCESS_HELP_TEXT: [&str; 14] = [
|
||||
"+, -, click Collapse/expand a branch while in tree mode",
|
||||
];
|
||||
|
||||
pub const SEARCH_HELP_TEXT: [&str; 46] = [
|
||||
pub const SEARCH_HELP_TEXT: [&str; 48] = [
|
||||
"4 - Process search widget",
|
||||
"Tab Toggle between searching for PID and name",
|
||||
"Esc Close the search widget (retains the filter)",
|
||||
"Ctrl-a Skip to the start of the search query",
|
||||
"Ctrl-e Skip to the end of the search query",
|
||||
"Ctrl-u Clear the current search query",
|
||||
"Ctrl-w Delete a word behind the cursor",
|
||||
"Ctrl-h Delete the character behind the cursor",
|
||||
"Backspace Delete the character behind the cursor",
|
||||
"Delete Delete the character at the cursor",
|
||||
"Alt-c, F1 Toggle matching case",
|
||||
|
@ -157,6 +157,8 @@ pub fn handle_key_event_or_break(
|
||||
KeyCode::Char('a') => app.skip_cursor_beginning(),
|
||||
KeyCode::Char('e') => app.skip_cursor_end(),
|
||||
KeyCode::Char('u') => app.clear_search(),
|
||||
KeyCode::Char('w') => app.clear_previous_word(),
|
||||
KeyCode::Char('h') => app.on_backspace(),
|
||||
// KeyCode::Char('j') => {}, // Move down
|
||||
// KeyCode::Char('k') => {}, // Move up
|
||||
// KeyCode::Char('h') => {}, // Move right
|
||||
|
Loading…
x
Reference in New Issue
Block a user