copilot-emacs / copilot.el

An unofficial Copilot plugin for Emacs.
MIT License
1.79k stars 126 forks source link

Fix handling of completions when they don't go to the end of line #132

Closed CeleritasCelery closed 1 year ago

CeleritasCelery commented 1 year ago

Currently copilot.el assumes that the completion text will go all the way to the end of the line, but this is not always the case. When this happens it will lead to incorrectly deleting the text that used to be there. This will lead to unbalanced parens or quotes.

This PR fixes this by using the API's :end property to determine where the end of the completed text should go.

Example: text given to copilot

print("hello |")

copilot will return the text world.

With the current implementation this will be the result if the user accepts the completion:

print("hello world

After this PR, the result would be as expected:

print("hello world")

This will resolve issues like #77 #62 #117

zerolfx commented 1 year ago

Thanks for your work. You have solved a long-standing problem.

I made some minor changes by refactoring the code and changing the meaning of the end property from length to absolute position. Additionally, I removed the calls to goto-line, as it is only intended for interactive use.

CeleritasCelery commented 1 year ago

Thanks. I initially tried to use end as an absolute position like you did, but it doesn't work when you have automatic pair insertion (via smartparens, electric-pair-mode, cleverparens, etc). The issue is that if I insert ( it will also insert ). The end position should move forward 2 places, but we only advance it one with cl-incf. I don't know of a reliable way to detect the auto-pair case, so that is why I defined end to be an offset from the end of the line.

zerolfx commented 1 year ago

Oh no, I haven't tested that case. I will revert my changes if there is a bug.

zerolfx commented 1 year ago

Fixed in https://github.com/zerolfx/copilot.el/commit/7986e38726879350c2d2a13e4751e99f1a89daed