Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

- Bugfix: `eca-chat-add-context-to-user-prompt` and `eca-chat-add-filepath-to-user-prompt` no longer error with `window-live-p, nil` when the chat buffer is not visible; the chat window is now displayed first. With a prefix arg (`C-u`) they add the context without selecting the chat window, leaving point where it was. #266
- Add `eca-chat-hide-markdown-markup`, an opt-in display control for users seeing fenced code blocks jump in chat buffers. The default preserves the existing hidden-markup rendering; set it to `nil` to keep markdown fences/backticks visible, which avoids markdown-mode's fenced-code boundary invisibility during typing and streaming.
- Bugfix: don't move the cursor while the chat is streaming. `eca-chat-content-received` rendered without a `save-excursion`, so content streamed above the prompt (e.g. while "thinking") dragged point up to the middle of the buffer; point is now preserved.
- Bugfix: keep the `:usage` and `:trust` mode-line segments visible after adding the context-usage bar. The right-alignment reserved space from `(length right)`, which counts the bar's pixel-width `display` spaces (and wide glyphs) as ~1 char each, so the segments overflowed off the right edge. It now measures the real rendered width via `string-pixel-width` and aligns flush to the right edge in pixels (Emacs 29+ only; on Emacs 28 right segments follow left without alignment).
- Bugfix: closing a chat (`kill-buffer`, `C-c C-k`, or the tab close button) now switches the chat window to a sibling chat (the previous tab, or the only one left) instead of falling back to an unrelated buffer like the settings buffer, and drops the dead chat from the session registry. `C-c C-k` (`eca-chat-reset`) only starts a fresh chat when the closed chat was the last one.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ Chat
- `eca-chat-prompt-prefix`: Prompt prefix string shown before user input.
- `eca-chat-prompt-prefix-loading`: Prompt prefix string while a request is in progress.
- `eca-chat-read-only-history`: Whether the chat history/output, the `---` separator and the task area are read-only so only the progress, `@`-context and prompt input lines stay editable (default `t`). Set to `nil` to keep the whole buffer writable.
- `eca-chat-hide-markdown-markup`: Whether to hide markdown markup in chat buffers (default `t`). Set to `nil` to keep fences/backticks visible, which may avoid fenced code blocks jumping while typing or streaming.
- `eca-chat-history-page-size`: Number of newest messages to load when opening a persisted chat (default `50`). When non-nil, `eca-chat-resume` opens chats with a bounded window and shows a "Load older messages" control to page through earlier history on demand; set to `nil` to replay the entire history on open.
- `eca-chat-context-prefix`: Prefix used for context references in the chat buffer (default `@`).
- `eca-chat-filepath-prefix`: Prefix used for file path references in the chat buffer (default `#`).
Expand Down
19 changes: 17 additions & 2 deletions eca-chat.el
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,21 @@ updates during streaming)."
(number :tag "Seconds"))
:group 'eca)

