treewide: &RopeSlice -> RopeSlice. It's Copy so no reason to pass by ref

pull/8/head
Blaž Hrastnik 4 years ago
parent bd85460698
commit c9dd1c930e

@ -26,7 +26,7 @@ pub fn grapheme_width(g: &str) -> usize {
} }
} }
pub fn nth_prev_grapheme_boundary(slice: &RopeSlice, char_idx: usize, n: usize) -> usize { pub fn nth_prev_grapheme_boundary(slice: RopeSlice, char_idx: usize, n: usize) -> usize {
// TODO: implement this more efficiently. This has to do a lot of // TODO: implement this more efficiently. This has to do a lot of
// re-scanning of rope chunks. Probably move the main implementation here, // re-scanning of rope chunks. Probably move the main implementation here,
// and have prev_grapheme_boundary call this instead. // 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)
} }
/// Finds the previous grapheme boundary before the given char position. /// Finds the previous grapheme boundary before the given char position.
pub fn prev_grapheme_boundary(slice: &RopeSlice, char_idx: usize) -> usize { pub fn prev_grapheme_boundary(slice: RopeSlice, char_idx: usize) -> usize {
// Bounds check // Bounds check
debug_assert!(char_idx <= slice.len_chars()); debug_assert!(char_idx <= slice.len_chars());
@ -74,7 +74,7 @@ pub fn prev_grapheme_boundary(slice: &RopeSlice, char_idx: usize) -> usize {
} }
} }
pub fn nth_next_grapheme_boundary(slice: &RopeSlice, char_idx: usize, n: usize) -> usize { pub fn nth_next_grapheme_boundary(slice: RopeSlice, char_idx: usize, n: usize) -> usize {
// TODO: implement this more efficiently. This has to do a lot of // TODO: implement this more efficiently. This has to do a lot of
// re-scanning of rope chunks. Probably move the main implementation here, // re-scanning of rope chunks. Probably move the main implementation here,
// and have next_grapheme_boundary call this instead. // 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)
} }
/// Finds the next grapheme boundary after the given char position. /// Finds the next grapheme boundary after the given char position.
pub fn next_grapheme_boundary(slice: &RopeSlice, char_idx: usize) -> usize { pub fn next_grapheme_boundary(slice: RopeSlice, char_idx: usize) -> usize {
// Bounds check // Bounds check
debug_assert!(char_idx <= slice.len_chars()); debug_assert!(char_idx <= slice.len_chars());
@ -123,7 +123,7 @@ pub fn next_grapheme_boundary(slice: &RopeSlice, char_idx: usize) -> usize {
} }
/// Returns whether the given char position is a grapheme boundary. /// Returns whether the given char position is a grapheme boundary.
pub fn is_grapheme_boundary(slice: &RopeSlice, char_idx: usize) -> bool { pub fn is_grapheme_boundary(slice: RopeSlice, char_idx: usize) -> bool {
// Bounds check // Bounds check
debug_assert!(char_idx <= slice.len_chars()); debug_assert!(char_idx <= slice.len_chars());
@ -160,11 +160,11 @@ pub struct RopeGraphemes<'a> {
} }
impl<'a> RopeGraphemes<'a> { impl<'a> RopeGraphemes<'a> {
pub fn new<'b>(slice: &RopeSlice<'b>) -> RopeGraphemes<'b> { pub fn new<'b>(slice: RopeSlice<'b>) -> RopeGraphemes<'b> {
let mut chunks = slice.chunks(); let mut chunks = slice.chunks();
let first_chunk = chunks.next().unwrap_or(""); let first_chunk = chunks.next().unwrap_or("");
RopeGraphemes { RopeGraphemes {
text: *slice, text: slice,
chunks, chunks,
cur_chunk: first_chunk, cur_chunk: first_chunk,
cur_chunk_start: 0, cur_chunk_start: 0,

@ -1,4 +1,5 @@
use crate::{ use crate::{
find_first_non_whitespace_char,
syntax::Syntax, syntax::Syntax,
tree_sitter::{Node, Tree}, tree_sitter::{Node, Tree},
Rope, RopeSlice, State, Rope, RopeSlice, State,
@ -9,7 +10,7 @@ use crate::{
pub const TAB_WIDTH: usize = 4; pub const TAB_WIDTH: usize = 4;
fn indent_level_for_line(line: &RopeSlice) -> usize { fn indent_level_for_line(line: RopeSlice) -> usize {
let mut len = 0; let mut len = 0;
for ch in line.chars() { for ch in line.chars() {
match ch { match ch {
@ -159,27 +160,11 @@ fn calculate_indentation(node: Option<Node>, newline: bool) -> usize {
increment as usize increment as usize
} }
fn find_first_non_whitespace_char(state: &State, line_num: usize) -> Option<usize> {
let line = state.doc.line(line_num);
let mut start = state.doc.line_to_char(line_num);
// find first non-whitespace char
for ch in line.chars() {
// TODO: could use memchr with chunks?
if ch != ' ' && ch != '\t' && ch != '\n' {
return Some(start);
}
start += 1;
}
None
}
fn suggested_indent_for_line(syntax: Option<&Syntax>, state: &State, line_num: usize) -> usize { fn suggested_indent_for_line(syntax: Option<&Syntax>, state: &State, line_num: usize) -> usize {
let line = state.doc.line(line_num); let line = state.doc.line(line_num);
let current = indent_level_for_line(&line); let current = indent_level_for_line(line);
if let Some(start) = find_first_non_whitespace_char(state, line_num) { if let Some(start) = find_first_non_whitespace_char(state.doc.slice(..), line_num) {
return suggested_indent_for_pos(syntax, state, start, false); return suggested_indent_for_pos(syntax, state, start, false);
}; };
@ -216,12 +201,12 @@ mod test {
#[test] #[test]
fn test_indent_level() { fn test_indent_level() {
let line = Rope::from(" fn new"); // 8 spaces let line = Rope::from(" fn new"); // 8 spaces
assert_eq!(indent_level_for_line(&line.slice(..)), 2); assert_eq!(indent_level_for_line(line.slice(..)), 2);
let line = Rope::from("\t\t\tfn new"); // 3 tabs let line = Rope::from("\t\t\tfn new"); // 3 tabs
assert_eq!(indent_level_for_line(&line.slice(..)), 3); assert_eq!(indent_level_for_line(line.slice(..)), 3);
// mixed indentation // mixed indentation
let line = Rope::from("\t \tfn new"); // 1 tab, 4 spaces, tab let line = Rope::from("\t \tfn new"); // 1 tab, 4 spaces, tab
assert_eq!(indent_level_for_line(&line.slice(..)), 3); assert_eq!(indent_level_for_line(line.slice(..)), 3);
} }
#[test] #[test]
@ -306,7 +291,7 @@ where
for i in 0..state.doc.len_lines() { for i in 0..state.doc.len_lines() {
let line = text.line(i); let line = text.line(i);
let indent = indent_level_for_line(&line); let indent = indent_level_for_line(line);
assert_eq!( assert_eq!(
suggested_indent_for_line(Some(&syntax), &state, i), suggested_indent_for_line(Some(&syntax), &state, i),
indent, indent,

@ -11,6 +11,36 @@ pub mod state;
pub mod syntax; pub mod syntax;
mod transaction; mod transaction;
pub(crate) fn find_first_non_whitespace_char2(line: RopeSlice) -> Option<usize> {
let mut start = 0;
// find first non-whitespace char
for ch in line.chars() {
// TODO: could use memchr with chunks?
if ch != ' ' && ch != '\t' && ch != '\n' {
return Some(start);
}
start += 1;
}
None
}
pub(crate) fn find_first_non_whitespace_char(text: RopeSlice, line_num: usize) -> Option<usize> {
let line = text.line(line_num);
let mut start = text.line_to_char(line_num);
// find first non-whitespace char
for ch in line.chars() {
// TODO: could use memchr with chunks?
if ch != ' ' && ch != '\t' && ch != '\n' {
return Some(start);
}
start += 1;
}
None
}
pub use ropey::{Rope, RopeSlice}; pub use ropey::{Rope, RopeSlice};
pub use tendril::StrTendril as Tendril; pub use tendril::StrTendril as Tendril;

@ -120,7 +120,7 @@ impl Range {
// groupAt // groupAt
#[inline] #[inline]
pub fn fragment<'a>(&'a self, text: &'a RopeSlice) -> Cow<'a, str> { pub fn fragment<'a>(&'a self, text: RopeSlice<'a>) -> Cow<'a, str> {
Cow::from(text.slice(self.from()..self.to() + 1)) Cow::from(text.slice(self.from()..self.to() + 1))
} }
} }
@ -267,7 +267,7 @@ impl Selection {
) )
} }
pub fn fragments<'a>(&'a self, text: &'a RopeSlice) -> impl Iterator<Item = Cow<str>> + 'a { pub fn fragments<'a>(&'a self, text: RopeSlice<'a>) -> impl Iterator<Item = Cow<str>> + 'a {
self.ranges.iter().map(move |range| range.fragment(text)) self.ranges.iter().map(move |range| range.fragment(text))
} }
} }
@ -275,7 +275,7 @@ impl Selection {
// TODO: checkSelection -> check if valid for doc length // TODO: checkSelection -> check if valid for doc length
pub fn select_on_matches( pub fn select_on_matches(
text: &RopeSlice, text: RopeSlice,
selections: &Selection, selections: &Selection,
regex: &crate::regex::Regex, regex: &crate::regex::Regex,
) -> Option<Selection> { ) -> Option<Selection> {
@ -283,7 +283,7 @@ pub fn select_on_matches(
for sel in selections.ranges() { for sel in selections.ranges() {
// TODO: can't avoid occasional allocations since Regex can't operate on chunks yet // TODO: can't avoid occasional allocations since Regex can't operate on chunks yet
let fragment = sel.fragment(&text); let fragment = sel.fragment(text);
let mut sel_start = sel.from(); let mut sel_start = sel.from();
let sel_end = sel.to(); let sel_end = sel.to();
@ -309,7 +309,7 @@ pub fn select_on_matches(
// TODO: support to split on capture #N instead of whole match // TODO: support to split on capture #N instead of whole match
pub fn split_on_matches( pub fn split_on_matches(
text: &RopeSlice, text: RopeSlice,
selections: &Selection, selections: &Selection,
regex: &crate::regex::Regex, regex: &crate::regex::Regex,
) -> Selection { ) -> Selection {
@ -317,7 +317,7 @@ pub fn split_on_matches(
for sel in selections.ranges() { for sel in selections.ranges() {
// TODO: can't avoid occasional allocations since Regex can't operate on chunks yet // TODO: can't avoid occasional allocations since Regex can't operate on chunks yet
let fragment = sel.fragment(&text); let fragment = sel.fragment(text);
let mut sel_start = sel.from(); let mut sel_start = sel.from();
let sel_end = sel.to(); let sel_end = sel.to();
@ -420,7 +420,7 @@ mod test {
let selections = Selection::new(smallvec![Range::new(0, 8), Range::new(10, 19),], 0); let selections = Selection::new(smallvec![Range::new(0, 8), Range::new(10, 19),], 0);
let result = split_on_matches(&text.slice(..), &selections, &Regex::new(r"\s+").unwrap()); let result = split_on_matches(text.slice(..), &selections, &Regex::new(r"\s+").unwrap());
assert_eq!( assert_eq!(
result.ranges(), result.ranges(),
@ -434,7 +434,7 @@ mod test {
); );
assert_eq!( assert_eq!(
result.fragments(&text.slice(..)).collect::<Vec<_>>(), result.fragments(text.slice(..)).collect::<Vec<_>>(),
&["abcd", "efg", "rs", "xyz", "1"] &["abcd", "efg", "rs", "xyz", "1"]
); );
} }

@ -101,7 +101,7 @@ impl State {
let line = text.char_to_line(pos); let line = text.char_to_line(pos);
let start = text.line_to_char(line); let start = text.line_to_char(line);
let pos = std::cmp::max( let pos = std::cmp::max(
nth_prev_grapheme_boundary(&text.slice(..), pos, count), nth_prev_grapheme_boundary(text.slice(..), pos, count),
start, start,
); );
Range::new(if extend { range.anchor } else { pos }, pos) Range::new(if extend { range.anchor } else { pos }, pos)
@ -113,14 +113,14 @@ impl State {
// subtract another 1 because the line ends with \n // subtract another 1 because the line ends with \n
let end = text.line_to_char(line + 1).saturating_sub(2); let end = text.line_to_char(line + 1).saturating_sub(2);
let pos = let pos =
std::cmp::min(nth_next_grapheme_boundary(&text.slice(..), pos, count), end); std::cmp::min(nth_next_grapheme_boundary(text.slice(..), pos, count), end);
Range::new(if extend { range.anchor } else { pos }, pos) Range::new(if extend { range.anchor } else { pos }, pos)
} }
(_, Granularity::Line) => move_vertically(&text.slice(..), dir, range, count, extend), (_, Granularity::Line) => move_vertically(text.slice(..), dir, range, count, extend),
} }
} }
pub fn move_next_word_start(slice: &RopeSlice, mut pos: usize) -> usize { pub fn move_next_word_start(slice: RopeSlice, mut pos: usize) -> usize {
// TODO: confirm it's fine without using graphemes, I think it should be // TODO: confirm it's fine without using graphemes, I think it should be
let ch = slice.char(pos); let ch = slice.char(pos);
let next = slice.char(pos.saturating_add(1)); let next = slice.char(pos.saturating_add(1));
@ -143,7 +143,7 @@ impl State {
pos pos
} }
pub fn move_prev_word_start(slice: &RopeSlice, mut pos: usize) -> usize { pub fn move_prev_word_start(slice: RopeSlice, mut pos: usize) -> usize {
// TODO: confirm it's fine without using graphemes, I think it should be // TODO: confirm it's fine without using graphemes, I think it should be
let ch = slice.char(pos); let ch = slice.char(pos);
let prev = slice.char(pos.saturating_sub(1)); // TODO: just return original pos if at start let prev = slice.char(pos.saturating_sub(1)); // TODO: just return original pos if at start
@ -169,7 +169,7 @@ impl State {
pos.saturating_add(1) pos.saturating_add(1)
} }
pub fn move_next_word_end(slice: &RopeSlice, mut pos: usize, _count: usize) -> usize { pub fn move_next_word_end(slice: RopeSlice, mut pos: usize, _count: usize) -> usize {
// TODO: confirm it's fine without using graphemes, I think it should be // TODO: confirm it's fine without using graphemes, I think it should be
let ch = slice.char(pos); let ch = slice.char(pos);
let next = slice.char(pos.saturating_add(1)); let next = slice.char(pos.saturating_add(1));
@ -217,7 +217,7 @@ impl State {
} }
/// Convert a character index to (line, column) coordinates. /// Convert a character index to (line, column) coordinates.
pub fn coords_at_pos(text: &RopeSlice, pos: usize) -> Position { pub fn coords_at_pos(text: RopeSlice, pos: usize) -> Position {
let line = text.char_to_line(pos); let line = text.char_to_line(pos);
let line_start = text.line_to_char(line); let line_start = text.line_to_char(line);
let col = text.slice(line_start..pos).len_chars(); let col = text.slice(line_start..pos).len_chars();
@ -225,14 +225,14 @@ pub fn coords_at_pos(text: &RopeSlice, pos: usize) -> Position {
} }
/// Convert (line, column) coordinates to a character index. /// Convert (line, column) coordinates to a character index.
pub fn pos_at_coords(text: &RopeSlice, coords: Position) -> usize { pub fn pos_at_coords(text: RopeSlice, coords: Position) -> usize {
let Position { row, col } = coords; let Position { row, col } = coords;
let line_start = text.line_to_char(row); let line_start = text.line_to_char(row);
nth_next_grapheme_boundary(text, line_start, col) nth_next_grapheme_boundary(text, line_start, col)
} }
fn move_vertically( fn move_vertically(
text: &RopeSlice, text: RopeSlice,
dir: Direction, dir: Direction,
range: Range, range: Range,
count: usize, count: usize,
@ -287,7 +287,7 @@ fn categorize(ch: char) -> Category {
} }
} }
fn skip_over_next<F>(slice: &RopeSlice, pos: &mut usize, fun: F) fn skip_over_next<F>(slice: RopeSlice, pos: &mut usize, fun: F)
where where
F: Fn(char) -> bool, F: Fn(char) -> bool,
{ {
@ -301,7 +301,7 @@ where
} }
} }
fn skip_over_prev<F>(slice: &RopeSlice, pos: &mut usize, fun: F) fn skip_over_prev<F>(slice: RopeSlice, pos: &mut usize, fun: F)
where where
F: Fn(char) -> bool, F: Fn(char) -> bool,
{ {
@ -323,34 +323,36 @@ mod test {
#[test] #[test]
fn test_coords_at_pos() { fn test_coords_at_pos() {
let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ"); let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
assert_eq!(coords_at_pos(&text.slice(..), 0), (0, 0).into()); let slice = text.slice(..);
assert_eq!(coords_at_pos(&text.slice(..), 5), (0, 5).into()); // position on \n assert_eq!(coords_at_pos(slice, 0), (0, 0).into());
assert_eq!(coords_at_pos(&text.slice(..), 6), (1, 0).into()); // position on w assert_eq!(coords_at_pos(slice, 5), (0, 5).into()); // position on \n
assert_eq!(coords_at_pos(&text.slice(..), 7), (1, 1).into()); // position on o assert_eq!(coords_at_pos(slice, 6), (1, 0).into()); // position on w
assert_eq!(coords_at_pos(&text.slice(..), 10), (1, 4).into()); // position on d assert_eq!(coords_at_pos(slice, 7), (1, 1).into()); // position on o
assert_eq!(coords_at_pos(slice, 10), (1, 4).into()); // position on d
} }
#[test] #[test]
fn test_pos_at_coords() { fn test_pos_at_coords() {
let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ"); let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
assert_eq!(pos_at_coords(&text.slice(..), (0, 0).into()), 0); let slice = text.slice(..);
assert_eq!(pos_at_coords(&text.slice(..), (0, 5).into()), 5); // position on \n assert_eq!(pos_at_coords(slice, (0, 0).into()), 0);
assert_eq!(pos_at_coords(&text.slice(..), (1, 0).into()), 6); // position on w assert_eq!(pos_at_coords(slice, (0, 5).into()), 5); // position on \n
assert_eq!(pos_at_coords(&text.slice(..), (1, 1).into()), 7); // position on o assert_eq!(pos_at_coords(slice, (1, 0).into()), 6); // position on w
assert_eq!(pos_at_coords(&text.slice(..), (1, 4).into()), 10); // position on d assert_eq!(pos_at_coords(slice, (1, 1).into()), 7); // position on o
assert_eq!(pos_at_coords(slice, (1, 4).into()), 10); // position on d
} }
#[test] #[test]
fn test_vertical_move() { fn test_vertical_move() {
let text = Rope::from("abcd\nefg\nwrs"); let text = Rope::from("abcd\nefg\nwrs");
let pos = pos_at_coords(&text.slice(..), (0, 4).into());
let slice = text.slice(..); let slice = text.slice(..);
let pos = pos_at_coords(slice, (0, 4).into());
let range = Range::new(pos, pos); let range = Range::new(pos, pos);
assert_eq!( assert_eq!(
coords_at_pos( coords_at_pos(
&slice, slice,
move_vertically(&slice, Direction::Forward, range, 1, false).head move_vertically(slice, Direction::Forward, range, 1, false).head
), ),
(1, 2).into() (1, 2).into()
); );

@ -406,7 +406,7 @@ impl LanguageLayer {
} }
pub(crate) fn generate_edits( pub(crate) fn generate_edits(
old_text: &RopeSlice, old_text: RopeSlice,
changeset: &ChangeSet, changeset: &ChangeSet,
) -> Vec<tree_sitter::InputEdit> { ) -> Vec<tree_sitter::InputEdit> {
use Operation::*; use Operation::*;
@ -419,7 +419,7 @@ impl LanguageLayer {
// TODO; this is a lot easier with Change instead of Operation. // TODO; this is a lot easier with Change instead of Operation.
fn point_at_pos(text: &RopeSlice, pos: usize) -> (usize, Point) { fn point_at_pos(text: RopeSlice, pos: usize) -> (usize, Point) {
let byte = text.char_to_byte(pos); // <- attempted to index past end let byte = text.char_to_byte(pos); // <- attempted to index past end
let line = text.char_to_line(pos); let line = text.char_to_line(pos);
let line_start_byte = text.line_to_byte(line); let line_start_byte = text.line_to_byte(line);
@ -458,8 +458,8 @@ impl LanguageLayer {
new_pos += len; new_pos += len;
} }
Delete(_) => { Delete(_) => {
let (start_byte, start_position) = point_at_pos(&old_text, old_pos); let (start_byte, start_position) = point_at_pos(old_text, old_pos);
let (old_end_byte, old_end_position) = point_at_pos(&old_text, old_end); let (old_end_byte, old_end_position) = point_at_pos(old_text, old_end);
// TODO: Position also needs to be byte based... // TODO: Position also needs to be byte based...
// let byte = char_to_byte(old_pos) // let byte = char_to_byte(old_pos)
@ -478,14 +478,14 @@ impl LanguageLayer {
}); });
} }
Insert(s) => { Insert(s) => {
let (start_byte, start_position) = point_at_pos(&old_text, old_pos); let (start_byte, start_position) = point_at_pos(old_text, old_pos);
let ins = s.chars().count(); let ins = s.chars().count();
// a subsequent delete means a replace, consume it // a subsequent delete means a replace, consume it
if let Some(Delete(len)) = iter.peek() { if let Some(Delete(len)) = iter.peek() {
old_end = old_pos + len; old_end = old_pos + len;
let (old_end_byte, old_end_position) = point_at_pos(&old_text, old_end); let (old_end_byte, old_end_position) = point_at_pos(old_text, old_end);
iter.next(); iter.next();
@ -530,7 +530,7 @@ impl LanguageLayer {
return Ok(()); return Ok(());
} }
let edits = Self::generate_edits(&old_source.slice(..), changeset); let edits = Self::generate_edits(old_source.slice(..), changeset);
// Notify the tree about all the changes // Notify the tree about all the changes
for edit in edits { for edit in edits {
@ -1528,7 +1528,7 @@ fn test_input_edits() {
&state, &state,
vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(), vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(),
); );
let edits = LanguageLayer::generate_edits(&state.doc.slice(..), &transaction.changes); let edits = LanguageLayer::generate_edits(state.doc.slice(..), &transaction.changes);
// transaction.apply(&mut state); // transaction.apply(&mut state);
assert_eq!( assert_eq!(
@ -1556,7 +1556,7 @@ fn test_input_edits() {
// Testing with the official example from tree-sitter // Testing with the official example from tree-sitter
let mut state = State::new("fn test() {}".into()); let mut state = State::new("fn test() {}".into());
let transaction = Transaction::change(&state, vec![(8, 8, Some("a: u32".into()))].into_iter()); let transaction = Transaction::change(&state, vec![(8, 8, Some("a: u32".into()))].into_iter());
let edits = LanguageLayer::generate_edits(&state.doc.slice(..), &transaction.changes); let edits = LanguageLayer::generate_edits(state.doc.slice(..), &transaction.changes);
transaction.apply(&mut state); transaction.apply(&mut state);
assert_eq!(state.doc(), "fn test(a: u32) {}"); assert_eq!(state.doc(), "fn test(a: u32) {}");

@ -303,7 +303,7 @@ impl Client {
new_pos += i; new_pos += i;
} }
Delete(_) => { Delete(_) => {
let start = pos_to_lsp_pos(&new_text, new_pos); let start = pos_to_lsp_pos(new_text, new_pos);
let end = traverse(start, old_text.slice(old_pos..old_end)); let end = traverse(start, old_text.slice(old_pos..old_end));
// deletion // deletion
@ -314,7 +314,7 @@ impl Client {
}); });
} }
Insert(s) => { Insert(s) => {
let start = pos_to_lsp_pos(&new_text, new_pos); let start = pos_to_lsp_pos(new_text, new_pos);
new_pos += s.chars().count(); new_pos += s.chars().count();

@ -30,12 +30,12 @@ pub mod util {
use super::*; use super::*;
use helix_core::{RopeSlice, State, Transaction}; use helix_core::{RopeSlice, State, Transaction};
pub fn lsp_pos_to_pos(doc: &RopeSlice, pos: lsp::Position) -> usize { pub fn lsp_pos_to_pos(doc: RopeSlice, pos: lsp::Position) -> usize {
let line = doc.line_to_char(pos.line as usize); let line = doc.line_to_char(pos.line as usize);
let line_start = doc.char_to_utf16_cu(line); let line_start = doc.char_to_utf16_cu(line);
doc.utf16_cu_to_char(pos.character as usize + line_start) doc.utf16_cu_to_char(pos.character as usize + line_start)
} }
pub fn pos_to_lsp_pos(doc: &RopeSlice, pos: usize) -> lsp::Position { pub fn pos_to_lsp_pos(doc: RopeSlice, pos: usize) -> lsp::Position {
let line = doc.char_to_line(pos); let line = doc.char_to_line(pos);
let line_start = doc.char_to_utf16_cu(doc.line_to_char(line)); let line_start = doc.char_to_utf16_cu(doc.line_to_char(line));
let col = doc.char_to_utf16_cu(pos) - line_start; let col = doc.char_to_utf16_cu(pos) - line_start;
@ -58,8 +58,8 @@ pub mod util {
None None
}; };
let start = lsp_pos_to_pos(&doc, edit.range.start); let start = lsp_pos_to_pos(doc, edit.range.start);
let end = lsp_pos_to_pos(&doc, edit.range.end); let end = lsp_pos_to_pos(doc, edit.range.end);
(start, end, replacement) (start, end, replacement)
}), }),
) )

@ -147,8 +147,8 @@ impl Application {
.into_iter() .into_iter()
.map(|diagnostic| { .map(|diagnostic| {
use helix_lsp::util::lsp_pos_to_pos; use helix_lsp::util::lsp_pos_to_pos;
let start = lsp_pos_to_pos(&doc, diagnostic.range.start); let start = lsp_pos_to_pos(doc, diagnostic.range.start);
let end = lsp_pos_to_pos(&doc, diagnostic.range.end); let end = lsp_pos_to_pos(doc, diagnostic.range.end);
helix_core::Diagnostic { helix_core::Diagnostic {
range: (start, end), range: (start, end),

@ -117,7 +117,7 @@ pub fn move_next_word_start(cx: &mut Context) {
let count = cx.count; let count = cx.count;
let doc = cx.doc(); let doc = cx.doc();
// TODO: count // TODO: count
let pos = State::move_next_word_start(&doc.text().slice(..), doc.selection().cursor()); let pos = State::move_next_word_start(doc.text().slice(..), doc.selection().cursor());
doc.set_selection(Selection::point(pos)); doc.set_selection(Selection::point(pos));
} }
@ -125,7 +125,7 @@ pub fn move_next_word_start(cx: &mut Context) {
pub fn move_prev_word_start(cx: &mut Context) { pub fn move_prev_word_start(cx: &mut Context) {
let count = cx.count; let count = cx.count;
let doc = cx.doc(); let doc = cx.doc();
let pos = State::move_prev_word_start(&doc.text().slice(..), doc.selection().cursor()); let pos = State::move_prev_word_start(doc.text().slice(..), doc.selection().cursor());
doc.set_selection(Selection::point(pos)); doc.set_selection(Selection::point(pos));
} }
@ -133,7 +133,7 @@ pub fn move_prev_word_start(cx: &mut Context) {
pub fn move_next_word_end(cx: &mut Context) { pub fn move_next_word_end(cx: &mut Context) {
let count = cx.count; let count = cx.count;
let doc = cx.doc(); let doc = cx.doc();
let pos = State::move_next_word_end(&doc.text().slice(..), doc.selection().cursor(), count); let pos = State::move_next_word_end(doc.text().slice(..), doc.selection().cursor(), count);
doc.set_selection(Selection::point(pos)); doc.set_selection(Selection::point(pos));
} }
@ -156,7 +156,7 @@ pub fn extend_next_word_start(cx: &mut Context) {
let count = cx.count; let count = cx.count;
let doc = cx.doc(); let doc = cx.doc();
let mut selection = doc.selection().transform(|mut range| { let mut selection = doc.selection().transform(|mut range| {
let pos = State::move_next_word_start(&doc.text().slice(..), doc.selection().cursor()); let pos = State::move_next_word_start(doc.text().slice(..), doc.selection().cursor());
range.head = pos; range.head = pos;
range range
}); // TODO: count }); // TODO: count
@ -168,7 +168,7 @@ pub fn extend_prev_word_start(cx: &mut Context) {
let count = cx.count; let count = cx.count;
let doc = cx.doc(); let doc = cx.doc();
let mut selection = doc.selection().transform(|mut range| { let mut selection = doc.selection().transform(|mut range| {
let pos = State::move_prev_word_start(&doc.text().slice(..), doc.selection().cursor()); let pos = State::move_prev_word_start(doc.text().slice(..), doc.selection().cursor());
range.head = pos; range.head = pos;
range range
}); // TODO: count }); // TODO: count
@ -179,7 +179,7 @@ pub fn extend_next_word_end(cx: &mut Context) {
let count = cx.count; let count = cx.count;
let doc = cx.doc(); let doc = cx.doc();
let mut selection = doc.selection().transform(|mut range| { let mut selection = doc.selection().transform(|mut range| {
let pos = State::move_next_word_end(&doc.text().slice(..), doc.selection().cursor(), count); let pos = State::move_next_word_end(doc.text().slice(..), doc.selection().cursor(), count);
range.head = pos; range.head = pos;
range range
}); // TODO: count }); // TODO: count
@ -303,7 +303,7 @@ pub fn select_all(cx: &mut Context) {
pub fn select_regex(cx: &mut Context) { pub fn select_regex(cx: &mut Context) {
let prompt = ui::regex_prompt(cx, "select:".to_string(), |doc, regex| { let prompt = ui::regex_prompt(cx, "select:".to_string(), |doc, regex| {
let text = &doc.text().slice(..); let text = doc.text().slice(..);
// TODO: if select on matches returns empty range, we need to abort // TODO: if select on matches returns empty range, we need to abort
let selection = let selection =
selection::select_on_matches(text, doc.selection(), &regex).expect("no matches"); selection::select_on_matches(text, doc.selection(), &regex).expect("no matches");
@ -331,7 +331,7 @@ pub fn split_selection(cx: &mut Context) {
// } // }
let prompt = ui::regex_prompt(cx, "split:".to_string(), |doc, regex| { let prompt = ui::regex_prompt(cx, "split:".to_string(), |doc, regex| {
let text = &doc.text().slice(..); let text = doc.text().slice(..);
let selection = selection::split_on_matches(text, doc.selection(), &regex); let selection = selection::split_on_matches(text, doc.selection(), &regex);
doc.set_selection(selection); doc.set_selection(selection);
}); });
@ -345,7 +345,7 @@ pub fn split_selection(cx: &mut Context) {
pub fn split_selection_on_newline(cx: &mut Context) { pub fn split_selection_on_newline(cx: &mut Context) {
let doc = cx.doc(); let doc = cx.doc();
let text = &doc.text().slice(..); let text = doc.text().slice(..);
// only compile the regex once // only compile the regex once
#[allow(clippy::trivial_regex)] #[allow(clippy::trivial_regex)]
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap()); static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\n").unwrap());
@ -489,7 +489,7 @@ pub fn append_mode(cx: &mut Context) {
doc.restore_cursor = true; doc.restore_cursor = true;
// TODO: as transaction // TODO: as transaction
let text = &doc.text().slice(..); let text = doc.text().slice(..);
let selection = doc.selection().transform(|range| { let selection = doc.selection().transform(|range| {
// TODO: to() + next char // TODO: to() + next char
Range::new( Range::new(
@ -721,7 +721,7 @@ pub fn normal_mode(cx: &mut Context) {
// if leaving append mode, move cursor back by 1 // if leaving append mode, move cursor back by 1
if doc.restore_cursor { if doc.restore_cursor {
let text = &doc.text().slice(..); let text = doc.text().slice(..);
let selection = doc.selection().transform(|range| { let selection = doc.selection().transform(|range| {
Range::new( Range::new(
range.from(), range.from(),
@ -775,7 +775,7 @@ pub mod insert {
pub fn delete_char_backward(cx: &mut Context) { pub fn delete_char_backward(cx: &mut Context) {
let count = cx.count; let count = cx.count;
let doc = cx.doc(); let doc = cx.doc();
let text = &doc.text().slice(..); let text = doc.text().slice(..);
let transaction = Transaction::change_by_selection(&doc.state, |range| { let transaction = Transaction::change_by_selection(&doc.state, |range| {
( (
graphemes::nth_prev_grapheme_boundary(text, range.head, count), graphemes::nth_prev_grapheme_boundary(text, range.head, count),
@ -789,7 +789,7 @@ pub mod insert {
pub fn delete_char_forward(cx: &mut Context) { pub fn delete_char_forward(cx: &mut Context) {
let count = cx.count; let count = cx.count;
let doc = cx.doc(); let doc = cx.doc();
let text = &doc.text().slice(..); let text = doc.text().slice(..);
let transaction = Transaction::change_by_selection(&doc.state, |range| { let transaction = Transaction::change_by_selection(&doc.state, |range| {
( (
range.head, range.head,
@ -826,7 +826,7 @@ pub fn yank(cx: &mut Context) {
let values = doc let values = doc
.state .state
.selection() .selection()
.fragments(&doc.text().slice(..)) .fragments(doc.text().slice(..))
.map(|cow| cow.into_owned()) .map(|cow| cow.into_owned())
.collect(); .collect();
@ -978,7 +978,7 @@ pub fn completion(cx: &mut Context) {
let doc = cx.doc(); let doc = cx.doc();
// TODO: blocking here is not ideal // TODO: blocking here is not ideal
let pos = helix_lsp::util::pos_to_lsp_pos(&doc.text().slice(..), doc.selection().cursor()); let pos = helix_lsp::util::pos_to_lsp_pos(doc.text().slice(..), doc.selection().cursor());
// TODO: handle fails // TODO: handle fails
let res = let res =

@ -134,7 +134,7 @@ impl EditorView {
let mut char_index = start; let mut char_index = start;
// iterate over range char by char // iterate over range char by char
for grapheme in RopeGraphemes::new(&text) { for grapheme in RopeGraphemes::new(text) {
// TODO: track current char_index // TODO: track current char_index
if grapheme == "\n" { if grapheme == "\n" {
@ -211,8 +211,8 @@ impl EditorView {
.filter(|range| range.overlaps(&screen)) .filter(|range| range.overlaps(&screen))
{ {
// TODO: render also if only one of the ranges is in viewport // TODO: render also if only one of the ranges is in viewport
let mut start = view.screen_coords_at_pos(&text, selection.anchor); let mut start = view.screen_coords_at_pos(text, selection.anchor);
let mut end = view.screen_coords_at_pos(&text, selection.head); let mut end = view.screen_coords_at_pos(text, selection.head);
// cursor // cursor
if let Some(end) = end { if let Some(end) = end {
@ -439,7 +439,7 @@ impl Component for EditorView {
let cursor = view.doc.state.selection().cursor(); let cursor = view.doc.state.selection().cursor();
let mut pos = view let mut pos = view
.screen_coords_at_pos(&view.doc.text().slice(..), cursor) .screen_coords_at_pos(view.doc.text().slice(..), cursor)
.expect("Cursor is out of bounds."); .expect("Cursor is out of bounds.");
pos.col += view.area.x as usize + area.x as usize + OFFSET as usize; pos.col += view.area.x as usize + area.x as usize + OFFSET as usize;
pos.row += view.area.y as usize + area.y as usize; pos.row += view.area.y as usize + area.y as usize;

@ -61,7 +61,7 @@ impl View {
/// Translates a document position to an absolute position in the terminal. /// Translates a document position to an absolute position in the terminal.
/// Returns a (line, col) position if the position is visible on screen. /// Returns a (line, col) position if the position is visible on screen.
// TODO: Could return width as well for the character width at cursor. // TODO: Could return width as well for the character width at cursor.
pub fn screen_coords_at_pos(&self, text: &RopeSlice, pos: usize) -> Option<Position> { pub fn screen_coords_at_pos(&self, text: RopeSlice, pos: usize) -> Option<Position> {
let line = text.char_to_line(pos); let line = text.char_to_line(pos);
if line < self.first_line as usize || line > self.last_line() { if line < self.first_line as usize || line > self.last_line() {
@ -73,7 +73,7 @@ impl View {
let line_slice = text.slice(line_start..pos); let line_slice = text.slice(line_start..pos);
let mut col = 0; let mut col = 0;
for grapheme in RopeGraphemes::new(&line_slice) { for grapheme in RopeGraphemes::new(line_slice) {
if grapheme == "\t" { if grapheme == "\t" {
col += TAB_WIDTH; col += TAB_WIDTH;
} else { } else {
@ -87,7 +87,7 @@ impl View {
Some(Position::new(row, col)) Some(Position::new(row, col))
} }
// pub fn traverse<F>(&self, text: &RopeSlice, start: usize, end: usize, fun: F) // pub fn traverse<F>(&self, text: RopeSlice, start: usize, end: usize, fun: F)
// where // where
// F: Fn(usize, usize), // F: Fn(usize, usize),
// { // {

Loading…
Cancel
Save