Monday, April 06, 2009

Emacs Tip: Better ActionScript Indentation

I've been developing Adobe AIR apps with Emacs for some time now, and it's been going quite well. For editing in emacs, I've been using ecmascript-mode, and for those most part, this works well.

But, not perfectly. I've found some combination of nested {...} and [...] can cause the indentation to break down. Today, I cracked open the CC-mode manual to figure out why.

I didn't find the answer, but I did learn enough to run just the right Google search. In doing so, I found this JavaScript mode. Testing it, showed that it handled indentation right. But alas, it wasn't designed for ActionScript, so it chokes on the package and import statements that Air uses.

What did work was applying the indentation logic to the ecmascript-mode. My resulting .emacs configuration is:

;; A helper function from:
;; Originally named js-lineup-arglist, renamed to as-lineup-arglist
(defun as-lineup-arglist (langelem)
  ;; the "DWIM" in c-mode doesn't Do What I Mean in JS.
  ;; see doc of c-lineup-arglist for why I redefined this
    (let ((indent-pos (point)))
      ;; Normal case.  Indent to the token after the arglist open paren.
      (goto-char (c-langelem-2nd-pos c-syntactic-element))
      (if (and c-special-brace-lists
          ;; Skip a special brace list opener like "({".
          (progn (c-forward-token-2)
      (let ((arglist-content-start (point)))
        (when (< (point) indent-pos)
          (goto-char arglist-content-start)
          (skip-chars-forward " \t"))
        (vector (current-column))))))

;; Load & associate the the mode with .as files
(require 'ecmascript-mode)
(add-to-list 'auto-mode-alist '("\\.as$" . ecmascript-mode))

;; My customizations to the mode.
(defun my-ecmascript-mode-hook ()
  (setq c-basic-offset 2) ; I like 2 spaces instead of 4 or 8
  ;; This is the indentation magic from:
  (c-set-offset 'arglist-close '(c-lineup-close-paren))
  (c-set-offset 'arglist-cont 0)
  (c-set-offset 'arglist-cont-nonempty '(as-lineup-arglist))
  (c-set-offset 'arglist-intro '+))
;; Associate my customization function with the mode's hook
(add-hook 'ecmascript-mode-hook 'my-ecmascript-mode-hook)

No comments:

Post a Comment