2012年11月16日金曜日

Scala Tips / Emacs

ScalaプログラミングはなんといってもEmacs+Ensimeですね!

先週サブノート目的でMacBook Air 11inchを入手したのですが、Emacs+Ensimeで満ち足りてしまって、まだEclipseは入れていない状況です。

Emacsのどこがよいかというと、まずテキストエディタとしての基本機能、シェルモードやディレクトリモードといったシェル機能が充実している点が挙げられますが、なんといってもelispで比較的簡単にカスタマイズができるのがよいですね。

カッコの捌き方

Scalaプログラミングをする時の生産性に影響があるのが「{」「}」の捌き方です。たとえば:

abc {

といれると、自動的に括弧を開いてくれてカーソルを所定の位置に持って行ってくれると便利です。

abc {
  ←カーソル
}

もちろん、これぐらいの自動化はどのエディタにもついていると思いますが、問題なのは「abc { }」と打った時に自動的・強制的に上の形になってしまうと、逆に「abc { x => x + 1 }」と書きたかった時に手戻りが発生してしまいます。

このような問題があるため、キーの入力で自動的に上記のような整形をする機能(Emacsのscala-modeではscala-mode-feature-electric)は案外使いづらく、ボクもたいてい切ってしまいます。

abc {
  ←カーソル
}

にしたい時と

abc { x => x + 1 }

にしたい時のどちらにも対応できる入力方法が欲しいところです。

カスタマイズ

この問題に対処するために、以下のelispの関数を作ってみました。

(defun my-scala-newline(arg)
  (interactive "p")
  (cond ((scala-in-multi-line-comment-p)
  (scala-newline))
 ((char-equal ?\} (following-char))
  (let (killed)
           (newline-and-indent)
           (newline-and-indent)
           (forward-char)
    (setq killed (not (my-end-of-line-p)))
    (if killed (kill-line))
           (previous-line)
           (indent-for-tab-command)
    (if killed (yank))))
 (t
  (newline-and-indent))))

.emacsまたはinit.elへの設定は以下になります。

(require 'scala-mode-feature-electric)

(setq scala-mode-feature:electric-expand-delimiters-list '(?\{))

(add-hook 'scala-mode-hook
          (function (lambda ()
        (scala-mode-feature-electric-mode)
          (define-key scala-mode-map "\r" 'my-scala-newline)

まずscala-mode-feature:electric-expand-delimiters-listで「{」のみを有効にするように設定しています。こうすることによって:

abc {

と打つと自動的に以下のようになります。

abc { }←カーソル

ここからの動きがポイントですが、先程のmy-scala-newline関数がReturnに設定されていると、この場所でReturnを押すことで、以下の形に整形されカーソルも所定の位置に移動します。

abc {
  ←カーソル
}

カーソルの位置が他の場所の場合、通常の改行キーの動作をするので、不必要な整形が行われません。「abc { x => x + 1 }」と書きたい時はそのまま入力をしていけばよいわけですね。

括弧を追加する場合の捌き方

my-scala-newline関数は、よく出てくるコーディングパターンをサポートするためにもう一工夫しています。

以下のように一行に書いていた文を:

abc xyz

括弧を入れて複数行に分割したい時がよくあります。

abc {
  xyz
}

まず、最初の状態で「abc 」の場所で「{」を打つと以下のようになります。カーソルは「}」の上になります。

abc { }xyz

ここでReturnを押下すると、「}」の後ろのxyzが自動的に括弧内に移動し、カーソルも所定の位置に移動します。

abc {
  xyz←カーソル
}

簡単なカスタマイズですが、なかなか効果抜群です。

0 件のコメント:

コメントを投稿