Skip to content

Instantly share code, notes, and snippets.

@ayman
Last active March 30, 2023 20:51
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ayman/01ad46f71edb7a833bfe247268b65b49 to your computer and use it in GitHub Desktop.
Save ayman/01ad46f71edb7a833bfe247268b65b49 to your computer and use it in GitHub Desktop.
Load and config Github Copilot for Emacs.
;;; copilot-helper --- Just helping run copilot safely.
;;; Commentary:
;; Reworking of https://github.com/zerolfx/copilot.el and
;; https://robert.kra.hn/posts/2023-02-22-copilot-emacs-setup/
;;; Code:
(use-package copilot
:straight (:host github :repo "zerolfx/copilot.el" :files ("dist" "*.el"))
:ensure t
:bind (("M-C-<escape>" . rk/copilot-change-activation)
(:map copilot-mode-map
("<tab>" . my-copilot-tab)
("M-C-<" . copilot-previous-completion)
("M-C->" . copilot-next-completion)
("M-C-<tab>" . copilot-accept-completion-by-line))
(:map company-mode-map
("<tab>" . my-copilot-tab))
(:map company-active-map
("<tab>" . my-copilot-tab)))
:hook
prog-mode
(copilot-disable-predicates . rk/copilot-disable-predicate)
:config
(advice-add 'keyboard-quit :before #'rk/copilot-quit))
;; (define-key copilot-mode-map (kbd "M-C-S-<right>") #'copilot-accept-completion-by-word)
;; (define-key copilot-mode-map (kbd "M-C-S-<down>") #'copilot-accept-completion-by-line)
(defun my-copilot-tab ()
"Call copilot if you can, else company else yasnippet, else indent."
(interactive)
(or (copilot-accept-completion)
(company-indent-or-complete-common nil)
;; (company-yasnippet-or-completion)
(indent-for-tab-command nil)))
(defun rk/no-copilot-mode ()
"Helper for `rk/no-copilot-modes'."
(copilot-mode -1))
(defvar rk/no-copilot-modes '(shell-mode
inferior-python-mode
eshell-mode
term-mode
vterm-mode
comint-mode
compilation-mode
debugger-mode
dired-mode-hook
compilation-mode-hook
flutter-mode-hook
lisp-interaction-mode-hook
minibuffer-mode-hook)
"Modes in which copilot is inconvenient.")
(defun rk/copilot-disable-predicate ()
"When copilot should not automatically show completions."
(or rk/copilot-manual-mode
(member major-mode rk/no-copilot-modes)
(company--active-p)))
(defvar rk/copilot-manual-mode nil
"When 't' will only show completions when manually triggered, e.g. via M-C-<return>.")
(defun rk/copilot-change-activation ()
"Switch between three activation modes:
- automatic: copilot will automatically overlay completions
- manual: you need to press a key (M-C-<return>) to trigger completions
- off: copilot is completely disabled."
(interactive)
(if (and copilot-mode rk/copilot-manual-mode)
(progn
(message "deactivating copilot")
(global-copilot-mode -1)
(setq rk/copilot-manual-mode nil))
(if copilot-mode
(progn
(message "activating copilot manual mode")
(setq rk/copilot-manual-mode t))
(message "activating copilot mode")
(global-copilot-mode))))
(defun rk/copilot-quit ()
"Run 'copilot-clear-overlay' or 'keyboard-quit'.
If copilot is cleared, make sure the overlay doesn't come back
too soon."
(interactive)
(condition-case err
(when copilot--overlay
(lexical-let ((pre-copilot-disable-predicates copilot-disable-predicates))
(setq copilot-disable-predicates (list (lambda () t)))
(copilot-clear-overlay)
(run-with-idle-timer
1.0
nil
(lambda ()
(setq copilot-disable-predicates pre-copilot-disable-predicates)))))
(error handler)))
(provide 'copilot-helper)
;;; copilot-helper.el ends here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment