diff options
author | Aleksey Kladov <[email protected]> | 2018-08-10 19:13:39 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-10 19:13:39 +0100 |
commit | 120789804d5483f14c9682b2b777adf6d2992547 (patch) | |
tree | bccbe4a72e648516f838499b91e5158484b5cbcd /libeditor/src | |
parent | 1be7af26a83b79863efb0d66a77b1fb7c0235bd2 (diff) |
Add line index
Diffstat (limited to 'libeditor/src')
-rw-r--r-- | libeditor/src/lib.rs | 2 | ||||
-rw-r--r-- | libeditor/src/line_index.rs | 56 |
2 files changed, 58 insertions, 0 deletions
diff --git a/libeditor/src/lib.rs b/libeditor/src/lib.rs index 4e9631a8b..9da71743f 100644 --- a/libeditor/src/lib.rs +++ b/libeditor/src/lib.rs | |||
@@ -1,6 +1,8 @@ | |||
1 | extern crate libsyntax2; | 1 | extern crate libsyntax2; |
2 | extern crate superslice; | ||
2 | 3 | ||
3 | mod extend_selection; | 4 | mod extend_selection; |
5 | mod line_index; | ||
4 | 6 | ||
5 | use libsyntax2::{ | 7 | use libsyntax2::{ |
6 | SyntaxNodeRef, AstNode, | 8 | SyntaxNodeRef, AstNode, |
diff --git a/libeditor/src/line_index.rs b/libeditor/src/line_index.rs new file mode 100644 index 000000000..feb482b32 --- /dev/null +++ b/libeditor/src/line_index.rs | |||
@@ -0,0 +1,56 @@ | |||
1 | use superslice::Ext; | ||
2 | use ::{TextUnit}; | ||
3 | |||
4 | pub struct LineIndex { | ||
5 | newlines: Vec<TextUnit>, | ||
6 | } | ||
7 | |||
8 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
9 | pub struct LineCol { | ||
10 | pub line: u32, | ||
11 | pub col: TextUnit, | ||
12 | } | ||
13 | |||
14 | impl LineIndex { | ||
15 | pub fn new(text: &str) -> LineIndex { | ||
16 | let mut newlines = vec![0.into()]; | ||
17 | let mut curr = 0.into(); | ||
18 | for c in text.chars() { | ||
19 | curr += TextUnit::of_char(c); | ||
20 | if c == '\n' { | ||
21 | newlines.push(curr); | ||
22 | } | ||
23 | } | ||
24 | LineIndex { newlines } | ||
25 | } | ||
26 | |||
27 | pub fn translate(&self, offset: TextUnit) -> LineCol { | ||
28 | let line = self.newlines.upper_bound(&offset) - 1; | ||
29 | let line_start_offset = self.newlines[line]; | ||
30 | let col = offset - line_start_offset; | ||
31 | return LineCol { line: line as u32, col } | ||
32 | } | ||
33 | } | ||
34 | |||
35 | #[test] | ||
36 | fn test_line_index() { | ||
37 | let text = "hello\nworld"; | ||
38 | let index = LineIndex::new(text); | ||
39 | assert_eq!(index.translate(0.into()), LineCol { line: 0, col: 0.into()}); | ||
40 | assert_eq!(index.translate(1.into()), LineCol { line: 0, col: 1.into()}); | ||
41 | assert_eq!(index.translate(5.into()), LineCol { line: 0, col: 5.into()}); | ||
42 | assert_eq!(index.translate(6.into()), LineCol { line: 1, col: 0.into()}); | ||
43 | assert_eq!(index.translate(7.into()), LineCol { line: 1, col: 1.into()}); | ||
44 | assert_eq!(index.translate(8.into()), LineCol { line: 1, col: 2.into()}); | ||
45 | assert_eq!(index.translate(10.into()), LineCol { line: 1, col: 4.into()}); | ||
46 | assert_eq!(index.translate(11.into()), LineCol { line: 1, col: 5.into()}); | ||
47 | assert_eq!(index.translate(12.into()), LineCol { line: 1, col: 6.into()}); | ||
48 | |||
49 | let text = "\nhello\nworld"; | ||
50 | let index = LineIndex::new(text); | ||
51 | assert_eq!(index.translate(0.into()), LineCol { line: 0, col: 0.into()}); | ||
52 | assert_eq!(index.translate(1.into()), LineCol { line: 1, col: 0.into()}); | ||
53 | assert_eq!(index.translate(2.into()), LineCol { line: 1, col: 1.into()}); | ||
54 | assert_eq!(index.translate(6.into()), LineCol { line: 1, col: 5.into()}); | ||
55 | assert_eq!(index.translate(7.into()), LineCol { line: 2, col: 0.into()}); | ||
56 | } | ||