I want it my way …

The M-x all-things-emacs blog had a post on tab-completion a while ago. It is basically what I need, but I’d like the opportunity to change the completer at will. Having my brain damaged by Haskell when I read it my first idea was to code a higher order indenter maker, something like this:

;; Higher order indenter
(defun make-indent-or-expander (expander)
  ;; Makes a function that either indent according to mode, or
  ;; expand the word preceding point with the supplied EXPANDER.
  (lexical-let ((expander-fun expander))
               "Either indent according to mode, or expand the word preceding point."
               (function (lambda (arg)
                           (interactive "*P")
                           (if (and
                                (or (bobp) (= ?w (char-syntax (char-before))))
                                (or (eobp) (not (= ?w (char-syntax (char-after))))))
                               (funcall expander-fun arg)
                               (indent-according-to-mode))))))

(fset 'indent-or-expand-h (make-indent-or-expander 'hippie-expand))

This isn’t a very emacsy solution. For example lexical-let isn’t in vanilla emacs but in the ‘cl package, and higher order functions feels so … functional. So I redid this with macros (yey!):

;; Higher order indenter
;;
;; Makes a function that either indent according to mode, or
;; expand the word preceding point with the supplied EXPANDER.
(defmacro make-indent-or-expander (expander)
 "Either indent according to mode, or expand the word preceding point."
 `(function (lambda (arg)
              (interactive "*P")
              (if (and
                   (or (bobp) (= ?w (char-syntax (char-before))))
                   (or (eobp) (not (= ?w (char-syntax (char-after))))))
                  (,expander arg)
                  (indent-according-to-mode)))))

(fset 'indent-or-expand-h (make-indent-or-expander hippie-expand))

Much better, right? Then I just need to hook in to company-mode (the lambda is because company-complete doesn’t take any arguments, unlike lisp-complete-symbol for example):

(fset 'indent-or-expand-comp (make-indent-or-expander (lambda (arg) (company-complete))))
(add-hook 'emacs-lisp-mode-hook (lambda () (local-set-key "\t" 'indent-or-expand-comp)))

Tags: ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: