header

2014年2月22日土曜日

EmacsでJavaの設定

Clojureを勉強しようとおもって、まずはJavaからとおもいEmacsでJavaの設定
をととのえた。でもJavaについてはまだよくわかっていないので変なことをし
ているかもしれない。


できるようになったこと


  • emacs-eclim を利用しauto-completeのコード補完
  • popupでeclimのエラーを表示
  • quickrunでコードの実行

eclim?

説明が前後してしまったけどeclim自体はeclipseをvimから使うプロジェクト
です。これのおかげでeclipse並のコード補完が実現できてるらしい。
(eclipseは10秒くらい起動してすぐ閉じてしまったのでほとんど知らない…)

なぜ僕がemacsから使えるかというと、emacsからもeclim使えるようにする
emacs-eclimという拡張を利用しました。(これより以下のeclimという用語は
emacs-eclimを指しています)
eclipse自体の機能を把握してないのでアレですが、projectの作成やリファク
タリングなどeclimから実行できるようです。


環境構築方法

多分日本語では、あまり情報がなさそうなので自分がやったことなどを書いて
おきます。
英語ですが、このサイト が一番参考になりました。(Installationの項が詳し
く書いてあります)


eclipseのダウンロード

僕はubuntu 12.04を利用していますが、apt-getからのインストールでは
うまくeclimをビルドできなかったので、参考サイトのように
ここの download linkからダウンロードしました。
参考(OSを確認してインストールしてください):

INSTALL_DIR=/opt/local
mkdir -p $INSTALL_DIR
cd $INSTALL_DIR
curl -o eclipse.tar.gz http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/juno/SR1/eclipse-java-juno-SR1-linux-gtk-x86_64.tar.gz
tar xvzf ./eclipse.tar.gz

eclim

続いてeclimのインストール(上の続きから)

git clone git://github.com/ervandew/eclim.git
cd eclim
ant clean deploy -Declipse.home=$INSTALL_DIR/eclipse

これでeclipseのあるディレクトリにeclimdが置かれるようになります。


emacs-eclim

これはEmacsに慣れてる人なら特にインストールの説明は必要ないとおもうの
ですが、、、
M-x list-package で確認したらemacs-eclimとあったので、MELPAから手軽に
インストールできると思います。
僕はel-getからインストールしました。


Emacsの設定

僕はinit_というprefixをつけて設定をわけています。
使えそうなところだけ抜きだす使いかたでもいいと思います。

init_java.el:

