Function: eca-chat--expandable-content-toggle

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

Signature

(eca-chat--expandable-content-toggle ID &optional FORCE? CLOSE?)

Documentation

Toggle the expandable-content of ID.

If FORCE? decide to CLOSE? or not.

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--expandable-content-toggle (id &optional force? close?)
  "Toggle the expandable-content of ID.
If FORCE? decide to CLOSE? or not."
  (when-let* ((ov-label (eca-chat--get-expandable-content id)))
    (let* ((inhibit-read-only t)
           (ov-content (overlay-get ov-label 'eca-chat--expandable-content-ov-content))
           (content (overlay-get ov-content 'eca-chat--expandable-content-content))
           (segments (overlay-get ov-label 'eca-chat--expandable-content-segments))
           (children (eca-chat--segments-children segments))
           (has-content? (or (not (string-empty-p content)) children))
           (currently-open? (overlay-get ov-label 'eca-chat--expandable-content-toggle))
           (close? (if force?
                       close?
                     currently-open?))
           ;; Skip when force-toggling to a state we're already in
           (already-in-state? (and force?
                                   (if close? (not currently-open?) currently-open?))))
      (unless already-in-state?
        (eca-chat--with-preserved-scroll
          (save-excursion
            (goto-char (overlay-start ov-label))
            (if (or close? (not has-content?))
                (progn
                  (put-text-property (point) (line-end-position)
                                     'line-prefix (when has-content?
                                                    (overlay-get ov-label 'eca-chat--expandable-content-open-icon)))
                  (goto-char (1+ (line-end-position)))
                  ;; Destroy nested blocks first (they are within content region)
                  (eca-chat--destroy-nested-blocks id)
                  (delete-region (overlay-start ov-content) (overlay-end ov-content))
                  (overlay-put ov-content 'face nil)
                  (overlay-put ov-label 'eca-chat--expandable-content-toggle nil))
              (progn
                (put-text-property (point) (line-end-position)
                                   'line-prefix (overlay-get ov-label 'eca-chat--expandable-content-close-icon))
                (goto-char (overlay-start ov-content))
                (if segments
                    ;; Segments-aware rendering: interleave text and children in order
                    (let* ((full-content content)
                           (segmented-text (eca-chat--segments-total-text segments))
                           (trailing-text (when (> (length full-content) (length segmented-text))
                                            (substring full-content (length segmented-text)))))
                      (dolist (seg segments)
                        (pcase (plist-get seg :type)
                          ('text (eca-chat--insert (plist-get seg :content)))
                          ('child
                           (eca-chat--render-nested-block ov-label seg)
                           ;; render-nested-block uses save-excursion so point stays
                           ;; before the child; advance past it to maintain order
                           (goto-char (overlay-end ov-content)))))
                      ;; Insert any trailing text not yet captured in segments
                      (when (and trailing-text (not (string-empty-p trailing-text)))
                        (eca-chat--insert trailing-text))
                      (eca-chat--insert "\n"))
                  ;; Legacy path: no segments, insert content then children
                  (eca-chat--insert content "\n")
                  (dolist (child-spec children)
                    (eca-chat--render-nested-block ov-label child-spec)))
                (let ((block-face (eca-chat--expandable-block-face
                                  (overlay-get ov-content 'eca-chat--expandable-block-nested))))
                  (overlay-put ov-content 'face block-face)
                  (eca-chat--apply-face-to-line-prefixes
                   (overlay-start ov-content) (overlay-end ov-content) block-face))
                (overlay-put ov-label 'eca-chat--expandable-content-toggle t)))
            ;; Repaint nested label's line-prefix after icon swap
            (eca-chat--paint-nested-label ov-label)))
        ;; Toggling open inserts block content into the read-only history
        ;; region, so re-protect it (from point-min, since the block may
        ;; belong to an earlier turn outside the streamed scope).
        (eca-chat--protect-non-prompt))
      close?)))