mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-25 19:03:30 +04:00
feat: complete implementation for replace surrounding tag
This commit is contained in:
parent
6f6ceda1ba
commit
6e4d022e98
@ -5704,7 +5704,7 @@ fn surround_add(cx: &mut Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn surround_replace(cx: &mut Context) {
|
fn surround_replace(cx: &mut Context) {
|
||||||
let layer = cx.count();
|
let count = cx.count();
|
||||||
cx.on_next_key(move |cx, event| {
|
cx.on_next_key(move |cx, event| {
|
||||||
let surround_ch = match event.char() {
|
let surround_ch = match event.char() {
|
||||||
Some('m') => None, // m selects the closest surround pair
|
Some('m') => None, // m selects the closest surround pair
|
||||||
@ -5715,17 +5715,8 @@ fn surround_replace(cx: &mut Context) {
|
|||||||
let text = doc.text().slice(..);
|
let text = doc.text().slice(..);
|
||||||
let selection = doc.selection(view.id);
|
let selection = doc.selection(view.id);
|
||||||
|
|
||||||
if false {
|
if surround_ch.is_some_and(|ch| ch == 'x') {
|
||||||
// let change_pos = match surround::get_surround_pos_tag(text, selection, layer) {
|
let change_pos = match surround::get_surround_pos_tag(text, &selection, count) {
|
||||||
// Ok(c) => c,
|
|
||||||
// Err(err) => {
|
|
||||||
// cx.editor.set_error(err.to_string());
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// TODO: add back the logic for other surround changes
|
|
||||||
} else {
|
|
||||||
let change_pos = match surround::get_surround_pos_tag(text, selection, layer) {
|
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
cx.editor.set_error(err.to_string());
|
cx.editor.set_error(err.to_string());
|
||||||
@ -5733,42 +5724,108 @@ fn surround_replace(cx: &mut Context) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let selection = selection.clone();
|
// change_pos is guaranteed to have at least one value, because if not, then we would have returned earlier
|
||||||
let ranges: SmallVec<[Range; 1]> = change_pos
|
let tag_name = change_pos.first().unwrap().1.clone();
|
||||||
|
let all_same = change_pos
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|&((opening_tag_range, closing_tag_range), _)| {
|
.all(|(_, tag_name_other)| tag_name_other == &tag_name);
|
||||||
vec![opening_tag_range, closing_tag_range]
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
|
let prompt = Prompt::new(
|
||||||
|
"tag name:".into(),
|
||||||
|
Some('z'),
|
||||||
|
ui::completers::none,
|
||||||
|
move |context: &mut compositor::Context, input: &str, event: PromptEvent| {
|
||||||
|
let (view, document) = current!(context.editor);
|
||||||
|
let copy_selection = document.selection(view.id);
|
||||||
|
|
||||||
|
if event != PromptEvent::Validate {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ranges: SmallVec<[Range; 1]> = change_pos
|
||||||
|
.iter()
|
||||||
|
.flat_map(|&((opening_tag_range, closing_tag_range), _)| {
|
||||||
|
vec![opening_tag_range, closing_tag_range]
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
document.set_selection(
|
||||||
|
view.id,
|
||||||
|
Selection::new(ranges, copy_selection.primary_index() * 2),
|
||||||
|
);
|
||||||
|
let tag = Tendril::from(input);
|
||||||
|
|
||||||
|
let transaction = Transaction::change(
|
||||||
|
document.text(),
|
||||||
|
change_pos.iter().flat_map(|(pos, _)| {
|
||||||
|
let opening_range = pos.0;
|
||||||
|
let closing_range = pos.1;
|
||||||
|
|
||||||
|
vec![
|
||||||
|
(opening_range.from(), opening_range.to(), Some(tag.clone())),
|
||||||
|
(closing_range.from(), closing_range.to(), Some(tag.clone())),
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// we don't need to touch this
|
||||||
|
// document.set_selection(view.id, *copy_selection);
|
||||||
|
document.apply(&transaction, view.id);
|
||||||
|
context.editor.mode = Mode::Normal;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let prompt = if all_same {
|
||||||
|
// prefill with tag name because all tags have the same name
|
||||||
|
prompt.with_line(tag_name, &cx.editor)
|
||||||
|
} else {
|
||||||
|
prompt
|
||||||
|
};
|
||||||
|
|
||||||
|
cx.push_layer(Box::new(prompt));
|
||||||
|
} else {
|
||||||
|
let change_pos =
|
||||||
|
match surround::get_surround_pos(doc.syntax(), text, selection, surround_ch, count)
|
||||||
|
{
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(err) => {
|
||||||
|
cx.editor.set_error(err.to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let selection = selection.clone();
|
||||||
|
let ranges: SmallVec<[Range; 1]> =
|
||||||
|
change_pos.iter().map(|&p| Range::point(p)).collect();
|
||||||
doc.set_selection(
|
doc.set_selection(
|
||||||
view.id,
|
view.id,
|
||||||
Selection::new(ranges, selection.primary_index() * 2),
|
Selection::new(ranges, selection.primary_index() * 2),
|
||||||
);
|
);
|
||||||
|
|
||||||
cx.on_next_key(move |cx, _event| {
|
cx.on_next_key(move |cx, event| {
|
||||||
let (view, doc) = current!(cx.editor);
|
let (view, doc) = current!(cx.editor);
|
||||||
|
let to = match event.char() {
|
||||||
|
Some(to) => to,
|
||||||
|
None => return doc.set_selection(view.id, selection),
|
||||||
|
};
|
||||||
|
let (open, close) = match_brackets::get_pair(to);
|
||||||
|
|
||||||
// TODO: obtain this value from the input
|
// the changeset has to be sorted to allow nested surrounds
|
||||||
let user_input = "help";
|
let mut sorted_pos: Vec<(usize, char)> = Vec::new();
|
||||||
|
for p in change_pos.chunks(2) {
|
||||||
|
sorted_pos.push((p[0], open));
|
||||||
|
sorted_pos.push((p[1], close));
|
||||||
|
}
|
||||||
|
sorted_pos.sort_unstable();
|
||||||
|
|
||||||
let transaction = Transaction::change(
|
let transaction = Transaction::change(
|
||||||
doc.text(),
|
doc.text(),
|
||||||
change_pos.iter().flat_map(|(pos, _)| {
|
sorted_pos.iter().map(|&pos| {
|
||||||
let mut tag = Tendril::new();
|
let mut t = Tendril::new();
|
||||||
tag.push_str(user_input);
|
t.push(pos.1);
|
||||||
|
(pos.0, pos.0 + 1, Some(t))
|
||||||
let opening_range = pos.0;
|
|
||||||
let closing_range = pos.1;
|
|
||||||
|
|
||||||
vec![
|
|
||||||
(opening_range.from(), opening_range.to(), Some(tag.clone())),
|
|
||||||
(closing_range.from(), closing_range.to(), Some(tag.clone())),
|
|
||||||
]
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// we don't need to touch this
|
|
||||||
doc.set_selection(view.id, selection);
|
doc.set_selection(view.id, selection);
|
||||||
doc.apply(&transaction, view.id);
|
doc.apply(&transaction, view.id);
|
||||||
exit_select_mode(cx);
|
exit_select_mode(cx);
|
||||||
|
Loading…
Reference in New Issue
Block a user