Function: claude-code-ide-mcp-handle-open-diff

claude-code-ide-mcp-handle-open-diff is a natively compiled function defined in claude-code-ide-mcp-handlers.el.

Signature

(claude-code-ide-mcp-handle-open-diff ARGUMENTS &optional SESSION)

Documentation

Open a diff view using ediff for SESSION.

SESSION is the instance whose websocket carried the request; the diff state and the deferred response belong to it. ARGUMENTS should contain:
- old_file_path: Original file path
- new_file_path: New file path (usually same as old)
- new_file_contents: New content to diff against
- tab_name: Name for the diff tab

Source Code

;; Defined in /nix/store/yjvbhwl7p6zrbw9xlnni7y4hra8sa3pl-emacs-packages-deps/share/emacs/site-lisp/claude-code-ide-mcp-handlers.el
(defun claude-code-ide-mcp-handle-open-diff (arguments &optional session)
  "Open a diff view using ediff for SESSION.
SESSION is the instance whose websocket carried the request; the diff
state and the deferred response belong to it.
ARGUMENTS should contain:
- `old_file_path': Original file path
- `new_file_path': New file path (usually same as old)
- `new_file_contents': New content to diff against
- `tab_name': Name for the diff tab"
  (let ((old-file-path (alist-get 'old_file_path arguments))
        (new-file-path (alist-get 'new_file_path arguments))
        (new-file-contents (alist-get 'new_file_contents arguments))
        (tab-name (alist-get 'tab_name arguments)))
    ;; Validate required parameters
    (unless (and old-file-path new-file-path new-file-contents tab-name)
      (signal 'mcp-error '("Missing required parameters for openDiff")))

    ;; Ensure we have a valid session
    (unless session
      (signal 'mcp-error '("No active MCP session found")))

    ;; Get the active diffs for this specific session
    (let ((active-diffs (claude-code-ide-mcp--get-active-diffs session)))
      ;; Check if there's already a diff with this tab_name
      (when-let* ((existing-diff (gethash tab-name active-diffs)))
        ;; Clean up existing diff
        (claude-code-ide-mcp--cleanup-diff tab-name session)))

    ;; Switch to original tab if we're on a different one (when configured)
    (when (and claude-code-ide-switch-tab-on-ediff
               (claude-code-ide-mcp-session-original-tab session))
      (let ((original-tab (claude-code-ide-mcp-session-original-tab session)))
        (when (and (fboundp 'tab-bar-mode)
                   tab-bar-mode
                   (fboundp 'tab-bar--current-tab)
                   (fboundp 'tab-bar-select-tab-by-name))
          (let ((current-tab (tab-bar--current-tab)))
            ;; Compare tab names or indices
            (when (and original-tab current-tab
                       (not (equal (alist-get 'name original-tab)
                                   (alist-get 'name current-tab))))
              ;; Switch to the original tab
              (tab-bar-select-tab-by-name (alist-get 'name original-tab)))))))

    ;; Save current window configuration
    (let* ((saved-winconf (current-window-configuration))
           (buffers (claude-code-ide-mcp--create-diff-buffers
                     old-file-path new-file-contents tab-name))
           (buffer-A (car buffers))
           (buffer-B (cdr buffers))
           (file-exists (file-exists-p old-file-path)))

      ;; Store diff session info with session reference
      (let ((active-diffs (claude-code-ide-mcp--get-active-diffs session)))
        (puthash tab-name
                 `((buffer-A . ,buffer-A)
                   (buffer-B . ,buffer-B)
                   (old-file-path . ,old-file-path)
                   (new-file-path . ,new-file-path)
                   (file-exists . ,file-exists)
                   (saved-winconf . ,saved-winconf)
                   (session . ,session)  ; Store the session reference
                   (created-at . ,(current-time)))
                 active-diffs))

      ;; Set up startup hook to configure ediff after it's fully initialized
      (let* ((hooks (claude-code-ide-mcp--setup-diff-hooks tab-name session saved-winconf))
             (before-setup-hook-fn (car hooks))
             (startup-hook-fn (cdr hooks)))

        ;; Add hooks
        (add-hook 'ediff-before-setup-hook before-setup-hook-fn)
        (add-hook 'ediff-startup-hook startup-hook-fn)

        ;; Start ediff
        (condition-case err
            (progn
              ;; Delete all side windows before starting ediff
              ;; This prevents "Cannot split side window" errors
              (dolist (window (window-list))
                (when (window-parameter window 'window-side)
                  (delete-window window)))

              ;; Start ediff with plain window setup (control panel at bottom).
              ;; Concurrent ediffs are distinguished by buffer identity in the
              ;; startup hook; ediff itself uniquifies control buffer names.
              (let ((old-setup-fn ediff-window-setup-function)
                    (old-split-fn ediff-split-window-function))
                (unwind-protect
                    (progn
                      (setq ediff-window-setup-function 'ediff-setup-windows-plain
                            ediff-split-window-function 'split-window-horizontally)
                      (ediff-buffers buffer-A buffer-B))
                  ;; Restore original values
                  (setq ediff-window-setup-function old-setup-fn
                        ediff-split-window-function old-split-fn))))
          (error
           ;; Handle ediff startup errors
           (when buffer-B
             (kill-buffer buffer-B))
           (let ((active-diffs (claude-code-ide-mcp--get-active-diffs session)))
             (remhash tab-name active-diffs))
           ;; Remove the hooks we added
           (remove-hook 'ediff-before-setup-hook before-setup-hook-fn)
           (remove-hook 'ediff-startup-hook startup-hook-fn)
           ;; Re-signal the error
           (signal (car err) (cdr err))))

        ;; Return deferred indicator; the dispatcher correlates the
        ;; response id with the requesting session itself
        `((deferred . t)
          (unique-key . ,tab-name))))))