diffler_core/syntax/
mod.rs1pub mod intraline;
7pub mod registry;
8pub mod scope;
9pub mod symbols;
10
11use std::ops::Range;
12
13use tree_sitter::Parser;
14
15pub use registry::{HIGHLIGHT_NAMES, LangEntry, LanguageRegistry};
16pub use scope::ScopeIndex;
17pub use symbols::Ident;
18
19pub(crate) const MAX_PARSE_BYTES: usize = 2_000_000;
21
22pub(crate) fn parse(entry: &LangEntry, src: &str) -> Option<tree_sitter::Tree> {
23 let mut parser = Parser::new();
24 parser.set_language(&entry.language).ok()?;
25 parser.parse(src, None)
26}
27
28pub(crate) fn line_bounds(content: &str) -> Vec<(usize, usize)> {
31 let bytes = content.as_bytes();
32 let mut out = Vec::new();
33 let mut start = 0;
34 for (i, &b) in bytes.iter().enumerate() {
35 if b == b'\n' {
36 let end = if i > start && bytes.get(i - 1) == Some(&b'\r') {
37 i - 1
38 } else {
39 i
40 };
41 out.push((start, end));
42 start = i + 1;
43 }
44 }
45 if start < bytes.len() {
46 let end = if bytes.last() == Some(&b'\r') {
47 bytes.len() - 1
48 } else {
49 bytes.len()
50 };
51 out.push((start, end));
52 }
53 out
54}
55
56pub(crate) fn split_range_by_line(
60 bounds: &[(usize, usize)],
61 starts: &[usize],
62 range: &Range<usize>,
63 mut emit: impl FnMut(usize, Range<usize>),
64) {
65 let mut li = match starts.binary_search(&range.start) {
66 Ok(i) => i,
67 Err(i) => i.saturating_sub(1),
68 };
69 while let Some(&(ls, le)) = bounds.get(li) {
70 if ls >= range.end {
71 break;
72 }
73 let s = range.start.max(ls);
74 let e = range.end.min(le);
75 if s < e {
76 emit(li, (s - ls)..(e - ls));
77 }
78 li += 1;
79 }
80}