1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-23 13:21:38 +03:00

quickselect: allow multiline matches

Turn on multi-line mode by default, and improve the localpane
search function to collapse runs of trailing whitespace into
just a newline.

That allows:

```
./target/debug/wezterm -n --config 'quick_select_patterns={"foo$"}'
```

to match the first line from this, but not the second:

```
printf "foo\nfoobar\n"
```

and this to match both:

```
./target/debug/wezterm -n --config 'quick_select_patterns={"^foo"}'
```

refs: https://github.com/wez/wezterm/issues/2008
This commit is contained in:
Wez Furlong 2022-05-20 09:47:08 -07:00
parent f72207e7f0
commit b312479266
3 changed files with 36 additions and 4 deletions

View File

@ -41,6 +41,7 @@ As features stabilize some brief notes about them will accumulate here.
* [Key Table](config/key-tables.md) lookups will now keep searching the activation stack until a matching assignment is found, allowing for layered key tables. [#993](https://github.com/wez/wezterm/issues/993)
* Search mode's search term is now remembered globally between activations of search mode. [#1912](https://github.com/wez/wezterm/issues/1912)
* Quickselect no longer jumps to the bottom of the viewport when activated, allowing you to quickselect within the current viewport region
* Quickselect now supports multi-line anchors such as `^` and `$`. [#2008](https://github.com/wez/wezterm/issues/2008)
#### Fixed
* Flush after replying to XTGETTCAP and DECRQM. [#1850](https://github.com/wez/wezterm/issues/1850) [#1950](https://github.com/wez/wezterm/issues/1950)

View File

@ -538,6 +538,7 @@ impl Pane for LocalPane {
Pattern::Regex(r) => {
if let Ok(re) = regex::Regex::new(r) {
// Allow for the regex to contain captures
log::trace!("regex search for {:?} in `{:?}`", r, haystack);
for c in re.captures_iter(haystack) {
// Look for the captures in reverse order, as index==0 is
// the whole matched string. We can't just call
@ -545,6 +546,9 @@ impl Pane for LocalPane {
for idx in (0..c.len()).rev() {
if let Some(m) = c.get(idx) {
let s = m.as_str();
if s.is_empty() {
continue;
}
let match_id = match uniq_matches.get(s).copied() {
Some(id) => id,
None => {
@ -577,6 +581,8 @@ impl Pane for LocalPane {
let stable_row = screen.phys_to_stable_row_index(idx);
let mut wrapped = false;
let mut trailing_spaces = None;
for (grapheme_idx, cell) in line.visible_cells() {
coords.push(Coord {
byte_idx: haystack.len(),
@ -585,6 +591,15 @@ impl Pane for LocalPane {
});
let s = cell.str();
if s == " " {
// Keep track of runs of trailing spaces; we'll prune
// them out so that `$` in a regex works as expected.
if trailing_spaces.is_none() {
trailing_spaces.replace(haystack.len());
}
} else {
trailing_spaces.take();
}
if let Pattern::CaseInSensitiveString(_) = &pattern {
// normalize the case so we match everything lowercase
haystack.push_str(&s.to_lowercase());
@ -594,6 +609,18 @@ impl Pane for LocalPane {
wrapped = cell.attrs().wrapped();
}
if let Some(trailing_spaces) = trailing_spaces {
// Remove trailing spaces from the haystack
haystack.truncate(trailing_spaces);
while coords
.last()
.map(|c| c.byte_idx >= trailing_spaces)
.unwrap_or(false)
{
coords.pop();
}
}
if !wrapped {
if let Pattern::Regex(_) = &pattern {
if let Some(coord) = coords.last().copied() {

View File

@ -191,28 +191,32 @@ impl QuickSelectOverlay {
let config = term_window.config.clone();
let mut pattern = "(".to_string();
let mut pattern = "(?m)(".to_string();
let mut have_patterns = false;
if !args.patterns.is_empty() {
for p in &args.patterns {
if pattern.len() > 1 {
if have_patterns {
pattern.push('|');
}
pattern.push_str(p);
have_patterns = true;
}
} else {
if !config.disable_default_quick_select_patterns {
for p in &PATTERNS {
if pattern.len() > 1 {
if have_patterns {
pattern.push('|');
}
pattern.push_str(p);
have_patterns = true;
}
}
for p in &config.quick_select_patterns {
if pattern.len() > 1 {
if have_patterns {
pattern.push('|');
}
pattern.push_str(p);
have_patterns = true;
}
}
pattern.push(')');