Commit Graph

320 Commits

Author SHA1 Message Date
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
7f0da36ada Bump version to 0.3.0; start changelog with the infrastructure work
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 00:12:22 +08:00
Kinneyzhang
b454cbb061 Make two doctest assertions property-order-insensitive for Emacs 28
Emacs 28 stores/prints text-property plists in a different order than
29+; the S-mystyle and L-paramgroup assertions compared whole prin1
strings and failed on 28.1 only. Compare per property instead (face,
tp-name, tp-layers — the stack order inside tp-layers is stable), and
note the version-dependent print order beside both README examples.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 23:58:12 +08:00
Kinneyzhang
ca405f977d CI: surface doctest failures as annotations
Job logs are not anonymously readable; emit FAIL/expected/got lines
(or the log tail on a load error) as ::error:: annotations so the
failing assertion is visible through the public Checks API.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 23:55:20 +08:00
Kinneyzhang
41e3de5865 Fix CI env export: glob matched GNU ELPA's .signed marker too
The dash install succeeded; the step failed writing GITHUB_ENV because
ls -d .elpa/dash-* matched both the package directory and the adjacent
dash-N.N.N.signed marker, producing a second non-KEY=value line
("Invalid format"). Restrict the glob to directories. Also bump
actions/checkout to v6 to clear the Node 20 deprecation warning.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 23:53:10 +08:00
Kinneyzhang
f422a0f3a9 Remove MELPA recipe draft; publication is not planned
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 23:49:56 +08:00
Kinneyzhang
36328a1cca Phase 1: CI matrix, zero-warning compile, shuffled runner, autoloads
Byte-compile warnings swept 57 -> 0 across all modules, tests, and
doctest (docstring rewraps and quoting, defvar declarations for the
reactive test variables, prefixed doctest counters, dead-binding
removal, one impossible eq -> equal in a face-merge assertion) with
behavior preserved. GitHub Actions workflow runs an Emacs 28.1/29.4/
30.1 matrix: compile-all with warnings-as-errors, the 443-test suite,
a genuinely shuffled-order rerun (tp-run-shuffled.el runs each test
individually; ERT's member selector cannot reorder), and the 63
README doctests. Makefile gains WERROR, compile-all, and
test-shuffled. Autoload cookies added for the four interactive
commands and the define-tp/define-tps macros. package-lint: 0
findings (main file tp.el); draft MELPA recipe in docs/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 23:46:52 +08:00
Kinneyzhang
2c5ce6c27b Merge refactor/modular-architecture: 0.2.0 modular split, bug fixes, docs
Splits tp.el into nine layered modules behind the tp.el umbrella,
fixes ~43 confirmed bugs across every subsystem, adds tp-member,
grows the ERT suite from 280 to 443 tests plus 63 executable README
doctests, and aligns CHANGELOG, bilingual READMEs, and docs/ with the
actual behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 21:19:05 +08:00
Kinneyzhang
ca2f02dcdf Add tp-doctest.el: README examples as executable tests
63 assertions reproduce README code blocks and compare against the
exact documented outputs; make doctest runs them in batch and exits
non-zero on any mismatch, so docs and code cannot silently drift
again. Wired into the Makefile and mentioned in both READMEs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 21:18:44 +08:00
Kinneyzhang
ecdd952b55 Unify -do shortfall to all-or-nothing on strings and buffers
tp-forward-do/tp-backward-do target the TIMES-th match specifically;
when fewer matches exist the string paths applied FUNCTION to the last
available match -- the wrong target -- while buffer paths applied
nothing. Both now apply nothing on shortfall and return the available
count. Updates the two legacy with-range tests that codified the
string behavior, adds four shortfall/exact-count regression tests, and
documents the contract in both READMEs and the docstrings. Suite
443/443 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 21:16:56 +08:00
Kinneyzhang
2b33495898 Align README (EN/CN) and docs/ with modular architecture and 0.2.0 semantics
README.md/README_CN.md: new verified Quick Start (fixes the dead
#quick-start nav link); Installation rewritten for the tp-*.el module
family; every broken or drifted example fixed and executed in batch
Emacs (mandatory () ARGLIST and quoted reactive keywords in all
define-tp/define-tps calls, corrected tp-search-map argument order,
interval-list returns, stacked duplicate-face results, gap intervals,
last-wins tp-plist, non-destructive string forms, per-pattern match
ordering, case-fold regexp outputs, rewired end-to-end theme example);
documents the symmetric tp-backward contract, the length-changing
replacement rules, all four tp-put-layer layer specs, and the
previously-missing tp-member, buffer/display macros, and palette
system; state resets now use tp-layer-reset; license corrected to
GPLv3+. CN mirrors EN exactly (119 headings / 258 fences each; code
blocks identical, comments translated).

docs/ARCHITECTURE.md rewritten around the real nine-module layering
and hook-variable inversions; nonexistent helper names removed.
docs/CODE-ANALYSIS.md marked as pre-split historical analysis with
locations/counts corrected. Reactive docs aligned with the fixed
engine semantics (replace-not-accumulate, buffer-local isolation,
nil computed values, batching union, first-render transform).

287 fenced blocks from both READMEs executed: 0 failures; 56-example
assertion suite passes; combined ERT suite 439/439 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 21:01:01 +08:00
Kinneyzhang
9aca18979b Reject length-changing string replacements instead of corrupting
tp--replace-match-text's string branch silently truncated longer
replacements and left residue on shorter ones ("<foo>" into a 3-char
match yielded "<fo"). Strings cannot change length in place, so the
honest contract is: same-length replacements mutate in place as before;
a different-length replacement signals a clear error directing the
caller to a buffer OBJECT. Buffer paths (delete+insert) are unchanged.
Updates the five tests that codified truncation/residue and adds a
same-length regression test; suite 439/439 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 20:12:37 +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
08b5d9aa1c Add tp-member: plist-member-style property lookup
Like tp-at but distinguishes a property present with value nil from an
absent property, returning (PROPERTY VALUE) or nil.  Covered by four
new tests in tp-ops-tests.el; full suite 338/338 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 19:33:34 +08:00
Kinneyzhang
49cb8d8062 Fix confirmed bugs in core ops and builtins/palette modules
ops/core (B1-B8): tp-remove no longer drops 3rd+ properties; string
removal is per-interval via tp--map-intervals instead of smearing
position-0 props; tp-clear defaults bounds from OBJECT; (tp-get STR N N)
works like the buffer region form; no bogus (:key nil) from trailing
bare keywords; region form signals immediately on flat PROP/VAL args;
face-family prepend semantics extended to font-lock-face/mouse-face.

builtins/palette (B45-B51): Emacs 28.1 compat for plistp/subr-x;
display-buffer macros use a minor-mode keymap instead of mutating the
major-mode map; tp-link resolves palette colors lazily (theme-correct);
tp-palette-alist is the single source of truth (stale defvars dropped);
tp-headline handles integer heights; tp-space matches its documented
pixel spec; tp-parse-color accepts one-sided cons colors.

Test infra: fixture gains unwind-protect teardown via tp-layer-reset
(incl. transforms); file header/provide renamed to tp-tests; suite is
order-independent (verified with shuffled runs). Adds Makefile with
test/compile/clean targets.

334 tests green (280 legacy + 54 new regression tests).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 18:31:59 +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
Kinneyzhang
af0980efef update 2026-07-26 16:31:36 +08:00
Kinneyzhang
29b2ee54d3 update 2026-01-13 18:11:40 +08:00
copilot-swe-agent[bot]
9aace2f6fe Update docs/CODE-ANALYSIS.md to include self-reference in file structure
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-10 09:31:01 +00:00
copilot-swe-agent[bot]
715ceaac1e Add comprehensive code analysis report for developers
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-10 09:29:32 +00:00
copilot-swe-agent[bot]
ce06c76089 Initial plan 2026-01-10 09:22:55 +00:00
Kinneyzhang
a1ce94c0dd add heatmap tp-palette 2026-01-08 15:48:34 +08:00
Kinneyzhang
5d75ff434c update tests 2026-01-08 11:52:16 +08:00
copilot-swe-agent[bot]
6b96d8575f Simplify reactive text replacement to directly reset properties with new values
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-08 03:43:55 +00:00
copilot-swe-agent[bot]
7d7979c54c Revert changes to tp--replace-reactive-text-in-buffer to fix checkbox strikethrough toggle
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-08 03:17:05 +00:00
copilot-swe-agent[bot]
89d76fa0cc Address code review feedback: improve docstring and null handling
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-08 03:00:59 +00:00
copilot-swe-agent[bot]
3a0f774c70 Optimize tp--replace-reactive-text-in-buffer to preserve all original text properties
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-08 02:58:45 +00:00
copilot-swe-agent[bot]
e383882a74 Initial plan 2026-01-08 02:53:22 +00:00
Kinneyzhang
041f53025e fix tp 'pointer 'hander 2026-01-08 10:43:21 +08:00
copilot-swe-agent[bot]
9d97430d62 Improve documentation for merge-mode parameter in tp--handle-tp-text-property
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-07 09:24:35 +00:00
copilot-swe-agent[bot]
148b255456 Fix tp-reset and tp-set to preserve embedded text properties from tp-text
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-07 09:22:32 +00:00
copilot-swe-agent[bot]
39f38018a4 Initial plan 2026-01-07 09:15:18 +00:00
Kinneyzhang
9bcf14b2b3 delete tests 2026-01-07 11:53:05 +08:00
copilot-swe-agent[bot]
710e52c67f Fix tp-parse-color to handle unknown background-mode
When (frame-parameter nil 'background-mode) returns nil (e.g., in
batch mode or certain configurations), both tp-theme-light-p and
tp-theme-dark-p return nil, causing color parsing to fail for
cons cell ("light" . "dark") and plist (:light "l" :dark "d") formats.

Added default fallback to light color when background-mode is unknown.
This is the root cause of tp-palette settings not taking effect.

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-07 03:51:28 +00:00
copilot-swe-agent[bot]
6c111dfd2b Fix pcase syntax error in tp-palette-pure function
Fixed the pcase branches for tp-palette-bg-p and tp-palette-fbg-p
predicates which had an extra `symbol` keyword incorrectly placed
between the pattern and the return expression. This caused these
branches to return the original symbol instead of the processed
intern result, leading to tp-palette settings not taking effect
when using palettes with -bg or -fbg suffixes.

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-07 03:43:33 +00:00
copilot-swe-agent[bot]
150d4e149c Initial plan 2026-01-07 03:40:16 +00:00
copilot-swe-agent[bot]
347abb601e Improve tp--apply-props-to-string to handle partial range correctly
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-07 03:26:47 +00:00
copilot-swe-agent[bot]
6392be848e Fix: Use propertize directly to preserve text property intervals
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-07 03:23:08 +00:00
copilot-swe-agent[bot]
fe0594c575 Fix: tp-match-set and tp-regexp-set now create a copy instead of modifying original string
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-07 03:00:25 +00:00
copilot-swe-agent[bot]
3621fbb92c Initial plan 2026-01-07 02:50:10 +00:00
Kinneyzhang
4dff70cd59 improve code 2026-01-07 02:20:38 +08:00
Kinneyzhang
676d41aba6 Merge remote-tracking branch 'origin/copilot/fix-tp-remove-custom-attributes' 2026-01-07 02:11:09 +08:00
Kinneyzhang
02ffc7f70f fix bug 2026-01-07 02:11:06 +08:00
copilot-swe-agent[bot]
aa53dc1b99 Improve variable naming: rename face-to-subtract to remaining-face for clarity
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-06 18:04:21 +00:00
copilot-swe-agent[bot]
18b85e446a Fix duplicate function name and test corrections
- Rename second tp--remove-nested-keys to tp--remove-nested-sub-keys
- Fix logic in tp--remove-props-from-string to properly handle nil face subtraction result
- Fix tests to properly use return values from tp-set and tp-remove
- Add face-was-modified tracking variable

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-06 18:02:35 +00:00
copilot-swe-agent[bot]
b062eb30fd Fix tp-remove for custom layers and complex face sub-properties
- Add tp--remove-sub-from-face-value to handle complex face structures
- Add tp--subtract-face-from-face-value to remove layer face contributions
- Add tp--get-layer-face-contribution helper function
- Update tp--remove-props-from-string to handle layer face subtraction
- Update tp--remove-sub-from-string to use new helper
- Update tp--expand-layer-to-props-list to detect layer properties
- Fix missing closing paren in tp--remove-property function
- Update tests to match expected behavior

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2026-01-06 17:52:57 +00:00
copilot-swe-agent[bot]
c223723d9a Initial plan 2026-01-06 17:21:38 +00:00