Go to file
2026-08-28 00:50:58 +08:00
docs docs: mark component target design reviewed 2026-08-28 00:39:58 +08:00
examples refactor: lower Views into canonical Ebox nodes 2026-08-27 12:14:51 +08:00
postmortem Implement retained ETAF reactive runtime 2026-08-22 06:19:00 +08:00
tests perf: expose scoped ETAF operation observation 2026-08-28 00:50:58 +08:00
.gitignore feat: establish unified etaf view foundation 2026-08-05 00:36:52 +08:00
AGENTS.md docs: classify Ebox DSL primitives and sugar 2026-08-26 15:14:27 +08:00
DESIGN.md refactor: remove manual app precompilation 2026-08-25 20:03:06 +08:00
DESIGN.zh-CN.md refactor: remove manual app precompilation 2026-08-25 20:03:06 +08:00
etaf-actions.el perf: expose scoped ETAF operation observation 2026-08-28 00:50:58 +08:00
etaf-behavior.el feat: implement unified etaf architecture 2026-08-05 02:56:13 +08:00
etaf-compiler.el refactor: lower Views into canonical Ebox nodes 2026-08-27 12:14:51 +08:00
etaf-component.el Add theme palette and reactive data contracts 2026-08-24 02:08:53 +08:00
etaf-context.el perf: precompile apps and trace retained runtime updates 2026-08-25 17:16:56 +08:00
etaf-data.el perf: expose scoped ETAF operation observation 2026-08-28 00:50:58 +08:00
etaf-events.el perf: expose scoped ETAF operation observation 2026-08-28 00:50:58 +08:00
etaf-observer.el perf: expose scoped ETAF operation observation 2026-08-28 00:50:58 +08:00
etaf-performance.el chore: migrate conditional bindings for Emacs 31 2026-08-26 00:09:58 +08:00
etaf-reactive.el chore: migrate conditional bindings for Emacs 31 2026-08-26 00:09:58 +08:00
etaf-renderer.el refactor: lower Views into canonical Ebox nodes 2026-08-27 12:14:51 +08:00
etaf-resource.el perf: expose scoped ETAF operation observation 2026-08-28 00:50:58 +08:00
etaf-runtime.el perf: expose scoped ETAF operation observation 2026-08-28 00:50:58 +08:00
etaf-theme-tp.el perf: precompile apps and trace retained runtime updates 2026-08-25 17:16:56 +08:00
etaf-view.el refactor: lower Views into canonical Ebox nodes 2026-08-27 12:14:51 +08:00
etaf.el perf: expose scoped ETAF operation observation 2026-08-28 00:50:58 +08:00
Makefile perf: expose scoped ETAF operation observation 2026-08-28 00:50:58 +08:00
README.md docs: add unimplemented module boundary proposal 2026-08-26 01:27:23 +08:00
README.zh-CN.md docs: add unimplemented module boundary proposal 2026-08-26 01:27:23 +08:00

ETAF

ETAF is a small text-application framework built above the independent Ebox layout and rendering engine.

Its complete public model is:

Component(props, Scope) → View → Renderer → Ebox Node → Emacs buffer

Every visible structure uses one form:

(name :property value ... child ...)

The only child computation bridge is expr :value; attribute values are ordinary Elisp expressions.

(etaf-view
 (column
  (text :face 'bold "Hello")
  (text
   :color "#687386"
   (expr :value (if ready "Ready" "Waiting")))))

Define a Component:

(etaf-define-component status-label (&key label)
  "Render a status label."
  :view
  (text :face 'bold (expr :value label)))

(etaf-mount
 "*etaf-demo*"
 (etaf-view (status-label :label "Connected")))

etaf-view is the single public View constructor. Structural forms do not use quote; quote remains ordinary Elisp data syntax, such as 'bold. A View returned from ordinary Elisp is explicitly constructed with (etaf-view ...) inside expr.

Performance records

ETAF includes an opt-in, application-neutral timing recorder. It recognizes public Event, Action, mount, flush, focus, Data, Resource, and viewport operations, then correlates coarse ETAF, Ebox, TP, and SQLite stages when those packages are loaded.

(etaf-performance-mode 1)
;; Use any mounted ETAF application normally.
(etaf-performance-show)

For an interactive capture, run M-x etaf-performance-clear first. After reproducing the operations, press c in the panel (or run M-x etaf-performance-copy-report) to copy a complete report. Press w (or run M-x etaf-performance-export) to save the same report as an .eld file. The portable report includes the Emacs/display environment, power source, low-power mode, system load, grouped p50/p95/max, individual operations, GC deltas, and nested stages. The panel header exposes the same environment context so a machine-wide slowdown is not mistaken for one package hotspot.

The *ETAF Performance* panel shows operation IDs and parent operations, generation changes, total latency, GC deltas, and nested stage inclusive/self time. Records are bounded by etaf-performance-max-records; disabling the mode removes all recorder advice. etaf-performance-summary computes operation p50/p95/max statistics on demand, while etaf-performance-operation-stage-summary ranks one operation's package categories by exclusive time.

The default registry deliberately uses coarse package boundaries to keep the measured application representative. A package or application can add a temporary detail probe without coupling itself to an example:

(etaf-performance-register-stage
 'my-package-expensive-step 'application 'expensive-step)

Use etaf-performance-call-operation or etaf-performance-with-operation to trace an arbitrary operation that has no built-in public boundary.

Executable examples

The examples/ directory contains three core-only best-practice applications: retained state and Actions, Data Controller ownership, and Resource error/cleanup lifecycle. They are byte-compiled and driven through mounted public event paths by make check.

(add-to-list 'load-path "/path/to/github/etaf/examples")
(require 'etaf-counter-example)
(etaf-counter-example-open)

Documentation

Independent packages

Package Role
etaf-ui Official Component catalog: Button, Checkbox, Label, Panel, and DataGrid.
etaf-sqlite Concrete SQLite Data Source; the Data Controller remains in ETAF core.
etaf-playground ETAF examples, with the UI catalog loaded only when requested.
ebox-playground Ebox-only layout examples, independent from ETAF.

There is no separate etaf-data install: Data is a core ETAF capability. There is no generic etaf-adapters package: other databases, services, files, or ORMs should provide concrete Data Source packages with explicit names.

Load and verify

ECSS 0.1.0 and TP 1.0.0 are independent packages and may be installed in either order. Install both before Ebox 2.0.0, then install ETAF. ETAF consumes only the Ebox 2.0 public rendering contract.

During development, load the sibling Ebox checkout before ETAF:

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

Run the complete local gate:

make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs

The core gate byte-compiles the implementation, runs the core/Data/Resource tests, and checks documentation/API boundaries. Run make check in the sibling etaf-ui, etaf-sqlite, etaf-playground, and ebox-playground repositories for their independent gates; none is loaded by the core facade.