This is an example of how the existing gptel-rewrite.el
file can be used to perform completion on an entire function,
replacing what's already written so far in that function.
To use:
- Install gptel: https://github.com/karthink/gptel , configure it, and provide the appropriate API keys
- Download the
gptel-manual-complete.el
file in this gist (below) to a location like~/gptel-manual-complete/gptel-manual-complete.el
- Add the following to your Emacs configuration (typically
~/.emacs.d/init.el
or similar):(add-to-list 'load-path (expand-file-name "~/gptel-manual-completion")) (autoload #'gptel-manual-complete "gptel-manual-complete" t)
- Now choose which key you'd like to bind it to. I typically add something like this to my Emacs config:
(defvar my-xref-map (let ((map (make-sparse-keymap))) (define-key map (kbd "c") #'gptel-manual-complete) (define-key map (kbd ".") #'xref-find-definitions) (define-key map (kbd ",") #'xref-go-back) (define-key map (kbd "/") #'xref-find-references) map) "My key customizations for AI and xref.") (global-set-key (kbd "C-c .") my-xref-map)
- Restart Emacs
If you've used the above keybinds, they work like this (the only with AI is the first one):
- C-c . c to complete the code at point using Claude AI; if you have a comment near the end, that will better inform the completion
- C-c . . to visit the definition of the thing at point
- C-c . , to return to the original point after visiting something
- C-c . / to find references to the thing at point
When I write this code in a sample.el
file:
(defun my-code ()
"AI should not modify this."
(message "Sample 1"))
(defun my-hello
;; print a welcoming message in a window off to the right
)
(defun my-other-code ()
"AI should not modify this either."
(message "Sample 2"))
Move the cursor into the body of my-hello
and hit C-c . c then gptel will rewrite that
my-hello
function to something like this, without touching the other functions or deleting lines around it
(results may vary, I used Claude 3.5 Sonnet in this example):
(defun my-hello ()
"Print a welcoming message in a window off to the right."
(let ((buf (get-buffer-create "*Hello*")))
(with-current-buffer buf
(erase-buffer)
(insert "Welcome to Emacs!\n\nHave a productive session."))
(display-buffer buf
'((display-buffer-reuse-window
display-buffer-in-side-window)
(side . right)
(window-width . 40)))))
From here, you can use the standard gptel-rewrite
keys like C-c C-a
on that code to accept it and remove
the overlay on it.
Note that the function must have balanced parentheses, otherwise the code will throw an error. This is to make it easier to locate the beginning and end of the function to send to gptel's context.
After adding a function to gptel's context, I was using gptel-rewrite
and accidentally hit Enter twice.
This resulted in just the basic "Rewrite: " text being sent, and to my surprise that was very effective at
having Claude fix the problem I was going to ask about.
I decided to see if Claude could also do code completions this way, with a very terse kind of prompt on top
of the standard gptel-rewrite
prompt, and it turns out that it can!
- This is intended to be more of a tech demo than a final project; it piggybacks on top of gptel-rewrite instead of doing things a more idiomatic way. I'd love for this to be improved upon, ideally with a solution that's part of gptel itself.
- I've only tested this with Claude.
- For automatically identifying the entire current function to complete, you may have the best luck with either Emacs Lisp or files with major modes that have a tree-sitter grammar installed, as otherwise we have to guess. In general it should err on the side of sending too little rather than too much.
- My Emacs setup is available at https://github.com/mwolson/emacs-shared which has this and other features
- Note that the install doc might take a while to get through, and may have opinionated settings
- The additional AI features which have more bindings on C-c . than in the above example are described here
karthink
and other gptel contributors may use the code in this gist freely and reassign copyright to themselves as need be if they would like.