mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-21 17:06:18 +04:00
Merge 109ede2e4b
into b8313da5a8
This commit is contained in:
commit
03bd4445c1
@ -154,13 +154,13 @@ ### Search
|
||||
|
||||
Search commands all operate on the `/` register by default. To use a different register, use `"<char>`.
|
||||
|
||||
| Key | Description | Command |
|
||||
| ----- | ----------- | ------- |
|
||||
| `/` | Search for regex pattern | `search` |
|
||||
| `?` | Search for previous pattern | `rsearch` |
|
||||
| `n` | Select next search match | `search_next` |
|
||||
| `N` | Select previous search match | `search_prev` |
|
||||
| `*` | Use current selection as the search pattern | `search_selection` |
|
||||
| Key | Description | Command |
|
||||
| ----- | ----------- | ------- |
|
||||
| `/` | Search for regex pattern | `search` |
|
||||
| `?` | Search for previous pattern | `rsearch` |
|
||||
| `n` | Select next search match | `search_next` |
|
||||
| `N` | Select previous search match | `search_prev` |
|
||||
| `*` | Use current selection as the search pattern, if only a single char is selected the current word (miW) is used instead | `search_selection` |
|
||||
|
||||
### Minor modes
|
||||
|
||||
|
@ -2266,19 +2266,37 @@ fn extend_search_prev(cx: &mut Context) {
|
||||
|
||||
fn search_selection(cx: &mut Context) {
|
||||
let register = cx.register.unwrap_or('/');
|
||||
let count = cx.count();
|
||||
let (view, doc) = current!(cx.editor);
|
||||
let contents = doc.text().slice(..);
|
||||
|
||||
let regex = doc
|
||||
.selection(view.id)
|
||||
.iter()
|
||||
.map(|selection| regex::escape(&selection.fragment(contents)))
|
||||
.collect::<HashSet<_>>() // Collect into hashset to deduplicate identical regexes
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>()
|
||||
.join("|");
|
||||
// Checks whether there is only one selection with a width of 1
|
||||
let selections = doc.selection(view.id);
|
||||
let primary = selections.primary();
|
||||
let regex = if selections.len() == 1 && primary.len() == 1 {
|
||||
let text = doc.text();
|
||||
let text_slice = text.slice(..);
|
||||
// In this case select the WORD under the cursor
|
||||
let current_word = textobject::textobject_word(
|
||||
text_slice,
|
||||
primary,
|
||||
textobject::TextObject::Inside,
|
||||
count,
|
||||
false,
|
||||
);
|
||||
let text_to_search = current_word.fragment(text_slice).to_string();
|
||||
regex::escape(&text_to_search)
|
||||
} else {
|
||||
selections
|
||||
.iter()
|
||||
.map(|selection| regex::escape(&selection.fragment(contents)))
|
||||
.collect::<HashSet<_>>() // Collect into hashset to deduplicate identical regexes
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>()
|
||||
.join("|")
|
||||
};
|
||||
|
||||
let msg = format!("register '{}' set to '{}'", register, ®ex);
|
||||
let msg = format!("register '{}' set to '{}'", '/', ®ex);
|
||||
match cx.editor.registers.push(register, regex) {
|
||||
Ok(_) => {
|
||||
cx.editor.registers.last_search_register = register;
|
||||
|
@ -178,6 +178,56 @@ fn match_paths(app: &Application, matches: Vec<&str>) -> usize {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_search_selection() -> anyhow::Result<()> {
|
||||
// Single selection with a length of 1: search for the whole word
|
||||
test_key_sequence(
|
||||
&mut helpers::AppBuilder::new().build()?,
|
||||
Some("ifoobar::baz<esc>3bl*"), // 3b places the cursor on the first letter of 'foobar', then move one to the right for good measure
|
||||
Some(&|app| {
|
||||
assert!(
|
||||
r#"register '/' set to 'foobar'"# == app.editor.get_status().unwrap().0
|
||||
&& Some(&"foobar".to_string()) == app.editor.registers.first('/')
|
||||
);
|
||||
}),
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Single selection with a length greather than 1: only search for the selection
|
||||
test_key_sequence(
|
||||
&mut helpers::AppBuilder::new().build()?,
|
||||
Some("ifoobar::baz<esc>3blvll*"), // 3b places the cursor on the first letter of 'foobar', then move one to the right for good measure, then select two more chars for a total of three
|
||||
Some(&|app| {
|
||||
assert!(
|
||||
r#"register '/' set to 'oob'"# == app.editor.get_status().unwrap().0
|
||||
&& Some(&"oob".to_string()) == app.editor.registers.first('/')
|
||||
);
|
||||
}),
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Multiple selection of length 1 each : should still only search for the selection
|
||||
test_key_sequence(
|
||||
&mut helpers::AppBuilder::new().build()?,
|
||||
Some("ifoobar::baz<ret>bar::crux<esc>k3blC*"), // k3b places the cursor on the first letter of 'foobar', then move one to the right for good measure, then adds a cursor on the line below
|
||||
Some(&|app| {
|
||||
assert!(
|
||||
// The selections don't seem to be ordered, so we have to test for the two possible orders.
|
||||
(r#"register '/' set to 'o|a'"# == app.editor.get_status().unwrap().0
|
||||
|| r#"register '/' set to 'a|o'"# == app.editor.get_status().unwrap().0)
|
||||
&& (Some(&"o|a".to_string()) == app.editor.registers.first('/')
|
||||
|| Some(&"a|o".to_string()) == app.editor.registers.first('/'))
|
||||
);
|
||||
}),
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_multi_selection_paste() -> anyhow::Result<()> {
|
||||
test((
|
||||
|
Loading…
Reference in New Issue
Block a user