diff options
Diffstat (limited to 'crates/ra_editor/src')
-rw-r--r-- | crates/ra_editor/src/line_index.rs | 14 | ||||
-rw-r--r-- | crates/ra_editor/src/line_index_utils.rs | 102 |
2 files changed, 68 insertions, 48 deletions
diff --git a/crates/ra_editor/src/line_index.rs b/crates/ra_editor/src/line_index.rs index c29e2e49a..6dbabd97e 100644 --- a/crates/ra_editor/src/line_index.rs +++ b/crates/ra_editor/src/line_index.rs | |||
@@ -4,8 +4,8 @@ use superslice::Ext; | |||
4 | 4 | ||
5 | #[derive(Clone, Debug, PartialEq, Eq)] | 5 | #[derive(Clone, Debug, PartialEq, Eq)] |
6 | pub struct LineIndex { | 6 | pub struct LineIndex { |
7 | newlines: Vec<TextUnit>, | 7 | pub(crate) newlines: Vec<TextUnit>, |
8 | utf16_lines: FxHashMap<u32, Vec<Utf16Char>>, | 8 | pub(crate) utf16_lines: FxHashMap<u32, Vec<Utf16Char>>, |
9 | } | 9 | } |
10 | 10 | ||
11 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 11 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
@@ -120,16 +120,6 @@ impl LineIndex { | |||
120 | 120 | ||
121 | col | 121 | col |
122 | } | 122 | } |
123 | |||
124 | pub(crate) fn newlines(&self) -> &[TextUnit] { | ||
125 | &self.newlines[..] | ||
126 | } | ||
127 | |||
128 | pub(crate) fn utf16_chars(&self, newline_idx: usize) -> Option<&[Utf16Char]> { | ||
129 | self.utf16_lines | ||
130 | .get(&(newline_idx as u32)) | ||
131 | .map(|x| x.as_slice()) | ||
132 | } | ||
133 | } | 123 | } |
134 | 124 | ||
135 | #[test] | 125 | #[test] |
diff --git a/crates/ra_editor/src/line_index_utils.rs b/crates/ra_editor/src/line_index_utils.rs index 9c8d801e9..382f3ac72 100644 --- a/crates/ra_editor/src/line_index_utils.rs +++ b/crates/ra_editor/src/line_index_utils.rs | |||
@@ -9,18 +9,17 @@ enum Step { | |||
9 | Utf16Char(TextRange), | 9 | Utf16Char(TextRange), |
10 | } | 10 | } |
11 | 11 | ||
12 | #[derive(Debug)] | ||
12 | struct LineIndexStepIter<'a> { | 13 | struct LineIndexStepIter<'a> { |
13 | line_index: &'a LineIndex, | 14 | line_index: &'a LineIndex, |
14 | newlines: std::slice::Iter<'a, TextUnit>, | ||
15 | next_newline_idx: usize, | 15 | next_newline_idx: usize, |
16 | utf16_chars: Option<std::slice::Iter<'a, Utf16Char>>, | 16 | utf16_chars: Option<(TextUnit, std::slice::Iter<'a, Utf16Char>)>, |
17 | } | 17 | } |
18 | 18 | ||
19 | impl<'a> LineIndexStepIter<'a> { | 19 | impl<'a> LineIndexStepIter<'a> { |
20 | fn from(line_index: &LineIndex) -> LineIndexStepIter { | 20 | fn from(line_index: &LineIndex) -> LineIndexStepIter { |
21 | let mut x = LineIndexStepIter { | 21 | let mut x = LineIndexStepIter { |
22 | line_index, | 22 | line_index, |
23 | newlines: line_index.newlines().iter(), | ||
24 | next_newline_idx: 0, | 23 | next_newline_idx: 0, |
25 | utf16_chars: None, | 24 | utf16_chars: None, |
26 | }; | 25 | }; |
@@ -35,20 +34,22 @@ impl<'a> Iterator for LineIndexStepIter<'a> { | |||
35 | fn next(&mut self) -> Option<Step> { | 34 | fn next(&mut self) -> Option<Step> { |
36 | self.utf16_chars | 35 | self.utf16_chars |
37 | .as_mut() | 36 | .as_mut() |
38 | .and_then(|x| { | 37 | .and_then(|(newline, x)| { |
39 | None | 38 | let x = x.next()?; |
40 | // TODO Enable | 39 | Some(Step::Utf16Char(TextRange::from_to( |
41 | // let x = x.next()?; | 40 | *newline + x.start, |
42 | // Some(Step::Utf16Char(TextRange::from_to(x.start, x.end))) | 41 | *newline + x.end, |
42 | ))) | ||
43 | }) | 43 | }) |
44 | .or_else(|| { | 44 | .or_else(|| { |
45 | let next_newline = *self.line_index.newlines.get(self.next_newline_idx)?; | ||
45 | self.utf16_chars = self | 46 | self.utf16_chars = self |
46 | .line_index | 47 | .line_index |
47 | .utf16_chars(self.next_newline_idx) | 48 | .utf16_lines |
48 | .map(|x| x.iter()); | 49 | .get(&(self.next_newline_idx as u32)) |
50 | .map(|x| (next_newline, x.iter())); | ||
49 | self.next_newline_idx += 1; | 51 | self.next_newline_idx += 1; |
50 | let x = self.newlines.next()?; | 52 | Some(Step::Newline(next_newline)) |
51 | Some(Step::Newline(*x)) | ||
52 | }) | 53 | }) |
53 | } | 54 | } |
54 | } | 55 | } |
@@ -71,18 +72,16 @@ impl<'a> Iterator for OffsetNewlineIter<'a> { | |||
71 | let next = Step::Newline(next_offset); | 72 | let next = Step::Newline(next_offset); |
72 | Some((next, next_offset)) | 73 | Some((next, next_offset)) |
73 | } else { | 74 | } else { |
74 | None | 75 | let char_len = TextUnit::of_char(c); |
75 | // TODO enable | 76 | if char_len.to_usize() > 1 { |
76 | // let char_len = TextUnit::of_char(c); | 77 | let start = self.offset + TextUnit::from_usize(i); |
77 | // if char_len.to_usize() > 1 { | 78 | let end = start + char_len; |
78 | // let start = self.offset + TextUnit::from_usize(i); | 79 | let next = Step::Utf16Char(TextRange::from_to(start, end)); |
79 | // let end = start + char_len; | 80 | let next_offset = end; |
80 | // let next = Step::Utf16Char(TextRange::from_to(start, end)); | 81 | Some((next, next_offset)) |
81 | // let next_offset = end; | 82 | } else { |
82 | // Some((next, next_offset)) | 83 | None |
83 | // } else { | 84 | } |
84 | // None | ||
85 | // } | ||
86 | } | 85 | } |
87 | }) | 86 | }) |
88 | .next()?; | 87 | .next()?; |
@@ -155,7 +154,7 @@ impl<'a, 'b> Edits<'a, 'b> { | |||
155 | fn next_step(&mut self, step: &Step) -> NextNewlines { | 154 | fn next_step(&mut self, step: &Step) -> NextNewlines { |
156 | let step_pos = match step { | 155 | let step_pos = match step { |
157 | &Step::Newline(n) => n, | 156 | &Step::Newline(n) => n, |
158 | &Step::Utf16Char(r) => unimplemented!(), | 157 | &Step::Utf16Char(r) => r.start(), |
159 | }; | 158 | }; |
160 | let res = match &mut self.current { | 159 | let res = match &mut self.current { |
161 | Some(edit) => { | 160 | Some(edit) => { |
@@ -215,7 +214,11 @@ impl<'a, 'b> Edits<'a, 'b> { | |||
215 | } | 214 | } |
216 | } | 215 | } |
217 | 216 | ||
218 | pub fn count_newlines(offset: TextUnit, line_index: &LineIndex, edits: &[AtomTextEdit]) -> u32 { | 217 | pub fn translate_offset_with_edit( |
218 | line_index: &LineIndex, | ||
219 | offset: TextUnit, | ||
220 | edits: &[AtomTextEdit], | ||
221 | ) -> LineCol { | ||
219 | let mut sorted_edits: Vec<&AtomTextEdit> = Vec::with_capacity(edits.len()); | 222 | let mut sorted_edits: Vec<&AtomTextEdit> = Vec::with_capacity(edits.len()); |
220 | for edit in edits { | 223 | for edit in edits { |
221 | let insert_index = | 224 | let insert_index = |
@@ -225,29 +228,55 @@ pub fn count_newlines(offset: TextUnit, line_index: &LineIndex, edits: &[AtomTex | |||
225 | 228 | ||
226 | let mut state = Edits::new(&sorted_edits); | 229 | let mut state = Edits::new(&sorted_edits); |
227 | 230 | ||
228 | let mut lines: u32 = 0; | 231 | let mut pos: LineCol = LineCol { |
232 | line: 0, | ||
233 | col_utf16: 0, | ||
234 | }; | ||
235 | |||
236 | let mut last_newline: TextUnit = TextUnit::from(0); | ||
237 | let mut col_adjust: TextUnit = TextUnit::from(0); | ||
229 | 238 | ||
230 | macro_rules! test_step { | 239 | macro_rules! test_step { |
231 | ($x:ident) => { | 240 | ($x:ident) => { |
232 | match &$x { | 241 | match &$x { |
233 | Step::Newline(n) => { | 242 | Step::Newline(n) => { |
234 | if offset < *n { | 243 | if offset < *n { |
235 | return lines; | 244 | return_pos!(); |
245 | } else if offset == *n { | ||
246 | pos.line += 1; | ||
247 | pos.col_utf16 = 0; | ||
248 | return pos; | ||
236 | } else { | 249 | } else { |
237 | lines += 1; | 250 | pos.line += 1; |
251 | pos.col_utf16 = 0; | ||
252 | last_newline = *n; | ||
253 | col_adjust = TextUnit::from(0); | ||
254 | } | ||
255 | } | ||
256 | Step::Utf16Char(x) => { | ||
257 | if offset < x.end() { | ||
258 | return_pos!(); | ||
259 | } else { | ||
260 | col_adjust += x.len() - TextUnit::from(1); | ||
238 | } | 261 | } |
239 | } | 262 | } |
240 | Step::Utf16Char(x) => unimplemented!(), | ||
241 | } | 263 | } |
242 | }; | 264 | }; |
243 | } | 265 | } |
244 | 266 | ||
267 | macro_rules! return_pos { | ||
268 | () => { | ||
269 | pos.col_utf16 = ((offset - last_newline) - col_adjust).into(); | ||
270 | return pos; | ||
271 | }; | ||
272 | } | ||
273 | |||
245 | for orig_step in LineIndexStepIter::from(line_index) { | 274 | for orig_step in LineIndexStepIter::from(line_index) { |
246 | loop { | 275 | loop { |
247 | let translated_newline = state.translate_step(&orig_step); | 276 | let translated_step = state.translate_step(&orig_step); |
248 | match state.next_step(&translated_newline) { | 277 | match state.next_step(&translated_step) { |
249 | NextNewlines::Use => { | 278 | NextNewlines::Use => { |
250 | test_step!(translated_newline); | 279 | test_step!(translated_step); |
251 | break; | 280 | break; |
252 | } | 281 | } |
253 | NextNewlines::ReplaceMany(ns) => { | 282 | NextNewlines::ReplaceMany(ns) => { |
@@ -276,7 +305,7 @@ pub fn count_newlines(offset: TextUnit, line_index: &LineIndex, edits: &[AtomTex | |||
276 | } | 305 | } |
277 | } | 306 | } |
278 | 307 | ||
279 | lines | 308 | return_pos!(); |
280 | } | 309 | } |
281 | 310 | ||
282 | // for bench | 311 | // for bench |
@@ -337,8 +366,9 @@ mod test { | |||
337 | fn test_translate_offset_with_edit(x in arb_text_with_offset_and_edits()) { | 366 | fn test_translate_offset_with_edit(x in arb_text_with_offset_and_edits()) { |
338 | let line_index = LineIndex::new(&x.text); | 367 | let line_index = LineIndex::new(&x.text); |
339 | let expected = translate_after_edit(&x.text, x.offset, x.edits.clone()); | 368 | let expected = translate_after_edit(&x.text, x.offset, x.edits.clone()); |
340 | let actual_lines = count_newlines(x.offset, &line_index, &x.edits); | 369 | let actual = translate_offset_with_edit(&line_index, x.offset, &x.edits); |
341 | assert_eq!(actual_lines, expected.line); | 370 | // assert_eq!(actual, expected); |
371 | assert_eq!(actual.line, expected.line); | ||
342 | } | 372 | } |
343 | } | 373 | } |
344 | } | 374 | } |