Fork of micro-editor/micro

Syntax highlighting #

Micro no longer ships a built-in regex engine. Syntax highlighting is provided by extensions through the micro/syntax Lua module. A file with no provider is not an error: it opens normally with its filetype detected and no colors.

Provider contract #

A provider registers a matcher and a request(ctx, reply) function:

local syntax = import("micro/syntax")

syntax.register {
    name = "my-provider",          -- required
    filetype = "go",               -- exact match against the buffer filetype
    filename = "\\.go$",           -- optional Go regexp against the full path
    header = "^package ",          -- optional Go regexp against line 0
    signature = "^// Code generated", -- optional Go regexp for tie-breaking
    priority = 10,                 -- higher wins; default 0
    request = function(ctx, reply)
        -- reply takes a flat array of line, startByte, endByte, group
        reply {
            0, 2, 7, "preproc",
            1, 4, 9, "constant.string",
        }
    end,
}

syntax.unregister(name) removes a provider. syntax.invalidate(buf) asks for fresh spans. syntax.has_color(name) reports whether the current colorscheme defines a group or one of its dotted prefixes. syntax.providers() returns the registered names.

Context #

ctx contains:

field meaning
buf the Buffer
id stable numeric id shared by split views of one buffer
text the whole buffer as UTF-8, lines joined with \n
path the buffer path
filetype the detected or explicitly set filetype
first, last inclusive line range; currently the whole buffer
generation monotonic counter for stale-reply checks
cause "open", "edit", "manual", or "reload"

Spans #

A span is four values: zero-based line, zero-based byte start, exclusive byte end, and a group name. Spans must stay on one line. Convert multi-line constructs by emitting one span per line. Later spans win over earlier ones; an empty group name clears its range. Offsets are bytes, not rune or display columns, so UTF-8 and combining marks map correctly.

A reply replaces every span in the buffer. Lines the reply does not mention are cleared. Groups are looked up by config.GetColor, which already handles dotted prefixes such as constant.string falling back to constant.

Matching #

An explicit filetype setting wins. Otherwise micro detects the filetype from its generated filename/header/signature table. A provider for that filetype is chosen by priority. If the filetype is unknown, providers are matched by filename first, then first line, with signatures breaking ties, then priority. Detection still works with no provider registered.

Async replies #

request and reply run on the main goroutine. A provider may keep reply and call it later, for example from micro.After or a micro/shell job callback. Edits are debounced (~25 ms), and at most one request is in flight per buffer. Replies for an older generation are dropped. A provider that errors three times is disabled.