htmx_lsp2/
to_input_edit.rs

1use ropey::Rope;
2use tower_lsp::lsp_types::{Position, Range};
3use tree_sitter::{InputEdit, Point};
4
5use crate::htmx_tags::Tag;
6
7/// Convert Tag to Positon range for lsp_types.
8pub fn to_position(tag: &Tag) -> (Position, Position) {
9    (
10        Position::new(tag.start.row as u32, tag.start.column as u32),
11        Position::new(tag.end.row as u32, tag.end.column as u32),
12    )
13}
14
15pub trait ToInputEdit {
16    fn to_point(&self, position: Position) -> Point;
17    fn to_byte(&self, position: Position) -> usize;
18    fn to_position(&self, offset: usize) -> Position;
19    fn to_input_edit(&self, range: Range, text: &str) -> InputEdit;
20}
21
22impl ToInputEdit for Rope {
23    fn to_point(&self, position: Position) -> Point {
24        Point::new(position.line as usize, position.character as usize)
25    }
26
27    fn to_byte(&self, position: Position) -> usize {
28        let start_line = self.line_to_byte(position.line as usize);
29        start_line + position.character as usize
30    }
31
32    fn to_position(&self, mut offset: usize) -> Position {
33        offset = offset.min(self.len_bytes());
34        let mut low = 0usize;
35        let mut high = self.len_lines();
36        if high == 0 {
37            return Position {
38                line: 0,
39                character: offset as u32,
40            };
41        }
42        while low < high {
43            let mid = low + (high - low) / 2;
44            if self.line_to_byte(mid) > offset {
45                high = mid;
46            } else {
47                low = mid + 1;
48            }
49        }
50        let line = low - 1;
51        let character = offset - self.line_to_byte(line);
52        Position::new(line as u32, character as u32)
53    }
54
55    fn to_input_edit(&self, range: Range, text: &str) -> InputEdit {
56        let start = range.start;
57        let end = range.end;
58
59        let start_byte = self.to_byte(start);
60        let start_position = self.to_point(start);
61
62        let new_end_byte = start_byte + text.len();
63        let new_end_position = self.to_position(new_end_byte);
64        let new_end_position = self.to_point(new_end_position);
65
66        let old_end_byte = self.to_byte(end);
67        let old_end_position = self.to_point(end);
68
69        InputEdit {
70            start_byte,
71            old_end_byte,
72            new_end_byte,
73            start_position,
74            old_end_position,
75            new_end_position,
76        }
77    }
78}
79
80pub fn to_position2(point: Point) -> Position {
81    Position::new(point.row as u32, point.column as u32)
82}