(defun my/java-init ()
(cond
((and
(not (string-match "^\\*Org Src .*\\*" (buffer-name)))
(string-match "/src/.*\\.java$" buffer-file-truename)
(my/boot-eclim)
(eclim--project-name))
(eclim-mode)
(ac-emacs-eclim-config))
(t
(require 'init_flymake-java)
(flymake-mode t))))

(add-hook 'java-mode-hook 'my/java-init)

project管理しているディレクトリの場合は、eclimdを起動する設定
そうでなければ、flymakeで利用するだけ
(もっとましなチェック方法がありそう。。。)

init_eclim.el:

(with-no-warnings (require 'eclim))
;; ECLIPSE_HOMEはeclipseのあるディレクトリを設定してください
(setq eclim-eclipse-dirs `(,(getenv "ECLIPSE_HOME"))
eclim-executable (eclim-executable-find))

(defconst eclimd-executable (format "%s/eclimd" (getenv "ECLIPSE_HOME")))
(require 'eclimd)

(defun my/boot-eclim ()
(let* ((boot-p (zerop (shell-command "pgrep eclimd")))
(answer (and (not boot-p) (y-or-n-p "Use eclim? "))))
(when answer
(call-interactively 'start-eclimd))
answer))

;; auto-completeにeclimの補完を表示
(require 'ac-emacs-eclim-source)
;; C-M-iを無効化
(define-key eclim-mode-map (kbd "C-M-i") nil)

(defadvice eclim-problems-highlight
(around avoid-this activate)
(when (eq 'java-mode major-mode)
ad-do-it))

eclim用の設定、eclimを利用するとeclipseの起動の重さがそのまま反映され
るデメリットもあるので起動するか尋ねるようにした。

init_flymake-java.el:

(require 'flymake)

(defun flymake-simple-generic-init (cmd &optional opts)
"Syntax check function for without Makefile.
CMD means command and OPTS means options."
(let* ((create-tempfile
(lambda ()
(let* ((temp-file
(flymake-init-create-temp-buffer-copy
(case major-mode
(java-mode 'flymake-create-temp-with-folder-structure)
(t 'flymake-create-temp-inplace))))
(local-file (file-relative-name
temp-file
(file-name-directory buffer-file-name))))
(if (file-exists-p local-file)
(expand-file-name local-file)))))
(file+opts (push (funcall create-tempfile) opts)))
`(,cmd ,file+opts)))

(defun flymake-simple-make-or-generic-init (command &optional options)
"Do syntax check function.
If makefile is exists, then do `flymake-simple-make-init'.
Otherwise, do `flymake-simple-generic-init' function with COMMAND and OPTIONS."
(if (or (file-exists-p "Makefile") (file-exists-p "makefile"))
(flymake-simple-make-init)
(flymake-simple-generic-init command options)))

(add-hook 'java-mode-hook
(lambda ()
;; TODO: add flymake-simple-ant-java-init?
(defun flymake-simple-make-java-init ()
(flymake-simple-make-or-generic-init "javac" '("-Xlint")))))

eclimを利用しない場合はflymakeでエラーチェックするようにしている。
冗長な書き方をしているのは、c/c++でflymakeを利用する時用。
(今の時代はflycheckがありますが、もったいなくてなんか消せない…)

init_quickrun.el:

(require 'quickrun)
;; override Java
(quickrun-add-command
"java"
'((:compile-only . "javac -source 1.6 -target 1.6 -Werror %o %s")
(:exec . ("javac -source 1.6 -target 1.6 %o %s" "%c %N %a")))
:override t)

設定しなくてもquickrunでJavaのコード実行できる人は必要ない設定です。
javacとjavaのバージョンがちがくて実行ができない場合、上の1.6と書いてあ
る部分を変えて設定してみてください。


eclimのエラーチェックをpopupで

emacs-eclim標準でエラーチェックをやってくれるのですが、
表示方法が別バッファ表示のようなので、僕はあんまりすきな感じでなかったので
flycheck-tip というflycheckのエラーをpopup.elのツールチップで表示する
拡張にねじこみました。
MELPAからインストールできます。

僕は mykie.el というEmacsのキーバインドを登録するのを便利にする拡張を利
用しているので設定はこんな感じになっています(mykie.elのステマ):

(require 'mykie)
(require 'error-tip)

(setq mykie:prefix-arg-conditions
(append mykie:prefix-arg-conditions
'((:C-u&error . (error-tip-error-p)))))

(mykie:set-keys nil
"C-l"
:default (recenter-top-bottom)
:C-u&error (mykie:do-while
"n" (error-tip-cycle-dwim)
"p" (error-tip-cycle-dwim-reverse)))

上のコードの意味は、C-u C-lを押したときにエラーが出ていれば
そのエラーをpopup.elのツールチップで表示します。
他のエラーをみたければ 'n' または 'p' キーを押すことで、
移動後エラーを表示します。それ以外のキーを押すと通常の入力モードに戻り
ます。
エラーが出てなければ、通常どおりrecenter-top-bottomを行います。

ちなみにerror-tip-cycle-dwim関数は、flycheck-modeならflycheck-tip,
eclim-modeならeclim用のエラー表示、flymakeを利用してたらflymakeのエラー
表示をする便利関数です。(いずれもpopupでエラー表示します)


eclimのメリット、デメリット

コード補完とエラーチェックは便利だと思うけど、eclimdを起動するのは
eclipseを起動するのと同じくらい時間がかかるので好みがわかれる気がしま
す。
僕はrevert-bufferをbuffer移動するときに実行していたんですが、
eclimを使うようにするとなんか重くなる感じがするんですよね。。。
git-gutter+の情報の更新のためだったので、git-gutter+-refleshで
なんとかなりましたが、、、
普段revert-bufferを頻繁に利用している人は注意が必要かもしれません。


注意事項


  1. 自分の設定をサルベージして書いたものなので、もしかしたらそのままでは動
    かない可能性もあります。。。
  2. auto-completeは有名なパッケージなので設定は書きませんでした。
  3. flycheck-tip/error-tipはflycheckとeclimの同時起動は想定していません
    のでどちらかはoffにしてください。

その他メモ

今回は入れてないけど、drip, flycheck-java, java-lookup
とかもあるらしい。(flycheck-javaはeclimがあればいらないと思うけど)
そういえば、malabar-modeとかどうなんだろう。。。


おわり

ほかにも便利な設定などあればコメントいただけるとうれしいです:)


0 件のコメント:

コメントを投稿

Popular Posts

Blogger templates

Blogger news