xyzzyのjavascript-modeにおけるインデントの挙動をカスタマイズする
配布されているjavascript-modeのインデントの挙動がいくつか気になったので調整した。
前提として、インデント設定としてはタブ不使用の空白4桁を使用している。
javascript-modeは以下のリンク先のものを利用。
http://xyzzy.s53.xrea.com/wiki/index.php?%B3%C8%C4%A5lisp%2Fjavascript-mode
オブジェクトのプロパティーがswitch文のラベルと誤認されることへの対処
以下のような状態で、矢印位置で改行した場合の挙動について。
var foo = { /* ↓ */ bar: 'foobar' };
デフォルトでは、以下のようにインデント量が2桁になってしまう。
javascript-modeでは内部的にC言語の組み込みインデント判定を利用しているようで、
どうも2行目がswitch文などのラベルと誤認されているらしい。
var foo = { bar: 'foobar' };
これについては以下のように、ラベルのインデント量をデフォルトの-2から0へ変更した。
switch文のラベルも4桁になってしまうが、ほとんど使わないので良しとする。
(setf c-label-offset 0)
オブジェクトの閉じ括弧が前行のプロパティーの継続行と誤認されることへの対処
以下のように、オブジェクトのプロパティーを表す行の次で、閉じ括弧が2桁インデントされてしまう。
var foo = { bar: 'foobar' }
こちらの場合は、どうもプロパティーの行がセミコロンで終わっていないために、
前の行が継続していると判定されているらしい。
対策として元のインデント用関数を上書きし、
現在行が閉じ括弧で始まる場合だけ継続行のインデントを一時的に0にするようにした。
siteinit.lに記載した内容は以下の通り。javascript-modeのロードより後ろに書くことに注意。
; 元のインデント関数の保持 (setf (symbol-function 'original-javascript-indent-line) #'javascript-indent-line) ; 現在行を文字列として取り出す関数 (defun current-line-string () "get current line as string" (save-excursion (buffer-substring (progn (goto-bol) (point)) (progn (goto-eol) (point))))) (defun javascript-indent-line () "revoke indent for right brases" (interactive "*") (if (not (string-match "^[ \t]*}" (current-line-string))) (original-javascript-indent-line) ; 現在行が閉じ括弧で始まる場合、継続行のインデントを一時的に0にする (let ((original-continued-offset c-continued-statement-offset)) (setf c-continued-statement-offset 0) (original-javascript-indent-line) (setf c-continued-statement-offset original-continued-offset))))
空の中括弧内で改行したら展開してブロック内の1行目にカーソルを移動する
以下のような中括弧内で改行した場合について。
var foo = {}
デフォルトでは以下のような状態になる。
var foo = { } // 行頭にカーソル
これを、以下のような状態になるよう変更した。
var foo = { // ここにカーソル }
siteinit.lに記載した内容は以下の通り。
改行した瞬間にカーソルが"{}"や"[]"の中に入っていたら、余分に改行やインデントを行うようにしている。
こちらもjavascript-modeのロードより後ろに書くことに注意。
;; 中括弧内で改行したら展開してカーソルを中に入れる (defun javascript-newline-and-expand-brases (&optional (arg 1)) "open brases and move the cursor inside of the brases" (interactive "*") (javascript-newline-and-indent arg) (flet ((current-line-string () (buffer-substring (progn (goto-bol) (point)) (progn (goto-eol) (point))))) (if (or (save-excursion (and (string-match "^[ \t]*}" (current-line-string)) ; {}内で改行した場合 (string-match "{[ \t]*$" (progn (previous-line) (current-line-string))))) (save-excursion (and (string-match "^[ \t]*\\]" (current-line-string)) ; []内で改行した場合 (string-match "\\[[ \t]*$" (progn (previous-line) (current-line-string)))))) (progn (save-excursion (javascript-newline-and-indent arg)) (javascript-indent-line))))) (define-key *javascript-mode-map* #\RET 'javascript-newline-and-expand-brases) (define-key *javascript-mode-map* #\LFD 'javascript-newline-and-expand-brases)
設定ファイル全体は以下
https://github.com/phithon/dotfiles/blob/master/siteinit.l