Skip to content

Commit

Permalink
LSP snippet sort and merge tabstop
Browse files Browse the repository at this point in the history
  • Loading branch information
Urgau committed Feb 8, 2023
1 parent 961c5bf commit b2cef33
Showing 1 changed file with 29 additions and 12 deletions.
41 changes: 29 additions & 12 deletions helix-lsp/src/snippet.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::borrow::Cow;

use anyhow::{anyhow, Result};
use helix_core::SmallVec;

use crate::{util::lsp_pos_to_pos, OffsetEncoding};

Expand Down Expand Up @@ -87,7 +88,7 @@ pub fn into_transaction<'a>(

let mut insert = String::new();
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 {
match element {
Expand All @@ -111,20 +112,15 @@ pub fn into_transaction<'a>(
offset += text.chars().count();
insert.push_str(text);
}
Tabstop { .. } => {
// TODO: tabstop indexing: 0 is final cursor position. 1,2,.. are positions.
// TODO: merge tabstops with the same index
tabstops.push(Range::point(offset));
Tabstop { tabstop } => {
tabstops.push((tabstop, Range::point(offset)));
}
Placeholder {
tabstop: _tabstop,
value,
} => match value.as_ref() {
Placeholder { tabstop, value } => match value.as_ref() {
// https://doc.rust-lang.org/beta/unstable-book/language-features/box-patterns.html
// would make this a bit nicer
Text(text) => {
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;
insert.push_str(text);
}
Expand Down Expand Up @@ -155,8 +151,29 @@ pub fn into_transaction<'a>(
)
});

if let Some(first) = tabstops.first() {
transaction.with_selection(Selection::new(smallvec![*first], 0))
// sort in assending order (except for 0, which should always be the last one (per lsp doc))
tabstops.sort_unstable_by(|(n1, _r1), (n2, _r2)| {
let n1 = if *n1 == 0 { usize::MAX } else { *n1 };
let n2 = if *n2 == 0 { usize::MAX } else { *n2 };
n1.cmp(&n2)
});

// 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 {
transaction
}
Expand Down

0 comments on commit b2cef33

Please sign in to comment.