From 120789804d5483f14c9682b2b777adf6d2992547 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Aug 2018 21:13:39 +0300 Subject: Add line index --- libeditor/src/lib.rs | 2 ++ libeditor/src/line_index.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 libeditor/src/line_index.rs (limited to 'libeditor/src') 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 @@ extern crate libsyntax2; +extern crate superslice; mod extend_selection; +mod line_index; use libsyntax2::{ 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 @@ +use superslice::Ext; +use ::{TextUnit}; + +pub struct LineIndex { + newlines: Vec, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct LineCol { + pub line: u32, + pub col: TextUnit, +} + +impl LineIndex { + pub fn new(text: &str) -> LineIndex { + let mut newlines = vec![0.into()]; + let mut curr = 0.into(); + for c in text.chars() { + curr += TextUnit::of_char(c); + if c == '\n' { + newlines.push(curr); + } + } + LineIndex { newlines } + } + + pub fn translate(&self, offset: TextUnit) -> LineCol { + let line = self.newlines.upper_bound(&offset) - 1; + let line_start_offset = self.newlines[line]; + let col = offset - line_start_offset; + return LineCol { line: line as u32, col } + } +} + +#[test] +fn test_line_index() { + let text = "hello\nworld"; + let index = LineIndex::new(text); + assert_eq!(index.translate(0.into()), LineCol { line: 0, col: 0.into()}); + assert_eq!(index.translate(1.into()), LineCol { line: 0, col: 1.into()}); + assert_eq!(index.translate(5.into()), LineCol { line: 0, col: 5.into()}); + assert_eq!(index.translate(6.into()), LineCol { line: 1, col: 0.into()}); + assert_eq!(index.translate(7.into()), LineCol { line: 1, col: 1.into()}); + assert_eq!(index.translate(8.into()), LineCol { line: 1, col: 2.into()}); + assert_eq!(index.translate(10.into()), LineCol { line: 1, col: 4.into()}); + assert_eq!(index.translate(11.into()), LineCol { line: 1, col: 5.into()}); + assert_eq!(index.translate(12.into()), LineCol { line: 1, col: 6.into()}); + + let text = "\nhello\nworld"; + let index = LineIndex::new(text); + assert_eq!(index.translate(0.into()), LineCol { line: 0, col: 0.into()}); + assert_eq!(index.translate(1.into()), LineCol { line: 1, col: 0.into()}); + assert_eq!(index.translate(2.into()), LineCol { line: 1, col: 1.into()}); + assert_eq!(index.translate(6.into()), LineCol { line: 1, col: 5.into()}); + assert_eq!(index.translate(7.into()), LineCol { line: 2, col: 0.into()}); +} -- cgit v1.2.3