Variable: eca-chat-mode-abbrev-table

eca-chat-mode-abbrev-table is a variable defined in eca-chat.el.

Value

#<obarray n=1>

Documentation

Abbrev table for eca-chat-mode.

Source Code

;; Defined in /nix/store/jklqzw6pzz6j4jrbv8wy0iwgi7jlrbld-emacs-packages-deps/share/emacs/site-lisp/elpa/eca-20260928.1827/eca-chat.el
;; Public

(eca-chat-define-derived-mode eca-chat-mode "eca-chat"
  "Major mode for ECA chat sessions.
\\{eca-chat-mode-map}"
  :group 'eca
  ;; Use word-wrap instead of visual-line-mode to preserve table formatting.
  ;; visual-line-mode wraps all lines including tables, breaking their layout.
  (setq-local word-wrap t)
  (setq-local truncate-lines nil)
  ;; Scroll just enough to keep point visible instead of recentering,
  ;; otherwise the window jumps up and down while streamed chunks push
  ;; the prompt around (#268).  Users customizing `scroll-conservatively'
  ;; globally never see this, but the Emacs default (0) recenters.
  (setq-local scroll-conservatively 101)
  (setq-local scroll-margin 0)
  ;; The spinner is padded with trailing spaces to keep a fixed width.
  (setq-local show-trailing-whitespace nil)
  (hl-line-mode -1)
  (setq-local eca-chat--history '())
  (setq-local eca-chat--history-index -1)

  ;; Mutable defaults would otherwise be shared until locally assigned.
  (setq-local eca-chat-expandable--id->ov
              (make-hash-table :test 'equal))
  (setq-local eca-chat--tool-call-prepare-counters
              (make-hash-table :test 'equal))
  (setq-local eca-chat--tool-call-prepare-content-cache
              (make-hash-table :test 'equal))
  (setq-local eca-chat--tool-call-elapsed-times
              (make-hash-table :test 'equal))
  (setq-local eca-chat--subagent-chat-id->tool-call-id
              (make-hash-table :test 'equal))
  (setq-local eca-chat--subagent-usage
              (make-hash-table :test 'equal))

  ;; 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.
  (setq-local markdown-hide-markup t)
  (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
  ;; strip these properties from the entire buffer on every
  ;; refontification cycle.  ECA uses these properties on interactive
  ;; elements (approval buttons, expandable block labels, etc.) that
  ;; must survive font-lock.  Remove them so font-lock leaves our
  ;; interactive text properties intact.
  (setq-local font-lock-extra-managed-props
              (seq-difference font-lock-extra-managed-props
                              '(keymap help-echo mouse-face)))

  ;; Keep chat fontification overrides together.  Skip font-lock on
  ;; ranges tagged with `eca-no-fontify', which stops gfm/markdown
  ;; matchers from re-fontifying streaming tool-call argument bodies on
  ;; every chunk (see #234).  When configured, also skip prompt-area
  ;; Markdown block scans during typing.
  (eca-chat--install-fontification-overrides)

  (make-local-variable 'completion-at-point-functions)
  (setq-local completion-at-point-functions (list #'eca-chat-completion-at-point))

  ;; The server filters candidates by substring over full paths; make
  ;; sure client-side completion styles keep those candidates visible
  ;; regardless of the user's global completion configuration.
  (setq-local completion-category-defaults
              (cons '(eca-capf (styles basic substring))
                    completion-category-defaults))
  (setq-local completion-ignore-case t)

  ;; Turn raw @path/#path tokens into proper items after a space.
  (add-hook 'post-self-insert-hook #'eca-chat--post-self-insert nil t)

  (eca-chat--setup-item-stickiness)
  (add-hook 'after-change-functions
            #'eca-chat--auto-show-image-thumbnails-after-change nil t)

  (make-local-variable 'company-box-icons-functions)
  (when (featurep 'company-box)
    (add-to-list 'company-box-icons-functions #'eca-chat--completion-item-company-box-icon))

  (let ((session (or eca--chat-init-session (eca-session))))
    (when session
      (setq-local eca--session-id-cache (eca--session-id session)))
    (unless (listp header-line-format)
      (setq-local header-line-format (list header-line-format)))
    (add-to-list 'header-line-format `(t (:eval (eca-chat--header-line-string (eca-session)))))

    (when (eq 0 (length (string-trim (buffer-string))))
      (save-excursion
        (goto-char (point-min))
        (eca-chat--insert "\n")
        (unless eca--chat-init-skip-welcome
          (eca-chat--insert (propertize (eca--session-chat-welcome-message session)
                                        'font-lock-face 'eca-chat-welcome-face))
          (eca-chat--insert "\n")
          (eca-chat--insert (eca-buttonize
                             eca-chat-mode-map
                             (propertize "Resume a previous session"
                                         'font-lock-face 'eca-chat-resume-link-face)
                             #'eca-chat-resume))
          (setq-local eca-chat--welcome-shown t))
        (eca-chat--insert-prompt-string)))

    ;; TODO is there a better way to do that?
    (advice-add 'delete-char :around #'eca-chat--key-pressed-deletion)
    (advice-add 'delete-backward-char :around #'eca-chat--key-pressed-deletion)
    (advice-add 'backward-delete-char :around #'eca-chat--key-pressed-deletion)
    (advice-add 'backward-delete-char-untabify :around #'eca-chat--key-pressed-deletion)
    (advice-add 'backward-kill-word :around #'eca-chat--key-pressed-deletion)
    (dolist (cmd eca-chat--kill-guarded-commands)
      (advice-add cmd :around #'eca-chat--key-pressed-kill))
    (when (featurep 'evil)
      (advice-add 'evil-delete-backward-word :around #'eca-chat--key-pressed-deletion)
      (advice-add 'evil-delete-back-to-indentation :around #'eca-chat--key-pressed-deletion)
      (advice-add 'evil-delete-whole-line :around #'eca-chat--key-pressed-deletion)
      (advice-add 'evil-delete-char :around #'eca-chat--key-pressed-deletion)
      (advice-add 'evil-delete :around #'eca-chat--key-pressed-deletion)
      (advice-add 'evil-delete-backward-char :around #'eca-chat--key-pressed-deletion))

    (add-hook 'eldoc-documentation-functions #'eca-chat-eldoc-function nil t)
    (eldoc-mode 1)

    (add-hook 'kill-buffer-hook #'eca-chat--on-buffer-killed nil t)

    ;; Paste image from clipboard support
    (when (fboundp 'yank-media-handler)
      ;; reset current handlers inherit from markdown
      (setq-local yank-media--registered-handlers nil)
      (yank-media-handler "image/png" #'eca-chat--yank-image-handler)
      (yank-media-handler "image/jpeg" #'eca-chat--yank-image-handler)
      (yank-media-handler "image/jpg" #'eca-chat--yank-image-handler)
      (yank-media-handler "image/gif" #'eca-chat--yank-image-handler)
      (yank-media-handler "image/webp" #'eca-chat--yank-image-handler)
      (advice-add 'yank :around #'eca-chat--yank-considering-image)
      (when (featurep 'evil)
        (advice-add 'evil-paste-after :around #'eca-chat--yank-considering-image)
        (advice-add 'evil-paste-before :around #'eca-chat--yank-considering-image)))

    (let ((chat-buffer (current-buffer)))
      (run-with-timer
       0.05
       nil
       (lambda ()
         (eca-chat--with-current-buffer chat-buffer
           (display-line-numbers-mode -1)
           (when (fboundp 'vi-tilde-fringe-mode) (vi-tilde-fringe-mode -1))
           (when (fboundp 'company-mode)
             (setq-local company-backends '(company-capf)
                         company-minimum-prefix-length 0))
           (when (fboundp 'corfu-mode)
             (setq-local corfu-auto-prefix 0))
           (setq-local eca-chat--server-version
                       (eca-process--get-current-server-version))
           (when eca-chat-override-mode-line
             (setq-local mode-line-format
                         (if (functionp eca-chat-mode-line-format)
                             (funcall eca-chat-mode-line-format session)
                           `(t (:eval (eca-chat--mode-line-string ,session))))))

           ;; Tab-line: show a tab for each open chat
           (when eca-chat-tab-line
             (require 'tab-line)
             (setq-local tab-line-tabs-function #'eca-chat--tab-line-tabs)
             (setq-local tab-line-new-button-show t)
             (setq-local tab-line-close-button-show eca-chat-tab-line-close-button-show)
             (setq-local tab-line-new-tab-function #'eca-chat-new)
             (setq-local tab-line-separator "")
             (setq-local tab-line-tab-face-functions '(eca-chat--tab-line-face))
             (face-remap-add-relative 'tab-line :height 0.9)
             ;; Use text × instead of XPM image so it inherits the tab background
             (setq-local tab-line-close-button
                         (propertize " × "
                                     'keymap eca-chat--tab-close-map
                                     'mouse-face 'tab-line-close-highlight
                                     'help-echo "Click to close tab"))
             (tab-line-mode 1))

           ;; Keep session last-chat-buffer in sync with the displayed chat
           (add-hook 'post-command-hook #'eca-chat--sync-last-buffer nil t)

           (force-mode-line-update)
           (run-hooks 'eca-chat-mode-hook))))))

  (face-remap-add-relative 'markdown-line-break-face
                           '(:underline nil))

  ;; Ensure markdown links look clickable regardless of theme.
  (face-remap-add-relative 'markdown-link-face
                           '(:underline t))
  (face-remap-add-relative 'markdown-plain-url-face
                           '(:underline t))

  ;; Ensure tables use a monospace font for proper alignment.
  (face-remap-add-relative 'markdown-table-face
                           '(:inherit fixed-pitch))

  ;; Compute expandable-block background faces from current theme and
  ;; keep them in sync when the user switches themes (#301).
  (eca-chat--refresh-theme-faces)
  (eca-chat--register-theme-refresh)

  ;; Re-evaluate table action bars when window is resized.
  (add-hook 'window-size-change-functions
            #'eca-chat--on-window-size-change)

  (goto-char (point-max)))