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

Reply via email to