aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/ui/picker.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-term/src/ui/picker.rs')
-rw-r--r--helix-term/src/ui/picker.rs61
1 files changed, 32 insertions, 29 deletions
diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs
index ebff9827..1581b0a1 100644
--- a/helix-term/src/ui/picker.rs
+++ b/helix-term/src/ui/picker.rs
@@ -6,6 +6,7 @@ use crate::{
use crossterm::event::Event;
use tui::{
buffer::Buffer as Surface,
+ text::Spans,
widgets::{Block, BorderType, Borders},
};
@@ -15,7 +16,6 @@ use tui::widgets::Widget;
use std::time::Instant;
use std::{
- borrow::Cow,
cmp::Reverse,
collections::HashMap,
io::Read,
@@ -87,7 +87,7 @@ impl Preview<'_, '_> {
impl<T> FilePicker<T> {
pub fn new(
options: Vec<T>,
- format_fn: impl Fn(&T) -> Cow<str> + 'static,
+ format_fn: impl Fn(&T) -> Spans + 'static,
callback_fn: impl Fn(&mut Context, &T, Action) + 'static,
preview_fn: impl Fn(&Editor, &T) -> Option<FileLocation> + 'static,
) -> Self {
@@ -299,14 +299,14 @@ pub struct Picker<T> {
/// Whether to truncate the start (default true)
pub truncate_start: bool,
- format_fn: Box<dyn Fn(&T) -> Cow<str>>,
+ format_fn: Box<dyn Fn(&T) -> Spans>,
callback_fn: Box<dyn Fn(&mut Context, &T, Action)>,
}
impl<T> Picker<T> {
pub fn new(
options: Vec<T>,
- format_fn: impl Fn(&T) -> Cow<str> + 'static,
+ format_fn: impl Fn(&T) -> Spans + 'static,
callback_fn: impl Fn(&mut Context, &T, Action) + 'static,
) -> Self {
let prompt = Prompt::new(
@@ -372,9 +372,8 @@ impl<T> Picker<T> {
self.matches.retain_mut(|(index, score)| {
let option = &self.options[*index];
// TODO: maybe using format_fn isn't the best idea here
- let text = (self.format_fn)(option);
-
- match self.matcher.fuzzy_match(&text, pattern) {
+ let line: String = (self.format_fn)(option).into();
+ match self.matcher.fuzzy_match(&line, pattern) {
Some(s) => {
// Update the score
*score = s;
@@ -401,10 +400,10 @@ impl<T> Picker<T> {
}
// TODO: maybe using format_fn isn't the best idea here
- let text = (self.format_fn)(option);
+ let line: String = (self.format_fn)(option).into();
self.matcher
- .fuzzy_match(&text, pattern)
+ .fuzzy_match(&line, pattern)
.map(|score| (index, score))
}),
);
@@ -611,30 +610,34 @@ impl<T: 'static> Component for Picker<T> {
surface.set_string(inner.x.saturating_sub(2), inner.y + i as u16, ">", selected);
}
- let formatted = (self.format_fn)(option);
-
+ let spans = (self.format_fn)(option);
let (_score, highlights) = self
.matcher
- .fuzzy_indices(&formatted, self.prompt.line())
+ .fuzzy_indices(&String::from(&spans), self.prompt.line())
.unwrap_or_default();
- surface.set_string_truncated(
- inner.x,
- inner.y + i as u16,
- &formatted,
- inner.width as usize,
- |idx| {
- if highlights.contains(&idx) {
- highlighted
- } else if is_active {
- selected
- } else {
- text_style
- }
- },
- true,
- self.truncate_start,
- );
+ spans.0.into_iter().fold(inner, |pos, span| {
+ let new_x = surface
+ .set_string_truncated(
+ pos.x,
+ pos.y + i as u16,
+ &span.content,
+ pos.width as usize,
+ |idx| {
+ if highlights.contains(&idx) {
+ highlighted.patch(span.style)
+ } else if is_active {
+ selected.patch(span.style)
+ } else {
+ text_style.patch(span.style)
+ }
+ },
+ true,
+ self.truncate_start,
+ )
+ .0;
+ pos.clip_left(new_x - pos.x)
+ });
}
}