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))))))