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