エディタ難民からEmacs統一へ その2

前振り

 さて、あれから10年も〜♪経ってしまったのね。

 あれから10年。まだプログラムを書き続けているってことは、まぁそういうこと、スーパー貧乏。。emacsの設定もちょこちょこ変わってる。ここ10年で変わった事といえば、Macのemacsはcocoaになったしemacsは22から24に変わった。10年経ったけどあまり変わってないね・・。自分はといえば、家ではmacというのは変わってないが、職場は完全にLinuxに移行しWindowsは全く使わなくなってしまった。よってMeadowは今は全然使ってない。また、自分の環境の変化として、C言語がメインの組み込み屋さんだったのが、組み込みにもjavaなんかが入ってきた。組み込みだけでは食って行けず、最近はjavascript,php,rubyなんかも書いてる。文字コードも当然のようにutf-8に変わってる。更にここ最近になってTextMateやEclipseなどのIDE環境に近い物が主力になってきていた。そこで、重い腰を上げて環境を再構築。まだプログラマやるのか俺?。(2014.04.06)

このページのコンセプト

 だいたい以下の通りで以前からは変わった。

  • MacOS-X,Linuxで動かす。windowsはもう忘れた(win2000以降ほとんど使ってない)
  • Emacsを使う
  • IDEみたいに便利に使いたい
  • マウスもそれなりに使う
  • 「邪道だ!」と言われても耐える
  • 適当に更新する
  • コンセプトすら変わる

まぁあまり変わってないわけだが。人の思想なんてそんなに変わらんよ。。

他のエディタへの乗り換えを模索してみた

一応、他のエディタへの乗り換えも考えた。まずMacのTextMateがとってもよいという話だったので、それのクローンでLinux,Macで動く物を探してみた。textmateの後継といわれる sublime textなんていうのも使ってみたがOpenSourceじゃない。オープンソースのRedcarってのも使ってみたがこれはJRubyで書かれてて重い・・。EclipsやNetbeansはJavaなんでこれもまた重厚なわけで・・・。結局Emacsから離れるには至らなかった。だが、プログラム言語を同時にいくつも使うようになると、コード補完というかコーディング補助が欲しい!!!。ってのが実情なわけで・・もうプログラマとしては歳なので脳みそのメモリ容量も減っているのよね。。

MacとLinuxの分岐

Emacasをカスタマイズして使うには.emacsなり.emacs.elなりを作ってlispで設定を書かなければいけないわけだが、LinuxとMac-OSXをどうやって切り替えるかだが、以前"mac"で切り替えていた物がcocoaになったので以下のように分岐する。基本的にはすべて共通でfontやらfaceやらを分岐するだけだけど、キーボードが違ったりしてたまに切り替えたい時がある。

;; carbon emacs
(if (eq window-system 'mac) (progn
  (set-file-name-coding-system 'utf-8)
))
;; cocoa emacs
(if (eq window-system 'ns) (progn
  (set-default-coding-systems 'utf-8)
))
;; meadow
(if (eq window-system 'w32) (progn
  (set-language-environment "Japanese")
  (set-default-coding-systems 'sjis)
  (set-keyboard-coding-system 'sjis)
))
;; emacs window system
(if (eq window-system 'x) (progn 
  ;; mozc.el
  (require 'mozc)
  (setq default-input-method "japanese-mozc")
  (setq mozc-candidate-style 'overlay)
))

こんな感じ。macは旧macなので、もう使う事はないかな。今のMac版emacsはEmacs24でcocoaになった。cocoa emacsはnsで判別する。nsってのはNextStepのns。それとLinuxはxだね。xなのでLinuxでGUIで使った場合だけど、ほとんどコンソールでemacsを使う事はないのであまりテストしていない。コンソールでエディタを使う場合にはGNU nanoを使用している。各OSで大きく違うのはInput Method。macではOSデフォルトのことえりをそのまま使っていて、winはそのままIME、Linuxはibus経由のmozcを使用している。上記のOS別の分岐の中もその辺がちょっとだけサンプルとして入ってる。

Helm導入

しばらくの間大きな変化もなくちょこちょこemacs.elをいじって使っていたが、不満があると"emacs 設定"とかでググってみるわけだ。すると2,3年前頃から「anything.elがすごい」というのによく引っかかる。でも、文章で見てても何がすごいんだか分からん。。そこで入れてみようと思うんだが、何やら依存関係や設定が面倒くさく、断念orz、となり放置。で、どうやらそれの対抗だか後継だかでHelmというのがあり、とりあえずそっちを入れてみた。
 インストールは簡単。HelmのGitに行ってreleaseタグのところの1.6.0をダウンロードして自分のlispフォルダに展開する。俺の場合~/lispというディレクトリが自分のカスタマイズディレクトリなのでその中に放り込む。

そんでもって.emacs.elに設定を書く

(add-to-list 'load-path "~/lisp/helm-1.6.0")
(require 'helm-config)
(helm-mode 1)

これだけ。いやーanythingの初期に比べてなんて簡単なんだ。さぁと使ってみた。helm-modeを1にするこで何かに反応すると画面の下半分が候補リストとインクリメンタルサーチ状態になり絞り込みながら選択するというシステムなのである。やっぱり文章で書いてもよくわからんな。。Webブラウザの進化っぽくemacsが進化した感じ。たとえば、何かをググる時って1)Googleを開く、2)サーチボックスに文字をいれる 3)候補がどんどん出てくる 4)それっぽいのがあったらリータンして確定 5)結果画面から選択という手順を踏むでしょ?。同じように1)helmのバッファーリストを開く 2)miniバッファーの入力窓に文字をいれて絞り込む 3)絞られたらリストを選択してリターン 4)対象の編集開始。見たいな。とても効率的。触ってみないとなかなか通じない。
 たとえば下の画面。

helm-for-filesという物を使っているんだが、これをC-bで起動するように割り当ててる。

  (global-set-key "\C-b" 'helm-for-files)

C-bを押してhelm-for-filesを起動すると、下半分にhelm画面が出てきて、buffer一覧とrecentフィアル一覧が同時に表示され、minibufferはpattern文字列入力待ち状態になる。そのままカーソルキーで開いてるバッファや過去に使用したファイルから選択しても良いし、pattern文字列入力待ちになっているので、"inde"とか普段インクリメンタルサーチで探すように絞り込んで行っても良い。リターンを押せば再びエディタ画面に戻る。いやーとても便利。
 あまりに便利すぎて、なんでもこの候補リストとpatternマッチングで絞り込んで行くインターフェースで使用したくなるんだと。これをanything脳というらしい。
 このインターフェースを体験してIDEよりemacsの方が進んでいる!と思えた。単なる古いエディタじゃない、emacsはエディタじゃなくて環境であるといわれてたけど、まさしくなのである。

 これにより、いままで使っていたmifes風バッファ一覧とdiredは要らなくなりそう。だってよく使うものが一覧で一括して見れるんだから・・・。今まではバッファはバッファ、fileはfileだったわけだがWWWでなんてでも同じように検索して来れるようにemacsでも何でも同時に検索して来れるようになった。今風だ。ただ、ちょっと色とバッファ一覧が不便なのでちょっとだけカスタマイズ。

;face
; 選択されている物を目立つようにでっかく表示と緑!
(custom-set-faces
 '(autoface-default ((((type ns)) (:inherit default :height 120 :family "Menlo" :background "#00004A" :foreground "AntiqueWhite"))))
 '(helm-selection ((t (:background "green1" :foreground "#600000" :underline t :height 1.2)))))

; killバッファーにはhelmはいらない
(add-to-list 'helm-completing-read-handlers-alist '(kill-buffer . nil))

; ワードラップしなくて良い!。のとバッファリストに余計な物は出したくない。
(custom-set-variables
 '(helm-truncate-lines t)
 '(helm-buffer-max-length 20)
 '(helm-boring-buffer-regexp-list '("^*"))
 '(tramp-mode nil)
 )

気に入らないのは、編集したバッファなり、見ただけのバッファを閉じるのにイチイチhelmが立ち上がる事。kill-buffer時にはhelmは立ち上がらなくて良いようにした。また、バッファー一覧に*message*や作業用のバッファーも入ってきてしまうので頭に"*"が付いたバッファーは表示しないようにした。更に、バッファー名やファイル名が長いとエディタの橋でワードラップして見難くなるのでtruncateでロングラインにする。全部見える必要はないのだ。それと、職場のLinux(OpenSuse12.3)だとAuto-completeと組み合わせると、trampが起動してしまうのでnilにセットしている。使わんので。

Auto-Complete

 いまさらだがAuto-Completeも入れてみた。かなり優秀な補完システムらしい。そもそもEclipsやIDEを入れようと思ったのは、色々な言語を同時に使うので、arrayがどういう書き方だったかわからなくなるので、補完したいという目的があった。それをとても便利に実現してくれる。これもまたダウンロードもインストールも簡単 Auto-Complete mode - Emacsのための最も賢い自動補完からelispをダウンロードして軽く書くだけ。

(add-to-list 'load-path "~/lisp/auto-complete-1.3.1")
(require 'auto-complete-config)
(ac-config-default)

これだけでOKなんだけど、使ってると色々不都合が出てくるので、ちょっとカスタマイズ。

(add-to-list 'load-path "~/lisp/auto-complete-1.3.1")
(require 'auto-complete-config)
;辞書は別でにして自分で育てる。
(add-to-list 'ac-dictionary-directories "~/lisp/my_ac_dict")
;ファイル名の補完はいらん。c++コメントを使うと出てくるのがうざい。
(defun ac-common-setup ()
  (setq ac-sources '(
					 ac-source-functions 
					 ac-source-variables 
					 ac-source-symbols 
					 ac-source-features 
;				   ac-source-filename
					 ac-source-abbrev 
					 ac-source-dictionary 
					 ac-source-words-in-same-mode-buffers
					 ))
										;
  )
(ac-config-default)
;ポップアップメニューが出てくるのは1.2秒後
(setq ac-auto-show-menu 1.2)
(setq ac-dwim t)

こんな感じだろうか。もうちょっと便利にできそうだけど、その辺は追々。


yasnippetも導入

次に、テンプレート機能であるYasnippetも導入。htmlの入力やあまり使わない機能の入力には便利そう。"href"と書いて補完キーを押せば "<a href=""></a>"と挿入される。他にモ使う局面は多そう。組み込み屋さんだとfile処理はあまりやらないので直ぐ忘れるのだが、fileを開いて1行ずつ処理とかお決まりのパターンなので、前に書いたソースを探してコピペする。でもそれよりテンプレートに登録しておいて、呼び出した方が便利だよねやっぱり。これも導入は簡単 Yasnippetからダウンロードして~/lispに展開(俺の場合)、でemacs.elにでロード

 add-to-list 'load-path "~/lisp/yasnippet-0.8.0")
(require 'yasnippet)
(setq yas-snippet-dirs
      '("~/lisp/my_snippets"
      "~/lisp/yasnippet-0.8.0/snippets"
        ))
(yas-global-mode 1)
(define-key yas-minor-mode-map (kbd "C-c") nil)
(custom-set-variables '(yas-trigger-key "C-i"))

こんな感じ。Auto-completeと同様に自分のテンプレートは別にして置けるようにmy_snippetsを別にしてある。lispって家にあるサーバーのsvnに入れて職場と家と共有してる。キーはCtrl+iに割り当てた。insertの意。まぁいい位置に空いてるキーがあっただけってだけの話なんだけど。Ctrl+cはコピーキーとして使っててかぶってしまったのでnil定義で解除。なんだかなぁ、MacユーザーなんだかWinユーザーなんだかLinuxユーザーなんだか分からんキー配置になっちゃったなぁ。。身に付いちゃった物は仕方ない。でも家にいるときは普通にCommand+Cでコピーしてるんだよな。。
 で、yasnippet関係の設定等をググっていたら、helmに流し込めるという記事を発見。おすすめの helm拡張ここから頂戴して、コードも読まずに貼付けた(^^;。

;(require 'dropdown-list)
;(setq yas-prompt-functions '(yas-dropdown-prompt
;                                    yas-ido-prompt
;                                    yas-completing-prompt))
(define-key yas-minor-mode-map (kbd "C-c") nil)
;(custom-set-variables '(yas-trigger-key "C-;"))
(custom-set-variables '(yas-trigger-key "C-i"))

(defun my-yas/prompt (prompt choices &optional display-fn)
  (let* ((names (loop for choice in choices
                      collect (or (and display-fn (funcall display-fn choice))
                                  coice)))
        (selected (helm-other-buffer
                    `(((name . ,(format "%s" prompt))
                       (candidates . names)
                       (action . (("Insert snippet" . (lambda (arg) arg))))))
                    "*helm yas/prompt*")))
    (if selected
        (let ((n (position selected names :test 'equal)))
          (nth n choices))
      (signal 'quit "user quit!"))))
(custom-set-variables '(yas/prompt-functions '(my-yas/prompt)))

こうすると、文字を入力してCtrl+iを押した時に、1つしか候補が無い場合はそのままテンプレートが挿入され、複数候補がある場合はhelmが動いて下半分の画面から選択できる。例えば"div"と入力してCtrl+iを押した場合には、次のようになる。

いやーとっても便利。とりあえず、脳内メモリが減ってきたロートルプログラマの助けにはなりそうだぞ。当分生活保護に頼らずに生きて行けそうだ。

Top 前へ戻る