@@ -1,66 +1,397 @@
1+use crate::{Change, Rope, RopeSlice, Transaction};
2+pub use helix_syntax::LANG;
3+pub use helix_syntax::{get_language, get_language_name};
1−// pub struct Syntax {
5+pub struct Syntax {
2−// parser: Parser,
7+ parser: Parser,
3−// }
8+ cursors: Vec<QueryCursor>,
10+ config: HighlightConfiguration,
12+ root_layer: LanguageLayer,
5−//impl Syntax {
15+impl Syntax {
6−// // buffer, grammar, config, grammars, sync_timeout?
16+ // buffer, grammar, config, grammars, sync_timeout?
7−// pub fn new() -> Self {
17+ pub fn new(language: LANG, source: &Rope, config: HighlightConfiguration) -> Self {
8−// unimplemented!()
18+ // fetch grammar for parser based on language string
9−// // make a new root layer
19+ let grammar = get_language(&language);
20+ let parser = Parser::new();
22+ let root_layer = LanguageLayer::new();
10−// // track markers of injections
24+ // track markers of injections
12−// // track scope_descriptor: a Vec of scopes for item in tree
25+ // track scope_descriptor: a Vec of scopes for item in tree
14−// // fetch grammar for parser based on language string
27+ let mut syntax = Self {
15−// // update root layer
28+ grammar,
36+ syntax.root_layer.parse(
43+ end_byte: usize::MAX,
44+ start_point: Point::new(0, 0),
45+ end_point: Point::new(usize::MAX, usize::MAX),
51+ pub fn configure(&mut self, scopes: &[String]) {
52+ self.config.configure(scopes)
55+ pub fn update(&mut self, source: &Rope, changeset: &ChangeSet) -> Result<(), Error> {
57+ .update(&mut self.parser, &self.config, source, changeset)
59+ // TODO: deal with injections and update them too
18−// // fn buffer_changed -> call layer.update(range, new_text) on root layer and then all marker layers
62+ // fn buffer_changed -> call layer.update(range, new_text) on root layer and then all marker layers
20−// // call this on transaction.apply() -> buffer_changed(changes)
64+ // call this on transaction.apply() -> buffer_changed(changes)
22−// // fn parse(language, old_tree, ranges)
66+ // fn parse(language, old_tree, ranges)
24−// // fn tree() -> Tree
68+ fn tree(&self) -> &Tree {
25−// //
69+ self.root_layer.tree()
26−// // <!--update_for_injection(grammar)-->
72+ // <!--update_for_injection(grammar)-->
28−// // Highlighting
74+ // Highlighting
29−// // fn highlight_iter() -> iterates over all the scopes
75+
76+ /// Iterate over the highlighted regions for a given slice of source code.
77+ pub fn highlight_iter<'a>(
80+ cancellation_flag: Option<&'a AtomicUsize>,
81+ mut injection_callback: impl FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
82+ ) -> Result<impl Iterator<Item = Result<HighlightEvent, Error>> + 'a, Error> {
83+ // The `captures` iterator borrows the `Tree` and the `QueryCursor`, which
84+ // prevents them from being moved. But both of these values are really just
85+ // pointers, so it's actually ok to move them.
87+ let mut cursor = QueryCursor::new(); // reuse a pool
88+ let tree_ref = unsafe { mem::transmute::<_, &'static Tree>(self.tree()) };
89+ let cursor_ref = unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) };
90+ let query_ref = unsafe { mem::transmute::<_, &'static mut Query>(&mut self.config.query) };
92+ unsafe { mem::transmute::<_, &'static HighlightConfiguration>(&self.config) };
93+ let captures = cursor_ref
94+ .captures(query_ref, tree_ref.root_node(), move |n: Node| {
95+ &source[n.byte_range()]
99+ // manually craft the root layer based on the existing tree
100+ let layer = HighlightIterLayer {
101+ highlight_end_stack: Vec::new(),
102+ scope_stack: vec![LocalScope {
104+ range: 0..usize::MAX,
105+ local_defs: Vec::new(),
112+ ranges: vec![Range {
114+ end_byte: usize::MAX,
115+ start_point: Point::new(0, 0),
116+ end_point: Point::new(usize::MAX, usize::MAX),
120+ let mut result = HighlightIter {
127+ layers: vec![layer],
129+ last_highlight_range: None,
131+ result.sort_layers();
30−// // on_tokenize
134+ // on_tokenize
31−// // on_change_highlighting
135+ // on_change_highlighting
33−// // Commenting
137+ // Commenting
34−// // comment_strings_for_pos
138+ // comment_strings_for_pos
35−// // is_commented
139+ // is_commented
37−// // Indentation
141+ // Indentation
38−// // suggested_indent_for_line_at_buffer_row
142+ // suggested_indent_for_line_at_buffer_row
39−// // suggested_indent_for_buffer_row
143+ // suggested_indent_for_buffer_row
40−// // indent_level_for_line
144+ // indent_level_for_line
42−// // TODO: Folding
146+ // TODO: Folding
44−// // Syntax APIs
148+ // Syntax APIs
45−// // get_syntax_node_containing_range ->
149+ // get_syntax_node_containing_range ->
47−// // get_syntax_node_at_pos
151+ // get_syntax_node_at_pos
48−// // buffer_range_for_scope_at_pos
152+ // buffer_range_for_scope_at_pos
51pub struct LanguageLayer {
155pub struct LanguageLayer {
53−// grammar
157+ // grammar
55−// tree: Tree,
159+ tree: Option<Tree>,
162+use crate::state::{coords_at_pos, Coords};
163+use crate::transaction::{ChangeSet, Operation};
58−// impl LanguageLayer {
166+impl LanguageLayer {
167+ pub fn new() -> Self {
171+ fn tree(&self) -> &Tree {
173+ self.tree.as_ref().unwrap()
178+ parser: &mut Parser,
179+ config: &HighlightConfiguration,
182+ mut ranges: Vec<Range>,
183+ ) -> Result<(), Error> {
184+ if parser.set_included_ranges(&ranges).is_ok() {
186+ .set_language(config.language)
187+ .map_err(|_| Error::InvalidLanguage)?;
189+ // unsafe { syntax.parser.set_cancellation_flag(cancellation_flag) };
193+ if byte <= source.len_bytes() {
194+ let (chunk, start_byte, _, _) = source.chunk_at_byte(byte);
195+ chunk[byte - start_byte..].as_bytes()
203+ .ok_or(Error::Cancelled)?;
204+ // unsafe { syntax.parser.set_cancellation_flag(None) };
205+ // let mut cursor = syntax.cursors.pop().unwrap_or_else(QueryCursor::new);
207+ // Process combined injections. (ERB, EJS, etc https://github.com/tree-sitter/tree-sitter/pull/526)
208+ // if let Some(combined_injections_query) = &config.combined_injections_query {
209+ // let mut injections_by_pattern_index =
210+ // vec![(None, Vec::new(), false); combined_injections_query.pattern_count()];
212+ // cursor.matches(combined_injections_query, tree.root_node(), |n: Node| {
213+ // &source[n.byte_range()]
215+ // for mat in matches {
216+ // let entry = &mut injections_by_pattern_index[mat.pattern_index];
217+ // let (language_name, content_node, include_children) =
218+ // injection_for_match(config, combined_injections_query, &mat, source);
219+ // if language_name.is_some() {
220+ // entry.0 = language_name;
222+ // if let Some(content_node) = content_node {
223+ // entry.1.push(content_node);
225+ // entry.2 = include_children;
227+ // for (lang_name, content_nodes, includes_children) in injections_by_pattern_index {
228+ // if let (Some(lang_name), false) = (lang_name, content_nodes.is_empty()) {
229+ // if let Some(next_config) = (injection_callback)(lang_name) {
231+ // Self::intersect_ranges(&ranges, &content_nodes, includes_children);
232+ // if !ranges.is_empty() {
233+ // queue.push((next_config, depth + 1, ranges));
239+ self.tree = Some(tree)
244+ pub(crate) fn generate_edits(
246+ changeset: &ChangeSet,
247+ ) -> Vec<tree_sitter::InputEdit> {
249+ let mut old_pos = 0;
250+ let mut new_pos = 0;
252+ let mut edits = Vec::new();
254+ let mut iter = changeset.changes.iter().peekable();
256+ // TODO; this is a lot easier with Change instead of Operation.
258+ fn point_at_pos(text: &RopeSlice, pos: usize) -> (usize, Point) {
259+ let byte = text.char_to_byte(pos);
260+ let line = text.char_to_line(pos);
261+ let line_start_byte = text.line_to_byte(line);
262+ let col = byte - line_start_byte;
264+ (byte, Point::new(line, col))
267+ fn traverse(point: Point, text: &Tendril) -> Point {
273+ // TODO: there should be a better way here
274+ for ch in text.bytes() {
282+ Point { row, column }
285+ while let Some(change) = iter.next() {
286+ let len = match change {
287+ Delete(i) | Retain(i) => *i,
290+ let old_end = old_pos + len;
297+ let (start_byte, start_position) = point_at_pos(&text, old_pos);
298+ let (old_end_byte, old_end_position) = point_at_pos(&text, old_end);
300+ // TODO: Position also needs to be byte based...
301+ // let byte = char_to_byte(old_pos)
302+ // let line = char_to_line(old_pos)
303+ // let line_start_byte = line_to_byte()
304+ // Position::new(line, line_start_byte - byte)
306+ // a subsequent ins means a replace, consume it
307+ if let Some(Insert(s)) = iter.peek() {
309+ let ins = s.chars().count();
312+ edits.push(tree_sitter::InputEdit {
313+ start_byte, // old_pos to byte
314+ old_end_byte, // old_end to byte
315+ new_end_byte: start_byte + s.len(), // old_pos to byte + s.len()
316+ start_position, // old pos to coords
317+ old_end_position, // old_end to coords
318+ new_end_position: traverse(start_position, s), // old pos + chars, newlines matter too (iter over)
324+ edits.push(tree_sitter::InputEdit {
325+ start_byte, // old_pos to byte
326+ old_end_byte, // old_end to byte
327+ new_end_byte: start_byte, // old_pos to byte
328+ start_position, // old pos to coords
329+ old_end_position, // old_end to coords
330+ new_end_position: start_position, // old pos to coords
335+ let (start_byte, start_position) = point_at_pos(&text, old_pos);
337+ let ins = s.chars().count();
340+ edits.push(tree_sitter::InputEdit {
341+ start_byte, // old_pos to byte
342+ old_end_byte: start_byte, // same
343+ new_end_byte: start_byte + s.len(), // old_pos + s.len()
344+ start_position, // old pos to coords
345+ old_end_position: start_position, // same
346+ new_end_position: traverse(start_position, s), // old pos + chars, newlines matter too (iter over)
359+ parser: &mut Parser,
360+ config: &HighlightConfiguration,
362+ changeset: &ChangeSet,
363+ ) -> Result<(), Error> {
364+ if changeset.is_empty() {
368+ let edits = Self::generate_edits(&source.slice(..), changeset);
370+ // Notify the tree about all the changes
372+ self.tree.as_mut().unwrap().edit(&edit);
380+ // TODO: what to do about this range on update
383+ end_byte: usize::MAX,
384+ start_point: Point::new(0, 0),
385+ end_point: Point::new(usize::MAX, usize::MAX),
59−// // fn highlight_iter() -> same as Mode but for this layer. Mode composits these
390+ // fn highlight_iter() -> same as Mode but for this layer. Mode composits these
60−// // fn buffer_changed
391+ // fn buffer_changed
61−// // fn update(range)
392+ // fn update(range)
62−// // fn update_injections()
393+ // fn update_injections()
65// -- refactored from tree-sitter-highlight to be able to retain state
396// -- refactored from tree-sitter-highlight to be able to retain state
66// TODO: add seek() to iter
397// TODO: add seek() to iter
@@ -169,7 +500,7 @@ where
170 source: &'a [u8],
501 source: &'a [u8],
171 byte_offset: usize,
502 byte_offset: usize,
172− highlighter: &'a mut Highlighter,
503+ highlighter: &'a mut Syntax,
173 injection_callback: F,
504 injection_callback: F,
174 cancellation_flag: Option<&'a AtomicUsize>,
505 cancellation_flag: Option<&'a AtomicUsize>,
175 layers: Vec<HighlightIterLayer<'a>>,
506 layers: Vec<HighlightIterLayer<'a>>,
@@ -179,7 +510,7 @@ where
181struct HighlightIterLayer<'a> {
512struct HighlightIterLayer<'a> {
182− _tree: Tree,
513+ _tree: Option<Tree>,
183 cursor: QueryCursor,
514 cursor: QueryCursor,
184 captures: iter::Peekable<QueryCaptures<'a, &'a [u8]>>,
515 captures: iter::Peekable<QueryCaptures<'a, &'a [u8]>>,
185 config: &'a HighlightConfiguration,
516 config: &'a HighlightConfiguration,
@@ -207,43 +538,43 @@ impl Highlighter {
207 &mut self.parser
538 &mut self.parser
210− /// Iterate over the highlighted regions for a given slice of source code.
541+ // /// Iterate over the highlighted regions for a given slice of source code.
211− pub fn highlight<'a>(
542+ // pub fn highlight<'a>(
212− &'a mut self,
543+ // &'a mut self,
213− config: &'a HighlightConfiguration,
544+ // config: &'a HighlightConfiguration,
214− source: &'a [u8],
545+ // source: &'a [u8],
215− cancellation_flag: Option<&'a AtomicUsize>,
546+ // cancellation_flag: Option<&'a AtomicUsize>,
216− mut injection_callback: impl FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
547+ // mut injection_callback: impl FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
217− ) -> Result<impl Iterator<Item = Result<HighlightEvent, Error>> + 'a, Error> {
548+ // ) -> Result<impl Iterator<Item = Result<HighlightEvent, Error>> + 'a, Error> {
218− let layers = HighlightIterLayer::new(
549+ // let layers = HighlightIterLayer::new(
219− source,
550+ // source,
221− cancellation_flag,
552+ // cancellation_flag,
222− &mut injection_callback,
553+ // &mut injection_callback,
223− config,
554+ // config,
225− vec![Range {
556+ // vec![Range {
226− start_byte: 0,
557+ // start_byte: 0,
227− end_byte: usize::MAX,
558+ // end_byte: usize::MAX,
228− start_point: Point::new(0, 0),
559+ // start_point: Point::new(0, 0),
229− end_point: Point::new(usize::MAX, usize::MAX),
560+ // end_point: Point::new(usize::MAX, usize::MAX),
232− assert_ne!(layers.len(), 0);
563+ // assert_ne!(layers.len(), 0);
233− let mut result = HighlightIter {
564+ // let mut result = HighlightIter {
234− source,
565+ // source,
235− byte_offset: 0,
566+ // byte_offset: 0,
236− injection_callback,
567+ // injection_callback,
237− cancellation_flag,
568+ // cancellation_flag,
238− highlighter: self,
569+ // highlighter: self,
239− iter_count: 0,
570+ // iter_count: 0,
240− layers,
571+ // layers,
241− next_event: None,
572+ // next_event: None,
242− last_highlight_range: None,
573+ // last_highlight_range: None,
244− result.sort_layers();
575+ // result.sort_layers();
245− Ok(result)
576+ // Ok(result)
249impl HighlightConfiguration {
580impl HighlightConfiguration {
@@ -413,7 +744,7 @@ impl<'a> HighlightIterLayer<'a> {
413 /// added to the returned vector.
744 /// added to the returned vector.
414 fn new<F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a>(
745 fn new<F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a>(
415 source: &'a [u8],
746 source: &'a [u8],
416− highlighter: &mut Highlighter,
747+ highlighter: &mut Syntax,
417 cancellation_flag: Option<&'a AtomicUsize>,
748 cancellation_flag: Option<&'a AtomicUsize>,
418 injection_callback: &mut F,
749 injection_callback: &mut F,
419 mut config: &'a HighlightConfiguration,
750 mut config: &'a HighlightConfiguration,
@@ -423,6 +754,8 @@ impl<'a> HighlightIterLayer<'a> {
423 let mut result = Vec::with_capacity(1);
754 let mut result = Vec::with_capacity(1);
424 let mut queue = Vec::new();
755 let mut queue = Vec::new();
757+ // --> Tree parsing part
426 if highlighter.parser.set_included_ranges(&ranges).is_ok() {
759 if highlighter.parser.set_included_ranges(&ranges).is_ok() {
427 highlighter
760 highlighter
@@ -474,6 +807,8 @@ impl<'a> HighlightIterLayer<'a> {
810+ // --> Highlighting query part
477 // The `captures` iterator borrows the `Tree` and the `QueryCursor`, which
812 // The `captures` iterator borrows the `Tree` and the `QueryCursor`, which
478 // prevents them from being moved. But both of these values are really just
813 // prevents them from being moved. But both of these values are really just
479 // pointers, so it's actually ok to move them.
814 // pointers, so it's actually ok to move them.
@@ -495,7 +830,7 @@ impl<'a> HighlightIterLayer<'a> {
498− _tree: tree,
833+ _tree: Some(tree),
499 captures,
834 captures,
@@ -1016,3 +1351,106 @@ fn shrink_and_clear<T>(vec: &mut Vec<T>, capacity: usize) {
1017 vec.clear();
1352 vec.clear();
1357+ let highlight_names: Vec<String> = [
1360+ "function.builtin",
1366+ "punctuation.bracket",
1367+ "punctuation.delimiter",
1374+ "variable.builtin",
1375+ "variable.parameter",
1382+ let language = get_language(&LANG::Rust);
1383+ let mut config = HighlightConfiguration::new(
1385+ &std::fs::read_to_string(
1386+ "../helix-syntax/languages/tree-sitter-rust/queries/highlights.scm",
1389+ &std::fs::read_to_string(
1390+ "../helix-syntax/languages/tree-sitter-rust/queries/injections.scm",
1396+ config.configure(&highlight_names);
1398+ let source = Rope::from_str(
1404+ let syntax = Syntax::new(LANG::Rust, &source, config);
1405+ let tree = syntax.root_layer.tree.unwrap();
1406+ let root = tree.root_node();
1407+ assert_eq!(root.kind(), "source_file");
1413+ "(struct_item name: (type_identifier) body: (field_declaration_list)) ",
1414+ "(function_item name: (identifier) parameters: (parameters) body: (block)))"
1418+ let struct_node = root.child(0).unwrap();
1419+ assert_eq!(struct_node.kind(), "struct_item");
1423+fn test_input_edits() {
1425+ use tree_sitter::InputEdit;
1427+ let mut state = State::new("hello world!\ntest 123".into());
1428+ let transaction = Transaction::change(
1430+ vec![(6, 11, Some("test".into())), (12, 17, None)].into_iter(),
1432+ let edits = LanguageLayer::generate_edits(&state.doc.slice(..), &transaction.changes);
1433+ // transaction.apply(&mut state);
1442+ start_position: Point { row: 0, column: 6 },
1443+ old_end_position: Point { row: 0, column: 11 },
1444+ new_end_position: Point { row: 0, column: 10 }
1450+ start_position: Point { row: 0, column: 12 },
1451+ old_end_position: Point { row: 1, column: 4 },
1452+ new_end_position: Point { row: 0, column: 12 }