2018-10-15 17:05:26 +00:00
|
|
|
use crate::TextUnit;
|
2018-10-15 21:44:23 +00:00
|
|
|
use superslice::Ext;
|
2018-08-10 18:13:39 +00:00
|
|
|
|
2018-10-07 10:18:25 +00:00
|
|
|
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
2018-08-10 18:13:39 +00:00
|
|
|
pub struct LineIndex {
|
|
|
|
newlines: Vec<TextUnit>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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 }
|
|
|
|
}
|
|
|
|
|
2018-08-10 19:23:17 +00:00
|
|
|
pub fn line_col(&self, offset: TextUnit) -> LineCol {
|
2018-08-10 18:13:39 +00:00
|
|
|
let line = self.newlines.upper_bound(&offset) - 1;
|
|
|
|
let line_start_offset = self.newlines[line];
|
|
|
|
let col = offset - line_start_offset;
|
2018-10-16 15:51:58 +00:00
|
|
|
LineCol {
|
2018-10-15 21:44:23 +00:00
|
|
|
line: line as u32,
|
|
|
|
col,
|
2018-10-16 15:51:58 +00:00
|
|
|
}
|
2018-08-10 19:23:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn offset(&self, line_col: LineCol) -> TextUnit {
|
|
|
|
//TODO: return Result
|
|
|
|
self.newlines[line_col.line as usize] + line_col.col
|
2018-08-10 18:13:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_line_index() {
|
|
|
|
let text = "hello\nworld";
|
|
|
|
let index = LineIndex::new(text);
|
2018-10-15 21:44:23 +00:00
|
|
|
assert_eq!(
|
|
|
|
index.line_col(0.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 0,
|
|
|
|
col: 0.into()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index.line_col(1.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 0,
|
|
|
|
col: 1.into()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index.line_col(5.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 0,
|
|
|
|
col: 5.into()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index.line_col(6.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 1,
|
|
|
|
col: 0.into()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index.line_col(7.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 1,
|
|
|
|
col: 1.into()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index.line_col(8.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 1,
|
|
|
|
col: 2.into()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index.line_col(10.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 1,
|
|
|
|
col: 4.into()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index.line_col(11.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 1,
|
|
|
|
col: 5.into()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index.line_col(12.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 1,
|
|
|
|
col: 6.into()
|
|
|
|
}
|
|
|
|
);
|
2018-08-10 18:13:39 +00:00
|
|
|
|
|
|
|
let text = "\nhello\nworld";
|
|
|
|
let index = LineIndex::new(text);
|
2018-10-15 21:44:23 +00:00
|
|
|
assert_eq!(
|
|
|
|
index.line_col(0.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 0,
|
|
|
|
col: 0.into()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index.line_col(1.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 1,
|
|
|
|
col: 0.into()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index.line_col(2.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 1,
|
|
|
|
col: 1.into()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index.line_col(6.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 1,
|
|
|
|
col: 5.into()
|
|
|
|
}
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
index.line_col(7.into()),
|
|
|
|
LineCol {
|
|
|
|
line: 2,
|
|
|
|
col: 0.into()
|
|
|
|
}
|
|
|
|
);
|
2018-08-10 18:13:39 +00:00
|
|
|
}
|