diff --git a/agent-shell-ui.el b/agent-shell-ui.el index cf09835f..0217ae33 100644 --- a/agent-shell-ui.el +++ b/agent-shell-ui.el @@ -41,6 +41,13 @@ "A hash table used to save sui content like body. This avoids duplicating body content in text properties which is more costly.") +(defvar agent-shell-ui-post-toggle-fragment-at-point-functions nil + "Hook called after toggling a fragment at point. +Each function is called with three arguments: + BLOCK - the block range alist with :start and :end + BODY - the body range alist with :start and :end + COLLAPSED - non-nil if the fragment is now collapsed") + (cl-defun agent-shell-ui-make-fragment-model (&key (namespace-id "global") (block-id "1") label-left label-right body) "Create a fragment model alist. NAMESPACE-ID, BLOCK-ID, LABEL-LEFT, LABEL-RIGHT, and BODY are the keys." @@ -529,7 +536,9 @@ When NO-UNDO is non-nil, disable undo recording." (point) indicator-properties) (map-put! state :collapsed new-collapsed-state) (put-text-property (map-elt block :start) - (map-elt block :end) 'agent-shell-ui-state state))))) + (map-elt block :end) 'agent-shell-ui-state state) + (run-hook-with-args 'agent-shell-ui-post-toggle-fragment-at-point-functions + block body new-collapsed-state))))) (defun agent-shell-ui-collapse-fragment-by-id (namespace-id block-id) "Collapse fragment with NAMESPACE-ID and BLOCK-ID." diff --git a/agent-shell-viewport.el b/agent-shell-viewport.el index 5e3b6636..2c38ee13 100644 --- a/agent-shell-viewport.el +++ b/agent-shell-viewport.el @@ -73,6 +73,7 @@ (declare-function agent-shell-ui-backward-block "agent-shell") (declare-function agent-shell-ui-forward-block "agent-shell") (declare-function agent-shell-ui-mode "agent-shell") +(declare-function agent-shell--apply-markdown-overlays-on-body-expand "agent-shell") (declare-function agent-shell-completion-mode "agent-shell-completion") (declare-function agent-shell-yank-dwim "agent-shell") @@ -1315,6 +1316,8 @@ For example, offer to kill associated shell session." \\{agent-shell-viewport-view-mode-map}" (cursor-intangible-mode +1) (agent-shell-ui-mode +1) + (add-hook 'agent-shell-ui-post-toggle-fragment-at-point-functions + #'agent-shell--apply-markdown-overlays-on-body-expand nil t) (agent-shell-viewport--update-header) (setq-local filter-buffer-substring-function #'agent-shell--filter-buffer-substring) (setq buffer-read-only t) diff --git a/agent-shell.el b/agent-shell.el index 88ee413f..5ecb9e50 100644 --- a/agent-shell.el +++ b/agent-shell.el @@ -244,6 +244,15 @@ See https://github.com/xenodium/agent-shell/issues/119" :type 'boolean :group 'agent-shell) +(defun agent-shell--apply-markdown-overlays-on-body-expand (_block body collapsed) + "Apply markdown overlays when BODY is expanded (COLLAPSED is nil). +Intended for use with `agent-shell-ui-post-toggle-fragment-at-point-functions'." + (unless collapsed + (save-restriction + (narrow-to-region (map-elt body :start) (map-elt body :end)) + (let ((markdown-overlays-highlight-blocks agent-shell-highlight-blocks)) + (markdown-overlays-put))))) + (defcustom agent-shell-confirm-interrupt t "Whether to prompt for confirmation before interrupting. @@ -2816,6 +2825,8 @@ variable (see makunbound)")) (add-hook 'kill-buffer-hook #'agent-shell--clean-up nil t) (add-hook 'change-major-mode-hook #'agent-shell--clean-up nil t) (agent-shell-ui-mode +1) + (add-hook 'agent-shell-ui-post-toggle-fragment-at-point-functions + #'agent-shell--apply-markdown-overlays-on-body-expand nil t) (when agent-shell-file-completion-enabled (agent-shell-completion-mode +1)) (agent-shell--setup-modeline) @@ -3003,9 +3014,11 @@ by default, RENDER-BODY-IMAGES to enable inline image rendering in body." (when-let ((body-start (map-nested-elt range '(:body :start))) (body-end (map-nested-elt range '(:body :end)))) (narrow-to-region body-start body-end) - (let ((markdown-overlays-highlight-blocks agent-shell-highlight-blocks) - (markdown-overlays-render-images render-body-images)) - (markdown-overlays-put)))) + ;; Skip overlays when body is collapsed. + (unless (text-property-any (point-min) (point-max) 'invisible t) + (let ((markdown-overlays-highlight-blocks agent-shell-highlight-blocks) + (markdown-overlays-render-images render-body-images)) + (markdown-overlays-put))))) ;; Note: For now, we're skipping applying markdown overlays ;; on left labels as they currently carry propertized text ;; for statuses (ie. boxed). @@ -3053,13 +3066,15 @@ by default, RENDER-BODY-IMAGES to enable inline image rendering in body." ;; `agent-shell-next-item' and `agent-shell-previous-item'. (add-text-properties (or padding-start block-start) (or padding-end block-end) '(field output))) - ;; Apply markdown overlay to body. - (when-let ((body-start (map-nested-elt range '(:body :start))) - (body-end (map-nested-elt range '(:body :end)))) - (narrow-to-region body-start body-end) - (let ((markdown-overlays-highlight-blocks agent-shell-highlight-blocks)) - (markdown-overlays-put)) - (widen)) + ;; Apply markdown overlay to body. + (when-let ((body-start (map-nested-elt range '(:body :start))) + (body-end (map-nested-elt range '(:body :end)))) + (narrow-to-region body-start body-end) + ;; Skip overlays when body is collapsed. + (unless (text-property-any (point-min) (point-max) 'invisible t) + (let ((markdown-overlays-highlight-blocks agent-shell-highlight-blocks)) + (markdown-overlays-put))) + (widen)) ;; ;; Note: For now, we're skipping applying markdown overlays ;; on left labels as they currently carry propertized text