aboutsummaryrefslogtreecommitdiff
path: root/helix-core
diff options
context:
space:
mode:
authorNathan Vegdahl2021-07-02 02:37:28 +0000
committerNathan Vegdahl2021-07-02 02:37:28 +0000
commit2224a1527ec9592f16131b0aa3923fc3d37592e7 (patch)
tree2a08b053cb32cef9dc1db5895778d419ebaebb5b /helix-core
parente725957704274b1ec814a34ddf6f75faf35358e7 (diff)
parent9f62ad0715240156b512dfc7c584d2d0df05a664 (diff)
Merge branch 'master' into great_line_ending_and_cursor_range_cleanup
Diffstat (limited to 'helix-core')
-rw-r--r--helix-core/src/auto_pairs.rs2
-rw-r--r--helix-core/src/history.rs10
-rw-r--r--helix-core/src/indent.rs10
-rw-r--r--helix-core/src/lib.rs1
-rw-r--r--helix-core/src/line_ending.rs2
-rw-r--r--helix-core/src/match_brackets.rs4
-rw-r--r--helix-core/src/movement.rs26
-rw-r--r--helix-core/src/object.rs1
-rw-r--r--helix-core/src/position.rs7
-rw-r--r--helix-core/src/selection.rs15
-rw-r--r--helix-core/src/syntax.rs315
-rw-r--r--helix-core/src/transaction.rs18
12 files changed, 202 insertions, 209 deletions
diff --git a/helix-core/src/auto_pairs.rs b/helix-core/src/auto_pairs.rs
index 746f201a..d9569acd 100644
--- a/helix-core/src/auto_pairs.rs
+++ b/helix-core/src/auto_pairs.rs
@@ -139,7 +139,7 @@ fn handle_close(doc: &Rope, selection: &Selection, _open: char, close: char) ->
}
// handle cases where open and close is the same, or in triples ("""docstring""")
-fn handle_same(doc: &Rope, selection: &Selection, token: char) -> Option<Transaction> {
+fn handle_same(_doc: &Rope, _selection: &Selection, _token: char) -> Option<Transaction> {
// if not cursor but selection, wrap
// let next = next char
diff --git a/helix-core/src/history.rs b/helix-core/src/history.rs
index 23680275..67ded166 100644
--- a/helix-core/src/history.rs
+++ b/helix-core/src/history.rs
@@ -1,7 +1,6 @@
use crate::{ChangeSet, Rope, State, Transaction};
use once_cell::sync::Lazy;
use regex::Regex;
-use smallvec::{smallvec, SmallVec};
use std::num::NonZeroUsize;
use std::time::{Duration, Instant};
@@ -127,7 +126,6 @@ impl History {
let last_child = current_revision.last_child?;
self.current = last_child.get();
- let last_child_revision = &self.revisions[last_child.get()];
Some(&self.revisions[last_child.get()].transaction)
}
@@ -377,21 +375,21 @@ mod test {
if let Some(transaction) = history.undo() {
transaction.apply(&mut state.doc);
}
- };
+ }
fn earlier(history: &mut History, state: &mut State, uk: UndoKind) {
let txns = history.earlier(uk);
for txn in txns {
txn.apply(&mut state.doc);
}
- };
+ }
fn later(history: &mut History, state: &mut State, uk: UndoKind) {
let txns = history.later(uk);
for txn in txns {
txn.apply(&mut state.doc);
}
- };
+ }
fn commit_change(
history: &mut History,
@@ -402,7 +400,7 @@ mod test {
let txn = Transaction::change(&state.doc, vec![change.clone()].into_iter());
history.commit_revision_at_timestamp(&txn, &state, instant);
txn.apply(&mut state.doc);
- };
+ }
let t0 = Instant::now();
let t = |n| t0.checked_add(Duration::from_secs(n)).unwrap();
diff --git a/helix-core/src/indent.rs b/helix-core/src/indent.rs
index 8e0379e2..81bdffc0 100644
--- a/helix-core/src/indent.rs
+++ b/helix-core/src/indent.rs
@@ -1,13 +1,13 @@
use crate::{
find_first_non_whitespace_char,
syntax::{IndentQuery, LanguageConfiguration, Syntax},
- tree_sitter::{Node, Tree},
- Rope, RopeSlice,
+ tree_sitter::Node,
+ RopeSlice,
};
/// To determine indentation of a newly inserted line, figure out the indentation at the last col
/// of the previous line.
-
+#[allow(dead_code)]
fn indent_level_for_line(line: RopeSlice, tab_width: usize) -> usize {
let mut len = 0;
for ch in line.chars() {
@@ -98,12 +98,13 @@ fn calculate_indentation(query: &IndentQuery, node: Option<Node>, newline: bool)
increment as usize
}
+#[allow(dead_code)]
fn suggested_indent_for_line(
language_config: &LanguageConfiguration,
syntax: Option<&Syntax>,
text: RopeSlice,
line_num: usize,
- tab_width: usize,
+ _tab_width: usize,
) -> usize {
if let Some(start) = find_first_non_whitespace_char(text.line(line_num)) {
return suggested_indent_for_pos(
@@ -150,6 +151,7 @@ pub fn suggested_indent_for_pos(
#[cfg(test)]
mod test {
use super::*;
+ use crate::Rope;
#[test]
fn test_indent_level() {
diff --git a/helix-core/src/lib.rs b/helix-core/src/lib.rs
index ae135b00..dfbbd748 100644
--- a/helix-core/src/lib.rs
+++ b/helix-core/src/lib.rs
@@ -1,4 +1,3 @@
-#![allow(unused)]
pub mod auto_pairs;
pub mod chars;
pub mod comment;
diff --git a/helix-core/src/line_ending.rs b/helix-core/src/line_ending.rs
index 7ea3f14a..e3ff6478 100644
--- a/helix-core/src/line_ending.rs
+++ b/helix-core/src/line_ending.rs
@@ -1,4 +1,4 @@
-use crate::{Rope, RopeGraphemes, RopeSlice};
+use crate::{Rope, RopeSlice};
#[cfg(target_os = "windows")]
pub const DEFAULT_LINE_ENDING: LineEnding = LineEnding::Crlf;
diff --git a/helix-core/src/match_brackets.rs b/helix-core/src/match_brackets.rs
index 288b4586..2aa87620 100644
--- a/helix-core/src/match_brackets.rs
+++ b/helix-core/src/match_brackets.rs
@@ -1,4 +1,4 @@
-use crate::{Range, Rope, Selection, Syntax};
+use crate::{Rope, Syntax};
const PAIRS: &[(char, char)] = &[('(', ')'), ('{', '}'), ('[', ']'), ('<', '>')];
// limit matching pairs to only ( ) { } [ ] < >
@@ -12,7 +12,7 @@ pub fn find(syntax: &Syntax, doc: &Rope, pos: usize) -> Option<usize> {
// most naive implementation: find the innermost syntax node, if we're at the edge of a node,
// return the other edge.
- let mut node = match tree
+ let node = match tree
.root_node()
.named_descendant_for_byte_range(byte_pos, byte_pos)
{
diff --git a/helix-core/src/movement.rs b/helix-core/src/movement.rs
index a4c7f9c9..acc95e7e 100644
--- a/helix-core/src/movement.rs
+++ b/helix-core/src/movement.rs
@@ -1,12 +1,9 @@
-use std::iter::{self, from_fn, Peekable, SkipWhile};
+use std::iter::{self, from_fn};
use ropey::iter::Chars;
use crate::{
- chars::{
- categorize_char, char_is_line_ending, char_is_punctuation, char_is_whitespace,
- char_is_word, CharCategory,
- },
+ chars::{categorize_char, char_is_line_ending, CharCategory},
coords_at_pos,
graphemes::{nth_next_grapheme_boundary, nth_prev_grapheme_boundary},
line_ending::{get_line_ending, line_end_char_index},
@@ -116,7 +113,7 @@ pub fn move_prev_long_word_start(slice: RopeSlice, range: Range, count: usize) -
word_move(slice, range, count, WordMotionTarget::PrevLongWordStart)
}
-fn word_move(slice: RopeSlice, mut range: Range, count: usize, target: WordMotionTarget) -> Range {
+fn word_move(slice: RopeSlice, range: Range, count: usize, target: WordMotionTarget) -> Range {
(0..count).fold(range, |range, _| {
slice.chars_at(range.head).range_to_target(target, range)
})
@@ -182,7 +179,6 @@ enum WordMotionPhase {
impl CharHelpers for Chars<'_> {
fn range_to_target(&mut self, target: WordMotionTarget, origin: Range) -> Range {
- let range = origin;
// Characters are iterated forward or backwards depending on the motion direction.
let characters: Box<dyn Iterator<Item = char>> = match target {
WordMotionTarget::PrevWordStart | WordMotionTarget::PrevLongWordStart => {
@@ -270,20 +266,20 @@ fn reached_target(target: WordMotionTarget, peek: char, next_peek: Option<&char>
match target {
WordMotionTarget::NextWordStart => {
- (is_word_boundary(peek, *next_peek)
- && (char_is_line_ending(*next_peek) || !next_peek.is_whitespace()))
+ is_word_boundary(peek, *next_peek)
+ && (char_is_line_ending(*next_peek) || !next_peek.is_whitespace())
}
WordMotionTarget::NextWordEnd | WordMotionTarget::PrevWordStart => {
- (is_word_boundary(peek, *next_peek)
- && (!peek.is_whitespace() || char_is_line_ending(*next_peek)))
+ is_word_boundary(peek, *next_peek)
+ && (!peek.is_whitespace() || char_is_line_ending(*next_peek))
}
WordMotionTarget::NextLongWordStart => {
- (is_long_word_boundary(peek, *next_peek)
- && (char_is_line_ending(*next_peek) || !next_peek.is_whitespace()))
+ is_long_word_boundary(peek, *next_peek)
+ && (char_is_line_ending(*next_peek) || !next_peek.is_whitespace())
}
WordMotionTarget::NextLongWordEnd | WordMotionTarget::PrevLongWordStart => {
- (is_long_word_boundary(peek, *next_peek)
- && (!peek.is_whitespace() || char_is_line_ending(*next_peek)))
+ is_long_word_boundary(peek, *next_peek)
+ && (!peek.is_whitespace() || char_is_line_ending(*next_peek))
}
}
}
diff --git a/helix-core/src/object.rs b/helix-core/src/object.rs
index 950b7592..d9558dd8 100644
--- a/helix-core/src/object.rs
+++ b/helix-core/src/object.rs
@@ -1,5 +1,4 @@
use crate::{Range, RopeSlice, Selection, Syntax};
-use smallvec::smallvec;
// TODO: to contract_selection we'd need to store the previous ranges before expand.
// Maybe just contract to the first child node?
diff --git a/helix-core/src/position.rs b/helix-core/src/position.rs
index 392eee9c..3d114b52 100644
--- a/helix-core/src/position.rs
+++ b/helix-core/src/position.rs
@@ -1,7 +1,7 @@
use crate::{
chars::char_is_line_ending,
graphemes::{nth_next_grapheme_boundary, RopeGraphemes},
- Rope, RopeSlice,
+ RopeSlice,
};
/// Represents a single point in a text buffer. Zero indexed.
@@ -70,6 +70,7 @@ pub fn pos_at_coords(text: RopeSlice, coords: Position) -> usize {
#[cfg(test)]
mod test {
use super::*;
+ use crate::Rope;
#[test]
fn test_ordering() {
@@ -79,8 +80,8 @@ mod test {
#[test]
fn test_coords_at_pos() {
- let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
- let slice = text.slice(..);
+ // let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ");
+ // let slice = text.slice(..);
// assert_eq!(coords_at_pos(slice, 0), (0, 0).into());
// assert_eq!(coords_at_pos(slice, 5), (0, 5).into()); // position on \n
// assert_eq!(coords_at_pos(slice, 6), (1, 0).into()); // position on w
diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs
index e9dea518..5f77d7ad 100644
--- a/helix-core/src/selection.rs
+++ b/helix-core/src/selection.rs
@@ -6,7 +6,7 @@ use crate::{
graphemes::{
ensure_grapheme_boundary_next, ensure_grapheme_boundary_prev, next_grapheme_boundary,
},
- Assoc, ChangeSet, Rope, RopeSlice,
+ Assoc, ChangeSet, RopeSlice,
};
use smallvec::{smallvec, SmallVec};
use std::borrow::Cow;
@@ -426,10 +426,8 @@ pub fn select_on_matches(
// TODO: can't avoid occasional allocations since Regex can't operate on chunks yet
let fragment = sel.fragment(text);
- let mut sel_start = sel.from();
- let sel_end = sel.to();
-
- let mut start_byte = text.char_to_byte(sel_start);
+ let sel_start = sel.from();
+ let start_byte = text.char_to_byte(sel_start);
for mat in regex.find_iter(&fragment) {
// TODO: retain range direction
@@ -466,10 +464,10 @@ pub fn split_on_matches(
// TODO: can't avoid occasional allocations since Regex can't operate on chunks yet
let fragment = sel.fragment(text);
- let mut sel_start = sel.from();
+ let sel_start = sel.from();
let sel_end = sel.to();
- let mut start_byte = text.char_to_byte(sel_start);
+ let start_byte = text.char_to_byte(sel_start);
let mut start = sel_start;
@@ -492,11 +490,12 @@ pub fn split_on_matches(
#[cfg(test)]
mod test {
use super::*;
+ use crate::Rope;
#[test]
#[should_panic]
fn test_new_empty() {
- let sel = Selection::new(smallvec![], 0);
+ let _ = Selection::new(smallvec![], 0);
}
#[test]
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs
index c556a347..9dbb2c03 100644
--- a/helix-core/src/syntax.rs
+++ b/helix-core/src/syntax.rs
@@ -1,4 +1,10 @@
-use crate::{chars::char_is_line_ending, regex::Regex, Change, Rope, RopeSlice, Transaction};
+use crate::{
+ chars::char_is_line_ending,
+ regex::Regex,
+ transaction::{ChangeSet, Operation},
+ Rope, RopeSlice, Tendril,
+};
+
pub use helix_syntax::{get_language, get_language_name, Lang};
use arc_swap::ArcSwap;
@@ -8,7 +14,7 @@ use std::{
cell::RefCell,
collections::{HashMap, HashSet},
fmt,
- path::{Path, PathBuf},
+ path::Path,
sync::Arc,
};
@@ -160,7 +166,7 @@ impl LanguageConfiguration {
None
} else {
let language = get_language(self.language_id);
- let mut config = HighlightConfiguration::new(
+ let config = HighlightConfiguration::new(
language,
&highlights_query,
&injections_query,
@@ -326,7 +332,8 @@ impl Syntax {
// update root layer
PARSER.with(|ts_parser| {
- syntax.root_layer.parse(
+ // TODO: handle the returned `Result` properly.
+ let _ = syntax.root_layer.parse(
&mut ts_parser.borrow_mut(),
&syntax.config,
source,
@@ -381,7 +388,7 @@ impl Syntax {
source: RopeSlice<'a>,
range: Option<std::ops::Range<usize>>,
cancellation_flag: Option<&'a AtomicUsize>,
- mut injection_callback: impl FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
+ injection_callback: impl FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
) -> impl Iterator<Item = Result<HighlightEvent, Error>> + 'a {
// The `captures` iterator borrows the `Tree` and the `QueryCursor`, which
// prevents them from being moved. But both of these values are really just
@@ -473,12 +480,6 @@ pub struct LanguageLayer {
pub(crate) tree: Option<Tree>,
}
-use crate::{
- coords_at_pos,
- transaction::{ChangeSet, Operation},
- Tendril,
-};
-
impl LanguageLayer {
// pub fn new() -> Self {
// Self { tree: None }
@@ -494,8 +495,8 @@ impl LanguageLayer {
ts_parser: &mut TsParser,
config: &HighlightConfiguration,
source: &Rope,
- mut depth: usize,
- mut ranges: Vec<Range>,
+ _depth: usize,
+ ranges: Vec<Range>,
) -> Result<(), Error> {
if ts_parser.parser.set_included_ranges(&ranges).is_ok() {
ts_parser
@@ -566,7 +567,6 @@ impl LanguageLayer {
) -> Vec<tree_sitter::InputEdit> {
use Operation::*;
let mut old_pos = 0;
- let mut new_pos = 0;
let mut edits = Vec::new();
@@ -610,9 +610,7 @@ impl LanguageLayer {
let mut old_end = old_pos + len;
match change {
- Retain(_) => {
- new_pos += len;
- }
+ Retain(_) => {}
Delete(_) => {
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);
@@ -636,8 +634,6 @@ impl LanguageLayer {
Insert(s) => {
let (start_byte, start_position) = point_at_pos(old_text, old_pos);
- let ins = s.chars().count();
-
// a subsequent delete means a replace, consume it
if let Some(Delete(len)) = iter.peek() {
old_end = old_pos + len;
@@ -665,8 +661,6 @@ impl LanguageLayer {
new_end_position: traverse(start_position, s), // old pos + chars, newlines matter too (iter over)
});
}
-
- new_pos += ins;
}
}
old_pos = old_end;
@@ -1480,7 +1474,6 @@ where
// local scope at the top of the scope stack.
else if Some(capture.index) == layer.config.local_def_capture_index {
reference_highlight = None;
- definition_highlight = None;
let scope = layer.scope_stack.last_mut().unwrap();
let mut value_range = 0..0;
@@ -1644,13 +1637,13 @@ fn injection_for_match<'a>(
(language_name, content_node, include_children)
}
-fn shrink_and_clear<T>(vec: &mut Vec<T>, capacity: usize) {
- if vec.len() > capacity {
- vec.truncate(capacity);
- vec.shrink_to_fit();
- }
- vec.clear();
-}
+// fn shrink_and_clear<T>(vec: &mut Vec<T>, capacity: usize) {
+// if vec.len() > capacity {
+// vec.truncate(capacity);
+// vec.shrink_to_fit();
+// }
+// vec.clear();
+// }
pub struct Merge<I> {
iter: I,
@@ -1691,7 +1684,7 @@ impl<I: Iterator<Item = HighlightEvent>> Iterator for Merge<I> {
loop {
match (self.next_event, &self.next_span) {
// this happens when range is partially or fully offscreen
- (Some(Source { start, end }), Some((span, range))) if start > range.start => {
+ (Some(Source { start, .. }), Some((span, range))) if start > range.start => {
if start > range.end {
self.next_span = self.spans.next();
} else {
@@ -1711,7 +1704,7 @@ impl<I: Iterator<Item = HighlightEvent>> Iterator for Merge<I> {
self.next_event = self.iter.next();
Some(HighlightEnd)
}
- (Some(Source { start, end }), Some((span, range))) if start < range.start => {
+ (Some(Source { start, end }), Some((_, range))) if start < range.start => {
let intersect = range.start.min(end);
let event = Source {
start,
@@ -1766,7 +1759,7 @@ impl<I: Iterator<Item = HighlightEvent>> Iterator for Merge<I> {
Some(event)
}
// can happen if deleting and cursor at EOF, and diagnostic reaches past the end
- (None, Some((span, range))) => {
+ (None, Some((_, _))) => {
self.next_span = None;
None
}
@@ -1776,135 +1769,141 @@ impl<I: Iterator<Item = HighlightEvent>> Iterator for Merge<I> {
}
}
-#[test]
-fn test_parser() {
- let highlight_names: Vec<String> = [
- "attribute",
- "constant",
- "function.builtin",
- "function",
- "keyword",
- "operator",
- "property",
- "punctuation",
- "punctuation.bracket",
- "punctuation.delimiter",
- "string",
- "string.special",
- "tag",
- "type",
- "type.builtin",
- "variable",
- "variable.builtin",
- "variable.parameter",
- ]
- .iter()
- .cloned()
- .map(String::from)
- .collect();
-
- let language = get_language(Lang::Rust);
- let mut config = HighlightConfiguration::new(
- language,
- &std::fs::read_to_string(
- "../helix-syntax/languages/tree-sitter-rust/queries/highlights.scm",
- )
- .unwrap(),
- &std::fs::read_to_string(
- "../helix-syntax/languages/tree-sitter-rust/queries/injections.scm",
- )
- .unwrap(),
- "", // locals.scm
- )
- .unwrap();
- config.configure(&highlight_names);
-
- let source = Rope::from_str(
- "
- struct Stuff {}
- fn main() {}
- ",
- );
- let syntax = Syntax::new(&source, Arc::new(config));
- let tree = syntax.tree();
- let root = tree.root_node();
- assert_eq!(root.kind(), "source_file");
-
- assert_eq!(
- root.to_sexp(),
- concat!(
- "(source_file ",
- "(struct_item name: (type_identifier) body: (field_declaration_list)) ",
- "(function_item name: (identifier) parameters: (parameters) body: (block)))"
+#[cfg(test)]
+mod test {
+ use super::*;
+ use crate::{Rope, Transaction};
+
+ #[test]
+ fn test_parser() {
+ let highlight_names: Vec<String> = [
+ "attribute",
+ "constant",
+ "function.builtin",
+ "function",
+ "keyword",
+ "operator",
+ "property",
+ "punctuation",
+ "punctuation.bracket",
+ "punctuation.delimiter",
+ "string",
+ "string.special",
+ "tag",
+ "type",
+ "type.builtin",
+ "variable",
+ "variable.builtin",
+ "variable.parameter",
+ ]
+ .iter()
+ .cloned()
+ .map(String::from)
+ .collect();
+
+ let language = get_language(Lang::Rust);
+ let config = HighlightConfiguration::new(
+ language,
+ &std::fs::read_to_string(
+ "../helix-syntax/languages/tree-sitter-rust/queries/highlights.scm",
+ )
+ .unwrap(),
+ &std::fs::read_to_string(
+ "../helix-syntax/languages/tree-sitter-rust/queries/injections.scm",
+ )
+ .unwrap(),
+ "", // locals.scm
)
- );
+ .unwrap();
+ config.configure(&highlight_names);
+
+ let source = Rope::from_str(
+ "
+ struct Stuff {}
+ fn main() {}
+ ",
+ );
+ let syntax = Syntax::new(&source, Arc::new(config));
+ let tree = syntax.tree();
+ let root = tree.root_node();
+ assert_eq!(root.kind(), "source_file");
+
+ assert_eq!(
+ root.to_sexp(),
+ concat!(
+ "(source_file ",
+ "(struct_item name: (type_identifier) body: (field_declaration_list)) ",
+ "(function_item name: (identifier) parameters: (parameters) body: (block)))"
+ )
+ );
- let struct_node = root.child(0).unwrap();
- assert_eq!(struct_node.kind(), "struct_item");
-}
+ let struct_node = root.child(0).unwrap();
+ assert_eq!(struct_node.kind(), "struct_item");
+ }
-#[test]
-fn test_input_edits() {
- use crate::State;
- use tree_sitter::InputEdit;
-
- let mut state = State::new("hello world!\ntest 123".into());
- let transaction = Transaction::change(
- &state.doc,
- vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(),
- );
- let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
- // transaction.apply(&mut state);
-
- assert_eq!(
- edits,
- &[
- InputEdit {
- start_byte: 6,
- old_end_byte: 11,
- new_end_byte: 10,
- start_position: Point { row: 0, column: 6 },
- old_end_position: Point { row: 0, column: 11 },
- new_end_position: Point { row: 0, column: 10 }
- },
- InputEdit {
- start_byte: 12,
- old_end_byte: 17,
- new_end_byte: 12,
- start_position: Point { row: 0, column: 12 },
- old_end_position: Point { row: 1, column: 4 },
- new_end_position: Point { row: 0, column: 12 }
- }
- ]
- );
-
- // Testing with the official example from tree-sitter
- let mut state = State::new("fn test() {}".into());
- let transaction =
- Transaction::change(&state.doc, vec![(8, 8, Some("a: u32".into()))].into_iter());
- let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
- transaction.apply(&mut state.doc);
-
- assert_eq!(state.doc, "fn test(a: u32) {}");
- assert_eq!(
- edits,
- &[InputEdit {
- start_byte: 8,
- old_end_byte: 8,
- new_end_byte: 14,
- start_position: Point { row: 0, column: 8 },
- old_end_position: Point { row: 0, column: 8 },
- new_end_position: Point { row: 0, column: 14 }
- }]
- );
-}
+ #[test]
+ fn test_input_edits() {
+ use crate::State;
+ use tree_sitter::InputEdit;
+
+ let state = State::new("hello world!\ntest 123".into());
+ let transaction = Transaction::change(
+ &state.doc,
+ vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(),
+ );
+ let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
+ // transaction.apply(&mut state);
+
+ assert_eq!(
+ edits,
+ &[
+ InputEdit {
+ start_byte: 6,
+ old_end_byte: 11,
+ new_end_byte: 10,
+ start_position: Point { row: 0, column: 6 },
+ old_end_position: Point { row: 0, column: 11 },
+ new_end_position: Point { row: 0, column: 10 }
+ },
+ InputEdit {
+ start_byte: 12,
+ old_end_byte: 17,
+ new_end_byte: 12,
+ start_position: Point { row: 0, column: 12 },
+ old_end_position: Point { row: 1, column: 4 },
+ new_end_position: Point { row: 0, column: 12 }
+ }
+ ]
+ );
+
+ // Testing with the official example from tree-sitter
+ let mut state = State::new("fn test() {}".into());
+ let transaction =
+ Transaction::change(&state.doc, vec![(8, 8, Some("a: u32".into()))].into_iter());
+ let edits = LanguageLayer::generate_edits(state.doc.slice(..), transaction.changes());
+ transaction.apply(&mut state.doc);
+
+ assert_eq!(state.doc, "fn test(a: u32) {}");
+ assert_eq!(
+ edits,
+ &[InputEdit {
+ start_byte: 8,
+ old_end_byte: 8,
+ new_end_byte: 14,
+ start_position: Point { row: 0, column: 8 },
+ old_end_position: Point { row: 0, column: 8 },
+ new_end_position: Point { row: 0, column: 14 }
+ }]
+ );
+ }
-#[test]
-fn test_load_runtime_file() {
- // Test to make sure we can load some data from the runtime directory.
- let contents = load_runtime_file("rust", "indents.toml").unwrap();
- assert!(!contents.is_empty());
+ #[test]
+ fn test_load_runtime_file() {
+ // Test to make sure we can load some data from the runtime directory.
+ let contents = load_runtime_file("rust", "indents.toml").unwrap();
+ assert!(!contents.is_empty());
- let results = load_runtime_file("rust", "does-not-exist");
- assert!(results.is_err());
+ let results = load_runtime_file("rust", "does-not-exist");
+ assert!(results.is_err());
+ }
}
diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs
index 10219142..048839b3 100644
--- a/helix-core/src/transaction.rs
+++ b/helix-core/src/transaction.rs
@@ -1,5 +1,5 @@
-use crate::{Range, Rope, Selection, State, Tendril};
-use std::{borrow::Cow, convert::TryFrom};
+use crate::{Range, Rope, Selection, Tendril};
+use std::borrow::Cow;
/// (from, to, replacement)
pub type Change = (usize, usize, Option<Tendril>);
@@ -163,7 +163,7 @@ impl ChangeSet {
head_a = a;
head_b = changes_b.next();
}
- (None, val) | (val, None) => return unreachable!("({:?})", val),
+ (None, val) | (val, None) => unreachable!("({:?})", val),
(Some(Retain(i)), Some(Retain(j))) => match i.cmp(&j) {
Ordering::Less => {
changes.retain(i);
@@ -202,7 +202,7 @@ impl ChangeSet {
}
}
}
- (Some(Insert(mut s)), Some(Retain(j))) => {
+ (Some(Insert(s)), Some(Retain(j))) => {
let len = s.chars().count();
match len.cmp(&j) {
Ordering::Less => {
@@ -274,7 +274,6 @@ impl ChangeSet {
let mut changes = Self::with_capacity(self.changes.len());
let mut pos = 0;
- let mut len = 0;
for change in &self.changes {
use Operation::*;
@@ -581,6 +580,7 @@ impl<'a> Iterator for ChangeIterator<'a> {
#[cfg(test)]
mod test {
use super::*;
+ use crate::State;
#[test]
fn composition() {
@@ -699,7 +699,7 @@ mod test {
#[test]
fn changes_iter() {
- let mut state = State::new("hello world!\ntest 123".into());
+ let state = State::new("hello world!\ntest 123".into());
let changes = vec![(6, 11, Some("void".into())), (12, 17, None)];
let transaction = Transaction::change(&state.doc, changes.clone().into_iter());
assert_eq!(transaction.changes_iter().collect::<Vec<_>>(), changes);
@@ -731,7 +731,7 @@ mod test {
// retain 1, e
// retain 2, l
- let mut changes = t1
+ let changes = t1
.changes
.compose(t2.changes)
.compose(t3.changes)
@@ -746,7 +746,7 @@ mod test {
#[test]
fn combine_with_empty() {
let empty = Rope::from("");
- let mut a = ChangeSet::new(&empty);
+ let a = ChangeSet::new(&empty);
let mut b = ChangeSet::new(&empty);
b.insert("a".into());
@@ -762,7 +762,7 @@ mod test {
const TEST_CASE: &'static str = "Hello, これはヘリックスエディターです!";
let empty = Rope::from("");
- let mut a = ChangeSet::new(&empty);
+ let a = ChangeSet::new(&empty);
let mut b = ChangeSet::new(&empty);
b.insert(TEST_CASE.into());