diff --git a/src/parser/org_source.rs b/src/parser/org_source.rs index 9789c8ea..db252d41 100644 --- a/src/parser/org_source.rs +++ b/src/parser/org_source.rs @@ -18,6 +18,7 @@ pub struct OrgSource<'s> { end: usize, // exclusive start_of_line: usize, preceding_character: Option, + line_number: usize, } impl<'s> OrgSource<'s> { @@ -31,6 +32,7 @@ impl<'s> OrgSource<'s> { end: input.len(), start_of_line: 0, preceding_character: None, + line_number: 1, } } @@ -56,6 +58,10 @@ impl<'s> OrgSource<'s> { assert!(other.end <= self.end); self.slice(..(other.start - self.start)) } + + pub fn get_line_number(&self) -> usize { + self.line_number + } } impl<'s> InputTake for OrgSource<'s> { @@ -119,10 +125,14 @@ where } let skipped_text = &self.full_source[self.start..new_start]; - let start_of_line = skipped_text - .rfind('\n') - .map(|idx| self.start + idx + 1) - .unwrap_or(self.start_of_line); + let mut start_of_line = self.start_of_line; + let mut line_number = self.line_number; + for (offset, character) in skipped_text.char_indices() { + if character == '\n' { + start_of_line = self.start + offset + 1; + line_number += 1; + } + } OrgSource { full_source: self.full_source, @@ -130,6 +140,7 @@ where end: new_end, start_of_line, preceding_character: skipped_text.chars().last(), + line_number, } } } @@ -369,4 +380,13 @@ mod tests { assert_eq!(input.get_preceding_character(), None); assert_eq!(input.slice(8..).get_preceding_character(), Some('💛')); } + + #[test] + fn line_number() { + let input = OrgSource::new("lorem\nfoo\nbar\nbaz\nipsum"); + assert_eq!(input.get_line_number(), 1); + assert_eq!(input.slice(5..).get_line_number(), 1); + assert_eq!(input.slice(6..).get_line_number(), 2); + assert_eq!(input.slice(6..).slice(10..).get_line_number(), 4); + } }