Skip to content

Instantly share code, notes, and snippets.

@textarcana
Last active September 29, 2025 20:20
Show Gist options
  • Save textarcana/e57968c701288925528a4e5a45a61be2 to your computer and use it in GitHub Desktop.
Save textarcana/e57968c701288925528a4e5a45a61be2 to your computer and use it in GitHub Desktop.
Contextual tab completion for Emacs using hippie-expand-mode
(defadvice hippie-expand (around hippie-expand-case-fold)
"Try to do case-sensitive matching (not effective with all functions)."
(let ((case-fold-search nil))
ad-do-it))
(ad-activate 'hippie-expand)
(defun arcane/hippie-expand-completions (&optional hippie-expand-function)
"Use menus to show the possible hippie-expand completions
instead of making me guess. Because I got REALLY sick of
pounding on M-/
This code taken from EmacsWiki: http://www.emacswiki.org/emacs/HippieExpand#toc2
Return the full list of possible completions generated by `hippie-expand'.
The optional argument can be generated with `make-hippie-expand-function'."
(let ((this-command 'arcane/hippie-expand-completions)
(last-command last-command)
(buffer-modified (buffer-modified-p))
(hippie-expand-function (or hippie-expand-function 'hippie-expand)))
(cl-flet ((ding))
(while (progn
(funcall hippie-expand-function nil)
(setq last-command 'arcane/hippie-expand-completions)
(not (equal he-num -1)))))
(set-buffer-modified-p buffer-modified)
(delete he-search-string (reverse he-tried-table))))
(defmacro arcane/ido-hippie-expand-with (hippie-expand-function)
"Generate an interactively-callable function that offers
ido-based completion using the specified hippie-expand
function."
`(call-interactively
(lambda (&optional selection)
(interactive
(let ((options (arcane/hippie-expand-completions ,hippie-expand-function)))
(if options
(list (ido-completing-read "Completions: " options)))))
(if selection
(he-substitute-string selection t)
(message "No expansion found")))))
(defun arcane/ido-hippie-expand-choose-from-menu ()
"Offer ido-based completion for the word at point.
Note that ispell-complete-word does NOT work in this
context."
(interactive)
(arcane/ido-hippie-expand-with (make-hippie-expand-function
'(try-expand-dabbrev-visible
try-expand-dabbrev-from-kill
try-expand-dabbrev
try-expand-dabbrev-all-buffers
try-expand-all-abbrevs
try-expand-dabbrev-visible
try-expand-dabbrev-from-kill
try-expand-dabbrev
try-expand-dabbrev-all-buffers
try-complete-file-name
try-complete-file-name-partially
try-expand-list
try-expand-line
try-complete-lisp-symbol
try-complete-lisp-symbol-partially))))
(defun arcane/hippie-expand-autocomplete-with-ispell ()
"Smart TAB binding code from StackOverflow:
http://stackoverflow.com/questions/2149899/code-completion-key-bindings-in-emacs
This smart tab is minibuffer compliant: it acts as usual in
the minibuffer. Else, if mark is active, indents region. Else if
point is at the end of a symbol, expands it. Else indents the
current line."
(interactive)
(if (minibufferp)
(unless (minibuffer-complete)
(interactive)
(arcane/ido-hippie-expand-with (make-hippie-expand-function
'(try-expand-dabbrev-visible
try-expand-dabbrev-from-kill
try-expand-dabbrev
try-expand-list
ispell-complete-word))))
(if mark-active
(indent-region (region-beginning)
(region-end))
(if (looking-at "\\_>")
(hippie-expand nil)
(indent-for-tab-command)))))
(global-set-key (kbd "TAB") 'arcane/hippie-expand-autocomplete-with-ispell)
(global-set-key "\M-/" 'arcane/ido-hippie-expand-choose-from-menu)
(global-set-key "\M- " 'arcane/ido-hippie-expand-choose-from-menu)
(provide 'ido-hippie-expand)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment