Emacs Completions with Hippie-Expand and Snippets

September 4, 2008

One of the most important features of a text editor is the completing of text inside a buffer. There a lots of packages for Emacs, which provide this feature in many different ways. I will show you, what I use to improve my life as coder.

Multifunctional tab key

Most of the time the tab key in Emacs is bound to the indentation command, which will indent the current line. So if you want to use the tab key for other things, you need some kind of multiplexer, which tries to figure out, what is the right thing to do in each situation.

So I copied the indent-and-complete from the emacs-rails package:

  1. (require 'hippie-exp)
  2. (require 'snippet)
  3. (defun indent-and-complete ()
  4. "Indent line and complete"
  5. (interactive)
  6. (cond
  7. ((and (boundp 'snippet) snippet)
  8. (snippet-next-field))
  9. ((looking-at "\\_>")
  10. (hippie-expand nil))
  11. ((indent-for-tab-command))))

The function indent-and-complete does one of the following actions:

  • if a snippet is active, it jumps to the next field
  • if we are at a word boundary, it tries to complete with hippie-expand
  • otherwise it indents the current line

HTML mode initialization

Well, this function alone will not change your editor behaviour. For activating our tab function, we need to bind the tab key.

Additionally we want to setup hippie-expand, an expansion package, which will try to expand the word before the cursor in a configurable way. hippie-expand-try-functions-list is a variable, which defines a list of functions, which should be called for completion.

Let’s have a look at my html-mode initialization function. It will configure the completion behaviour of hippie-expand an bind the tab key to indent-and-complete.

  1. ;; We need a simple wrapper for expand-abbrev
  2. (defun try-expand-abbrev (old)
  3. (expand-abbrev))
  4. ;; ********************************************************************************
  5. ;; HTML Mode
  6. ;;
  7. (add-to-list 'auto-mode-alist '("\\.html\\'" . html-mode))
  8. (defun html-mode-on-init ()
  9. (set (make-local-variable 'hippie-expand-try-functions-list)
  10. '(try-expand-abbrev
  11. try-expand-dabbrev))
  12. (define-key html-mode-map (kbd "<tab>") 'indent-and-complete))
  13. (add-hook 'html-mode-hook 'html-mode-on-init)

There a two functions, which will be asked to complete the current word:

  • try-expand-abbrev: Expands the current word by looking into the list of defined abbreviations. So called abbrevs are just shortcuts in Emacs. So if you type li and hit the tab key it will be expanded to <li></li>.

  • try-expand-dabbrev: Dynamic abbreviation is a pragmatic method for completing words. Emacs will look for words with the same beginning and use them for completion. Hitting multiple times the tab key will give you different completions, as you may know from the unix shell.

Defining your snippets

Now if you want to use snippets for your html-mode, you have to define a abbrev-table with your desired snippets.

  1. (define-abbrev-table 'html-mode-abbrev-table ())
  2. (snippet-with-abbrev-table 'html-mode-abbrev-table
  3. ("h1" . "<h1>$.</h1>")
  4. ("h2" . "<h2>$.</h2>")
  5. ("h3" . "<h3>$.</h3>")
  6. ("h4" . "<h3>$.</h4>")
  7. ("h5" . "<h3>$.</h5>")
  8. ("h6" . "<h6>$.</h6>")
  9. ("div" . "<div>$.</div>")
  10. ("divc" . "<div class=\"$${class}\">$.</div>")
  11. ("span" . "<span>$.</span>")
  12. ("spans" . "<span style=\"$${style}\">$.</span>")
  13. ("form" . "<form action=\"$${action}\" method=\"$${post}\">$.</form>")
  14. ("input" . "<input type=\"$${text}\" name=\"$${name}\" value=\"$${value}\"/>")
  15. ("a" . "<a href=\"$${href}\">$.</a>")
  16. ("br" . "<br/>$.")
  17. ("ul" . "<ul>$.</ul>")
  18. ("ol" . "<ul>$.</ul>")
  19. ("li" . "<li>$.</li>")
  20. ("tab" . "<table>$.</table>")
  21. ("tr" . "<tr>$.</tr>")
  22. ("td" . "<td>$.</td>")
  23. ("th" . "<th>$.</th>")
  24. ("str" . "<strong>$.</strong>")
  25. ("em" . "<em>$.</em>")
  26. ("meta" . "<meta name=\"$${name}\" content=\"$${content}\"/>")
  27. ("style" . "<style type=\"text/css\">$.</style>")
  28. ("script" . "<script type=\"text/javascript\">$.</script>")
  29. ("scripts" . "<script src=\"$${src}\" type=\"text/javascript\">$.</script>")
  30. ("img" . "<img src=\"$.\"/>")
  31. ("link" . "<link href=\"$${href}\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\"/>"))

Great. If you put all the code in your .emacs file, you should be able to use your tab key for completions. In our case we defined snippets for the html-mode and activated hippie-expand to use abbrevs and dynamic abbreviation. There is much more stuff I will show you next time, like customizations for other language modes like Ruby and Javascript.


Posted in category Emacs by Matthias Georgi. Tagged with completion, hippie-expand, snippet.
Similar Posts