mirror of
https://github.com/jimeh/.emacs.d.git
synced 2026-02-19 13:46:41 +00:00
feat(completion/copilot): add accept completion "mods" concept
Essentially, if accepted completion string matches a given regexp pattern, text can be inserted both before and after point. This is useful in certain situations where Copilot suggests the opening line to a if statement, for loop, etc., which leads to unbalanced curly brackets. This can help reduce the annoyance of unbalanced brackets.
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
|
||||
(use-package copilot
|
||||
:straight (:host github :repo "zerolfx/copilot.el"
|
||||
:files ("dist" "*.el"))
|
||||
@@ -13,15 +15,16 @@
|
||||
(prog-mode . copilot-mode)
|
||||
|
||||
:general
|
||||
("C-<tab>" 'siren-copilot-accept-completion-dwim)
|
||||
("<backtab>" 'siren-copilot-accept-completion-dwim)
|
||||
("M-F" 'siren-copilot-accept-completion-by-word-dwim)
|
||||
("M-E" 'siren-copilot-accept-completion-by-line-dwim)
|
||||
("C-<tab>" 'siren-copilot-dwim-with-mods)
|
||||
("<backtab>" 'siren-copilot-dwim-with-mods)
|
||||
("M-F" 'siren-copilot-dwim-by-word)
|
||||
("M-E" 'siren-copilot-dwim-by-line)
|
||||
(:keymaps 'copilot-completion-map
|
||||
"M-N" 'copilot-next-completion
|
||||
"M-P" 'copilot-previous-completion)
|
||||
|
||||
:custom
|
||||
(copilot-auto-balance t)
|
||||
(copilot-disable-predicates '(siren-copilot-disable-predicate))
|
||||
|
||||
:preface
|
||||
@@ -29,41 +32,84 @@
|
||||
(when buffer-file-name
|
||||
(let ((base (file-name-nondirectory buffer-file-name))
|
||||
(dir (file-name-directory buffer-file-name)))
|
||||
(or (string-prefix-p ".env" base)))))
|
||||
(or (string-prefix-p ".env" base)
|
||||
(string-match-p "\/\.ansible\/tmp\/ansible-local-.+$" dir)))))
|
||||
|
||||
(defun siren-copilot-accept-completion-dwim ()
|
||||
"Accept the current completion or trigger copilot-compilot."
|
||||
(defun siren-copilot-dwim ()
|
||||
"Trigger or accept completion."
|
||||
(interactive)
|
||||
(siren-copilot-complete-or-call
|
||||
'siren-copilot-accept-completion-with-balanced-brackets))
|
||||
(siren-copilot--complete-or-call
|
||||
'copilot-accept-completion))
|
||||
|
||||
(defun siren-copilot-accept-completion-by-word-dwim ()
|
||||
"Accept the current completion by word, or trigger copilot-compilot."
|
||||
(defun siren-copilot-dwim-by-word (n-word)
|
||||
"Trigger or accept N-WORD words from current completion."
|
||||
(interactive "p")
|
||||
(siren-copilot--complete-or-call
|
||||
'copilot-accept-completion-by-word n-word))
|
||||
|
||||
(defun siren-copilot-dwim-by-line (n-line)
|
||||
"Trigger or accept N-LINE lines from current completion."
|
||||
(interactive "p")
|
||||
(siren-copilot--complete-or-call
|
||||
'copilot-accept-completion-by-line n-line))
|
||||
|
||||
(defun siren-copilot-dwim-with-mods ()
|
||||
"Trigger or accept completion."
|
||||
(interactive)
|
||||
(siren-copilot-complete-or-call 'copilot-accept-completion-by-word 1))
|
||||
(if (copilot--overlay-visible)
|
||||
(siren-copilot-accept-with-mods)
|
||||
(copilot-complete)))
|
||||
|
||||
(defun siren-copilot-accept-completion-by-line-dwim ()
|
||||
"Accept the current completion by word, or trigger copilot-compilot."
|
||||
(interactive)
|
||||
(siren-copilot-complete-or-call 'copilot-accept-completion-by-line 1))
|
||||
|
||||
(defun siren-copilot-complete-or-call (f &rest args)
|
||||
(defun siren-copilot--complete-or-call (f &rest args)
|
||||
"Trigger copilot-complete or call F."
|
||||
(if (copilot-current-completion)
|
||||
(if (copilot--overlay-visible)
|
||||
(apply f args)
|
||||
(copilot-complete)))
|
||||
|
||||
(defun siren-copilot-accept-completion-with-balanced-brackets ()
|
||||
"Accept completion, add '}' after point if completion ends with '{'."
|
||||
(defgroup siren-copilot nil
|
||||
"Siren: copilot customization."
|
||||
:group 'copilot)
|
||||
|
||||
(defcustom siren-copilot-accept-mods
|
||||
'((ruby-mode . ((" do\\( |.+|\\)?" . ("\n" "\nend"))))
|
||||
(t . (("\{$" . ("\n" "\n}"))
|
||||
("\\[$" . ("\n" "\n]"))
|
||||
("\($" . ("\n" "\n)")))))
|
||||
"List of mods of characters to balance."
|
||||
:type '(alist :key-type symbol
|
||||
:value-type (alist :key-type string
|
||||
:value-type (list string string)))
|
||||
:group 'siren-copilot)
|
||||
|
||||
(defun siren-copilot-accept-with-mods ()
|
||||
"Accept completion, and add balance text after point if needed."
|
||||
(interactive)
|
||||
(let ((bracket-open nil))
|
||||
(let ((mod nil))
|
||||
(copilot-accept-completion (lambda (completion)
|
||||
(setq bracket-open
|
||||
(string-suffix-p "{" completion))
|
||||
(setq mod (siren-copilot--get-mod completion))
|
||||
completion))
|
||||
(when bracket-open
|
||||
(insert "}")
|
||||
(backward-char))))
|
||||
(siren-copilot--insert-mod mod)))
|
||||
|
||||
(defun siren-copilot--get-mod (text)
|
||||
(let ((mods (append (cdr (assoc major-mode siren-copilot-accept-mods))
|
||||
(cdr (assoc t siren-copilot-accept-mods)))))
|
||||
(when (length> mods 0)
|
||||
(cl-loop for (open . mod) in mods
|
||||
when (string-match-p open text)
|
||||
return mod))))
|
||||
|
||||
(defun siren-copilot--insert-mod (mod)
|
||||
(when mod
|
||||
(let ((before (if (length> mod 1) (car mod)))
|
||||
(after (if (length> mod 1) (cadr mod) (car mod))))
|
||||
(let ((start (point))
|
||||
(end (point)))
|
||||
(if before (insert before))
|
||||
(save-excursion
|
||||
(insert after)
|
||||
(setq end (point)))
|
||||
(indent-region start end)
|
||||
(indent-according-to-mode)))))
|
||||
|
||||
:config
|
||||
(with-eval-after-load 'company
|
||||
|
||||
Reference in New Issue
Block a user