Move the batch flush and tp-with-batch-updates up into tp-render
tp--flush-batch-updates existed to re-render buffers, which is tp-render's whole job - but it lived down in tp-reactive and reached the renderer through the tp--reactive-flush-function inversion, complete with a guard that silently DROPPED queued re-renders when no hook was installed. A partial load could thus discard updates without a trace. Move tp--flush-batch-updates and the public tp-with-batch-updates macro (same name, same behavior - only the home file changes) into tp-render.el, next to tp--reactive-flush-entry, which the flush now calls directly. Delete the tp--reactive-flush-function defvar, its silent-drop guard, and the install line. The queue state (tp--batch-update-pending, tp--batch-update-active, tp--reactive-updating) and tp--queue-batch-update stay in tp-reactive; the relocated macro let-binds them downward, which is legal. Together with the tp-text handler move this takes the sanctioned upward hooks from four to two - only the genuine lower-layer event sources remain (tp--reactive-update-function in tp-reactive, tp--layer-refresh-function in tp-layer) - and a degraded partial load now fails honestly with a void-function error instead of silently discarding queued re-renders. The ARCH-4 unwind-protect around the flush tail in tp--reactive-apply-update is untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
2b000b5f0e
commit
6295d5ccbc
@ -13,9 +13,10 @@
|
||||
|
||||
;; Reactive core of tp: storage for variable dependencies, watchers,
|
||||
;; computed properties and data variables; registration/unregistration;
|
||||
;; the variable-watcher shell and the batching queue. The actual
|
||||
;; re-rendering of buffers lives in tp-render.el, which installs
|
||||
;; itself via `tp--reactive-update-function' / `tp--reactive-flush-function'.
|
||||
;; the variable-watcher shell and the batching queue state. The
|
||||
;; actual re-rendering of buffers - including the queue flush and the
|
||||
;; public `tp-with-batch-updates' macro - lives in tp-render.el, which
|
||||
;; installs itself via `tp--reactive-update-function'.
|
||||
|
||||
;;; Code:
|
||||
|
||||
@ -254,11 +255,6 @@ SYMBOL NEWVAL WHERE OVERRIDE-ALIST) after the user watch callbacks
|
||||
have run. When nil, variable changes only invoke watch callbacks and
|
||||
no re-rendering happens.")
|
||||
|
||||
(defvar tp--reactive-flush-function nil
|
||||
"Function flushing one pending batched update entry.
|
||||
Installed by tp-render.el. Called with (LAYER-NAME WHERE
|
||||
TP-TEXT-AFFECTED).")
|
||||
|
||||
(defun tp--reactive-variable-watcher (symbol newval operation where)
|
||||
"Watcher function called when a reactive variable changes.
|
||||
SYMBOL is the variable that changed.
|
||||
@ -321,48 +317,6 @@ NEWVAL is the new value, OLDVAL is the old value."
|
||||
(error (message "tp: watcher error for %s watching %s: %s"
|
||||
layer-name watch-sym err))))))))
|
||||
|
||||
(defun tp--flush-batch-updates ()
|
||||
"Flush all pending batch updates.
|
||||
This processes all updates collected during a `tp-with-batch-updates' form."
|
||||
(tp-debug-log "Flushing %d pending batch updates" (length tp--batch-update-pending))
|
||||
(let ((processed-layers nil))
|
||||
;; Process each pending update, avoiding duplicate layer updates
|
||||
(dolist (pending (nreverse tp--batch-update-pending))
|
||||
(let ((layer-name (car pending))
|
||||
(where (caddr pending))
|
||||
(tp-text-affected (cadddr pending)))
|
||||
(unless (memq layer-name processed-layers)
|
||||
(push layer-name processed-layers)
|
||||
(tp-debug-log " Batch updating layer %s (tp-text: %s)"
|
||||
layer-name (if tp-text-affected "yes" "no"))
|
||||
(when tp--reactive-flush-function
|
||||
(funcall tp--reactive-flush-function
|
||||
layer-name where tp-text-affected))))))
|
||||
(setq tp--batch-update-pending nil))
|
||||
|
||||
(defmacro tp-with-batch-updates (&rest body)
|
||||
"Execute BODY with reactive updates batched.
|
||||
Multiple variable changes within BODY are collected and applied
|
||||
together at the end, avoiding redundant buffer modifications.
|
||||
|
||||
This is useful when changing multiple reactive variables simultaneously:
|
||||
|
||||
(tp-with-batch-updates
|
||||
(setq my-color \"red\")
|
||||
(setq my-size 14)
|
||||
(setq my-text \"Hello\"))
|
||||
|
||||
Without batching, each `setq' would trigger a separate buffer update.
|
||||
With batching, all updates are consolidated and applied once at the end."
|
||||
(declare (indent 0) (debug t))
|
||||
`(let ((tp--batch-update-active t)
|
||||
(tp--batch-update-pending nil))
|
||||
(tp-debug-log "Starting batch updates")
|
||||
(unwind-protect
|
||||
(progn ,@body)
|
||||
(tp-debug-log "Ending batch updates")
|
||||
(tp--flush-batch-updates))))
|
||||
|
||||
(defun tp--register-layer-watchers (layer-name watchers)
|
||||
"Register WATCHERS for LAYER-NAME.
|
||||
WATCHERS is a list of (VAR-SYMBOL CALLBACK) pairs."
|
||||
|
||||
55
tp-render.el
55
tp-render.el
@ -13,10 +13,12 @@
|
||||
|
||||
;; The reactive update engine: when a reactive variable changes, this
|
||||
;; module recomputes layer definitions and re-renders every affected
|
||||
;; buffer region, including live `tp-text' text replacement. It
|
||||
;; installs itself into tp-reactive.el (update/flush hooks) and
|
||||
;; tp-layer.el (layer refresh hook), and calls down into tp-ops.el
|
||||
;; for the `tp-text' helper chain.
|
||||
;; buffer region, including live `tp-text' text replacement. It also
|
||||
;; owns the batching flush and the public `tp-with-batch-updates'
|
||||
;; macro (the queue state lives in tp-reactive.el). It installs
|
||||
;; itself into tp-reactive.el (update hook) and tp-layer.el (layer
|
||||
;; refresh hook), and calls down into tp-ops.el for the `tp-text'
|
||||
;; helper chain.
|
||||
|
||||
;;; Code:
|
||||
|
||||
@ -500,15 +502,54 @@ installed as `tp--reactive-update-function'."
|
||||
TP-TEXT-AFFECTED non-nil means the layer's `tp-text' changed and the
|
||||
text itself must be replaced. Runs after the changed variables have
|
||||
actually been set, so layer props re-resolve against current
|
||||
\(buffer-local aware) values. Installed as
|
||||
`tp--reactive-flush-function'."
|
||||
\(buffer-local aware) values. This is the per-entry worker of
|
||||
`tp--flush-batch-updates'."
|
||||
(if tp-text-affected
|
||||
(tp--update-reactive-text layer-name where)
|
||||
(tp--update-layer-regions layer-name where)))
|
||||
|
||||
(defun tp--flush-batch-updates ()
|
||||
"Flush all pending batch updates.
|
||||
This processes all updates collected during a `tp-with-batch-updates' form."
|
||||
(tp-debug-log "Flushing %d pending batch updates" (length tp--batch-update-pending))
|
||||
(let ((processed-layers nil))
|
||||
;; Process each pending update, avoiding duplicate layer updates
|
||||
(dolist (pending (nreverse tp--batch-update-pending))
|
||||
(let ((layer-name (car pending))
|
||||
(where (caddr pending))
|
||||
(tp-text-affected (cadddr pending)))
|
||||
(unless (memq layer-name processed-layers)
|
||||
(push layer-name processed-layers)
|
||||
(tp-debug-log " Batch updating layer %s (tp-text: %s)"
|
||||
layer-name (if tp-text-affected "yes" "no"))
|
||||
(tp--reactive-flush-entry layer-name where tp-text-affected)))))
|
||||
(setq tp--batch-update-pending nil))
|
||||
|
||||
(defmacro tp-with-batch-updates (&rest body)
|
||||
"Execute BODY with reactive updates batched.
|
||||
Multiple variable changes within BODY are collected and applied
|
||||
together at the end, avoiding redundant buffer modifications.
|
||||
|
||||
This is useful when changing multiple reactive variables simultaneously:
|
||||
|
||||
(tp-with-batch-updates
|
||||
(setq my-color \"red\")
|
||||
(setq my-size 14)
|
||||
(setq my-text \"Hello\"))
|
||||
|
||||
Without batching, each `setq' would trigger a separate buffer update.
|
||||
With batching, all updates are consolidated and applied once at the end."
|
||||
(declare (indent 0) (debug t))
|
||||
`(let ((tp--batch-update-active t)
|
||||
(tp--batch-update-pending nil))
|
||||
(tp-debug-log "Starting batch updates")
|
||||
(unwind-protect
|
||||
(progn ,@body)
|
||||
(tp-debug-log "Ending batch updates")
|
||||
(tp--flush-batch-updates))))
|
||||
|
||||
;; Install the engine into the lower modules.
|
||||
(setq tp--reactive-update-function #'tp--reactive-apply-update)
|
||||
(setq tp--reactive-flush-function #'tp--reactive-flush-entry)
|
||||
(setq tp--layer-refresh-function #'tp--update-layer-regions)
|
||||
|
||||
(provide 'tp-render)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user