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,
|
TabNew,
|
||||||
TermEvent(segmented_button::Entity, TermEvent),
|
TermEvent(segmented_button::Entity, TermEvent),
|
||||||
TermEventTx(mpsc::Sender<(segmented_button::Entity, TermEvent)>),
|
TermEventTx(mpsc::Sender<(segmented_button::Entity, TermEvent)>),
|
||||||
Todo(&'static str),
|
|
||||||
ToggleContextPage(ContextPage),
|
ToggleContextPage(ContextPage),
|
||||||
ShowAdvancedFontSettings(bool),
|
ShowAdvancedFontSettings(bool),
|
||||||
WindowClose,
|
WindowClose,
|
||||||
|
|
@ -806,7 +805,11 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
Message::FindNext => {
|
Message::FindNext => {
|
||||||
if !self.find_search_value.is_empty() {
|
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
|
// Focus correct input
|
||||||
|
|
@ -814,7 +817,11 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
Message::FindPrevious => {
|
Message::FindPrevious => {
|
||||||
if !self.find_search_value.is_empty() {
|
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
|
// Focus correct input
|
||||||
|
|
@ -1006,9 +1013,6 @@ impl Application for App {
|
||||||
Message::TermEventTx(term_event_tx) => {
|
Message::TermEventTx(term_event_tx) => {
|
||||||
self.term_event_tx_opt = Some(term_event_tx);
|
self.term_event_tx_opt = Some(term_event_tx);
|
||||||
}
|
}
|
||||||
Message::Todo(todo) => {
|
|
||||||
log::warn!("TODO: {}", todo);
|
|
||||||
}
|
|
||||||
Message::ToggleContextPage(context_page) => {
|
Message::ToggleContextPage(context_page) => {
|
||||||
if self.context_page == context_page {
|
if self.context_page == context_page {
|
||||||
self.core.window.show_context = !self.core.window.show_context;
|
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)
|
widget::text_input::text_input(fl!("find-placeholder"), &self.find_search_value)
|
||||||
.id(self.find_search_id.clone())
|
.id(self.find_search_id.clone())
|
||||||
.on_input(Message::FindSearchValueChanged)
|
.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) {
|
.on_submit(if self.modifiers.contains(Modifiers::SHIFT) {
|
||||||
Message::FindPrevious
|
|
||||||
} else {
|
|
||||||
Message::FindNext
|
Message::FindNext
|
||||||
|
} else {
|
||||||
|
Message::FindPrevious
|
||||||
})
|
})
|
||||||
.width(Length::Fixed(320.0))
|
.width(Length::Fixed(320.0))
|
||||||
.trailing_icon(
|
.trailing_icon(
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,13 @@ use alacritty_terminal::{
|
||||||
event::{Event, EventListener, Notify, OnResize, WindowSize},
|
event::{Event, EventListener, Notify, OnResize, WindowSize},
|
||||||
event_loop::{EventLoop, Msg, Notifier},
|
event_loop::{EventLoop, Msg, Notifier},
|
||||||
grid::Dimensions,
|
grid::Dimensions,
|
||||||
index::{Column, Line, Point, Side},
|
index::{Column, Direction, Line, Point, Side},
|
||||||
selection::{Selection, SelectionType},
|
selection::{Selection, SelectionType},
|
||||||
sync::FairMutex,
|
sync::FairMutex,
|
||||||
term::{
|
term::{
|
||||||
cell::Flags,
|
cell::Flags,
|
||||||
color::{self, Colors},
|
color::{self, Colors},
|
||||||
|
search::{Match, RegexSearch},
|
||||||
viewport_to_point, Config, TermMode,
|
viewport_to_point, Config, TermMode,
|
||||||
},
|
},
|
||||||
tty::{self, Options},
|
tty::{self, Options},
|
||||||
|
|
@ -135,6 +136,8 @@ pub struct Terminal {
|
||||||
notifier: Notifier,
|
notifier: Notifier,
|
||||||
pub context_menu: Option<cosmic::iced::Point>,
|
pub context_menu: Option<cosmic::iced::Point>,
|
||||||
pub needs_update: bool,
|
pub needs_update: bool,
|
||||||
|
search_regex_opt: Option<RegexSearch>,
|
||||||
|
search_value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Terminal {
|
impl Terminal {
|
||||||
|
|
@ -205,6 +208,8 @@ impl Terminal {
|
||||||
notifier,
|
notifier,
|
||||||
context_menu: None,
|
context_menu: None,
|
||||||
needs_update: true,
|
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) {
|
pub fn select_all(&mut self) {
|
||||||
{
|
{
|
||||||
let mut term = self.term.lock();
|
let mut term = self.term.lock();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue