Commit Graph

8 Commits

Author SHA1 Message Date
Kinneyzhang
99bd6f7c15 Drop tp-stack's phantom dependency on tp-ops
tp-stack.el required tp-ops but used nothing from it: a whole-word
sweep of every symbol tp-ops defines finds exactly one hit in
tp-stack, and it is a docstring cross-reference to tp-set, not code.
The require only made the module graph look denser than it is and
suggested a stack->ops edge that never existed.

The stack module's real dependencies are tp-core (interval walking),
tp-reactive (the buffer registry it feeds via
tp-reactive--register-layer-buffer) and tp-layer (the stack-storage
codec).  All three requires are already present, and tp-stack.el
byte-compiles independently with warnings-as-errors after the
deletion.  Load order through tp.el is unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 02:07:43 +08:00
Kinneyzhang
e15a18d718 Flatten/merge no longer render hidden layers; both return run counts
tp-hide-layer's contract says a hidden layer "no longer renders", but
tp-flatten-layers merged the whole stack unfiltered and
tp-merge-layers merged every listed layer unfiltered (only the
tp-hidden bookkeeping flag was stripped), so flattening or merging a
stack with a hidden layer silently un-hid it: the hidden layer's
props became the visible rendering (green -> red in the review
probe).  The shipped flatten test asserted only flag absence, missing
the rendering flip.

New semantics, stated in both docstrings:
- tp-flatten-layers discards hidden layers (image-editor flatten):
  only visible layers' props merge; a run whose every layer is hidden
  flattens to bare text, consistent with all-hidden rendering.
- tp-merge-layers merges hidden matched layers away but excludes
  their props, so a merge can never render what was hidden.  When ALL
  matched layers are hidden the merged layer keeps their merged props
  but carries tp-hidden itself - data preserved, nothing un-hidden,
  tp-show-layer reveals it.

API-RET-01 slice: both functions now return the number of modified
runs, counting exactly like tp-delete-layer (their previous hardcoded
nil return was undocumented, so no documented behavior changes).

Tests: the flatten-drops-tp-hidden-flag test now asserts the rendered
face; new tests port the hid2-probe scenarios (flatten with hidden
top, all-hidden flatten to bare text, merge excluding hidden props,
all-hidden merge staying hidden and revealable) plus count-return
coverage for both functions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 01:47:03 +08:00
Kinneyzhang
c6fbccf659 Move the layer-stack storage codec from tp-stack down to tp-layer
Behavior-preserving relocation of tp--stack-hidden-p,
tp--stack-props-to-list and tp--stack-build-props into tp-layer.el,
beside their existing dependencies tp--layer-stack-to-list and
tp--build-layer-props.  The codec's only inputs are dash/seq/plist
utilities, so it sits naturally at the layer-definition level, and
the move lets the reactive re-render engine (tp-render.el, which may
not require tp-stack) read and write stack storage without
duplicating format knowledge - the prerequisite for making reactive
updates write through to hidden/buried layer storage.  tp-stack keeps
calling the codec downward; no callers change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 01:36:31 +08:00
Kinneyzhang
28acdae183 Register every buffer-mutating layer write in the reactive registry
The 0.3.0 buffer registry made reactive updates walk only registered
buffers, but only tp-set/tp-reset/tp-add registered.  Layer stack
mutators (tp-push-layer, tp-put-layer, hide/show, move/raise/rotate,
merge/flatten, add-to-layers) and the pattern-apply paths
(tp-match-add/-reset, tp-regexp-add/-reset) stamped tp-name via
direct set-text-properties without registering, so the moment a layer
was known from one tp-set anywhere, every buffer reached only through
those paths was silently and permanently skipped by reactive updates
- including the README's own flagship tp-push-layer example.  This
regressed 0.2.0, whose full buffer-list scan reached every buffer.

Fix: every buffer write that stamps tp-name now registers the buffer
via tp-reactive--register-layer-buffer (called directly, so tp-stack
and tp-search gain no tp-ops edge):

- tp-stack.el: new tp--stack-register-layers registers every named
  plist of the freshly written stack - buried and hidden layers
  included, which the stack-aware GC liveness fix builds on - beside
  all eleven set-text-properties sites; requires tp-reactive.
- tp-search.el: tp--deep-merge-apply and tp--reset-apply register the
  target buffer for the applied props' tp-name (and any group
  tp-layers entries); requires tp-reactive.

Regression tests: reactive updates reach a second buffer whose layer
arrived via tp-push-layer / tp-regexp-add / tp-match-reset after a
tp-set registered the layer elsewhere, and stack writes register
buried and hidden layers that arrived via string insertion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 01:35:05 +08:00
Kinneyzhang
27ad7325c5 Close cross-module seams for multi-argument parameterized specs
tp-put-layer now dispatches multi-argument layer and group specs —
flat (NAME A1 .. AN) and wrapped (NAME (A1 .. AN)) — checked before
the list-of-specs branch so argument values that are themselves layer
names are not misread as a stack of layers. tp-remove's layer-key
extraction binds every parameter with dummy args via
tp-layer-props-with-args instead of passing a single dummy to the
first parameter only. Five regression tests; suite 527/527, doctests
63/63, compile clean.

Known pre-existing gap surfaced while testing (deliberately not fixed
here, queued for the design review): parameterized layers applied via
the tp-set plist forms never stamp tp-name, so tp-remove by layer
name is a silent no-op for them regardless of arity.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 00:36:19 +08:00
Kinneyzhang
507ccf798c Integrate 0.3.0 feature tracks: reactive perf, stack visibility, search/API
Reactive performance (tp-reactive/tp-render/tp-ops): layer->buffer
registry replaces full buffer-list scans on reactive updates, with a
conservative unknown->learning-scan fallback, kill-buffer pruning,
and tp-reactive-track-buffer to close the propertized-string-insert
gap; minimal-diff tp-text replacement preserves point and markers and
makes identical-text updates true no-ops; tp-gc-anonymous-layers
collects interned anonymous layers no registered buffer still shows.

Stack capabilities (tp-stack): tp-hide-layer/tp-show-layer visibility
(hidden layers stay in the stack but do not render; hiding the top
reveals the next visible layer), tp-lower-layer, tp-rotate-layer
DIRECTION/COUNT, tp-layer-stack-at, and modified-run-count returns
with NOERROR options.

Search and layer APIs (tp-search/tp-layer): SUBEXP capture groups and
START/END bounds for tp-regexp-*/tp-match-*, PREDICATE/NOT-CURRENT
exposure on tp-forward/tp-backward/-do (defaults keep 0.2.0 semantics),
multi-argument parameterized layers (define-tp/define-tps arglists of
any arity, tp-layer-props-with-args, tp-layer-arglist), and the
interactive tp-describe-layer.

79 new regression tests; combined suite 522/522 green, shuffled run
green, doctests 63/63, byte-compile clean with warnings-as-errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 00:32:47 +08:00
Kinneyzhang
ceb0dfb0bc Fix confirmed bugs in layer, stack, search, and reactive-render modules
35 fixes across tp-layer.el, tp-stack.el, tp-search.el, tp-reactive.el
and tp-render.el, each empirically reproduced before and after:
layer-definition resolution/cycles/copying/cleanup, clipped region-local
stack mutators, symmetric backward search matching, length-changing
replacements, and reactive re-render correctness (replace-not-accumulate,
buffer-local isolation, batching union, per-interval props).

Adds four per-module regression suites (100 new tests); combined suite
is 438/438 green. tp-test-backward updated to the now-symmetric backward
matching contract it previously codified inverted. The string-vs-buffer
shortfall divergence in tp-forward-do/tp-backward-do is documented in
CHANGELOG as a known divergence rather than changed. Adds CHANGELOG.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 20:01:20 +08:00
Kinneyzhang
5e5017a726 Split tp.el monolith into layered modules (behavior-preserving)
tp.el (4866 lines) is now an umbrella over nine modules with an
enforceable dependency order: tp-core -> tp-reactive -> tp-layer ->
tp-ops -> tp-search -> tp-render -> tp-stack -> tp-palette ->
tp-builtins.  Upward dependencies are inverted through four hook
variables installed by tp-render.el.

Also: require text-property-search (fixes tp-backward void-function),
clip tp-intervals to the requested range, add the shared clipping
interval walker tp--map-intervals and tp-face-properties, remove
synced-conflict junk files, byte-compilation now succeeds (define-tp
macroexpansion previously failed at compile time).

All 280 legacy tests pass plus 8 new tp-core tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 17:13:44 +08:00