on master help sign in
treewide: &RopeSlice -> RopeSlice. It's Copy so no reason to pass by ref
c9dd1c9Blaž Hrastnik
helix-core/src/graphemes.rs+7−7
@@ -26,7 +26,7 @@ pub fn grapheme_width(g: &str) -> usize {
26 }
26 }
27}
27}
28
28
29−pub fn nth_prev_grapheme_boundary(slice: &RopeSlice, char_idx: usize, n: usize) -> usize {
29+pub fn nth_prev_grapheme_boundary(slice: RopeSlice, char_idx: usize, n: usize) -> usize {
30 // TODO: implement this more efficiently. This has to do a lot of
30 // TODO: implement this more efficiently. This has to do a lot of
31 // re-scanning of rope chunks. Probably move the main implementation here,
31 // re-scanning of rope chunks. Probably move the main implementation here,
32 // and have prev_grapheme_boundary call this instead.
32 // and have prev_grapheme_boundary call this instead.
@@ -38,7 +38,7 @@ pub fn nth_prev_grapheme_boundary(slice: &RopeSlice, char_idx: usize, n: usize)
38}
38}
39
39
40/// Finds the previous grapheme boundary before the given char position.
40/// Finds the previous grapheme boundary before the given char position.
41−pub fn prev_grapheme_boundary(slice: &RopeSlice, char_idx: usize) -> usize {
41+pub fn prev_grapheme_boundary(slice: RopeSlice, char_idx: usize) -> usize {
42 // Bounds check
42 // Bounds check
43 debug_assert!(char_idx <= slice.len_chars());
43 debug_assert!(char_idx <= slice.len_chars());
44
44
@@ -74,7 +74,7 @@ pub fn prev_grapheme_boundary(slice: &RopeSlice, char_idx: usize) -> usize {
74 }
74 }
75}
75}
76
76
77−pub fn nth_next_grapheme_boundary(slice: &RopeSlice, char_idx: usize, n: usize) -> usize {
77+pub fn nth_next_grapheme_boundary(slice: RopeSlice, char_idx: usize, n: usize) -> usize {
78 // TODO: implement this more efficiently. This has to do a lot of
78 // TODO: implement this more efficiently. This has to do a lot of
79 // re-scanning of rope chunks. Probably move the main implementation here,
79 // re-scanning of rope chunks. Probably move the main implementation here,
80 // and have next_grapheme_boundary call this instead.
80 // and have next_grapheme_boundary call this instead.
@@ -86,7 +86,7 @@ pub fn nth_next_grapheme_boundary(slice: &RopeSlice, char_idx: usize, n: usize)
86}
86}
87
87
88/// Finds the next grapheme boundary after the given char position.
88/// Finds the next grapheme boundary after the given char position.
89−pub fn next_grapheme_boundary(slice: &RopeSlice, char_idx: usize) -> usize {
89+pub fn next_grapheme_boundary(slice: RopeSlice, char_idx: usize) -> usize {
90 // Bounds check
90 // Bounds check
91 debug_assert!(char_idx <= slice.len_chars());
91 debug_assert!(char_idx <= slice.len_chars());
92
92
@@ -123,7 +123,7 @@ pub fn next_grapheme_boundary(slice: &RopeSlice, char_idx: usize) -> usize {
123}
123}
124
124
125/// Returns whether the given char position is a grapheme boundary.
125/// Returns whether the given char position is a grapheme boundary.
126−pub fn is_grapheme_boundary(slice: &RopeSlice, char_idx: usize) -> bool {
126+pub fn is_grapheme_boundary(slice: RopeSlice, char_idx: usize) -> bool {
127 // Bounds check
127 // Bounds check
128 debug_assert!(char_idx <= slice.len_chars());
128 debug_assert!(char_idx <= slice.len_chars());
129
129
@@ -160,11 +160,11 @@ pub struct RopeGraphemes<'a> {
160}
160}
161
161
162impl<'a> RopeGraphemes<'a> {
162impl<'a> RopeGraphemes<'a> {
163− pub fn new<'b>(slice: &RopeSlice<'b>) -> RopeGraphemes<'b> {
163+ pub fn new<'b>(slice: RopeSlice<'b>) -> RopeGraphemes<'b> {
164 let mut chunks = slice.chunks();
164 let mut chunks = slice.chunks();
165 let first_chunk = chunks.next().unwrap_or("");
165 let first_chunk = chunks.next().unwrap_or("");
166 RopeGraphemes {
166 RopeGraphemes {
167− text: *slice,
167+ text: slice,
168 chunks,
168 chunks,
169 cur_chunk: first_chunk,
169 cur_chunk: first_chunk,
170 cur_chunk_start: 0,
170 cur_chunk_start: 0,
helix-core/src/indent.rs+8−23
@@ -1,4 +1,5 @@
1use crate::{
1use crate::{
2+ find_first_non_whitespace_char,
2 syntax::Syntax,
3 syntax::Syntax,
3 tree_sitter::{Node, Tree},
4 tree_sitter::{Node, Tree},
4 Rope, RopeSlice, State,
5 Rope, RopeSlice, State,
@@ -9,7 +10,7 @@ use crate::{
9
10
10pub const TAB_WIDTH: usize = 4;
11pub const TAB_WIDTH: usize = 4;
11
12
12−fn indent_level_for_line(line: &RopeSlice) -> usize {
13+fn indent_level_for_line(line: RopeSlice) -> usize {
13 let mut len = 0;
14 let mut len = 0;
14 for ch in line.chars() {
15 for ch in line.chars() {
15 match ch {
16 match ch {
@@ -159,27 +160,11 @@ fn calculate_indentation(node: Option<Node>, newline: bool) -> usize {
159 increment as usize
160 increment as usize
160}
161}
161
162
162−fn find_first_non_whitespace_char(state: &State, line_num: usize) -> Option<usize> {
163− let line = state.doc.line(line_num);
164− let mut start = state.doc.line_to_char(line_num);
165−
166− // find first non-whitespace char
167− for ch in line.chars() {
168− // TODO: could use memchr with chunks?
169− if ch != ' ' && ch != '\t' && ch != '\n' {
170− return Some(start);
171− }
172− start += 1;
173− }
174−
175− None
176−}
177−
178fn suggested_indent_for_line(syntax: Option<&Syntax>, state: &State, line_num: usize) -> usize {
163fn suggested_indent_for_line(syntax: Option<&Syntax>, state: &State, line_num: usize) -> usize {
179 let line = state.doc.line(line_num);
164 let line = state.doc.line(line_num);
180− let current = indent_level_for_line(&line);
165+ let current = indent_level_for_line(line);
181
166
182− if let Some(start) = find_first_non_whitespace_char(state, line_num) {
167+ if let Some(start) = find_first_non_whitespace_char(state.doc.slice(..), line_num) {
183 return suggested_indent_for_pos(syntax, state, start, false);
168 return suggested_indent_for_pos(syntax, state, start, false);
184 };
169 };
185
170
@@ -216,12 +201,12 @@ mod test {
216 #[test]
201 #[test]
217 fn test_indent_level() {
202 fn test_indent_level() {
218 let line = Rope::from(" fn new"); // 8 spaces
203 let line = Rope::from(" fn new"); // 8 spaces
219− assert_eq!(indent_level_for_line(&line.slice(..)), 2);
204+ assert_eq!(indent_level_for_line(line.slice(..)), 2);
220 let line = Rope::from("\t\t\tfn new"); // 3 tabs
205 let line = Rope::from("\t\t\tfn new"); // 3 tabs
221− assert_eq!(indent_level_for_line(&line.slice(..)), 3);
206+ assert_eq!(indent_level_for_line(line.slice(..)), 3);
222 // mixed indentation
207 // mixed indentation
223 let line = Rope::from("\t \tfn new"); // 1 tab, 4 spaces, tab
208 let line = Rope::from("\t \tfn new"); // 1 tab, 4 spaces, tab
224− assert_eq!(indent_level_for_line(&line.slice(..)), 3);
209+ assert_eq!(indent_level_for_line(line.slice(..)), 3);
225 }
210 }
226
211
227 #[test]
212 #[test]
@@ -306,7 +291,7 @@ where
306
291
307 for i in 0..state.doc.len_lines() {
292 for i in 0..state.doc.len_lines() {
308 let line = text.line(i);
293 let line = text.line(i);
309− let indent = indent_level_for_line(&line);
294+ let indent = indent_level_for_line(line);
310 assert_eq!(
295 assert_eq!(
311 suggested_indent_for_line(Some(&syntax), &state, i),
296 suggested_indent_for_line(Some(&syntax), &state, i),
312 indent,
297 indent,
helix-core/src/lib.rs+30
@@ -11,6 +11,36 @@ pub mod state;
11pub mod syntax;
11pub mod syntax;
12mod transaction;
12mod transaction;
13
13
14+pub(crate) fn find_first_non_whitespace_char2(line: RopeSlice) -> Option<usize> {
15+ let mut start = 0;
16+
17+ // find first non-whitespace char
18+ for ch in line.chars() {
19+ // TODO: could use memchr with chunks?
20+ if ch != ' ' && ch != '\t' && ch != '\n' {
21+ return Some(start);
22+ }
23+ start += 1;
24+ }
25+
26+ None
27+}
28+pub(crate) fn find_first_non_whitespace_char(text: RopeSlice, line_num: usize) -> Option<usize> {
29+ let line = text.line(line_num);
30+ let mut start = text.line_to_char(line_num);
31+
32+ // find first non-whitespace char
33+ for ch in line.chars() {
34+ // TODO: could use memchr with chunks?
35+ if ch != ' ' && ch != '\t' && ch != '\n' {
36+ return Some(start);
37+ }
38+ start += 1;
39+ }
40+
41+ None
42+}
43+
14pub use ropey::{Rope, RopeSlice};
44pub use ropey::{Rope, RopeSlice};
15
45
16pub use tendril::StrTendril as Tendril;
46pub use tendril::StrTendril as Tendril;
helix-core/src/selection.rs+8−8
@@ -120,7 +120,7 @@ impl Range {
120 // groupAt
120 // groupAt
121
121
122 #[inline]
122 #[inline]
123− pub fn fragment<'a>(&'a self, text: &'a RopeSlice) -> Cow<'a, str> {
123+ pub fn fragment<'a>(&'a self, text: RopeSlice<'a>) -> Cow<'a, str> {
124 Cow::from(text.slice(self.from()..self.to() + 1))
124 Cow::from(text.slice(self.from()..self.to() + 1))
125 }
125 }
126}
126}
@@ -267,7 +267,7 @@ impl Selection {
267 )
267 )
268 }
268 }
269
269
270− pub fn fragments<'a>(&'a self, text: &'a RopeSlice) -> impl Iterator<Item = Cow<str>> + 'a {
270+ pub fn fragments<'a>(&'a self, text: RopeSlice<'a>) -> impl Iterator<Item = Cow<str>> + 'a {
271 self.ranges.iter().map(move |range| range.fragment(text))
271 self.ranges.iter().map(move |range| range.fragment(text))
272 }
272 }
273}
273}
@@ -275,7 +275,7 @@ impl Selection {
275// TODO: checkSelection -> check if valid for doc length
275// TODO: checkSelection -> check if valid for doc length
276
276
277pub fn select_on_matches(
277pub fn select_on_matches(
278− text: &RopeSlice,
278+ text: RopeSlice,
279 selections: &Selection,
279 selections: &Selection,
280 regex: &crate::regex::Regex,
280 regex: &crate::regex::Regex,
281) -> Option<Selection> {
281) -> Option<Selection> {
@@ -283,7 +283,7 @@ pub fn select_on_matches(
283
283
284 for sel in selections.ranges() {
284 for sel in selections.ranges() {
285 // TODO: can't avoid occasional allocations since Regex can't operate on chunks yet
285 // TODO: can't avoid occasional allocations since Regex can't operate on chunks yet
286− let fragment = sel.fragment(&text);
286+ let fragment = sel.fragment(text);
287
287
288 let mut sel_start = sel.from();
288 let mut sel_start = sel.from();
289 let sel_end = sel.to();
289 let sel_end = sel.to();
@@ -309,7 +309,7 @@ pub fn select_on_matches(
309
309
310// TODO: support to split on capture #N instead of whole match
310// TODO: support to split on capture #N instead of whole match
311pub fn split_on_matches(
311pub fn split_on_matches(
312− text: &RopeSlice,
312+ text: RopeSlice,
313 selections: &Selection,
313 selections: &Selection,
314 regex: &crate::regex::Regex,
314 regex: &crate::regex::Regex,
315) -> Selection {
315) -> Selection {
@@ -317,7 +317,7 @@ pub fn split_on_matches(
317
317
318 for sel in selections.ranges() {
318 for sel in selections.ranges() {
319 // TODO: can't avoid occasional allocations since Regex can't operate on chunks yet
319 // TODO: can't avoid occasional allocations since Regex can't operate on chunks yet
320− let fragment = sel.fragment(&text);
320+ let fragment = sel.fragment(text);
321
321
322 let mut sel_start = sel.from();
322 let mut sel_start = sel.from();
323 let sel_end = sel.to();
323 let sel_end = sel.to();
@@ -420,7 +420,7 @@ mod test {
420
420
421 let selections = Selection::new(smallvec![Range::new(0, 8), Range::new(10, 19),], 0);
421 let selections = Selection::new(smallvec![Range::new(0, 8), Range::new(10, 19),], 0);
422
422
423− let result = split_on_matches(&text.slice(..), &selections, &Regex::new(r"\s+").unwrap());
423+ let result = split_on_matches(text.slice(..), &selections, &Regex::new(r"\s+").unwrap());
424
424
425 assert_eq!(
425 assert_eq!(
426 result.ranges(),
426 result.ranges(),
@@ -434,7 +434,7 @@ mod test {
434 );
434 );
435
435
436 assert_eq!(
436 assert_eq!(
437− result.fragments(&text.slice(..)).collect::<Vec<_>>(),
437+ result.fragments(text.slice(..)).collect::<Vec<_>>(),
438 &["abcd", "efg", "rs", "xyz", "1"]
438 &["abcd", "efg", "rs", "xyz", "1"]
439 );
439 );
440 }
440 }
helix-core/src/state.rs+26−24
@@ -101,7 +101,7 @@ impl State {
101 let line = text.char_to_line(pos);
101 let line = text.char_to_line(pos);
102 let start = text.line_to_char(line);
102 let start = text.line_to_char(line);
103 let pos = std::cmp::max(
103 let pos = std::cmp::max(
104− nth_prev_grapheme_boundary(&text.slice(..), pos, count),
104+ nth_prev_grapheme_boundary(text.slice(..), pos, count),
105 start,
105 start,
106 );
106 );
107 Range::new(if extend { range.anchor } else { pos }, pos)
107 Range::new(if extend { range.anchor } else { pos }, pos)
@@ -113,14 +113,14 @@ impl State {
113 // subtract another 1 because the line ends with \n
113 // subtract another 1 because the line ends with \n
114 let end = text.line_to_char(line + 1).saturating_sub(2);
114 let end = text.line_to_char(line + 1).saturating_sub(2);
115 let pos =
115 let pos =
116− std::cmp::min(nth_next_grapheme_boundary(&text.slice(..), pos, count), end);
116+ std::cmp::min(nth_next_grapheme_boundary(text.slice(..), pos, count), end);
117 Range::new(if extend { range.anchor } else { pos }, pos)
117 Range::new(if extend { range.anchor } else { pos }, pos)
118 }
118 }
119− (_, Granularity::Line) => move_vertically(&text.slice(..), dir, range, count, extend),
119+ (_, Granularity::Line) => move_vertically(text.slice(..), dir, range, count, extend),
120 }
120 }
121 }
121 }
122
122
123− pub fn move_next_word_start(slice: &RopeSlice, mut pos: usize) -> usize {
123+ pub fn move_next_word_start(slice: RopeSlice, mut pos: usize) -> usize {
124 // TODO: confirm it's fine without using graphemes, I think it should be
124 // TODO: confirm it's fine without using graphemes, I think it should be
125 let ch = slice.char(pos);
125 let ch = slice.char(pos);
126 let next = slice.char(pos.saturating_add(1));
126 let next = slice.char(pos.saturating_add(1));
@@ -143,7 +143,7 @@ impl State {
143 pos
143 pos
144 }
144 }
145
145
146− pub fn move_prev_word_start(slice: &RopeSlice, mut pos: usize) -> usize {
146+ pub fn move_prev_word_start(slice: RopeSlice, mut pos: usize) -> usize {
147 // TODO: confirm it's fine without using graphemes, I think it should be
147 // TODO: confirm it's fine without using graphemes, I think it should be
148 let ch = slice.char(pos);
148 let ch = slice.char(pos);
149 let prev = slice.char(pos.saturating_sub(1)); // TODO: just return original pos if at start
149 let prev = slice.char(pos.saturating_sub(1)); // TODO: just return original pos if at start
@@ -169,7 +169,7 @@ impl State {
169 pos.saturating_add(1)
169 pos.saturating_add(1)
170 }
170 }
171
171
172− pub fn move_next_word_end(slice: &RopeSlice, mut pos: usize, _count: usize) -> usize {
172+ pub fn move_next_word_end(slice: RopeSlice, mut pos: usize, _count: usize) -> usize {
173 // TODO: confirm it's fine without using graphemes, I think it should be
173 // TODO: confirm it's fine without using graphemes, I think it should be
174 let ch = slice.char(pos);
174 let ch = slice.char(pos);
175 let next = slice.char(pos.saturating_add(1));
175 let next = slice.char(pos.saturating_add(1));
@@ -217,7 +217,7 @@ impl State {
217}
217}
218
218
219/// Convert a character index to (line, column) coordinates.
219/// Convert a character index to (line, column) coordinates.
220−pub fn coords_at_pos(text: &RopeSlice, pos: usize) -> Position {
220+pub fn coords_at_pos(text: RopeSlice, pos: usize) -> Position {
221 let line = text.char_to_line(pos);
221 let line = text.char_to_line(pos);
222 let line_start = text.line_to_char(line);
222 let line_start = text.line_to_char(line);
223 let col = text.slice(line_start..pos).len_chars();
223 let col = text.slice(line_start..pos).len_chars();
@@ -225,14 +225,14 @@ pub fn coords_at_pos(text: &RopeSlice, pos: usize) -> Position {
225}
225}
226
226
227/// Convert (line, column) coordinates to a character index.
227/// Convert (line, column) coordinates to a character index.
228−pub fn pos_at_coords(text: &RopeSlice, coords: Position) -> usize {
228+pub fn pos_at_coords(text: RopeSlice, coords: Position) -> usize {
229 let Position { row, col } = coords;
229 let Position { row, col } = coords;
230 let line_start = text.line_to_char(row);
230 let line_start = text.line_to_char(row);
231 nth_next_grapheme_boundary(text, line_start, col)
231 nth_next_grapheme_boundary(text, line_start, col)
232}
232}
233
233
234fn move_vertically(
234fn move_vertically(
235− text: &RopeSlice,
235+ text: RopeSlice,
236 dir: Direction,
236 dir: Direction,
237 range: Range,
237 range: Range,
238 count: usize,
238 count: usize,
@@ -287,7 +287,7 @@ fn categorize(ch: char) -> Category {
287 }
287 }
288}
288}
289
289
290−fn skip_over_next<F>(slice: &RopeSlice, pos: &mut usize, fun: F)
290+fn skip_over_next<F>(slice: RopeSlice, pos: &mut usize, fun: F)
291where
291where
292 F: Fn(char) -> bool,
292 F: Fn(char) -> bool,
293{
293{
@@ -301,7 +301,7 @@ where
301 }
301 }
302}
302}
303
303
304−fn skip_over_prev<F>(slice: &RopeSlice, pos: &mut usize, fun: F)
304+fn skip_over_prev<F>(slice: RopeSlice, pos: &mut usize, fun: F)
305where
305where
306 F: Fn(char) -> bool,
306 F: Fn(char) -> bool,
307{
307{
@@ -323,34 +323,36 @@ mod test {
323 #[test]
323 #[test]
324 fn test_coords_at_pos() {
324 fn test_coords_at_pos() {
325 let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
325 let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
326− assert_eq!(coords_at_pos(&text.slice(..), 0), (0, 0).into());
326+ let slice = text.slice(..);
327+ assert_eq!(coords_at_pos(slice, 0), (0, 0).into());
327− assert_eq!(coords_at_pos(&text.slice(..), 5), (0, 5).into()); // position on \n
328+ assert_eq!(coords_at_pos(slice, 5), (0, 5).into()); // position on \n
328− assert_eq!(coords_at_pos(&text.slice(..), 6), (1, 0).into()); // position on w
329+ assert_eq!(coords_at_pos(slice, 6), (1, 0).into()); // position on w
329− assert_eq!(coords_at_pos(&text.slice(..), 7), (1, 1).into()); // position on o
330+ assert_eq!(coords_at_pos(slice, 7), (1, 1).into()); // position on o
330− assert_eq!(coords_at_pos(&text.slice(..), 10), (1, 4).into()); // position on d
331+ assert_eq!(coords_at_pos(slice, 10), (1, 4).into()); // position on d
331 }
332 }
332
333
333 #[test]
334 #[test]
334 fn test_pos_at_coords() {
335 fn test_pos_at_coords() {
335 let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
336 let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
336− assert_eq!(pos_at_coords(&text.slice(..), (0, 0).into()), 0);
337+ let slice = text.slice(..);
338+ assert_eq!(pos_at_coords(slice, (0, 0).into()), 0);
337− assert_eq!(pos_at_coords(&text.slice(..), (0, 5).into()), 5); // position on \n
339+ assert_eq!(pos_at_coords(slice, (0, 5).into()), 5); // position on \n
338− assert_eq!(pos_at_coords(&text.slice(..), (1, 0).into()), 6); // position on w
340+ assert_eq!(pos_at_coords(slice, (1, 0).into()), 6); // position on w
339− assert_eq!(pos_at_coords(&text.slice(..), (1, 1).into()), 7); // position on o
341+ assert_eq!(pos_at_coords(slice, (1, 1).into()), 7); // position on o
340− assert_eq!(pos_at_coords(&text.slice(..), (1, 4).into()), 10); // position on d
342+ assert_eq!(pos_at_coords(slice, (1, 4).into()), 10); // position on d
341 }
343 }
342
344
343 #[test]
345 #[test]
344 fn test_vertical_move() {
346 fn test_vertical_move() {
345 let text = Rope::from("abcd\nefg\nwrs");
347 let text = Rope::from("abcd\nefg\nwrs");
346− let pos = pos_at_coords(&text.slice(..), (0, 4).into());
347 let slice = text.slice(..);
348 let slice = text.slice(..);
349+ let pos = pos_at_coords(slice, (0, 4).into());
348
350
349 let range = Range::new(pos, pos);
351 let range = Range::new(pos, pos);
350 assert_eq!(
352 assert_eq!(
351 coords_at_pos(
353 coords_at_pos(
352− &slice,
354+ slice,
353− move_vertically(&slice, Direction::Forward, range, 1, false).head
355+ move_vertically(slice, Direction::Forward, range, 1, false).head
354 ),
356 ),
355 (1, 2).into()
357 (1, 2).into()
356 );
358 );
helix-core/src/syntax.rs+9−9
@@ -406,7 +406,7 @@ impl LanguageLayer {
406 }
406 }
407
407
408 pub(crate) fn generate_edits(
408 pub(crate) fn generate_edits(
409− old_text: &RopeSlice,
409+ old_text: RopeSlice,
410 changeset: &ChangeSet,
410 changeset: &ChangeSet,
411 ) -> Vec<tree_sitter::InputEdit> {
411 ) -> Vec<tree_sitter::InputEdit> {
412 use Operation::*;
412 use Operation::*;
@@ -419,7 +419,7 @@ impl LanguageLayer {
419
419
420 // TODO; this is a lot easier with Change instead of Operation.
420 // TODO; this is a lot easier with Change instead of Operation.
421
421
422− fn point_at_pos(text: &RopeSlice, pos: usize) -> (usize, Point) {
422+ fn point_at_pos(text: RopeSlice, pos: usize) -> (usize, Point) {
423 let byte = text.char_to_byte(pos); // <- attempted to index past end
423 let byte = text.char_to_byte(pos); // <- attempted to index past end
424 let line = text.char_to_line(pos);
424 let line = text.char_to_line(pos);
425 let line_start_byte = text.line_to_byte(line);
425 let line_start_byte = text.line_to_byte(line);
@@ -458,8 +458,8 @@ impl LanguageLayer {
458 new_pos += len;
458 new_pos += len;
459 }
459 }
460 Delete(_) => {
460 Delete(_) => {
461− let (start_byte, start_position) = point_at_pos(&old_text, old_pos);
461+ let (start_byte, start_position) = point_at_pos(old_text, old_pos);
462− let (old_end_byte, old_end_position) = point_at_pos(&old_text, old_end);
462+ let (old_end_byte, old_end_position) = point_at_pos(old_text, old_end);
463
463
464 // TODO: Position also needs to be byte based...
464 // TODO: Position also needs to be byte based...
465 // let byte = char_to_byte(old_pos)
465 // let byte = char_to_byte(old_pos)
@@ -478,14 +478,14 @@ impl LanguageLayer {
478 });
478 });
479 }
479 }
480 Insert(s) => {
480 Insert(s) => {
481− let (start_byte, start_position) = point_at_pos(&old_text, old_pos);
481+ let (start_byte, start_position) = point_at_pos(old_text, old_pos);
482
482
483 let ins = s.chars().count();
483 let ins = s.chars().count();
484
484
485 // a subsequent delete means a replace, consume it
485 // a subsequent delete means a replace, consume it
486 if let Some(Delete(len)) = iter.peek() {
486 if let Some(Delete(len)) = iter.peek() {
487 old_end = old_pos + len;
487 old_end = old_pos + len;
488− let (old_end_byte, old_end_position) = point_at_pos(&old_text, old_end);
488+ let (old_end_byte, old_end_position) = point_at_pos(old_text, old_end);
489
489
490 iter.next();
490 iter.next();
491
491
@@ -530,7 +530,7 @@ impl LanguageLayer {
530 return Ok(());
530 return Ok(());
531 }
531 }
532
532
533− let edits = Self::generate_edits(&old_source.slice(..), changeset);
533+ let edits = Self::generate_edits(old_source.slice(..), changeset);
534
534
535 // Notify the tree about all the changes
535 // Notify the tree about all the changes
536 for edit in edits {
536 for edit in edits {
@@ -1528,7 +1528,7 @@ fn test_input_edits() {
1528 &state,
1528 &state,
1529 vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(),
1529 vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(),
1530 );
1530 );
1531− let edits = LanguageLayer::generate_edits(&state.doc.slice(..), &transaction.changes);
1531+ let edits = LanguageLayer::generate_edits(state.doc.slice(..), &transaction.changes);
1532 // transaction.apply(&mut state);
1532 // transaction.apply(&mut state);
1533
1533
1534 assert_eq!(
1534 assert_eq!(
@@ -1556,7 +1556,7 @@ fn test_input_edits() {
1556 // Testing with the official example from tree-sitter
1556 // Testing with the official example from tree-sitter
1557 let mut state = State::new("fn test() {}".into());
1557 let mut state = State::new("fn test() {}".into());
1558 let transaction = Transaction::change(&state, vec![(8, 8, Some("a: u32".into()))].into_iter());
1558 let transaction = Transaction::change(&state, vec![(8, 8, Some("a: u32".into()))].into_iter());
1559− let edits = LanguageLayer::generate_edits(&state.doc.slice(..), &transaction.changes);
1559+ let edits = LanguageLayer::generate_edits(state.doc.slice(..), &transaction.changes);
1560 transaction.apply(&mut state);
1560 transaction.apply(&mut state);
1561
1561
1562 assert_eq!(state.doc(), "fn test(a: u32) {}");
1562 assert_eq!(state.doc(), "fn test(a: u32) {}");
helix-lsp/src/client.rs+2−2
@@ -303,7 +303,7 @@ impl Client {
303 new_pos += i;
303 new_pos += i;
304 }
304 }
305 Delete(_) => {
305 Delete(_) => {
306− let start = pos_to_lsp_pos(&new_text, new_pos);
306+ let start = pos_to_lsp_pos(new_text, new_pos);
307 let end = traverse(start, old_text.slice(old_pos..old_end));
307 let end = traverse(start, old_text.slice(old_pos..old_end));
308
308
309 // deletion
309 // deletion
@@ -314,7 +314,7 @@ impl Client {
314 });
314 });
315 }
315 }
316 Insert(s) => {
316 Insert(s) => {
317− let start = pos_to_lsp_pos(&new_text, new_pos);
317+ let start = pos_to_lsp_pos(new_text, new_pos);
318
318
319 new_pos += s.chars().count();
319 new_pos += s.chars().count();
320
320
helix-lsp/src/lib.rs+4−4
@@ -30,12 +30,12 @@ pub mod util {
30 use super::*;
30 use super::*;
31 use helix_core::{RopeSlice, State, Transaction};
31 use helix_core::{RopeSlice, State, Transaction};
32
32
33− pub fn lsp_pos_to_pos(doc: &RopeSlice, pos: lsp::Position) -> usize {
33+ pub fn lsp_pos_to_pos(doc: RopeSlice, pos: lsp::Position) -> usize {
34 let line = doc.line_to_char(pos.line as usize);
34 let line = doc.line_to_char(pos.line as usize);
35 let line_start = doc.char_to_utf16_cu(line);
35 let line_start = doc.char_to_utf16_cu(line);
36 doc.utf16_cu_to_char(pos.character as usize + line_start)
36 doc.utf16_cu_to_char(pos.character as usize + line_start)
37 }
37 }
38− pub fn pos_to_lsp_pos(doc: &RopeSlice, pos: usize) -> lsp::Position {
38+ pub fn pos_to_lsp_pos(doc: RopeSlice, pos: usize) -> lsp::Position {
39 let line = doc.char_to_line(pos);
39 let line = doc.char_to_line(pos);
40 let line_start = doc.char_to_utf16_cu(doc.line_to_char(line));
40 let line_start = doc.char_to_utf16_cu(doc.line_to_char(line));
41 let col = doc.char_to_utf16_cu(pos) - line_start;
41 let col = doc.char_to_utf16_cu(pos) - line_start;
@@ -58,8 +58,8 @@ pub mod util {
58 None
58 None
59 };
59 };
60
60
61− let start = lsp_pos_to_pos(&doc, edit.range.start);
61+ let start = lsp_pos_to_pos(doc, edit.range.start);
62− let end = lsp_pos_to_pos(&doc, edit.range.end);
62+ let end = lsp_pos_to_pos(doc, edit.range.end);
63 (start, end, replacement)
63 (start, end, replacement)
64 }),
64 }),
65 )
65 )
helix-term/src/application.rs+2−2
@@ -147,8 +147,8 @@ impl Application {
147 .into_iter()
147 .into_iter()
148 .map(|diagnostic| {
148 .map(|diagnostic| {
149 use helix_lsp::util::lsp_pos_to_pos;
149 use helix_lsp::util::lsp_pos_to_pos;
150− let start = lsp_pos_to_pos(&doc, diagnostic.range.start);
150+ let start = lsp_pos_to_pos(doc, diagnostic.range.start);
151− let end = lsp_pos_to_pos(&doc, diagnostic.range.end);
151+ let end = lsp_pos_to_pos(doc, diagnostic.range.end);
152
152
153 helix_core::Diagnostic {
153 helix_core::Diagnostic {
154 range: (start, end),
154 range: (start, end),
helix-term/src/commands.rs+15−15
@@ -117,7 +117,7 @@ pub fn move_next_word_start(cx: &mut Context) {
117 let count = cx.count;
117 let count = cx.count;
118 let doc = cx.doc();
118 let doc = cx.doc();
119 // TODO: count
119 // TODO: count
120− let pos = State::move_next_word_start(&doc.text().slice(..), doc.selection().cursor());
120+ let pos = State::move_next_word_start(doc.text().slice(..), doc.selection().cursor());
121
121
122 doc.set_selection(Selection::point(pos));
122 doc.set_selection(Selection::point(pos));
123}
123}
@@ -125,7 +125,7 @@ pub fn move_next_word_start(cx: &mut Context) {
125pub fn move_prev_word_start(cx: &mut Context) {
125pub fn move_prev_word_start(cx: &mut Context) {
126 let count = cx.count;
126 let count = cx.count;
127 let doc = cx.doc();
127 let doc = cx.doc();
128− let pos = State::move_prev_word_start(&doc.text().slice(..), doc.selection().cursor());
128+ let pos = State::move_prev_word_start(doc.text().slice(..), doc.selection().cursor());
129
129
130 doc.set_selection(Selection::point(pos));
130 doc.set_selection(Selection::point(pos));
131}
131}
@@ -133,7 +133,7 @@ pub fn move_prev_word_start(cx: &mut Context) {
133pub fn move_next_word_end(cx: &mut Context) {
133pub fn move_next_word_end(cx: &mut Context) {
134 let count = cx.count;
134 let count = cx.count;
135 let doc = cx.doc();
135 let doc = cx.doc();
136− let pos = State::move_next_word_end(&doc.text().slice(..), doc.selection().cursor(), count);
136+ let pos = State::move_next_word_end(doc.text().slice(..), doc.selection().cursor(), count);
137
137
138 doc.set_selection(Selection::point(pos));
138 doc.set_selection(Selection::point(pos));
139}
139}
@@ -156,7 +156,7 @@ pub fn extend_next_word_start(cx: &mut Context) {
156 let count = cx.count;
156 let count = cx.count;
157 let doc = cx.doc();
157 let doc = cx.doc();
158 let mut selection = doc.selection().transform(|mut range| {
158 let mut selection = doc.selection().transform(|mut range| {
159− let pos = State::move_next_word_start(&doc.text().slice(..), doc.selection().cursor());
159+ let pos = State::move_next_word_start(doc.text().slice(..), doc.selection().cursor());
160 range.head = pos;
160 range.head = pos;
161 range
161 range
162 }); // TODO: count
162 }); // TODO: count
@@ -168,7 +168,7 @@ pub fn extend_prev_word_start(cx: &mut Context) {
168 let count = cx.count;
168 let count = cx.count;
169 let doc = cx.doc();
169 let doc = cx.doc();
170 let mut selection = doc.selection().transform(|mut range| {
170 let mut selection = doc.selection().transform(|mut range| {
171− let pos = State::move_prev_word_start(&doc.text().slice(..), doc.selection().cursor());
171+ let pos = State::move_prev_word_start(doc.text().slice(..), doc.selection().cursor());
172 range.head = pos;
172 range.head = pos;
173 range
173 range
174 }); // TODO: count
174 }); // TODO: count
@@ -179,7 +179,7 @@ pub fn extend_next_word_end(cx: &mut Context) {
179 let count = cx.count;
179 let count = cx.count;
180 let doc = cx.doc();
180 let doc = cx.doc();
181 let mut selection = doc.selection().transform(|mut range| {
181 let mut selection = doc.selection().transform(|mut range| {
182− let pos = State::move_next_word_end(&doc.text().slice(..), doc.selection().cursor(), count);
182+ let pos = State::move_next_word_end(doc.text().slice(..), doc.selection().cursor(), count);
183 range.head = pos;
183 range.head = pos;
184 range
184 range
185 }); // TODO: count
185 }); // TODO: count
@@ -303,7 +303,7 @@ pub fn select_all(cx: &mut Context) {
303
303
304pub fn select_regex(cx: &mut Context) {
304pub fn select_regex(cx: &mut Context) {
305 let prompt = ui::regex_prompt(cx, "select:".to_string(), |doc, regex| {
305 let prompt = ui::regex_prompt(cx, "select:".to_string(), |doc, regex| {
306− let text = &doc.text().slice(..);
306+ let text = doc.text().slice(..);
307 // TODO: if select on matches returns empty range, we need to abort
307 // TODO: if select on matches returns empty range, we need to abort
308 let selection =
308 let selection =
309 selection::select_on_matches(text, doc.selection(), &regex).expect("no matches");
309 selection::select_on_matches(text, doc.selection(), &regex).expect("no matches");
@@ -331,7 +331,7 @@ pub fn split_selection(cx: &mut Context) {
331 // }
331 // }
332
332
333 let prompt = ui::regex_prompt(cx, "split:".to_string(), |doc, regex| {
333 let prompt = ui::regex_prompt(cx, "split:".to_string(), |doc, regex| {
334− let text = &doc.text().slice(..);
334+ let text = doc.text().slice(..);
335 let selection = selection::split_on_matches(text, doc.selection(), &regex);
335 let selection = selection::split_on_matches(text, doc.selection(), &regex);
336 doc.set_selection(selection);
336 doc.set_selection(selection);
337 });
337 });
@@ -345,7 +345,7 @@ pub fn split_selection(cx: &mut Context) {
345
345
346pub fn split_selection_on_newline(cx: &mut Context) {
346pub fn split_selection_on_newline(cx: &mut Context) {
347 let doc = cx.doc();
347 let doc = cx.doc();
348− let text = &doc.text().slice(..);
348+ let text = doc.text().slice(..);
349 // only compile the regex once
349 // only compile the regex once
350 #[allow(clippy::trivial_regex)]
350 #[allow(clippy::trivial_regex)]
351 static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap());
351 static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap());
@@ -489,7 +489,7 @@ pub fn append_mode(cx: &mut Context) {
489 doc.restore_cursor = true;
489 doc.restore_cursor = true;
490
490
491 // TODO: as transaction
491 // TODO: as transaction
492− let text = &doc.text().slice(..);
492+ let text = doc.text().slice(..);
493 let selection = doc.selection().transform(|range| {
493 let selection = doc.selection().transform(|range| {
494 // TODO: to() + next char
494 // TODO: to() + next char
495 Range::new(
495 Range::new(
@@ -721,7 +721,7 @@ pub fn normal_mode(cx: &mut Context) {
721
721
722 // if leaving append mode, move cursor back by 1
722 // if leaving append mode, move cursor back by 1
723 if doc.restore_cursor {
723 if doc.restore_cursor {
724− let text = &doc.text().slice(..);
724+ let text = doc.text().slice(..);
725 let selection = doc.selection().transform(|range| {
725 let selection = doc.selection().transform(|range| {
726 Range::new(
726 Range::new(
727 range.from(),
727 range.from(),
@@ -775,7 +775,7 @@ pub mod insert {
775 pub fn delete_char_backward(cx: &mut Context) {
775 pub fn delete_char_backward(cx: &mut Context) {
776 let count = cx.count;
776 let count = cx.count;
777 let doc = cx.doc();
777 let doc = cx.doc();
778− let text = &doc.text().slice(..);
778+ let text = doc.text().slice(..);
779 let transaction = Transaction::change_by_selection(&doc.state, |range| {
779 let transaction = Transaction::change_by_selection(&doc.state, |range| {
780 (
780 (
781 graphemes::nth_prev_grapheme_boundary(text, range.head, count),
781 graphemes::nth_prev_grapheme_boundary(text, range.head, count),
@@ -789,7 +789,7 @@ pub mod insert {
789 pub fn delete_char_forward(cx: &mut Context) {
789 pub fn delete_char_forward(cx: &mut Context) {
790 let count = cx.count;
790 let count = cx.count;
791 let doc = cx.doc();
791 let doc = cx.doc();
792− let text = &doc.text().slice(..);
792+ let text = doc.text().slice(..);
793 let transaction = Transaction::change_by_selection(&doc.state, |range| {
793 let transaction = Transaction::change_by_selection(&doc.state, |range| {
794 (
794 (
795 range.head,
795 range.head,
@@ -826,7 +826,7 @@ pub fn yank(cx: &mut Context) {
826 let values = doc
826 let values = doc
827 .state
827 .state
828 .selection()
828 .selection()
829− .fragments(&doc.text().slice(..))
829+ .fragments(doc.text().slice(..))
830 .map(|cow| cow.into_owned())
830 .map(|cow| cow.into_owned())
831 .collect();
831 .collect();
832
832
@@ -978,7 +978,7 @@ pub fn completion(cx: &mut Context) {
978 let doc = cx.doc();
978 let doc = cx.doc();
979
979
980 // TODO: blocking here is not ideal
980 // TODO: blocking here is not ideal
981− let pos = helix_lsp::util::pos_to_lsp_pos(&doc.text().slice(..), doc.selection().cursor());
981+ let pos = helix_lsp::util::pos_to_lsp_pos(doc.text().slice(..), doc.selection().cursor());
982
982
983 // TODO: handle fails
983 // TODO: handle fails
984 let res =
984 let res =
helix-term/src/ui/editor.rs+4−4
@@ -134,7 +134,7 @@ impl EditorView {
134 let mut char_index = start;
134 let mut char_index = start;
135
135
136 // iterate over range char by char
136 // iterate over range char by char
137− for grapheme in RopeGraphemes::new(&text) {
137+ for grapheme in RopeGraphemes::new(text) {
138 // TODO: track current char_index
138 // TODO: track current char_index
139
139
140 if grapheme == "\n" {
140 if grapheme == "\n" {
@@ -211,8 +211,8 @@ impl EditorView {
211 .filter(|range| range.overlaps(&screen))
211 .filter(|range| range.overlaps(&screen))
212 {
212 {
213 // TODO: render also if only one of the ranges is in viewport
213 // TODO: render also if only one of the ranges is in viewport
214− let mut start = view.screen_coords_at_pos(&text, selection.anchor);
214+ let mut start = view.screen_coords_at_pos(text, selection.anchor);
215− let mut end = view.screen_coords_at_pos(&text, selection.head);
215+ let mut end = view.screen_coords_at_pos(text, selection.head);
216
216
217 // cursor
217 // cursor
218 if let Some(end) = end {
218 if let Some(end) = end {
@@ -439,7 +439,7 @@ impl Component for EditorView {
439 let cursor = view.doc.state.selection().cursor();
439 let cursor = view.doc.state.selection().cursor();
440
440
441 let mut pos = view
441 let mut pos = view
442− .screen_coords_at_pos(&view.doc.text().slice(..), cursor)
442+ .screen_coords_at_pos(view.doc.text().slice(..), cursor)
443 .expect("Cursor is out of bounds.");
443 .expect("Cursor is out of bounds.");
444 pos.col += view.area.x as usize + area.x as usize + OFFSET as usize;
444 pos.col += view.area.x as usize + area.x as usize + OFFSET as usize;
445 pos.row += view.area.y as usize + area.y as usize;
445 pos.row += view.area.y as usize + area.y as usize;
helix-view/src/view.rs+3−3
@@ -61,7 +61,7 @@ impl View {
61 /// Translates a document position to an absolute position in the terminal.
61 /// Translates a document position to an absolute position in the terminal.
62 /// Returns a (line, col) position if the position is visible on screen.
62 /// Returns a (line, col) position if the position is visible on screen.
63 // TODO: Could return width as well for the character width at cursor.
63 // TODO: Could return width as well for the character width at cursor.
64− pub fn screen_coords_at_pos(&self, text: &RopeSlice, pos: usize) -> Option<Position> {
64+ pub fn screen_coords_at_pos(&self, text: RopeSlice, pos: usize) -> Option<Position> {
65 let line = text.char_to_line(pos);
65 let line = text.char_to_line(pos);
66
66
67 if line < self.first_line as usize || line > self.last_line() {
67 if line < self.first_line as usize || line > self.last_line() {
@@ -73,7 +73,7 @@ impl View {
73 let line_slice = text.slice(line_start..pos);
73 let line_slice = text.slice(line_start..pos);
74 let mut col = 0;
74 let mut col = 0;
75
75
76− for grapheme in RopeGraphemes::new(&line_slice) {
76+ for grapheme in RopeGraphemes::new(line_slice) {
77 if grapheme == "\t" {
77 if grapheme == "\t" {
78 col += TAB_WIDTH;
78 col += TAB_WIDTH;
79 } else {
79 } else {
@@ -87,7 +87,7 @@ impl View {
87 Some(Position::new(row, col))
87 Some(Position::new(row, col))
88 }
88 }
89
89
90− // pub fn traverse<F>(&self, text: &RopeSlice, start: usize, end: usize, fun: F)
90+ // pub fn traverse<F>(&self, text: RopeSlice, start: usize, end: usize, fun: F)
91 // where
91 // where
92 // F: Fn(usize, usize),
92 // F: Fn(usize, usize),
93 // {
93 // {