diff --git a/users/crumb/programs/emacs/init.el b/users/crumb/programs/emacs/init.el index 7645798..00ab391 100755 --- a/users/crumb/programs/emacs/init.el +++ b/users/crumb/programs/emacs/init.el @@ -51,6 +51,7 @@ (require 'syd-completion) (require 'syd-custom) (require 'syd-display-startup-time) +(require 'syd-ediff) (require 'syd-editing) (require 'syd-eshell) (require 'syd-evil) @@ -60,6 +61,6 @@ (require 'syd-projects) (require 'syd-scratch) (require 'syd-smartparens) -(require 'syd-tramp) (require 'syd-tooling) +(require 'syd-tramp) (require 'syd-ui) diff --git a/users/crumb/programs/emacs/lib/syd-file.el b/users/crumb/programs/emacs/lib/syd-file.el index 3ab7c0b..abb2bbd 100644 --- a/users/crumb/programs/emacs/lib/syd-file.el +++ b/users/crumb/programs/emacs/lib/syd-file.el @@ -94,4 +94,45 @@ If FORCE-P, delete without confirmation." :desc "Open current file as root. See `doom/sudo-this-file'." :interactive t) +(defun syd--make-syncthing-merge-finalise-hook (file-name conflict-file-name) + (lambda () + (let ((merge-result-file (read-file-name + (format "Write merge to (default: %s):" + file-name) + nil file-name)) + (delete-conflict-p (yes-or-no-p (format "Delete conflict file? (%s)" + conflict-file-name))))) + (when merge-result-file + (with-current-buffer ediff-buffer-C + (set-visited-file-name merge-result-file) + (save-buffer)) + (kill-buffer ediff-buffer-C)) + (when delete-conflict-p + (kill-buffer (find-buffer-visiting conflict-file-name)) + (delete-file conflict-file-name)))) + +(defun syd--read-syncthing-conflict-file (&optional directory) + (let ((conflict-files (directory-files-recursively + (or directory default-directory) + (rx ".sync-conflict-")))) + (completing-read "Conflict file: " conflict-files nil t))) + +(defun syd--syncthing-conflict-file-base-name (conflict-file) + (replace-regexp-in-string (rx ".sync-conflict-" (* (not ?.))) + "" + conflict-file)) + +(defun syd-resolve-syncthing-conflict (conflict-file) + (interactive (list (syd--read-syncthing-conflict-file))) + (require 'ediff) + (let* ((base-file (syd--syncthing-conflict-file-base-name conflict-file)) + (ediff-after-quit-hook-internal + ;; Override Ediff's "save and quit" hook with our own. + (cons (syd--make-syncthing-merge-finalise-hook base-file conflict-file) + (remq #'ediff-write-merge-buffer-and-maybe-kill + (ensure-list ediff-quit-merge-hook))))) + (ediff-merge-files + base-file + conflict-file))) + (provide 'syd-file) diff --git a/users/crumb/programs/emacs/modules/syd-ediff.el b/users/crumb/programs/emacs/modules/syd-ediff.el new file mode 100644 index 0000000..9aca8d8 --- /dev/null +++ b/users/crumb/programs/emacs/modules/syd-ediff.el @@ -0,0 +1,19 @@ +;;; syd-ediff.el -*- lexical-binding: t; -*- + +(require 'syd-prelude) + +(with-eval-after-load 'ediff + (setq ediff-diff-options "-w" ; Ignore whitespace + ediff-window-setup-function #'ediff-setup-windows-plain) + (defvar syd--ediff-saved-wconf nil) + + ;; Restore window config after quitting Ediff. + (syd-add-hook 'ediff-before-setup-hook + (defun syd--ediff-save-wconf-h () + (setq syd--ediff-saved-wconf (current-window-configuration)))) + (syd-add-hook '(ediff-quit-hook ediff-suspend-hook) + (defun syd--ediff-restore-wconf-h () + (when (window-configuration-p syd--ediff-saved-wconf) + (set-window-configuration syd--ediff-saved-wconf))))) + +(provide 'syd-ediff)