Implement search

This commit is contained in:
Jeremy Soller 2024-01-11 14:31:20 -07:00
parent 928269a239
commit 9b2ab1202a
No known key found for this signature in database
GPG key ID: DCFCA852D3906975
2 changed files with 103 additions and 9 deletions

View file

@ -181,7 +181,6 @@ pub enum Message {
TabNew,
TermEvent(segmented_button::Entity, TermEvent),
TermEventTx(mpsc::Sender<(segmented_button::Entity, TermEvent)>),
Todo(&'static str),
ToggleContextPage(ContextPage),
ShowAdvancedFontSettings(bool),
WindowClose,
@ -806,7 +805,11 @@ impl Application for App {
}
Message::FindNext => {
if !self.find_search_value.is_empty() {
//TODO
let entity = self.tab_model.active();
if let Some(terminal) = self.tab_model.data::<Mutex<Terminal>>(entity) {
let mut terminal = terminal.lock().unwrap();
terminal.search(&self.find_search_value, true);
}
}
// Focus correct input
@ -814,7 +817,11 @@ impl Application for App {
}
Message::FindPrevious => {
if !self.find_search_value.is_empty() {
//TODO
let entity = self.tab_model.active();
if let Some(terminal) = self.tab_model.data::<Mutex<Terminal>>(entity) {
let mut terminal = terminal.lock().unwrap();
terminal.search(&self.find_search_value, false);
}
}
// Focus correct input
@ -1006,9 +1013,6 @@ impl Application for App {
Message::TermEventTx(term_event_tx) => {
self.term_event_tx_opt = Some(term_event_tx);
}
Message::Todo(todo) => {
log::warn!("TODO: {}", todo);
}
Message::ToggleContextPage(context_page) => {
if self.context_page == context_page {
self.core.window.show_context = !self.core.window.show_context;
@ -1121,10 +1125,12 @@ impl Application for App {
widget::text_input::text_input(fl!("find-placeholder"), &self.find_search_value)
.id(self.find_search_id.clone())
.on_input(Message::FindSearchValueChanged)
// This is inverted for ease of use, usually in terminals you want to search
// upwards, which is FindPrevious
.on_submit(if self.modifiers.contains(Modifiers::SHIFT) {
Message::FindPrevious
} else {
Message::FindNext
} else {
Message::FindPrevious
})
.width(Length::Fixed(320.0))
.trailing_icon(

View file

@ -2,12 +2,13 @@ use alacritty_terminal::{
event::{Event, EventListener, Notify, OnResize, WindowSize},
event_loop::{EventLoop, Msg, Notifier},
grid::Dimensions,
index::{Column, Line, Point, Side},
index::{Column, Direction, Line, Point, Side},
selection::{Selection, SelectionType},
sync::FairMutex,
term::{
cell::Flags,
color::{self, Colors},
search::{Match, RegexSearch},
viewport_to_point, Config, TermMode,
},
tty::{self, Options},
@ -135,6 +136,8 @@ pub struct Terminal {
notifier: Notifier,
pub context_menu: Option<cosmic::iced::Point>,
pub needs_update: bool,
search_regex_opt: Option<RegexSearch>,
search_value: String,
}
impl Terminal {
@ -205,6 +208,8 @@ impl Terminal {
notifier,
context_menu: None,
needs_update: true,
search_regex_opt: None,
search_value: String::new(),
}
}
@ -323,6 +328,89 @@ impl Terminal {
}
}
pub fn search(&mut self, value: &str, forwards: bool) {
//TODO: set max lines, run in thread?
{
let mut term = self.term.lock();
if self.search_value != value {
match RegexSearch::new(value) {
Ok(search_regex) => {
self.search_regex_opt = Some(search_regex);
self.search_value = value.to_string();
term.selection = None;
}
Err(err) => {
log::warn!("failed to parse regex {:?}: {}", value, err);
return;
}
}
}
let search_regex = match &mut self.search_regex_opt {
Some(some) => some,
None => return,
};
// Determine search origin
let search_origin = match term
.selection
.as_ref()
.and_then(|selection| selection.to_range(&term))
{
Some(range) => {
if forwards {
range.end
} else {
range.start
}
}
None => {
let grid = term.grid();
if forwards {
Point::new(Line(-(grid.history_size() as i32)), Column(0))
} else {
Point::new(
Line(grid.screen_lines() as i32 - 1),
Column(grid.columns() - 1),
)
}
}
};
// Find next search match
match term.search_next(
search_regex,
search_origin,
if forwards {
Direction::Right
} else {
Direction::Left
},
if forwards { Side::Left } else { Side::Right },
None,
) {
Some(search_match) => {
// Scroll to match
if forwards {
term.scroll_to_point(*search_match.end());
} else {
term.scroll_to_point(*search_match.start());
}
// Set selection to match
let mut selection =
Selection::new(SelectionType::Simple, *search_match.start(), Side::Left);
selection.update(*search_match.end(), Side::Right);
term.selection = Some(selection);
}
None => {}
}
}
self.update();
}
pub fn select_all(&mut self) {
{
let mut term = self.term.lock();