copilot.el icon indicating copy to clipboard operation
copilot.el copied to clipboard

Dismissing a suggestion at the end of buffer leaves extra empty lines

Open knu opened this issue 2 years ago • 1 comments

First of all, thank you for this amazing package!

Steps to reproduce:

  1. Open an empty file test.el with global-copilot-mode enabled
  2. Type something like (defun test () nil) and press Enter
  3. You'll see a suggestion like (defun test2 () nil).
  4. Dismiss it by hitting C-g or going back to the first line
  5. Save the buffer
  6. You can see the saved file has an empty line at the end.

I understand that you need to add empty lines at the step 3 for a suggestion to be shown, so I'm just wondering if it is possible to remove them when the suggestion is dismissed.

knu avatar Jul 15 '22 02:07 knu

Workaround: use https://github.com/lewang/ws-butler

I will try to fix it later.

zerolfx avatar Jul 15 '22 06:07 zerolfx

It seems that the problem comes from these lines:

    (if (= (line-end-position line) (1- (point-max)))
        ; special case if the last line is empty
        (progn
          (goto-char (point-max))
          (newline)
          (forward-char -1))
      (forward-line line)
      (forward-char col))

Do we actually need this special case? I tested removing it and everything worked fine for me:

@@ -389,14 +389,8 @@ USER-POS is the cursor position (for verification only)."
   (save-excursion
     (widen)
     (goto-char (point-min))
-    (if (= (line-end-position line) (1- (point-max)))
-        ; special case if the last line is empty
-        (progn
-          (goto-char (point-max))
-          (newline)
-          (forward-char -1))
-      (forward-line line)
-      (forward-char col))
+    (forward-line line)
+    (forward-char col)
 
     ; remove common prefix
     (let* ((cur-line (s-chop-suffix "\n" (or (thing-at-point 'line) "")))

(my Emacs version is 30.0.50)

Rogach avatar Mar 27 '23 09:03 Rogach

image

@Rogach In the screenshot, my cursor is on the second line while this file has only one line. With the special case, copilot.el can provide completions in this situation, otherwise, you will see an "End of buffer" message.

While creating new lines for users may seem strange, being able to show completions at the ends of files is useful. Any better workaround is welcome.

zerolfx avatar Mar 27 '23 09:03 zerolfx

My apologies, I somehow missed that case (despite the comment talking exactly about that).

Seems that error happens because (thing-at-point 'line) returns incorrect data at that last line (it returns previous line instead of what we expect). Here's the updated patch, now your example works as expected:

@@ -389,17 +389,11 @@ USER-POS is the cursor position (for verification only)."
   (save-excursion
     (widen)
     (goto-char (point-min))
-    (if (= (line-end-position line) (1- (point-max)))
-        ; special case if the last line is empty
-        (progn
-          (goto-char (point-max))
-          (newline)
-          (forward-char -1))
-      (forward-line line)
-      (forward-char col))
-
-    ; remove common prefix
-    (let* ((cur-line (s-chop-suffix "\n" (or (thing-at-point 'line) "")))
+    (forward-line line)
+    (forward-char col)
+
+    ;; remove common prefix
+    (let* ((cur-line (buffer-substring-no-properties (line-beginning-position) (line-end-position)))
            (common-prefix-len (length (s-shared-start completion cur-line))))
       (setq completion (substring completion common-prefix-len))
       (forward-char common-prefix-len))

Rogach avatar Mar 27 '23 10:03 Rogach

@Rogach Patch applied. Thanks for your elegant solution!

zerolfx avatar Mar 27 '23 17:03 zerolfx