implement infinitive search iter

This commit is contained in:
yggverse 2024-12-17 06:50:59 +02:00
parent f444d9b115
commit 58140ab335
3 changed files with 78 additions and 75 deletions

View File

@ -48,12 +48,13 @@ impl Form {
let navigation = navigation.clone(); let navigation = navigation.clone();
let subject = subject.clone(); let subject = subject.clone();
move |_| { move |_| {
navigation.update(find( let matches = find(
&subject, &subject,
input.entry.text().as_str(), input.entry.text().as_str(),
match_case.is_active(), match_case.is_active(),
)); );
input.update(navigation.is_match()); input.update(!matches.is_empty());
navigation.update(matches);
} }
}); });
@ -62,12 +63,9 @@ impl Form {
let navigation = navigation.clone(); let navigation = navigation.clone();
let subject = subject.clone(); let subject = subject.clone();
move |this| { move |this| {
navigation.update(find( let matches = find(&subject, input.entry.text().as_str(), this.is_active());
&subject, input.update(!matches.is_empty());
input.entry.text().as_str(), navigation.update(matches);
this.is_active(),
));
input.update(navigation.is_match());
} }
}); });

View File

@ -1,18 +1,17 @@
mod back; mod back;
mod forward; mod forward;
mod iter;
use back::Back; use back::Back;
use forward::Forward; use forward::Forward;
use iter::Iter;
use super::Subject; use super::Subject;
use gtk::{ use gtk::{
prelude::{BoxExt, TextBufferExt, TextViewExt}, prelude::{BoxExt, TextBufferExt, TextViewExt},
Box, Orientation, TextIter, Box, Orientation, TextIter,
}; };
use std::{ use std::cell::RefCell;
cell::{Cell, RefCell},
rc::Rc,
};
const MARGIN: i32 = 6; const MARGIN: i32 = 6;
@ -20,8 +19,7 @@ pub struct Navigation {
pub back: Back, pub back: Back,
pub forward: Forward, pub forward: Forward,
pub g_box: Box, pub g_box: Box,
index: Rc<Cell<usize>>, iter: RefCell<Option<Iter>>,
matches: Rc<RefCell<Vec<(TextIter, TextIter)>>>,
} }
impl Navigation { impl Navigation {
@ -29,10 +27,6 @@ impl Navigation {
/// Create new `Self` /// Create new `Self`
pub fn new() -> Self { pub fn new() -> Self {
// Init shared matches holder
let index = Rc::new(Cell::new(0));
let matches = Rc::new(RefCell::new(Vec::new()));
// Init components // Init components
let back = Back::new(); let back = Back::new();
let forward = Forward::new(); let forward = Forward::new();
@ -53,21 +47,16 @@ impl Navigation {
back, back,
forward, forward,
g_box, g_box,
index, iter: RefCell::new(None),
matches,
} }
} }
// Actions // Actions
pub fn update(&self, matches: Vec<(TextIter, TextIter)>) { pub fn update(&self, matches: Vec<(TextIter, TextIter)>) {
// Update self self.back.update(!matches.is_empty());
self.matches.replace(matches); self.forward.update(!matches.is_empty());
self.index.replace(0); // reset self.iter.replace(Some(Iter::new(matches)));
// Update child components
self.back.update(self.is_match());
self.forward.update(self.is_match());
} }
pub fn back(&self, subject: &Subject) -> Option<(TextIter, TextIter)> { pub fn back(&self, subject: &Subject) -> Option<(TextIter, TextIter)> {
@ -79,23 +68,15 @@ impl Navigation {
&buffer.end_iter(), &buffer.end_iter(),
); );
let index = self.index.take(); match self.iter.borrow_mut().as_mut() {
Some(iter) => match iter.back() {
match self.matches.borrow().get(back(index)) {
Some((start, end)) => { Some((start, end)) => {
buffer.apply_tag(&subject.tag.current, start, end); buffer.apply_tag(&subject.tag.current, &start, &end);
self.index.replace(if index == 0 { Some((start, end))
len_to_index(self.matches.borrow().len())
} else {
index
});
Some((*start, *end))
}
None => {
self.index
.replace(len_to_index(self.matches.borrow().len())); // go last
None
} }
None => iter.reset(),
},
None => todo!(),
} }
} }
@ -108,36 +89,15 @@ impl Navigation {
&buffer.end_iter(), &buffer.end_iter(),
); );
let index = self.index.take(); match self.iter.borrow_mut().as_mut() {
let next = forward(index); Some(iter) => match iter.forward() {
match self.matches.borrow().get(next) {
Some((start, end)) => { Some((start, end)) => {
buffer.apply_tag(&subject.tag.current, start, end); buffer.apply_tag(&subject.tag.current, &start, &end);
self.index.replace(next); Some((start, end))
Some((*start, *end))
} }
None => { None => iter.reset(),
self.index.replace(0); },
None None => todo!(),
} }
} }
}
// Getters
pub fn is_match(&self) -> bool {
!self.matches.borrow().is_empty()
}
}
fn back(index: usize) -> usize {
index - 1
}
fn forward(index: usize) -> usize {
index + 1
}
fn len_to_index(len: usize) -> usize {
len - 1
} }

View File

@ -0,0 +1,45 @@
use gtk::TextIter;
pub struct Iter {
value: Vec<(TextIter, TextIter)>,
index: Option<usize>,
}
impl Iter {
pub fn new(value: Vec<(TextIter, TextIter)>) -> Self {
Self { index: None, value }
}
pub fn back(&mut self) -> Option<(TextIter, TextIter)> {
self.index = match self.index {
Some(index) => {
if index > 0 {
Some(index - 1)
} else {
Some(self.value.len())
}
}
None => Some(self.value.len()), // init
};
self.value.get(self.index.unwrap_or_default()).copied()
}
pub fn forward(&mut self) -> Option<(TextIter, TextIter)> {
self.index = match self.index {
Some(index) => {
if index < self.value.len() {
Some(index + 1)
} else {
Some(0)
}
}
None => Some(0), // init
};
self.value.get(self.index.unwrap_or_default()).copied()
}
pub fn reset(&mut self) -> Option<(TextIter, TextIter)> {
self.index = None;
self.forward()
}
}