(defcustom eca-chat-hide-markdown-markup t
"Whether ECA chat renders `markdown-markup' as invisible.
When non-nil, preserve the historical hidden-markup look. When
nil, keep markup visible while leaving `markdown-hide-markup'
enabled. This is recommended if fenced code blocks jump while
typing or streaming."
:type 'boolean
:group 'eca)

(defun eca-chat--apply-markdown-markup-visibility ()
"Apply `eca-chat-hide-markdown-markup' in current buffer."
(if eca-chat-hide-markdown-markup
(add-to-invisibility-spec 'markdown-markup)
(remove-from-invisibility-spec 'markdown-markup)))

(defvar-local eca-chat--tool-call-prepare-counters (make-hash-table :test 'equal)
"Hash table mapping toolCall ID to message count.")

Expand Down Expand Up @@ -3110,9 +3125,9 @@ CHILD, NAME, DOCSTRING and BODY are passed down."

;; Show diff blocks in markdown-mode with colors.
(setq-local markdown-fontify-code-blocks-natively t)
;; Enable gfm-view-mode-like rendering without read-only
;; Enable gfm-view-mode-like rendering without read-only.
(setq-local markdown-hide-markup t)
(add-to-invisibility-spec 'markdown-markup)
(eca-chat--apply-markdown-markup-visibility)

;; markdown-mode declares keymap, help-echo, and mouse-face as
;; font-lock-extra-managed-props, which causes font-lock-ensure to
Expand Down
17 changes: 12 additions & 5 deletions eca-table.el
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
(require 'seq)
(require 'eca-util)

;; Forward-declare defcustom defined in eca-chat.el.
;; Forward-declare defcustoms defined in eca-chat.el.
(defvar eca-chat-hide-markdown-markup t)
(defvar eca-chat-table-beautify)
(defvar eca-chat-parent-mode)

Expand Down Expand Up @@ -96,6 +97,12 @@ is on it while leaving `o' untouched everywhere else."
(defvar eca-table--fontlock-buffer nil
"Reusable buffer for font-lock based width measurement.")

(defun eca-table--apply-markdown-markup-visibility ()
"Apply ECA chat markdown markup visibility in current buffer."
(if eca-chat-hide-markdown-markup
(add-to-invisibility-spec 'markdown-markup)
(remove-from-invisibility-spec 'markdown-markup)))

(defun eca-table--get-fontlock-buffer ()
"Return a reusable buffer configured for width measurement.
Uses the chat parent mode and markdown-hide-markup to match
Expand All @@ -107,9 +114,9 @@ the actual display rendering."
(mode (or eca-chat-parent-mode 'gfm-mode)))
(with-current-buffer buf
(unless (derived-mode-p mode)
(funcall mode)
(setq-local markdown-hide-markup t)
(add-to-invisibility-spec 'markdown-markup)))
(funcall mode))
(setq-local markdown-hide-markup t)
(eca-table--apply-markdown-markup-visibility))
buf))

(defun eca-table--display-width (str)
Expand Down Expand Up @@ -255,7 +262,7 @@ the mouse click on the action bar."
(erase-buffer)
(gfm-mode)
(setq-local markdown-hide-markup t)
(add-to-invisibility-spec 'markdown-markup)
(eca-table--apply-markdown-markup-visibility)
(setq-local markdown-fontify-code-blocks-natively t)
(face-remap-add-relative 'markdown-table-face '(:inherit fixed-pitch))
(insert text)
Expand Down
16 changes: 16 additions & 0 deletions test/eca-chat-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,22 @@ does not treat the first line as metadata. Returns FN's value."
;; Tests
;; ---------------------------------------------------------------------------

(describe "eca-chat--apply-markdown-markup-visibility"
(it "keeps the historical hidden-markup default"
(with-temp-buffer
(let ((eca-chat-hide-markdown-markup t))
(eca-chat--apply-markdown-markup-visibility)
(expect (memq 'markdown-markup buffer-invisibility-spec)
:to-be-truthy))))

(it "allows markdown markup to stay visible"
(with-temp-buffer
(add-to-invisibility-spec 'markdown-markup)
(let ((eca-chat-hide-markdown-markup nil))
(eca-chat--apply-markdown-markup-visibility)
(expect (memq 'markdown-markup buffer-invisibility-spec)
:to-be nil)))))

(describe "eca-chat--key-pressed-deletion"

(describe "multi-line prompt"
Expand Down
24 changes: 24 additions & 0 deletions test/eca-table-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
(expect (eca-table--display-width "**bold**")
:to-equal 4))

(it "can keep markup visible in display width calculations"
(let ((eca-chat-hide-markdown-markup nil))
(expect (eca-table--display-width "**bold**")
:to-equal 8)))

(it "returns display width for italic with asterisks"
(expect (eca-table--display-width "*italic*")
:to-equal 6))
Expand Down Expand Up @@ -222,6 +227,25 @@
(expect (string-match-p "Setting" (buffer-string)) :to-be-truthy))
(kill-buffer buf)))

(it "can keep markdown markup visible in the table buffer"
(when (get-buffer "*eca-table*") (kill-buffer "*eca-table*"))
(let ((eca-chat-hide-markdown-markup nil))
(with-temp-buffer
(gfm-mode)
(setq-local markdown-hide-markup t)
(insert "| Setting | What it does |\n")
(insert "|---|---|\n")
(insert "| alpha | **bold** things |\n")
(goto-char (point-min))
(forward-line 2)
(eca-table-open)))
(let ((buf (get-buffer "*eca-table*")))
(expect buf :to-be-truthy)
(with-current-buffer buf
(expect (memq 'markdown-markup buffer-invisibility-spec)
:to-be nil))
(kill-buffer buf)))

(it "errors when point is not on a table"
(with-temp-buffer
(gfm-mode)
Expand Down
Loading