tiny.syn.scan.line
Defined in scan.
Each call runs one line through the routine for its language and records the marked ranges in storage the caller provides.
API (2)
Actions
Public operations.
highlight: Marks up one line from a fresh continuation state.highlightLine: Marks up one line of a document and updatesstatewith what the line leaves open.
Source
Source: lib/syn/src/scan/line.zig
zig
//! Each call runs one line through the routine for its language and records the marked ranges in//! storage the caller provides. A line may begin inside a comment or string that an earlier line//! opened, and the rest of the line has to be marked as usual once that comment or string closes. A//! line may also be too long for the storage, and what it leaves open for the next line must still//! come out right.//!//! When the line starts inside an open comment or string, the text up to the closing delimiter//! becomes one marked byte range of a line and its role (*span*), and the routine for the language//! marks the rest of the line. That first span has the kind of the open comment or string. When the//! line is too long (*discarded line*), the storage drops every span, but the scan still runs over//! the whole line so what it leaves open stays exact. Languages share scanners by family: Lisp and//! Clojure use one with this repository's own Lisp-shaped programming language (*Chiclet*), HTML,//! XML, Vue and Svelte use another, and every language without a scanner of its own uses a generic//! one for C-like syntax.//!//! - *continuation state*: what one line leaves open for the next line//! - *text limit*: the longest line, in bytes, whose marks the storage keepsconst std = @import("std");const syn = @import("../root.zig");const diff = @import("diff.zig");const generic = @import("generic.zig");const json = @import("json.zig");const lisp = @import("lisp.zig");const markdown = @import("markdown.zig");const markup = @import("markup.zig");const python = @import("python.zig");const shell = @import("shell.zig");const structured = @import("structured.zig");const Language = syn.Language;const SpanStorage = syn.SpanStorage;const Kind = syn.Kind;const Mode = syn.Mode;const State = syn.State;/// Marks up one line from a fresh continuation state. A caller with one line on its own, such as a/// snippet or the README example, marks it up without keeping anything between calls. The function/// behaves as `highlightLine` with a new `State` that is dropped after the call, so a comment or/// string the line leaves open is forgotten. The call replaces the spans the storage held for the/// previous line. The storage must be activated before the call, and the call allocates nothing./// The call returns `.complete` when the spans were kept and `.discarded` when the line was longer/// than the text limit.pub fn highlight( language: Language, text: []const u8, spans: *SpanStorage,) syn.SpanMaterialization { var state: State = .{}; return highlightLine(language, text, &state, spans);}/// Marks up one line of a document and updates `state` with what the line leaves open. A caller/// walking a document line by line passes the same `State` to every call, so comments and strings/// that run over more than one line are marked correctly. The call replaces the storage's spans/// with this line's spans, each an offset into `text`. The call keeps no spans and returns/// `.discarded` when the line is longer than the text limit. That line is still scanned in full, so/// `state` comes out the same as it would with room to spare. A comment or string that `state`/// carries from a different language is dropped, and the line is scanned fresh. A comment or string/// that `state` carries from this language runs up to its closing delimiter as one comment or/// string span, and the rest of the line is scanned as usual. A line with no closing delimiter/// becomes one span, and the comment or string stays open. The storage must be activated before the/// call, and the call allocates nothing. The call keeps no reference to `text`.pub fn highlightLine( language: Language, text: []const u8, state: *State, spans: *SpanStorage,) syn.SpanMaterialization { const materialization = prepare(spans, text.len); state.rebind(language); if (!highlightContinuing(language, text, state, spans)) { state.retain(language, highlightFlat(language, text, spans)); } return materialization;}fn prepare(spans: *SpanStorage, text_bytes: usize) syn.SpanMaterialization { spans.prepare(text_bytes) catch |err| switch (err) { error.MaterializationCapacityExceeded => return .discarded, }; return .complete;}fn highlightFlat(language: Language, text: []const u8, spans: *SpanStorage) ?Mode { return switch (language) { .chiclet, .lisp, .clojure => { lisp.highlight(text, spans); return null; }, .json => { json.highlight(text, spans); return null; }, .shell => { shell.highlight(text, spans); return null; }, .diff => { diff.highlight(text, spans); return null; }, .markdown => { markdown.highlight(text, spans); return null; }, .python => python.highlight(text, spans), .yaml => { structured.highlightYaml(text, spans); return null; }, .toml => structured.highlightToml(text, spans), .html, .xml, .vue, .svelte => markup.highlightMarkup(language, text, spans), .css => markup.highlightCss(text, spans), else => generic.highlight(language, text, spans), };}fn highlightContinuing( language: Language, text: []const u8, state: *State, spans: *SpanStorage,) bool { const mode = state.mode() orelse return false; const format: ContinuationFormat = switch (mode) { .block_comment => .{ .close = "*/", .kind = .comment }, .haskell_comment => .{ .close = "-}", .kind = .comment }, .lua_comment => .{ .close = "]]", .kind = .comment }, .markup_comment => .{ .close = "-->", .kind = .comment }, .python_triple_single, .toml_triple_single, => .{ .close = "'''", .kind = .string }, .python_triple_double, .toml_triple_double, => .{ .close = "\"\"\"", .kind = .string }, }; highlightDelimitedContinuation( language, text, state, spans, mode, format, ); return true;}const ContinuationFormat = struct { close: []const u8, kind: Kind,};fn highlightDelimitedContinuation( language: Language, text: []const u8, state: *State, spans: *SpanStorage, mode: Mode, format: ContinuationFormat,) void { const end = continuationEnd(mode, text, format.close) orelse { spans.append(.{ .start = 0, .end = text.len, .kind = format.kind, }); return; }; spans.append(.{ .start = 0, .end = end, .kind = format.kind, }); state.reset(); if (end == text.len) return; appendHighlightedTail(language, text, end, state, spans);}fn continuationEnd( mode: Mode, text: []const u8, close: []const u8,) ?usize { return switch (mode) { .toml_triple_single => structured.tomlTripleEnd(text, '\''), .toml_triple_double => structured.tomlTripleEnd(text, '"'), else => if (std.mem.indexOf(u8, text, close)) |index| index + close.len else null, };}fn appendHighlightedTail( language: Language, text: []const u8, start: usize, state: *State, spans: *SpanStorage,) void { const tail_text = text[start..]; const previous_base = spans.setBase(start); defer _ = spans.setBase(previous_base); state.retain(language, highlightFlat(language, tail_text, spans));}Source: lib/syn/src/scan/root.zig:7
zig
pub const line = @import("line.zig");Audit
| Definitions | 1 |
|---|---|
| Public names | 1 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |