With that prelude out of the way, let's begin. Inside of emacs you can call up a list of potential completions by using the keyboard shortcut M-. (that’s "hit the meta key along with period", where "meta" is the Alt key for me). This applies in a wide variety of scenarios, like when completing class names or variables. If we want to ask emacs to hand us a list of potential references, then the system we want to hook into is this completions system. (This is the only time I'll assume we know where to go without crawling through documentation. You could discover it yourself looking for " completion " or similar string in emacs docs). To start our hero’s journey, we figure out what the hell M-. actually does. We can ask emacs this by calling the function describe-key , which is bound to C-h k . Hitting Ctrl-h , then k , then M-. drops us into a help buffer that looks like this: M-. runs the command completion-at-point (found in evil-insert-state-map), which is an interactive native-compiled Lisp function in ‘minibuffer.el’. It is bound to M-.. (completion-at-point) Perform completion on the text around point. The completion method is determined by ‘completion-at-point-functions’. Probably introduced at or before Emacs version 23.2. We have the next breadcrumb to follow, which is the variable completion-at-point-functions . Running completion-at-point by hitting M-. consults that variable to hand us completion candidates, so we describe-variable it with C-h v and then choose completion-at-point-functions from the list of variables: completion-at-point-functions is a variable defined in ‘minibuffer.el’. Its value is (cape-dict cape-file tags-completion-at-point-function) Special hook to find the completion table for the entity at point. Each function on this hook is called in turn without any argument and should return either nil, meaning it is not applicable at point, or a function of no arguments to perform completion (discouraged), or a list of the form (START END COLLECTION . PROPS) …and it goes on from there. You can see some existing completion functions in there: I use a package called cape to offer helpful suggestions like file paths if I start typing in something like ./filename . The description for this variable instructs us about how to add our own functions (scary!) You’ll note that emacs calls this a "hook", which is most often just a term used to describe a variable that is a list of functions that get called at a specific time (hooks show up everywhere). I elided the full description for completion-at-point-functions – which is lengthy! – but if you parse it all out, you learn the following: Your completion at point function should return either nil (the elisp "null") – which means your completion function doesn’t apply right now – or another function (which emacs discourages), or a list, which is what we’ll do because it sounds like the most-correct thing to do. (the elisp "null") – which means your completion function doesn’t apply right now – or another function (which emacs discourages), or a list, which is what we’ll do because it sounds like the most-correct thing to do. The list we return is ( START END COLLECTION . PROPS ) : START and END should be positions in the buffer between which emacs will replace the completed symbol with our candidate. That is, if your cursor is calling a method on a Python object like file.ope| (where the bar is your cursor), emacs will replace just ope when you select open from a list of completions and not the entire file.ope string. COLLECTION is the juicy bit. The documentation calls it a completion "table", and there’s probably hidden meaning there, but you can just return a list of candidates and move on with your day, which is what I'll do. : Okay, so we need to write something to find the bounds of a string to replace and a function that returns that list.