ebox/docs/user/ebox-api-reference.en.md
2026-08-26 00:09:53 +08:00

32 KiB
Raw Blame History

Ebox public API reference

中文

This document is the exhaustive user-facing inventory for the standalone Ebox package. It describes the supported node model, properties, layout helpers, rendering/publication workflows, selectors, scrolling, measurement, DSL, and optional native module. ebox--* names and undocumented module helpers are implementation details. The facade inventory is also available as the ebox-public-api constant after (require 'ebox).

Ebox owns box nodes, style normalization, measurement, layout, rendering, semantic update planning, selector integration, Grid, and the optional Rust reflow accelerator. TP owns live buffer publication, physical diff execution, revisions, and rollback. ECSS owns selector parsing, matching, and cascade semantics. Ebox does not provide Components, application state, UI controls, or an application lifecycle.

1. Install and load

Ebox requires Emacs 29.1 or newer, ECSS, and TP. With sibling source checkouts:

(add-to-list 'load-path "/path/to/github/ecss")
(add-to-list 'load-path "/path/to/github/tp")
(add-to-list 'load-path "/path/to/github/ebox")
(require 'ebox)

Loading Ebox loads the Elisp layout/runtime modules. It does not create a buffer, enable a mode in the current buffer, build Rust, or mutate the current editing buffer. The optional native module is loaded only when its workflow or an eligible native path requests it.

2. The normal lifecycle

The public workflow is:

(let ((root
       (ebox-column
        (ebox-create :id "status" :content "Ready" :width '(240))
        (ebox-create :content "A caller-owned source tree"))))
  ;; Pure materialization; returns a multi-line propertized string.
  (ebox-render root)

  ;; Retained TP surface; returns the live buffer.
  (ebox-render-to-buffer "*Ebox Demo*" root)

  ;; Later, build a new declarative root and publish it atomically.
  (ebox-commit
   "*Ebox Demo*"
   (ebox-column
    (ebox-create :id "status" :content "Updated" :width '(240))
    (ebox-create :content "The unchanged source is not mutated."))))

ebox-render has no live-buffer side effect. A static tree without an active stylesheet or inline inherited-style dependency can use isolated pure materialization; stylesheet-dependent pure renders use an ephemeral TP materialization. Both produce the same public string contract. The two buffer entry points use a retained TP surface. Ebox copies declarative input before assigning runtime identity, so the same source tree may be mounted in several buffers.

ebox-display-buffer is the convenience wrapper when Ebox should also display the buffer. It deletes other windows before switching to the rendered buffer; use ebox-render-to-buffer when the caller owns window selection.

3. Nodes and composition

Box and simple layout constructors

(ebox-create &rest properties)
(ebox-concat node-1 node-2)       ; two nodes side by side
(ebox-stack node-1 node-2)        ; two nodes vertically
(ebox-row &rest nodes)             ; many nodes side by side; a sole Range keeps its row parent
(ebox-column &rest nodes)          ; many nodes vertically; a sole Range keeps its column parent
(ebox-spacer &rest properties)    ; blank box

ebox-create returns a declarative box node. :content is string content; container children are normally supplied to ebox-row, ebox-column, ebox-flex, or ebox-grid. ebox-concat and ebox-stack accept two nodes; use the variadic row/column helpers for more than two children. Nil children are ignored. An empty row or column becomes a spacer.

In a row, omitted or auto widths use each childs intrinsic width when the children are concatenated; the parent viewport is not reused as every childs width. Explicit viewport, stretch, and definite widths still resolve against their containing block. A column fills narrower layout rows to its containing block, while a visual box paints its border and padding at its own used width.

:key is the stable application identity for a sibling. :id is a logical selector/update identifier. :host-ref is an opaque application-owned anchor used by host-reference lookup and logical candidate replacement. Host refs must be unique and non-nil within one source tree.

Flex

(ebox-flex
 :width '(480)
 :flex-flow '(row wrap)
 :gap '(1 (12))
 (ebox-flex-item (ebox-create :content "A")
                 :flex '(1 1 auto)
                 :align-self 'center)
 (ebox-create :content "B" :flex-grow 2))

Container properties are :flex-direction, :flex-wrap, :flex-flow, :justify-content, :align-items, :align-content, :gap, :row-gap, and :column-gap, plus ordinary box properties such as :width, :height, padding, border, and paint. Defaults are row direction, nowrap, flex-start main-axis justification, and stretch cross-axis alignment.

Item properties are :order, :flex, :flex-grow, :flex-shrink, :flex-basis, and :align-self. They may be placed directly on a child or attached with ebox-flex-item. Non-item properties passed to ebox-flex-item wrap the child in a normal box.

The supported size keywords for flex preferred/min/max sizes are the Ebox subset auto, min-content, max-content, fit-content, stretch, and contain; the max-size set also accepts none. fit-content may carry a numeric or viewport-relative limit. These are Ebox layout values, not a claim of full browser CSS compatibility.

Grid

(ebox-grid
 :width '(640)
 :grid-template-columns '((200) 1fr 1fr)
 :grid-template-rows '(1 1)
 :gap '(1 (12))
 (ebox-grid-item
  (ebox-create :content "Header")
  :grid-column '(1 :span 3))
 (ebox-create :content "Main" :grid-column 1 :grid-row 2)
 (ebox-create :content "Aside" :grid-column 2 :grid-row 2))

ebox-grid-fr constructs a fractional track: (ebox-grid-fr 2) returns (fr 2). Grid tracks support fixed sizes, auto, fractional tracks written as (fr FACTOR) or symbols such as 1fr, minmax, and repeat. Omitted positions use implicit tracks. :grid-auto-columns, :grid-auto-rows, and :grid-auto-flow (row or column) control implicit placement.

Grid item placement is one-based. :grid-column and :grid-row accept a positive start integer, (start :span positive-integer), or (start end) with end greater than start. :grid-column-span and :grid-row-span accept positive integers. ebox-grid-item is a convenience wrapper; placement properties may also be placed directly on a child node.

4. Units, box properties, and text properties

Size units

Value Meaning
Ordinary horizontal number, e.g. 12 Character columns, converted using the current display's space width.
One-element horizontal list, e.g. '(240) Absolute pixels.
Vertical number, e.g. 3 Lines.
(viewport) or viewport Current viewport width in pixels.
(viewport-height) or viewport-height Current viewport height in lines.
auto, min-content, max-content, fit-content, stretch, contain Intrinsic/preferred width values where the property and formatting context support them.

:box-sizing defaults to border-box; content-box is also supported. Width values include :width, :min-width, and :max-width; height values include :height, :min-height, and :max-height. Negative geometry is rejected. A viewport-dependent node must be rendered with a viewport context or rerendered with ebox-rerender-buffer-with-context.

Box, paint, and text properties

The following names are inputs to ebox-create. Style rules accept the style/geometry names in this table, while ebox-region-update accepts the mutable content/style/scroll subset supported by its target. Direct updates do not add children or change selector metadata; use ebox-commit or a logical candidate for structural changes. Structural metadata, :content, and :surface-properties are node/render inputs rather than stylesheet declarations. Canonical logical names and compatibility aliases are shown together.

Area Properties
Content/geometry :content, :box-sizing, :width, :min-width, :max-width, :height, :min-height, :max-height
Padding :padding, :padding-inline, :padding-block; longhands :padding-block-start, :padding-inline-end, :padding-block-end, :padding-inline-start; aliases :padding-top, :padding-right, :padding-bottom, :padding-left and the pixel/height aliases :padding-right-pixel, :padding-left-pixel, :padding-top-height, :padding-bottom-height
Margin :margin, :margin-inline, :margin-block; longhands :margin-block-start, :margin-inline-end, :margin-block-end, :margin-inline-start; aliases :margin-top, :margin-right, :margin-bottom, :margin-left and the pixel/height aliases :margin-right-pixel, :margin-left-pixel, :margin-top-height, :margin-bottom-height
Border :border, :border-top, :border-right, :border-bottom, :border-left, :border-width, :border-style, :border-color; side longhands :border-*-width, :border-*-style, :border-*-color; compatibility aliases :border-top-p, :border-bottom-p, :border-left-pixel, :border-right-pixel
Paint :color, :background-color, and alias :bgcolor
Typography :font, :font-family, :font-height and alias :font-size, :font-weight, :font-slant
Text/layout :text-align (left, center, right), :vertical-align (top, center/middle, bottom), :overflow (scroll, hidden, visible), :wrap-mode (word, char, kp, or nil), :visibility (visible or hidden)
Structural style :display is computed for node/layout contexts; the layout constructors normally choose the valid display tuple.
Flex container/item :flex-direction, :flex-wrap, :flex-flow, :justify-content, :align-items, :align-content, :gap, :row-gap, :column-gap (aliases :grid-row-gap, :grid-column-gap); item names :order, :flex, :flex-grow, :flex-shrink, :flex-basis, :align-self
Grid container/item :grid-template-columns, :grid-template-rows, :grid-auto-columns, :grid-auto-rows, :grid-auto-flow, :justify-items; item placement :grid-column, :grid-row, :grid-column-span, :grid-row-span
Extra text properties :surface-properties accepts an even property list of Emacs text properties, applied to rendered characters without newlines. Inner non-nil properties win.

Use :font, not :face, for the box font. :font accepts an Emacs face symbol, a face name string, or a face plist; the typography longhands are merged into that face. :visibility 'hidden suppresses ink while preserving layout footprint and metadata. With :overflow 'visible, excess lines are published as visible overflow; hidden clips them; scroll exposes a bounded window and enables Ebox scrolling when content is taller than the box.

Padding and margin use CSS 14-value expansion. Horizontal entries use the horizontal units above, while top/bottom entries use line units. Left/right border widths are pixel geometry. Top/bottom borders use Emacs overline and underline faces, so their width is a presence flag rather than arbitrary pixel thickness.

Node metadata and selector inputs

These inputs identify nodes without changing their geometry:

Input Meaning
:id Logical selector/update id. Symbols and other scalar values are normalized to strings; an id should be unique where a direct update resolves it.
:key Stable sibling identity used by reconciliation and also exposed as the built-in selector :key attribute.
:class One class token or a list of class tokens for selector matching.
:selector-state One state token or a list of state tokens matched by state pseudos such as :hover and :active.
:selector-attributes Explicit attribute alist, such as ((role . button)); content, layout values, and runtime fields are never inferred.
:host-ref Unique application-owned opaque anchor for ebox-host-ref-position, ebox-host-ref-bounds, and host-ref candidate replacement.
:scroll-offset Initial/controlled line offset for a scroll region. Prefer scroll commands for interaction; updates require a live region handle.

:id, :key, and :host-ref are not stylesheet declarations. :class, :selector-state, and :selector-attributes are selector metadata, not general-purpose application state.

5. Stylesheets and cascade

Inline properties are enough for most nodes. For selector-driven styles, use the isolated Ebox stylesheet:

(ebox-style-reset-rules)
(ebox-style-add-rule
 ".card"
 '(:color "#1F2937"
   :background-color "#F8FAFC"
   :padding '(1 (12)))
 :layer 'base)
(ebox-style-add-rule
 ".card:has(> .warning)"
 '(:border-color "#DC2626")
 :layer 'state)

ebox-style-add-rule accepts a selector string or parsed AST, an Ebox declaration plist, and the ECSS cascade keywords :origin, :layer, and :scope. ebox-style-reset-rules clears the stylesheet. Rules are global to the loaded Ebox style registry; changing rules does not silently publish an already-mounted buffer, so rerender or commit the affected buffer after a rule change. ebox-style-cascade-active-p reports whether rules are present.

The ECSS-backed style domain includes inheritance for color and typography, computed values, cascade layers, custom-property declarations, and dirty classification for paint/geometry/structure changes. Ebox interprets only the properties listed in this reference; percentages, absolute positioning, z-index, shadows, border radius, browser bidi, and full browser typography are outside the package.

Custom properties whose names start with -- may be carried by the ECSS style domain, but they do not affect Ebox output unless a host integration resolves them into one of the supported Ebox properties.

6. Rendering, identity, and updates

Region ids and logical handles

ebox-region-ids returns region ids in document order from an unrendered tree or rendered string. Capture ids before the first mount if a low-level source mapping needs them:

(let* ((root (ebox-column
              (ebox-create :id "title" :content "Title")
              (ebox-create :id "body" :content "Body")))
       (ids (ebox-region-ids root)))
  (ebox-render-to-buffer "*Ebox Demo*" root)
  ids)

For application updates, prefer logical ids and opaque handles:

(let ((handle (ebox-region-resolve "*Ebox Demo*" "body")))
  (ebox-region-update handle :content "Changed" :color "#166534"))

ebox-region-resolve signals when the buffer is absent, the logical id is missing, or the id is ambiguous. A handle is scoped to one retained TP surface; it becomes stale when its object is removed or its buffer is killed. Numeric region ids are render metadata and are not accepted by ebox-region-update.

Direct and selector updates

ebox-region-update accepts mutable content/style/scroll property keywords and returns the committed update report unless an explicit batch queues it. It builds an isolated candidate, plans the smallest safe Ebox owner, and asks TP to publish once. It does not add children or mutate :id, :class, :key, or other selector metadata. Invalid declarations, render failures, publication failures, and callback failures leave the previous buffer/runtime/report intact.

ebox-selector-update-buffer applies properties to all editable selector matches and returns:

(:selector SELECTOR
 :matched INTEGER
 :updated INTEGER
 :skipped ((:node-id ID :reason no-region) ...)
 :reports (REPORT ...))

An explicit multi-update batch can use the lower-level incremental batch functions only when an application deliberately owns that boundary; the normal public alternative is ebox-selector-update-buffer.

Logical candidates

Candidates are one-shot transactions based on the exact currently published runtime. They are useful when several stable subtrees must be replaced before one commit:

(let* ((buffer (get-buffer "*Ebox Demo*"))
       (candidate (ebox-candidate-begin buffer))
       (match (car (ebox-selector-query-buffer buffer "#body"))))
  (ebox-candidate-replace
   candidate
   (plist-get match :node-id)
   (ebox-create :id "body" :content "Candidate replacement"))
  (ebox-commit buffer candidate))

Frameworks that retain semantic owners separately from backend anchors can use ebox-range-ref-present-p as a read-only check before choosing a wider published owner. It returns nil when the semantic Range is nested inside a material anchor and therefore is not independently addressable in the current Ebox publication.

ebox-candidate-replace-host-ref uses an application-owned :host-ref instead of a runtime node id. Both replacement functions accept optional old-semantic-key and new-semantic-key pairs for bounded detached identity reuse. A candidate is sealed by commit and cannot be reused; it also becomes stale if the captured buffer runtime or buffer tick changes.

ebox-candidate-patch-host-paint compares previous and next declarative Host outputs and records a node-local patch only when every changed field is paint-only. It retains child/runtime identity, updates inherited foreground state in one affected-subtree pass, and returns nil when ordinary subtree replacement is required.

ebox-candidate-replace-root targets a private candidate-bound root address. It accepts exactly one declarative node, clears caller runtime identities, and is last-wins. The final root replacement absorbs descendant node and host-ref operations recorded before or after it, with no wrapper or public reference.

ebox-child-range creates a non-node segment descriptor in a material child list. Its non-nil ref is root-global and its items participate directly in the parent's key, selector, style, and layout scope. Use ebox-candidate-replace-range-ref with a proper declarative node list to replace that base payload. Empty payloads remain addressable.

Host-reference positions

(ebox-host-ref-position "*Ebox Demo*" 'toolbar)
;; => first live character position, or nil
(ebox-host-ref-bounds "*Ebox Demo*" 'toolbar)
;; => (START . END), excluding margins, or nil

Positions and bounds belong to the current publication generation. Obtain new values after any update. Ebox's host-reference table is distinct from logical selector ids.

Reports and viewport reflow

Frameworks that allocate a new view tree before calling Ebox can include the whole input callback in Ebox's render GC budget:

(ebox-call-with-render-burst
 (lambda ()
   (let ((next-root (build-framework-view)))
     (ebox-commit buffer next-root))))

ebox-call-with-render-burst is the preferred exception-safe boundary. When the operation cannot be expressed as one function call, ebox-render-burst-begin returns an opaque token for ebox-render-burst-end; callers must use unwind-protect and end nested tokens in last-in, first-out order. Interactive bursts share Ebox commit's deferred state and restore the caller's GC settings 0.2 seconds after the outermost end. A new burst cancels and supersedes the pending restore. Batch bursts restore the exact threshold and percentage immediately and do not run GC at the boundary. These functions only define allocation/GC ownership; they do not publish, commit, or expose Ebox runtime state.

ebox-buffer-update-report returns a defensive copy of the last successful report for a mounted buffer; it signals for a missing/non-Ebox buffer. A fresh mount has no update report until its first update. Reports include the Ebox strategy and publication scope plus TP surface revision and physical operation/reconciliation facts.

The complete commit signature is (ebox-commit BUFFER NEXT-ROOT &optional FRAMEWORK-PUBLISH FRAMEWORK-ROLLBACK). Publish receives the report after the buffer, TP surface, and Ebox runtime agree. If a later phase fails, rollback receives that same report at most once; rollback errors and quits are contained. :framework-participant-state, :framework-participant-diagnostics, and :scroll-finalization-diagnostics are read-only outcome fields.

Use ebox-rerender-buffer-with-context when a root depends on a new viewport:

(ebox-rerender-buffer-with-context
 (get-buffer "*Ebox Demo*")
 800                         ; viewport width in pixels
 30)                         ; optional viewport height in lines

This preserves node/region identity and routes the change through viewport dirty planning. (viewport) and (viewport-height) are resolved from this context. For pure rendering, callers may instead bind ebox-viewport-width in pixels and ebox-viewport-height in lines around the render. Do not mutate a published node tree in place.

Visible mounted buffers follow their displaying window automatically. Ebox publishes every size event immediately through its retained incremental path. The Emacs hook is serialized and reentrant calls are rejected; there is no second host hook, timer, or viewport queue. ebox-viewport-window-width returns the same display-safe pixel width used by that controller, so hosts must not install a second resize hook or width rule. The former ebox-viewport-resize-delay setting has been removed; immediate delivery has no timer setting to migrate.

7. Selectors

ebox-selector-parse delegates to ECSS and returns its structured AST. ebox-selector-match-node-p matches one declarative node against a selector or AST. ebox-selector-query-all returns document-ordered matches from an unmounted tree. ebox-selector-query-buffer queries the retained runtime of a live buffer and adds :buffer and, when the node is editable, :region-handle to each match record.

Supported selector syntax comes from ECSS:

  • selector lists and compound type/id/class selectors;
  • attribute presence and =, ~=, |=, ^=, $=, *= operators with i and s flags;
  • state pseudos such as :hover and :active through :selector-state;
  • :is(...), :where(...), :not(...), and relational :has(...);
  • descendant whitespace, child >, adjacent sibling +, and general sibling ~ combinators.

Ebox node types are exposed as selector types box, row, column, flex, grid, and item. :id and :key become built-in attributes. Additional attributes must be supplied explicitly, for example :selector-attributes '((role . button)); visible content, layout values, and internal runtime slots are never inferred as selector attributes.

(ebox-selector-query-buffer "*Ebox Demo*" ".toolbar > box.action")
(ebox-selector-query-buffer "*Ebox Demo*" "div:has(> .warning)")
(ebox-selector-update-buffer "*Ebox Demo*" "[role=button]"
                             :color "#2563EB")

The compatibility aliases ebox-select-all and ebox-update-selector refer to ebox-selector-query-buffer and ebox-selector-update-buffer.

8. Scrolling and viewport state

Set :overflow 'scroll (the default) and a finite :height to create a scroll window:

(ebox-create
 :id "log"
 :width '(420)
 :height 8
 :overflow 'scroll
 :content (mapconcat #'identity lines "\n"))

ebox-scroll-down, ebox-scroll-up, ebox-scroll-page-down, and ebox-scroll-page-up operate on the innermost scroll region at point. They delegate to ordinary Emacs scrolling when no Ebox region can consume the command. ebox-wheel-scroll-down and ebox-wheel-scroll-up accept mouse events, animate when ebox-wheel-smooth-scroll is non-nil, and otherwise delegate to mwheel-scroll. ebox-buffer-mode installs ebox-scroll-map locally; ebox-render-to-buffer enables the mode on its returned buffer.

ebox-scroll-state accepts a numeric region id and returns a read-only state plist for source-model mapping. Its useful public facts include the current :scroll-offset, content height/lines, and cached visible lines. Treat the plist as diagnostic/read-only data; use ebox-region-update with :scroll-offset or the scroll commands to change position.

Scroll content is lazily prefetched and can be rendered in bounded slices. Ebox preserves cached scroll state across safe retained updates and rolls it back with the rest of a failed publication.

9. Measurement and cache controls

ebox-string-pixel-width returns the first-line display pixel width of a string, honoring text scale and fixed display spaces. It is the same public measurement primitive used by layout. ebox-display-signature returns the current display inputs used for measurement cache invalidation. Call ebox-clear-cache after changing font or named-face metrics outside the normal display-signature signals.

The main customization variables are:

Group Variables and defaults
Render cache ebox-render-cache-max-entries 2048; ebox-render-cache-max-bytes 32 MiB; ebox-render-root-cache-max-entries 16; ebox-render-root-cache-max-bytes 8 MiB
Keyboard/mouse scroll ebox-scroll-step 1; ebox-wheel-scroll-step 1; ebox-wheel-smooth-scroll nil; ebox-wheel-smooth-scroll-interval 0.016; ebox-wheel-smooth-scroll-lines-per-tick 4; ebox-wheel-smooth-scroll-target-ticks 8. Keyboard uses point; wheel uses event position; residual lines bubble through nested owners. An interactive complete, chrome-free root document owner may be idle-materialized once and then use Emacs's native window line start; ordinary updates/resizes only warm retained indexes and never start a second native publication; nested/lazy/chrome owners retain transactional Ebox publication.
Lazy scroll ebox-scroll-lazy-prefix-lookahead-lines 8; ebox-scroll-lazy-idle-prefetch-lines 128; ebox-scroll-lazy-idle-prefetch-slice-lines 16; ebox-scroll-lazy-idle-prefetch-delay 0.15
Runtime prewarm ebox-runtime-idle-prewarm t; ebox-runtime-idle-prewarm-delay 0.1; ebox-runtime-idle-prewarm-prefix-resume-delay 2.0; ebox-runtime-idle-prewarm-slice-size 32; ebox-native-buffer-scroll t (initial/visible-window handoff only; strict root-owner proof)
Predicted reflow ebox-runtime-idle-reflow-cache-prewarm t; ebox-runtime-idle-reflow-cache-prewarm-delay 0.15
Reflow GC ebox-reflow-cache-prewarm-gc-cons-threshold auto; ebox-reflow-cache-prewarm-gc-auto-frame-budget 0.2; ebox-reflow-cache-prewarm-gc-auto-min-threshold 64 MiB; ebox-reflow-cache-prewarm-gc-auto-max-threshold 1 GiB; ebox-reflow-cache-prewarm-gc-auto-initial-threshold 512 MiB; ebox-reflow-cache-prewarm-gc-auto-target-layouts 24; ebox-reflow-cache-prewarm-gc-cons-percentage 0.1
Visual verification ebox-visual-check-output-dir points to the temporary directory used for optional screenshots and reports.

Idle prewarming never publishes buffer text or runtime state. Set the relevant boolean to nil when a host application must avoid background preparation.

10. Standalone .ebox DSL

ebox-build compiles a data-oriented list form. Supported tags are box and ebox, row, column, flex, item, grid, grid-item, and spacer:

(ebox-build
 '(grid :width (640)
        :grid-template-columns ((200) 1fr 1fr)
        :gap (1 (12))
        (grid-item :grid-column (1 :span 3)
                   (box :content "Header"))
        (box :content "Main")))

Strings directly under box become newline-joined content. Child forms become a default vertical child layout. row and column can receive box properties around their child layout. flex accepts container properties; item accepts flex item properties and exactly one or more child forms; grid-item requires exactly one child; spacer accepts no children.

Inside a .ebox file, keep structural forms unquoted. Quote list and symbol constants in property positions when they are data, such as :gap '(1 (12)) or :justify-content 'center; executable Elisp expressions remain unquoted for the sibling playground runner.

11. Optional Rust reflow

The native module is an accelerator, not a correctness dependency. Its Rust boundary receives bounded numeric layout work only; Ebox keeps the Elisp path as the exact fallback and never builds Rust while loading.

(ebox-native-status)       ; show toolchain, path, ABI, and load diagnosis
(ebox-native-build)        ; asynchronous build/install
(ebox-native-build t)      ; clean Ebox's private Cargo cache first

The equivalent repository command is make native-build. Configure ebox-native-reflow-module-path with a module file or directory. Session limits are ebox-native-reflow-max-jobs 512, ebox-native-reflow-max-results 512, and ebox-native-reflow-max-result-bytes 64 MiB. A missing or incompatible module leaves Ebox on Elisp; ebox-native-status reports the reason.

ebox-byte-compile recompiles all active Ebox Elisp sources and does not build Rust. Restart Emacs after a successful byte compilation if the current process should load the new .elc files.

12. Public function inventory

The following table covers the public functions in the facade inventory. The style-rule functions immediately below are public module-level style APIs.

Function Use
ebox-create, ebox-build Create a node or compile the .ebox list DSL.
ebox-concat, ebox-stack, ebox-row, ebox-column, ebox-spacer Compose simple horizontal/vertical layouts and blank boxes.
ebox-flex, ebox-flex-item Build flex containers and item metadata.
ebox-grid, ebox-grid-fr, ebox-grid-item Build Grid layouts, fractional tracks, and placement metadata.
ebox-render, ebox-render-to-buffer, ebox-display-buffer Pure materialization, retained mount, and display wrapper.
ebox-commit, ebox-buffer-update-report, ebox-rerender-buffer-with-context, ebox-viewport-window-width Atomic root commit, report lookup, viewport-context rerender, and the shared display-safe width sampler.
ebox-region-ids, ebox-region-resolve, ebox-region-update Region mapping, logical handle lookup, and direct update.
ebox-child-range, ebox-range-ref-present-p, ebox-candidate-begin, ebox-candidate-replace, ebox-candidate-replace-range-ref, ebox-candidate-replace-root, ebox-candidate-replace-host-ref, ebox-candidate-patch-host-paint Persistent material child segments, backend-anchor lookup, subtree replacement, and retained Host paint transactions.
ebox-host-ref-bounds, ebox-host-ref-position Live host-reference bounds and first position.
ebox-selector-parse, ebox-selector-match-node-p, ebox-selector-query-all, ebox-selector-query-buffer, ebox-selector-update-buffer ECSS selector compilation, matching, querying, and batch update.
ebox-select-all, ebox-update-selector Compatibility aliases for the two buffer selector functions.
ebox-buffer-mode, ebox-scroll-map, ebox-scroll-down, ebox-scroll-up, ebox-scroll-page-down, ebox-scroll-page-up, ebox-wheel-scroll-down, ebox-wheel-scroll-up, ebox-scroll-state Interactive scrolling, local keymap, and read-only scroll state.
ebox-string-pixel-width, ebox-display-signature, ebox-clear-cache Display-aware measurement and cache management.
ebox-native-build, ebox-native-status, ebox-byte-compile Optional native workflow and Elisp byte compilation.

Style-rule and style inspection entry points available after (require 'ebox) include ebox-style-add-rule, ebox-style-reset-rules, ebox-style-cascade-active-p, ebox-style-compute, ebox-style-expand-shorthands, ebox-style-compile-declarations, ebox-style-merge-declarations, ebox-style-compute-subject, ebox-style-property, ebox-style-canonical-name, and ebox-style-dirty-kind. The first two are the normal application entry points; the remaining helpers are for integrations that need to inspect or prepare ECSS-backed style data.

13. Verification and support boundary

From the repository root:

make load EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make compile EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make docs-contract-tests EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make native-rust-tests

Focused targets include make core-tests, make grid-tests, make surface-tests, make selector-tests, make dsl-tests, make flex-tests, and make visual-check-tests. The sibling ebox-playground package owns runnable example fixtures; ETAF owns Components, state, controls, and application behavior. Do not call private ebox--* functions or edit the historical Ebox checkout as part of this package.