1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-21 19:58:15 +03:00

wezterm: search: select current match

When cycling through matches, set the current selection to the
matched range.  This doesn't implicitly copy; it just marks the
range.

You can use the `Copy` key assignment to explicitly copy the
selection to the clipboard.

I'm sort of on the fence about implicit copying.
This commit is contained in:
Wez Furlong 2020-05-29 21:58:53 -07:00
parent 191a67bc9f
commit 7ff8d9e7a3
2 changed files with 70 additions and 21 deletions

View File

@ -1,3 +1,4 @@
use crate::frontend::gui::selection::{SelectionCoordinate, SelectionRange};
use crate::frontend::gui::termwindow::TermWindow;
use crate::mux::domain::DomainId;
use crate::mux::renderable::*;
@ -135,8 +136,7 @@ impl Tab for SearchOverlay {
} else {
r.results.len() - 1
};
r.result_pos.replace(prior);
r.set_viewport(Some(r.results[prior].start_y));
r.activate_match_number(prior);
}
}
(KeyCode::Char('n'), KeyModifiers::CTRL) => {
@ -148,8 +148,7 @@ impl Tab for SearchOverlay {
} else {
*cur + 1
};
r.result_pos.replace(next);
r.set_viewport(Some(r.results[next].start_y));
r.activate_match_number(next);
}
}
(KeyCode::Char('r'), KeyModifiers::CTRL) => {
@ -309,13 +308,54 @@ impl SearchRenderable {
self.recompute_results();
}
if let Some(last) = self.results.last() {
self.result_pos.replace(self.results.len() - 1);
self.set_viewport(Some(last.start_y));
if !self.results.is_empty() {
self.activate_match_number(self.results.len() - 1);
} else {
self.set_viewport(None);
self.clear_selection();
}
}
fn clear_selection(&mut self) {
let tab_id = self.delegate.tab_id();
self.window.apply(move |term_window, _window| {
if let Some(term_window) = term_window.downcast_mut::<TermWindow>() {
let mut selection = term_window.selection(tab_id);
selection.start.take();
selection.range.take();
}
Ok(())
});
}
fn activate_match_number(&mut self, n: usize) {
self.result_pos.replace(n);
let result = self.results[n].clone();
let tab_id = self.delegate.tab_id();
self.window.apply(move |term_window, _window| {
if let Some(term_window) = term_window.downcast_mut::<TermWindow>() {
let mut selection = term_window.selection(tab_id);
let start = SelectionCoordinate {
x: result.start_x,
y: result.start_y,
};
selection.start = Some(start);
selection.range = Some(SelectionRange {
start,
end: SelectionCoordinate {
// inclusive range for selection, but the result
// range is exclusive
x: result.end_x.saturating_sub(1),
y: result.end_y,
},
});
}
Ok(())
});
self.set_viewport(Some(result.start_y));
}
}
impl Renderable for SearchRenderable {

View File

@ -656,20 +656,29 @@ impl TermWindow {
let dirty = render.get_dirty_lines(visible_range);
if !dirty.is_empty() {
// If any of the changed lines intersect with the selection,
// then we need to clear the selection
let clear_selection = if let Some(selection_range) =
myself.selection(tab.tab_id()).range.as_ref()
{
let selection_rows = selection_range.rows();
selection_rows.into_iter().any(|row| dirty.contains(row))
} else {
false
};
if tab.downcast_ref::<SearchOverlay>().is_none() {
// If any of the changed lines intersect with the
// selection, then we need to clear the selection, but not
// when the search overlay is active; the search overlay
// marks lines as dirty to force invalidate them for
// highlighting purpose but also manipulates the selection
// and we want to allow it to retain the selection it made!
if clear_selection {
myself.selection(tab.tab_id()).range.take();
myself.selection(tab.tab_id()).start.take();
let clear_selection = if let Some(selection_range) =
myself.selection(tab.tab_id()).range.as_ref()
{
let selection_rows = selection_range.rows();
selection_rows
.into_iter()
.any(|row| dirty.contains(row))
} else {
false
};
if clear_selection {
myself.selection(tab.tab_id()).range.take();
myself.selection(tab.tab_id()).start.take();
}
}
myself.window.as_ref().unwrap().invalidate();
@ -2657,7 +2666,7 @@ impl TermWindow {
})
}
fn selection(&self, tab_id: TabId) -> RefMut<Selection> {
pub fn selection(&self, tab_id: TabId) -> RefMut<Selection> {
RefMut::map(self.tab_state(tab_id), |state| &mut state.selection)
}