Better search behaviour
This commit is contained in:
parent
df378b46de
commit
07837f7761
3 changed files with 28 additions and 7 deletions
|
|
@ -325,6 +325,8 @@ impl Regex {
|
||||||
postfix(1, just('*'), |r, _, _| Self::Many(0, !0, Box::new(r))),
|
postfix(1, just('*'), |r, _, _| Self::Many(0, !0, Box::new(r))),
|
||||||
postfix(1, just('+'), |r, _, _| Self::Many(1, !0, Box::new(r))),
|
postfix(1, just('+'), |r, _, _| Self::Many(1, !0, Box::new(r))),
|
||||||
postfix(1, just('?'), |r, _, _| Self::Many(0, 1, Box::new(r))),
|
postfix(1, just('?'), |r, _, _| Self::Many(0, 1, Box::new(r))),
|
||||||
|
// Non-standard: match the lhs, then rewind the input (i.e: as if it had never been parsed).
|
||||||
|
// Most useful at the end of tokens for context-sensitivie behaviour. For example, differentiating idents and function calls
|
||||||
postfix(1, just('%'), |r, _, _| Self::Rewind(Box::new(r))),
|
postfix(1, just('%'), |r, _, _| Self::Rewind(Box::new(r))),
|
||||||
// Non-standard: `x@y` parses `x` and then `y`. `y` can use `~` to refer to the extra string that was
|
// Non-standard: `x@y` parses `x` and then `y`. `y` can use `~` to refer to the extra string that was
|
||||||
// parsed by `x`. This supports nesting and is intended for context-sensitive patterns like Rust raw
|
// parsed by `x`. This supports nesting and is intended for context-sensitive patterns like Rust raw
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ pub struct Options<T> {
|
||||||
// (score, option)
|
// (score, option)
|
||||||
pub options: Vec<T>,
|
pub options: Vec<T>,
|
||||||
pub ranking: Vec<usize>,
|
pub ranking: Vec<usize>,
|
||||||
|
pub last_height: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Options<T> {
|
impl<T> Options<T> {
|
||||||
|
|
@ -123,6 +124,7 @@ impl<T> Options<T> {
|
||||||
selected: 0,
|
selected: 0,
|
||||||
options,
|
options,
|
||||||
ranking,
|
ranking,
|
||||||
|
last_height: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,13 +157,28 @@ impl<T> Options<T> {
|
||||||
impl<T: Clone> Element<T> for Options<T> {
|
impl<T: Clone> Element<T> for Options<T> {
|
||||||
fn handle(&mut self, state: &mut State, event: Event) -> Result<Resp<T>, Event> {
|
fn handle(&mut self, state: &mut State, event: Event) -> Result<Resp<T>, Event> {
|
||||||
match event.to_action(|e| e.to_go().or_else(|| e.to_move())) {
|
match event.to_action(|e| e.to_go().or_else(|| e.to_move())) {
|
||||||
Some(Action::Move(dir, Dist::Char, false, false)) => {
|
Some(Action::Move(dir, dist, false, false)) => {
|
||||||
|
let dist = match dist {
|
||||||
|
Dist::Char => 1,
|
||||||
|
Dist::Page => self.last_height.saturating_sub(1).min(self.ranking.len()),
|
||||||
|
Dist::Doc => self.ranking.len(),
|
||||||
|
};
|
||||||
match dir {
|
match dir {
|
||||||
Dir::Up => {
|
Dir::Up => {
|
||||||
self.selected = (self.selected + self.ranking.len()).saturating_sub(1)
|
if self.selected == 0 {
|
||||||
% self.ranking.len().max(1)
|
self.selected = self.ranking.len().saturating_sub(1);
|
||||||
|
} else {
|
||||||
|
self.selected = self.selected.saturating_sub(dist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::Down => {
|
||||||
|
if self.selected == self.ranking.len().saturating_sub(1) {
|
||||||
|
self.selected = 0;
|
||||||
|
} else {
|
||||||
|
self.selected =
|
||||||
|
(self.selected + dist).min(self.ranking.len().saturating_sub(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Dir::Down => self.selected = (self.selected + 1) % self.ranking.len().max(1),
|
|
||||||
_ => return Err(event),
|
_ => return Err(event),
|
||||||
}
|
}
|
||||||
Ok(Resp::handled(None))
|
Ok(Resp::handled(None))
|
||||||
|
|
@ -192,6 +209,8 @@ impl<T: Visual> Visual for Options<T> {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.last_height = frame.size()[1];
|
||||||
|
|
||||||
self.focus = self
|
self.focus = self
|
||||||
.focus
|
.focus
|
||||||
.max(
|
.max(
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,9 @@ impl Prompt {
|
||||||
- 1;
|
- 1;
|
||||||
Ok(Action::GotoLine(line))
|
Ok(Action::GotoLine(line))
|
||||||
}
|
}
|
||||||
Some("search") => {
|
Some(arg0 @ "search") => {
|
||||||
let needle = args.next().ok_or_else(|| "Expected argument".to_string())?;
|
let needle = cmd.get(arg0.len()..).unwrap().trim().to_string();
|
||||||
Ok(Action::BeginSearch(needle.to_string()))
|
Ok(Action::BeginSearch(needle))
|
||||||
}
|
}
|
||||||
Some(cmd) => Err(format!("Unknown command `{cmd}`")),
|
Some(cmd) => Err(format!("Unknown command `{cmd}`")),
|
||||||
None => Err(format!("No command entered")),
|
None => Err(format!("No command entered")),
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue