Implement LSP snippet tabstops sorting and merging
This commit is contained in:
parent
d2af31b916
commit
ded4381728
1 changed files with 25 additions and 12 deletions
|
@ -1,6 +1,7 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use helix_core::SmallVec;
|
||||||
|
|
||||||
use crate::{util::lsp_pos_to_pos, OffsetEncoding};
|
use crate::{util::lsp_pos_to_pos, OffsetEncoding};
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ pub fn into_transaction<'a>(
|
||||||
|
|
||||||
let mut insert = String::new();
|
let mut insert = String::new();
|
||||||
let mut offset = (primary_cursor as i128 + start_offset) as usize;
|
let mut offset = (primary_cursor as i128 + start_offset) as usize;
|
||||||
let mut tabstops: Vec<Range> = Vec::new();
|
let mut tabstops: Vec<(usize, Range)> = Vec::new();
|
||||||
|
|
||||||
for element in snippet.elements {
|
for element in snippet.elements {
|
||||||
match element {
|
match element {
|
||||||
|
@ -111,20 +112,15 @@ pub fn into_transaction<'a>(
|
||||||
offset += text.chars().count();
|
offset += text.chars().count();
|
||||||
insert.push_str(text);
|
insert.push_str(text);
|
||||||
}
|
}
|
||||||
Tabstop { .. } => {
|
Tabstop { tabstop } => {
|
||||||
// TODO: tabstop indexing: 0 is final cursor position. 1,2,.. are positions.
|
tabstops.push((tabstop, Range::point(offset)));
|
||||||
// TODO: merge tabstops with the same index
|
|
||||||
tabstops.push(Range::point(offset));
|
|
||||||
}
|
}
|
||||||
Placeholder {
|
Placeholder { tabstop, value } => match value.as_ref() {
|
||||||
tabstop: _tabstop,
|
|
||||||
value,
|
|
||||||
} => match value.as_ref() {
|
|
||||||
// https://doc.rust-lang.org/beta/unstable-book/language-features/box-patterns.html
|
// https://doc.rust-lang.org/beta/unstable-book/language-features/box-patterns.html
|
||||||
// would make this a bit nicer
|
// would make this a bit nicer
|
||||||
Text(text) => {
|
Text(text) => {
|
||||||
let len_chars = text.chars().count();
|
let len_chars = text.chars().count();
|
||||||
tabstops.push(Range::new(offset, offset + len_chars + 1));
|
tabstops.push((tabstop, Range::new(offset, offset + len_chars + 1)));
|
||||||
offset += len_chars;
|
offset += len_chars;
|
||||||
insert.push_str(text);
|
insert.push_str(text);
|
||||||
}
|
}
|
||||||
|
@ -155,8 +151,25 @@ pub fn into_transaction<'a>(
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(first) = tabstops.first() {
|
// sort in ascending order (except for 0, which should always be the last one (per lsp doc))
|
||||||
transaction.with_selection(Selection::new(smallvec![*first], 0))
|
tabstops.sort_unstable_by_key(|(n, _range)| if *n == 0 { usize::MAX } else { *n });
|
||||||
|
|
||||||
|
// merge tabstops with the same index (we take advantage of the fact that we just sorted them
|
||||||
|
// above to simply look backwards)
|
||||||
|
let mut ntabstops = Vec::<SmallVec<[Range; 1]>>::new();
|
||||||
|
let mut prev = None;
|
||||||
|
for (tabstop, range) in tabstops {
|
||||||
|
if prev == Some(tabstop) {
|
||||||
|
let len_1 = ntabstops.len() - 1;
|
||||||
|
ntabstops[len_1].push(range);
|
||||||
|
} else {
|
||||||
|
prev = Some(tabstop);
|
||||||
|
ntabstops.push(smallvec![range]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(first) = ntabstops.first() {
|
||||||
|
transaction.with_selection(Selection::new(first.clone(), 0))
|
||||||
} else {
|
} else {
|
||||||
transaction
|
transaction
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue