Function: eca-chat--update-expandable-content

eca-chat--update-expandable-content is a natively compiled function defined in eca-chat-expandable.el.

Signature

(eca-chat--update-expandable-content ID LABEL CONTENT &optional APPEND-CONTENT? PARENT-ID)

Documentation

Update to LABEL and CONTENT the expandable content of id ID.

If LABEL is nil, the existing label is preserved. If APPEND-CONTENT? is non-nil, append CONTENT to existing content. If PARENT-ID is provided and block doesn't exist yet, updates the spec in parent.

Source Code

;; Defined in /nix/store/jklqzw6pzz6j4jrbv8wy0iwgi7jlrbld-emacs-packages-deps/share/emacs/site-lisp/elpa/eca-20260928.1827/eca-chat-expandable.el
(defun eca-chat--update-expandable-content (id label content &optional append-content? parent-id)
  "Update to LABEL and CONTENT the expandable content of id ID.
If LABEL is nil, the existing label is preserved.
If APPEND-CONTENT? is non-nil, append CONTENT to existing content.
If PARENT-ID is provided and block doesn't exist yet, updates the spec
in parent."
  (if-let* ((ov-label (eca-chat--get-expandable-content id)))
      ;; Block exists (rendered), update it directly
      (let* ((ov-content (overlay-get ov-label 'eca-chat--expandable-content-ov-content))
             (nested? (overlay-get ov-label 'eca-chat--expandable-content-nested))
             (indent (if nested?
                         eca-chat--expandable-content-nested-indent
                       eca-chat--expandable-content-base-indent))
             (existing (overlay-get ov-content 'eca-chat--expandable-content-content))
             (delta (propertize content 'line-prefix indent))
             (new-content (if append-content?
                              (concat existing delta)
                            delta))
             (open? (overlay-get ov-label 'eca-chat--expandable-content-toggle)))
        (overlay-put ov-content 'eca-chat--expandable-content-content new-content)
        (save-excursion
          (when label
            ;; Update stored icons when the label face changes
            (let* ((new-icon-face (get-text-property 0 'font-lock-face label))
                   (label-indent (when nested? eca-chat--expandable-content-base-indent))
                   (new-icons (eca-chat--make-expandable-icons new-icon-face label-indent)))
              (overlay-put ov-label 'eca-chat--expandable-content-open-icon (car new-icons))
              (overlay-put ov-label 'eca-chat--expandable-content-close-icon (cdr new-icons)))
            (let* ((children (eca-chat--segments-children
                              (overlay-get ov-label 'eca-chat--expandable-content-segments)))
                   (has-content? (or (not (string-empty-p new-content)) children))
                   (label-prefix (cond
                                  (has-content?
                                   (if open?
                                       (overlay-get ov-label 'eca-chat--expandable-content-close-icon)
                                     (overlay-get ov-label 'eca-chat--expandable-content-open-icon)))
                                  (nested?
                                   (concat eca-chat--expandable-content-base-indent
                                           (make-string (length eca-chat-expandable-block-open-symbol) ?\s)))))
                   (label-start (overlay-start ov-label))
                   (label-end (1- (overlay-start ov-content)))
                   (cur-prefix (get-text-property label-start 'line-prefix)))
              ;; Skip the delete/re-insert when the rendered label is
              ;; already up to date; frequent while toolCallPrepare
              ;; streams argsText updates (#268).
              (unless (and (string= (substring-no-properties label)
                                    (buffer-substring-no-properties label-start label-end))
                           (equal (get-text-property 0 'font-lock-face label)
                                  (get-text-property label-start 'font-lock-face))
                           (equal (and (stringp label-prefix) (substring-no-properties label-prefix))
                                  (and (stringp cur-prefix) (substring-no-properties cur-prefix))))
                (goto-char label-start)
                (delete-region (point) label-end)
                (eca-chat--insert (propertize (eca-chat--propertize-only-first-word label
                                                                                    'line-prefix label-prefix)
                                              'help-echo "mouse-1 / RET / tab: expand/collapse"))
                ;; Repaint nested label's line-prefix after label replacement
                (eca-chat--paint-nested-label ov-label))))
          (when open?
            (let ((block-face (overlay-get ov-content 'face)))
              (if append-content?
                  (let ((insert-start (overlay-end ov-content)))
                    (goto-char insert-start)
                    (eca-chat--insert delta)
                    (when block-face
                      (eca-chat--apply-face-to-line-prefixes
                       insert-start (overlay-end ov-content) block-face)))
                (progn
                  (delete-region (overlay-start ov-content) (overlay-end ov-content))
                  (goto-char (overlay-start ov-content))
                  (eca-chat--insert new-content)
                  (when block-face
                    (eca-chat--apply-face-to-line-prefixes
                     (overlay-start ov-content) (overlay-end ov-content) block-face)))))))
        ;; When nested, sync updated label/content back to parent's child spec
        ;; so that toggling the parent closed and reopened preserves latest state
        (when nested?
          (when-let* ((parent-id (overlay-get ov-label 'eca-chat--expandable-content-parent-id))
                      (parent-ov (eca-chat--get-expandable-content parent-id))
                      (segments (overlay-get parent-ov 'eca-chat--expandable-content-segments))
                      (spec (-first (lambda (s) (and (eq 'child (plist-get s :type))
                                                     (string= id (plist-get s :id))))
                                    segments)))
            (when label (plist-put spec :label label))
            (plist-put spec :content new-content))))
    ;; Block not rendered yet
    (if parent-id
        ;; Nested: update spec in parent
        (when-let* ((parent-ov (eca-chat--get-expandable-content parent-id)))
          (let* ((segments (overlay-get parent-ov 'eca-chat--expandable-content-segments))
                 (existing-spec (-first (lambda (spec) (and (eq 'child (plist-get spec :type))
                                                            (string= id (plist-get spec :id))))
                                        segments)))
            (if existing-spec
                (let* ((old-content (plist-get existing-spec :content))
                       (new-content (if append-content?
                                        (concat old-content content)
                                      content)))
                  (when label
                    (plist-put existing-spec :label label)
                    (plist-put existing-spec :icon-face (get-text-property 0 'font-lock-face label)))
                  (plist-put existing-spec :content new-content))
              (let ((child-spec (list :type 'child :id id :label label :content content
                                     :icon-face (get-text-property 0 'font-lock-face label))))
                (overlay-put parent-ov 'eca-chat--expandable-content-segments
                             (append segments (list child-spec)))
                (when (overlay-get parent-ov 'eca-chat--expandable-content-toggle)
                  (eca-chat--render-nested-block parent-ov child-spec))))))
      ;; Top-level: create the block so toolCallRun et al. don't
      ;; silently lose content when no toolCallPrepare preceded them.
      (eca-chat--add-expandable-content id label (or content "")))))