copilot-emacs / copilot.el

An unofficial Copilot plugin for Emacs.
MIT License
1.74k stars 124 forks source link

[suggestion] new default keybindings #103

Open LemonBreezes opened 1 year ago

LemonBreezes commented 1 year ago

Hey, I have been experimenting with these keybindings for a month or two and they rock 🎸. They're like Fish completion keybindings. They allow for more fine-grained completion and they don't collide with Corfu nor Company TAB/C-n/C-p/RET usage.

(map! (:map copilot-completion-map
         "<right>" #'copilot-accept-completion
         "C-f" #'copilot-accept-completion
         "M-<right>" #'copilot-accept-completion-by-word
         "M-f" #'copilot-accept-completion-by-word
         "C-e" #'copilot-accept-completion-by-line
         "<end>" #'copilot-accept-completion-by-line
         "M-n" #'copilot-next-completion
         "M-p" #'copilot-previous-completion))
richsmith commented 1 year ago

I've been using something similar. I don't think I've got them quite perfected yet, but approaching something I'm happy with.

I think mapping C-g to 'copilot-clear-overlay is fairly essential.

(use-package copilot
  :straight (:host github :repo "zerolfx/copilot.el" :files ("dist" "*.el"))
  :ensure t
  :hook (prog-mode . copilot-mode)
  :bind (("C-c M-f" . copilot-complete)
         :map copilot-completion-map
         ("C-g" . 'copilot-clear-overlay)
         ("M-p" . 'copilot-previous-completion)
         ("M-n" . 'copilot-next-completion)
         ("<tab>" . 'copilot-accept-completion)
         ("M-f" . 'copilot-accept-completion-by-word)
         ("M-<return>" . 'copilot-accept-completion-by-line)))
LemonBreezes commented 1 year ago

I've been using something similar. I don't think I've got them quite perfected yet, but approaching something I'm happy with.

I think mapping C-g to 'copilot-clear-overlay is fairly essential.

(use-package copilot
  :straight (:host github :repo "zerolfx/copilot.el" :files ("dist" "*.el"))
  :ensure t
  :hook (prog-mode . copilot-mode)
  :bind (("C-c M-f" . copilot-complete)
         :map copilot-completion-map
         ("C-g" . 'copilot-clear-overlay)
         ("M-p" . 'copilot-previous-completion)
         ("M-n" . 'copilot-next-completion)
         ("<tab>" . 'copilot-accept-completion)
         ("M-f" . 'copilot-accept-completion-by-word)
         ("M-<return>" . 'copilot-accept-completion-by-line)))

Thanks. I've added that to my doom-escape-hook (since I'm using Doom Emacs).

(defun cae-copilot-clear-overlay-h ()
 "Like `copilot-clear-overlay', but returns `t' if the overlay was visible."
 (when (copilot--overlay-visible)
  (copilot-clear-overlay) t))
(add-hook 'doom-escape-hook #'cae-copilot-clear-overlay-h)
zerolfx commented 1 year ago

I have pinned this issue and would welcome any suggestions or recommendations on keybindings.

My intention is to make the default keybindings similar to those in VSCode, while also allowing for high customizability.

asmeurer commented 1 year ago

Since you asked for suggestions, these are the keybindings I'm using:

;; Based on function from https://robert.kra.hn/posts/2023-02-22-copilot-emacs-setup/
(defun copilot-complete-or-accept ()
  "Command that either triggers a completion or accepts one if one
is available."
  (interactive)
  (if (copilot--overlay-visible)
      (progn
        (copilot-accept-completion))
    (copilot-complete)))

(define-key copilot-completion-map (kbd "<tab>") 'copilot-accept-completion)
(define-key copilot-completion-map (kbd "TAB") 'copilot-accept-completion)
(define-key copilot-mode-map [C-down] #'copilot-next-completion)
(define-key copilot-mode-map [C-up] #'copilot-previous-completion)
(define-key copilot-mode-map [C-right] #'copilot-accept-completion-by-word)
(define-key copilot-mode-map [C-M-right] #'copilot-accept-completion-by-line)
(define-key global-map (kbd "C-<return>") #'copilot-complete-or-accept)

Where copilot-complete-or-accept based on rk/copilot-complete-or-accept from https://robert.kra.hn/posts/2023-02-22-copilot-emacs-setup/ sans the open-line bits (these bindings are similar to the ones suggested there). The C-Enter in particular is very nice and easy to type, and I find myself using it the most (I would suggest upstreaming copilot-complete-or-accept). I'm actually considering unbinding TAB so that it removes the ambiguity between completion and indentation (if I can train myself to stop typing it for completion).

C-up and C-down are probably not so great for defaults because they don't work in terminal emacs without some manual configuration to make the terminal emulator send the right ANSI sequence. I personally use M-p and M-n for something else, but they are probably better for defaults.

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

Jhonathan-Pedroso commented 1 year ago

Some keys working well for me in evil-mode:

;; Setup keys with copilot: (define-key copilot-completion-map (kbd ", a") 'copilot-accept-completion) (define-key copilot-completion-map (kbd ", n") 'copilot-next-completion) (define-key copilot-completion-map (kbd ", p") 'copilot-previous-completion) (define-key copilot-completion-map (kbd ", c") 'copilot-clear-overlay) (define-key copilot-completion-map (kbd ", w") 'copilot-accept-completion-by-word) (define-key copilot-completion-map (kbd ", l") 'copilot-accept-completion-by-line)

danlamanna commented 1 year ago

It seems like multiple people here are suggesting fixes that bind to a broader keymap than copilot-completion-map. Could this be because of a bug where the proper keymap isn't always overlaid correctly? This has been my experience, though I haven't been able to consistently reproduce it or track down what the error is yet.

richsmith commented 1 year ago

It seems like multiple people here are suggesting fixes that bind to a broader keymap than copilot-completion-map. Could this be because of a bug where the proper keymap isn't always overlaid correctly? This has been my experience, though I haven't been able to consistently reproduce it or track down what the error is yet.

I've also had this issue. I haven't got around to reporting to it because I was trying to get an idea about the problem first (e.g. whether it was something I'd misconfigured). The map isn't always active when the overlay is open, but I haven't been able to work out why not.

LemonBreezes commented 1 year ago

@richsmith @danlamanna

Have you updated copilot? An issue like that was fixed a while ago.

danlamanna commented 1 year ago

Have you updated copilot? An issue like that was fixed a while ago.

Yes, I'm running on the latest commit 9694981880b9fed7ced4ccff4e60fc072290c9a4.

kelvie commented 11 months ago

To pile it on here (this is more of a dicussion thread), for evil-mode I've been using:

;; accept completion from copilot and fallback to company
(use-package! copilot
  :hook (prog-mode . copilot-mode)
  :bind (:map copilot-completion-map
              ("<tab>" . 'copilot-accept-completion)
              ("TAB" . 'copilot-accept-completion)
              ("C-TAB" . 'copilot-accept-completion-by-word)
              ("C-<tab>" . 'copilot-accept-completion-by-word)
              ("M-n" . 'copilot-next-completion)
              ("M-p" . 'copilot-previous-completion)
              ))

This leaves C-n and C-p for company like before, and uses M-n and M-p to cycle through copilot suggestions

mattiuusitalo commented 7 months ago

I hope there aren't going to be automatically configured keybindings when this package loads, as that could conflict my configuration.

aguynamedben commented 3 weeks ago

I like when packages suggest keybindings that "just work". It makes packages more friendly to adopt. This package is especially tricky if you want to use tab complete for both company-mode (eglot) AND copilot. I wish there was a "blessed" example of how to tab complete both company-mode and copilot (i.e. mimic VS Code)—I tried for many hours but it's very finnicky to have the Tab key do multiple things, so I just decided to use M- for copilot-accept-completion and TAB for company-complete-selection.

I do think packages that have default keybindings should clearly document that fact and provide a simple example of how to get rid of them.

asmeurer commented 3 weeks ago

How would you make TAB do both? The only way I can see that working is if you intermingle the copilot completions with the company completions in the completion menu.