branch: elpa/gptel commit b68f0b91a3798060678f78e56ed6fc45dc265907 Author: Abin Simon <m...@meain.io> Commit: karthink <karthikchikmaga...@gmail.com>
Use git to produce better merge conflicts for rewrite Previously, we were producing simple conflict markers by placing both the original and generated code into conflict markers. if git is available, pass the original and new version through git to produce a more fine grained set of conflicts. * gptel-rewrite.el (gptel--git-merge-conflicts, gptel--rewrite-merge, gptel--simple-merge-conflicts): Implement by using two new functions to handle simple and git-based merging. These functions accept the original and replacement strings as arguments. --- gptel-rewrite.el | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/gptel-rewrite.el b/gptel-rewrite.el index 59fd5fac00..7ccbb72f27 100644 --- a/gptel-rewrite.el +++ b/gptel-rewrite.el @@ -328,6 +328,33 @@ BUF is the buffer to modify, defaults to the overlay buffer." (ediff-split-window-function #'split-window-horizontally)) (ediff-buffers ov-buf newbuf))))) +(defun gptel--git-merge-conflicts (original-str new-str) + "Get merge conflicts between ORIGINAL-STR and NEW-STR using git merge-file." + (when (executable-find "git") + (let ((original-temp-file (make-temp-file "gptel-merge-")) + (empty-temp-file (make-temp-file "gptel-merge-")) ; use /dev/null? (windows?) + (new-temp-file (make-temp-file "gptel-merge-"))) + (unwind-protect + (progn + (with-temp-file original-temp-file (insert original-str)) + (with-temp-file empty-temp-file (insert "")) + (with-temp-file new-temp-file (insert new-str)) + (shell-command-to-string + (format "git merge-file --no-diff3 -L original -L Empty -L '%s' -p %s %s %s" + (gptel-backend-name gptel-backend) + original-temp-file empty-temp-file new-temp-file))) + (delete-file original-temp-file) + (delete-file empty-temp-file) + (delete-file new-temp-file))))) + +(defun gptel--simple-merge-conflicts (original-str new-str) + "Get merge conflict markers with ORIGINAL-STR and NEW-STR." + (concat + "<<<<<<< original\n" original-str + (unless (string-suffix-p "\n" original-str) "\n") + "=======\n" new-str + "\n>>>>>>> " (gptel-backend-name gptel-backend) "\n")) + (defun gptel--rewrite-merge (&optional ovs) "Insert pending LLM responses in OVS as merge conflicts." (interactive (list (gptel--rewrite-overlay-at))) @@ -337,17 +364,17 @@ BUF is the buffer to modify, defaults to the overlay buffer." (let ((changed)) (dolist (ov (ensure-list ovs)) (save-excursion - (when-let* ((new-str (overlay-get ov 'gptel-rewrite))) - ;; Insert merge - (goto-char (overlay-start ov)) - (unless (bolp) (insert "\n")) - (insert-before-markers "<<<<<<< original\n") - (goto-char (overlay-end ov)) - (unless (bolp) (insert "\n")) - (insert - "=======\n" new-str - "\n>>>>>>> " (gptel-backend-name gptel-backend) "\n") - (setq changed t)))) + (when-let* ((new-str (overlay-get ov 'gptel-rewrite)) + (original-str (buffer-substring (overlay-start ov) (overlay-end ov)))) + (let ((merge-result + (or (gptel--git-merge-conflicts original-str new-str) + (gptel--simple-merge-conflicts original-str new-str)))) + ;; Replace overlay content with merge result + (goto-char (overlay-start ov)) + (unless (bolp) (insert "\n")) + (delete-region (overlay-start ov) (overlay-end ov)) + (insert merge-result) + (setq changed t))))) (when changed (smerge-mode 1))) (gptel--rewrite-reject ovs))))