1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-22 13:16:39 +03:00

quickselect: de-dup labels

refs: #1271
This commit is contained in:
Wez Furlong 2021-12-09 09:50:32 -07:00
parent b9aec2fcad
commit 348ddcb122
5 changed files with 72 additions and 13 deletions

View File

@ -401,7 +401,7 @@ macro_rules! pdu {
/// The overall version of the codec.
/// This must be bumped when backwards incompatible changes
/// are made to the types and protocol.
pub const CODEC_VERSION: usize = 9;
pub const CODEC_VERSION: usize = 10;
// Defines the Pdu enum.
// Each struct has an explicit identifying number.

View File

@ -15,6 +15,8 @@ As features stabilize some brief notes about them will accumulate here.
#### Changed
* quickselect: we now de-duplicate labels for results with the same textual content. [#1271](https://github.com/wez/wezterm/issues/1271)
#### Updated and Improved
* macos: removing the titlebar from `window_decorations` now preserves rounded window corners [#1034](https://github.com/wez/wezterm/issues/1034)

View File

@ -367,6 +367,7 @@ impl Pane for LocalPane {
let mut results = vec![];
let mut haystack = String::new();
let mut coords = vec![];
let mut uniq_matches: HashMap<String, usize> = HashMap::new();
#[derive(Copy, Clone)]
struct Coord {
@ -389,6 +390,7 @@ impl Pane for LocalPane {
pattern: &Pattern,
haystack: &str,
coords: &[Coord],
uniq_matches: &mut HashMap<String, usize>,
) {
if haystack.is_empty() {
return;
@ -399,6 +401,14 @@ impl Pane for LocalPane {
// haystack strings
Pattern::CaseInSensitiveString(s) | Pattern::CaseSensitiveString(s) => {
for (idx, s) in haystack.match_indices(s) {
let match_id = match uniq_matches.get(s).copied() {
Some(id) => id,
None => {
let id = uniq_matches.len();
uniq_matches.insert(s.to_owned(), id);
id
}
};
let (start_x, start_y) = haystack_idx_to_coord(idx, coords);
let (end_x, end_y) = haystack_idx_to_coord(idx + s.len(), coords);
results.push(SearchResult {
@ -406,6 +416,7 @@ impl Pane for LocalPane {
start_y,
end_x,
end_y,
match_id,
});
}
}
@ -418,6 +429,16 @@ impl Pane for LocalPane {
// `c.iter().rev()` as the capture iterator isn't double-ended.
for idx in (0..c.len()).rev() {
if let Some(m) = c.get(idx) {
let s = m.as_str();
let match_id = match uniq_matches.get(s).copied() {
Some(id) => id,
None => {
let id = uniq_matches.len();
uniq_matches.insert(s.to_owned(), id);
id
}
};
let (start_x, start_y) =
haystack_idx_to_coord(m.start(), coords);
let (end_x, end_y) = haystack_idx_to_coord(m.end(), coords);
@ -426,6 +447,7 @@ impl Pane for LocalPane {
start_y,
end_x,
end_y,
match_id,
});
break;
}
@ -468,14 +490,26 @@ impl Pane for LocalPane {
haystack.push('\n');
}
} else {
collect_matches(&mut results, &pattern, &haystack, &coords);
collect_matches(
&mut results,
&pattern,
&haystack,
&coords,
&mut uniq_matches,
);
haystack.clear();
coords.clear();
}
}
}
collect_matches(&mut results, &pattern, &haystack, &coords);
collect_matches(
&mut results,
&pattern,
&haystack,
&coords,
&mut uniq_matches,
);
Ok(results)
}
}

View File

@ -35,6 +35,9 @@ pub struct SearchResult {
pub end_y: StableRowIndex,
/// The cell index into the line of the end of the match
pub end_x: usize,
/// An identifier that can be used to group results that have
/// the same textual content
pub match_id: usize,
}
pub use config::keyassignment::Pattern;

View File

@ -520,18 +520,38 @@ impl QuickSelectRenderable {
}
fn recompute_results(&mut self) {
let num_results = self.results.len();
let labels = compute_labels_for_alphabet(&self.config.quick_select_alphabet, num_results);
/// Produce the sorted seq of unique match_ids from the results
fn compute_uniq_results(results: &[SearchResult]) -> Vec<usize> {
let mut ids: Vec<usize> = results.iter().map(|sr| sr.match_id).collect();
ids.sort();
ids.dedup();
ids
}
let uniq_results = compute_uniq_results(&self.results);
// Label each unique result
let labels =
compute_labels_for_alphabet(&self.config.quick_select_alphabet, uniq_results.len());
self.by_label.clear();
for ((result_index, res), label) in self
.results
.iter()
.enumerate()
.rev()
.take(labels.len())
.zip(labels.into_iter())
{
// Keep track of match_id -> label
let mut assigned_labels: HashMap<usize, usize> = HashMap::new();
// Work through the results in reverse order, so that we assign eg: `a` to the
// bottom-right-most result first and so on
for (result_index, res) in self.results.iter().enumerate().rev() {
// Figure out which label to use based on the match_id
let label_index = match assigned_labels.get(&res.match_id).copied() {
Some(idx) => idx,
None => {
let idx = assigned_labels.len();
assigned_labels.insert(res.match_id, idx);
idx
}
};
let label = &labels[label_index];
self.by_label.insert(label.clone(), result_index);
for idx in res.start_y..=res.end_y {
let range = if idx == res.start_y && idx == res.end_y {