Effortless Major Mode Development

存储架构 2016-04-28

28 April 2016

It’s now easier than ever to write major modes in Emacs. If you haven’t written a major mode in a while, or you’re just starting out, here are my three top tips:

Use regexp-opt

As of Emacs 24, regexp-opt takes a 'symbols option. You should write your font-lock keywords like this:

(defvar js-mode-font-lock-keywords
  `((,(regexp-opt
       '("var" "for" "function" "if" "else")
       'symbols)
     . font-lock-keyword-face)

This has two advantages. By whitelisting keywords, users can quickly spot mistakes when editing:


This also prevents a classic bug where Emacs highlights substrings that happen to be keywords:


(Don’t) use company

Company is excellent, and I highly recommend it. However, not all Emacsers use company. You don’t need to force company on your users.

Instead, you can use completion-at-point-functions . Your completion functionality will work in stock Emacs, and company users will benefit too through company-capf .

Ah, but what about all the extra annotations you can supply to company? We can have our cake and eat it too:

(defun racer-complete-at-point ()
  "Complete the symbol at point."
  (unless (nth 3 (syntax-ppss)) ;; not in string
    (let* ((bounds (bounds-of-thing-at-point 'symbol))
           (beg (or (car bounds) (point)))
           (end (or (cdr bounds) (point))))
      (list beg end
            (completion-table-dynamic #'racer-complete)
            :annotation-function #'racer-complete--annotation
            :company-prefix-length (racer-complete--prefix-p beg end)
            :company-docsig #'racer-complete--docsig
            :company-location #'racer-complete--location))))

Test with assess

Historically, it’s been rather awkward to test major modes. Many authors didn’t bother.

That’s all changed with the release of assess . Assess provides great assertions with readable error messages.

For example, here’s a simple indentation test from cask-mode :

(ert-deftest cask-mode-indent-inside-development ()
  "Ensure we correctly indent inside (development ...) blocks."
  (should (assess-indentation=
           'cask-mode
           ;; before:
           "
(development
(depends-on "foo"))"
           ;; after:
           "
(development
 (depends-on "foo"))")))

Highlighting is particularly helped by assess:

(ert-deftest cask-mode-highlight-sources ()
  "Ensure we highlight known values for source."
  (should (assess-face-at=
           "(source melpa)"
           'cask-mode
           "melpa"
           'cask-mode-source-face)))

If this test fails, we get a helpful message describing which faces were actually used:

#("Face does not match expected value
   Expected: cask-mode-source-face
   Actual: font-lock-keyword-face
   Location: 9
   Line Context: (source melpa)
   bol Position: 1"

These tips are all new things I’ve learnt writing a new major mode for Cask files . If you’re just getting started with Emacs development, check out adding a new language to Emacs . Finally, if I’ve missed your favourite tip, leave a comment on the /r/emacs discussion !

责编内容by:Wilfred Hughes Blog (源链)。感谢您的支持!

您可能感兴趣的

Small-time Patching Update: Added the improved backtrace Today #emacs reminded me of an odd...
使用 dotfiles 和 stow 管理你的 dotfiles 可能看标题你觉得我疯了,什么叫用 dotfiles 管理你的 dotfiles。 第一个单词 dotfiles 指将 HOME 目录下的 .XXX (它们...
You’re Doing It All Wrong™ As I write this article, I am putting the finishing touches on a septendecuple-...
You are not your tools Do you think of yourself as a Python programmer, or a Ruby programmer? Are you a...
Make M-RET better in Org Mode If you’re an Org mode user you probably know that Meta + Return can be us...