Implement search
This commit is contained in:
parent
928269a239
commit
9b2ab1202a
2 changed files with 103 additions and 9 deletions
22
src/main.rs
22
src/main.rs
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue