11use std:: collections:: HashMap ;
22use std:: num:: NonZeroU16 ;
33
4- use tree_sitter:: { InputEdit , Language , Node , Parser , Point , Range , Tree , TreeCursor } ;
4+ use tree_sitter:: {
5+ InputEdit , Language , Node , ParseOptions , Parser , Point , Range , Tree , TreeCursor ,
6+ } ;
57
68use crate :: { INLINE_LANGUAGE , LANGUAGE } ;
79
@@ -14,9 +16,17 @@ pub struct MarkdownParser {
1416 inline_language : Language ,
1517}
1618
19+ /// The options used while parsing a [`MarkdownTree`].
20+ ///
21+ /// This abstracts away the double block / inline structure of [`MarkdownParser`].
22+ pub struct MarkdownParseOptions < ' a > {
23+ block_options : Option < ParseOptions < ' a > > ,
24+ inline_options : Option < ParseOptions < ' a > > ,
25+ }
26+
1727/// A stateful object for walking a [`MarkdownTree`] efficiently.
1828///
19- /// This exposes the same methdos as [`TreeCursor`], but abstracts away the
29+ /// This exposes the same methods as [`TreeCursor`], but abstracts away the
2030/// double block / inline structure of [`MarkdownTree`].
2131pub struct MarkdownCursor < ' a > {
2232 markdown_tree : & ' a MarkdownTree ,
@@ -244,6 +254,16 @@ impl Default for MarkdownParser {
244254}
245255
246256impl MarkdownParser {
257+ /// Parse a slice of UTF8 text.
258+ #[ deprecated( since = "0.5.0" , note = "Prefer `parse_with_options` instead" ) ]
259+ pub fn parse_with < T : AsRef < [ u8 ] > , F : FnMut ( usize , Point ) -> T > (
260+ & mut self ,
261+ callback : & mut F ,
262+ old_tree : Option < & MarkdownTree > ,
263+ ) -> Option < MarkdownTree > {
264+ self . parse_with_options ( callback, old_tree, MarkdownParseOptions :: default ( ) )
265+ }
266+
247267 /// Parse a slice of UTF8 text.
248268 ///
249269 /// # Arguments:
@@ -252,14 +272,17 @@ impl MarkdownParser {
252272 /// If the text of the document has changed since `old_tree` was
253273 /// created, then you must edit `old_tree` to match the new text using
254274 /// [MarkdownTree::edit].
275+ /// * `options` The [options][MarkdownParseOptions] used for parsing.
276+ /// Use `MarkdownParseOptions::default()` if you don't need to pass any options.
255277 ///
256278 /// Returns a [MarkdownTree] if parsing succeeded, or `None` if:
257279 /// * The timeout set with [tree_sitter::Parser::set_timeout_micros] expired
258280 /// * The cancellation flag set with [tree_sitter::Parser::set_cancellation_flag] was flipped
259- pub fn parse_with < T : AsRef < [ u8 ] > , F : FnMut ( usize , Point ) -> T > (
281+ pub fn parse_with_options < T : AsRef < [ u8 ] > , F : FnMut ( usize , Point ) -> T > (
260282 & mut self ,
261283 callback : & mut F ,
262284 old_tree : Option < & MarkdownTree > ,
285+ mut options : MarkdownParseOptions < ' _ > ,
263286 ) -> Option < MarkdownTree > {
264287 let MarkdownParser {
265288 parser,
@@ -272,7 +295,11 @@ impl MarkdownParser {
272295 parser
273296 . set_language ( block_language)
274297 . expect ( "Could not load block grammar" ) ;
275- let block_tree = parser. parse_with ( callback, old_tree. map ( |tree| & tree. block_tree ) ) ?;
298+ let block_tree = parser. parse_with_options (
299+ callback,
300+ old_tree. map ( |tree| & tree. block_tree ) ,
301+ options. block_options ,
302+ ) ?;
276303 let ( mut inline_trees, mut inline_indices) = if let Some ( old_tree) = old_tree {
277304 let len = old_tree. inline_trees . len ( ) ;
278305 ( Vec :: with_capacity ( len) , HashMap :: with_capacity ( len) )
@@ -322,9 +349,10 @@ impl MarkdownParser {
322349 }
323350 ranges. push ( range) ;
324351 parser. set_included_ranges ( & ranges) . ok ( ) ?;
325- let inline_tree = parser. parse_with (
352+ let inline_tree = parser. parse_with_options (
326353 callback,
327354 old_tree. and_then ( |old_tree| old_tree. inline_trees . get ( i) ) ,
355+ options. inline_options . as_mut ( ) . map ( clone_parse_options) ,
328356 ) ?;
329357 inline_trees. push ( inline_tree) ;
330358 inline_indices. insert ( node. id ( ) , i) ;
@@ -353,7 +381,39 @@ impl MarkdownParser {
353381 /// * The timeout set with [tree_sitter::Parser::set_timeout_micros] expired
354382 /// * The cancellation flag set with [tree_sitter::Parser::set_cancellation_flag] was flipped
355383 pub fn parse ( & mut self , text : & [ u8 ] , old_tree : Option < & MarkdownTree > ) -> Option < MarkdownTree > {
356- self . parse_with ( & mut |byte, _| & text[ byte..] , old_tree)
384+ self . parse_with_options (
385+ & mut |byte, _| & text[ byte..] ,
386+ old_tree,
387+ MarkdownParseOptions :: default ( ) ,
388+ )
389+ }
390+ }
391+
392+ impl Default for MarkdownParseOptions < ' _ > {
393+ fn default ( ) -> Self {
394+ MarkdownParseOptions {
395+ block_options : None ,
396+ inline_options : None ,
397+ }
398+ }
399+ }
400+
401+ /// Creates a new [`ParseOptions`] that borrows all values while not consuming the original.
402+ fn clone_parse_options < ' a > ( options : & ' a mut ParseOptions < ' _ > ) -> ParseOptions < ' a > {
403+ // This is needed because we need to pass in `ParseOptions` multiple times for the inline
404+ // language. Since the struct contains `&mut`, it cannot implement `Clone` or `Copy`. We get
405+ // around this by manually specifying that we mean to temporarily borrow all fields.
406+ // This is obviously somewhat hacky. If `tree-sitter` adds fields to `ParseOptions` that are
407+ // not `&mut`, this method might become implossible. Given this situation, the "proper" way to
408+ // solve this problem seems to be changing the param type to `&mut ParseOptions` for
409+ // `Parser::parse_with_options()` in upstream `tree-sitter` crate.
410+ let ParseOptions { progress_callback } = options;
411+ ParseOptions {
412+ // Cannot do `progress_callback.as_mut().map(..)` due to lifetime complications.
413+ progress_callback : match progress_callback {
414+ Some ( cb) => Some ( * cb) ,
415+ None => None ,
416+ } ,
357417 }
358418}
359419
0 commit comments