pub struct SyntaxLayer {
pub directory: Arc<LanguageDirectory>,
/* private fields */
}Expand description
Per-App syntax highlighting layer. Multiplexes per-buffer state. Fully synchronous — no background thread.
§Examples
use std::sync::Arc;
use hjkl_syntax::SyntaxLayer;
use hjkl_bonsai::DotFallbackTheme;
use hjkl_lang::LanguageDirectory;
let theme = Arc::new(DotFallbackTheme::dark());
let dir = Arc::new(LanguageDirectory::new().unwrap());
let layer = SyntaxLayer::new(theme, dir);Fields§
§directory: Arc<LanguageDirectory>Shared grammar resolver.
Implementations§
Source§impl SyntaxLayer
impl SyntaxLayer
Sourcepub fn new(
theme: Arc<dyn Theme + Send + Sync>,
directory: Arc<LanguageDirectory>,
) -> Self
pub fn new( theme: Arc<dyn Theme + Send + Sync>, directory: Arc<LanguageDirectory>, ) -> Self
Create a new layer with no buffers attached.
§Examples
use std::sync::Arc;
use hjkl_syntax::SyntaxLayer;
use hjkl_bonsai::DotFallbackTheme;
use hjkl_lang::LanguageDirectory;
let theme = Arc::new(DotFallbackTheme::dark());
let dir = Arc::new(LanguageDirectory::new().unwrap());
let layer = SyntaxLayer::new(theme, dir);Sourcepub fn set_rainbow_brackets(&mut self, enabled: bool)
pub fn set_rainbow_brackets(&mut self, enabled: bool)
Update rainbow bracket settings. Pass enabled = false to disable the
rainbow overlay globally. No-op when the value is unchanged so per-frame
pushes from the app stay cheap. Caches invalidate only on actual change.
Sourcepub fn set_colorizer(&mut self, enabled: bool, filetypes: Vec<String>)
pub fn set_colorizer(&mut self, enabled: bool, filetypes: Vec<String>)
Update colorizer settings. Pass enabled = false to disable
the color-literal overlay globally. filetypes is the allowlist
of language names (e.g. "css", "toml"); an empty slice means
no filetype is allowed (same effect as enabled = false).
No-op when the values are unchanged so per-frame pushes from the app stay cheap. Caches invalidate only on actual change.
Sourcepub fn directory(&self) -> &Arc<LanguageDirectory> ⓘ
pub fn directory(&self) -> &Arc<LanguageDirectory> ⓘ
Borrow the shared language directory.
Sourcepub fn set_language_for_path(
&mut self,
id: BufferId,
path: &Path,
) -> SetLanguageOutcome
pub fn set_language_for_path( &mut self, id: BufferId, path: &Path, ) -> SetLanguageOutcome
Detect the language for path and attach a grammar.
Ready— grammar cached; highlighter installed immediately.Loading— grammar compiling; renders as plain text untilpoll_pending_loadsfiresLoadEvent::Ready.Unknown— unrecognized extension; plain text only.
§Examples
use std::sync::Arc;
use std::path::Path;
use hjkl_syntax::{SyntaxLayer, SetLanguageOutcome};
use hjkl_bonsai::DotFallbackTheme;
use hjkl_lang::LanguageDirectory;
let theme = Arc::new(DotFallbackTheme::dark());
let dir = Arc::new(LanguageDirectory::new().unwrap());
let mut layer = SyntaxLayer::new(theme, dir);
let outcome = layer.set_language_for_path(0, Path::new("a.zzz_not_real"));
assert!(!outcome.is_known());Sourcepub fn set_language_by_name(
&mut self,
id: BufferId,
name: &str,
) -> SetLanguageOutcome
pub fn set_language_by_name( &mut self, id: BufferId, name: &str, ) -> SetLanguageOutcome
Attach a grammar by its canonical language name, bypassing path
detection entirely. The name may come from content detection (shebang,
modeline ft=) or a manual :set filetype=.
Identical semantics to Self::set_language_for_path once the name
is known; an unrecognised name resolves to SetLanguageOutcome::Unknown
without attaching anything.
Sourcepub fn poll_pending_loads(&mut self) -> Vec<LoadEvent>
pub fn poll_pending_loads(&mut self) -> Vec<LoadEvent>
Poll all in-flight grammar loads. Call once per tick.
Returns one LoadEvent per handle that resolved during this tick.
Sourcepub fn set_theme(&mut self, theme: Arc<dyn Theme + Send + Sync>)
pub fn set_theme(&mut self, theme: Arc<dyn Theme + Send + Sync>)
Swap the active theme. Next render_viewport call uses the new theme.
Sourcepub fn apply_edits(&mut self, id: BufferId, edits: &[ContentEdit])
pub fn apply_edits(&mut self, id: BufferId, edits: &[ContentEdit])
Apply a batch of engine ContentEdits to the buffer’s retained tree
synchronously. The cache will be invalidated on the next render_viewport
call via dirty_gen mismatch.
No-op when no grammar is attached.
Sourcepub fn reset(&mut self, id: BufferId)
pub fn reset(&mut self, id: BufferId)
Drop the buffer’s retained tree. Next render_viewport reparses from scratch.
Call on :e! / content reset.
Sourcepub fn extract_fold_ranges(
&mut self,
id: BufferId,
buffer: &impl Query,
) -> Option<Vec<(usize, usize)>>
pub fn extract_fold_ranges( &mut self, id: BufferId, buffer: &impl Query, ) -> Option<Vec<(usize, usize)>>
Extract fold ranges from the buffer’s retained tree using the bundled
folds.scm for this grammar, plus one for each injected region using
ITS language’s query.
Returns Some(ranges) when the grammar is attached and the tree has
been parsed — ranges may be empty when the grammar has no bundled
folds.scm or the file contains no foldable nodes.
Injected regions (a ```rust block in markdown, a <script> body in
HTML) are parsed with their own grammar, folded with that language’s
query, and their rows offset into this document — see
hjkl_bonsai::extract_fold_ranges_rope_with_injections. Resolving an
injected grammar goes through the shared LanguageDirectory, which
may build one on first use; only languages with a bundled fold query
can trigger that.
Returns None when:
- No grammar is attached yet (grammar still loading or unknown extension).
- No highlighter has been created for this buffer.
- The tree has not been parsed yet (call
render_viewportfirst).
Callers must treat None as “not ready — retry later” and must NOT
record the dirty_gen as processed when None is returned. Returning
Some(empty) is the signal that the grammar ran but produced no folds
(e.g. no folds.scm for this language).
NOT viewport-bounded — runs over the full tree (once per reparse).
Do not call this per-frame; call it only when dirty_gen has changed.
Sourcepub fn render_viewport(
&mut self,
id: BufferId,
buffer: &impl Query,
viewport_top: usize,
viewport_height: usize,
) -> Option<RenderOutput>
pub fn render_viewport( &mut self, id: BufferId, buffer: &impl Query, viewport_top: usize, viewport_height: usize, ) -> Option<RenderOutput>
Render spans for the visible viewport, returning an owned span table.
Thin wrapper over Self::render_viewport_ref that deep-copies the
cached rows. Callers that immediately convert the table into their own
style type (every renderer adapter) should use render_viewport_ref
instead and skip the copy.
Sourcepub fn render_viewport_ref(
&mut self,
id: BufferId,
buffer: &impl Query,
viewport_top: usize,
viewport_height: usize,
) -> Option<RenderOutputRef<'_>>
pub fn render_viewport_ref( &mut self, id: BufferId, buffer: &impl Query, viewport_top: usize, viewport_height: usize, ) -> Option<RenderOutputRef<'_>>
Render spans for the visible viewport. Fully synchronous.
- Returns
Nonewhen no grammar is attached. - Clears the cache when
buffer.dirty_gen()has advanced. - Returns cached rows when the request is fully inside the cached range.
- Walks only rows outside the cache (extend prefix/suffix), splices into
cache_spans, extendscache_rows.
The returned RenderOutputRef borrows the viewport slice of
cache_spans — no per-call copy of the span table.
Sourcepub fn name_for_path(&self, path: &Path) -> Option<String>
pub fn name_for_path(&self, path: &Path) -> Option<String>
Resolve a path to its language name without loading a grammar.
Sourcepub fn dispatch_load_event(
event: &LoadEvent,
handler: impl FnMut(LoadEventKind<'_>),
) -> bool
pub fn dispatch_load_event( event: &LoadEvent, handler: impl FnMut(LoadEventKind<'_>), ) -> bool
Dispatch a LoadEvent through a caller-supplied handler.
§Examples
use hjkl_syntax::{LoadEvent, SyntaxLayer};
let event = LoadEvent::Ready { id: 0, name: "rust".into() };
let mut got_ready = false;
let handled = SyntaxLayer::dispatch_load_event(&event, |ev| {
use hjkl_syntax::LoadEventKind;
match ev {
LoadEventKind::Ready { id, name } => { got_ready = true; }
LoadEventKind::Failed { .. } => {}
}
});
assert!(handled);
assert!(got_ready);