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:
parent
f72207e7f0
commit
b312479266
@ -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)
|
||||
|
@ -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() {
|
||||
|
@ -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(')');
|
||||
|
Loading…
Reference in New Issue
Block a user