2013年2月3日日曜日

Emacs 設定いろいろ [Emacs24 (Cocoa Emacs) on Mac OS X]

年が明けたかと思っていたら、気がつけば 1 月が終わってしまいましたね。

久しぶりの投稿ですが、今回は Emacs ネタで。

Emacs に触り始めたのはもう 10 年以上前でしょうか。当時は Emacs20 とか 21 ぐらいでしたかね。古いバージョンのまま 6,7 年ぐらい使っていましたが、学生から社会人になったり環境が変わったりで 1 年ぐらい触る機会なくなってたのが、個人で自宅用に MacBook Air 買ったのキッカケでまたメインのエディタとして使うようになりました。慣れもあるのでしょうがやはり使いやすいですね。

現在使ってるのは Emacs24 (Cocoa Emacs) で最近バージョン 24.2 に更新しました。久しぶりだったこともあって設定を見なおしたり評判のいい機能を探して導入したりしました。ファンも未だに多いせいか、いろいろ進化してますね。ありがたいです。

せっかくなので「あ、これ便利」と思ってる機能など、自分への備忘録も兼ねて設定とともにご紹介でもしてみようかと思った次第です。

Index

環境およびインストールについて

Emacs および周辺環境は以下の通り。

  • Hardware: MacBook Air
  • OS: Mac OS X 1.8.2 (Mountain Lion)
  • Emacs: Cocoa Emacs v24.2
  • IME: Google 日本語入力
  • Browser: Google Chrome

インストール方法はググればあちこちに有用なドキュメントは出てくると思いますのでざっくり書きます。

  • Xcode (+ Command Line Tools) をインストール
  • Homebrew をインストール (https://github.com/mxcl/homebrew/wiki/installation)
  • Emacs 本体は brew install emacs --cocoa でさっくりとインストール
  • 適宜必要なシンボリックリンク張って、/Applications/Emacs.app で Emacs 起動できるようにする

まあこんなとこですかね。

ちなみに以降で説明する設定は全部 ~/.emacs.d/init.el に記載しているものです (むかーしは ~/.emacs に書いてたなぁ…)。

Emacs Lisp パッケージ管理

Emacs 用の各種 Lisp がパッケージ管理されるというありがたい機能。Emacs 24 から利用可能になったものですね。以下の設定は Emacs24 のインストールと新機能 : 紹介マニア で紹介されてたものを丸コピです。

M-x list-packages すると 1000 以上のパッケージリストが取得できます。h でヘルプが表示されますが、基本は i でインストールマーカを付けて x でインストールです。さらにありがたいのは各種 Emacs Lisp バージョンアップに伴うアップデートが楽ちんなところですね。久しぶりに M-x list-packages すると更新可能なパッケージが提案されますので U を押すとそれらのパッケージにインストールマーカが付き、後は x だけ。これで最新版のインストールと旧版のアンインストールをサクッとやってくれます。Emacs Lisp ファイルの更新って手動だとなかなかやらず、せっかくのバージョンアップのご利益を享受しそびれがちだったので助かりますね。

ちなみにこれで管理されてる Lisp ファイルは ~/.emacs.d/elpa/ 以下に置かれてるようです。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; [PKG管理] パッケージ取得先追加
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t)
(add-to-list 'package-archives '("marmalade" . "http://marmalade-repo.org/packages/"))
(package-initialize)

背景色と透過と設定 (複数フレーム対応)

make-frame-command (ショートカットキー: C-x 5 2) による新規フレーム作成時にも適用される、背景色と透過の設定になります。

Emacs の背景透過の設定とか検索すると色々出てくるのですが、複数フレームに対応したものになかなかヒットせず、"default-frame-alist alpha" あたりで検索してやっとお目当てのサイトが見つかりました。

私の場合 Emacs はメモ・ドキュメント書き・ファイル操作・メール草稿など多用途に使っているため基本起動しっぱなし&常に複数フレームを開いてる状態なので、下記のような複数フレーム対応の設定は重宝してます。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; [基本] 背景色・透過
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 背景色設定
(custom-set-faces
 '(default ((t (:background "#000022" :foreground "#EEEEEE"))))
 '(cursor (
           (((class color) (background dark )) (:background "#00AA00"))
           (((class color) (background light)) (:background "#999999"))
           (t ())
           )))
;; フレーム透過設定
(add-to-list 'default-frame-alist '(alpha . (0.75 0.75)))

Markdown 編集用・その一 (markdown-mode)

GitHub を使い始めた際に Markdown 記法を知りましたが、その後すっかりハマってしまい、何か事情がない限りテキストは常にこの記法で書くようになってしまいました。マーカとして使うものがシンプルで大抵はそれで用が足りますし、HTML へのコンバータも用意されてますし、いざ表とか必要な場合は HTML で直書きもできるとこが良いですね。

…というわけで Emacs にも markdown-mode がありまして重宝しております。前述しました list-package からパッケージインストールできます。

また Mac だと Homebrew 使って brew install markdown で markdown の HTML へのコンバータ (直接入手するなら こちら から) をさくっとインストールできます。以下の markdown-command はそれ前提の設定です。変換後 CSS で見やすくするために markdown-css-path も設定してます。ラップトップなのでローカルに適当に作った CSS を指定してますが、常時インターネットに接続してる環境であれば、気に入った Web 上の CSS を参照しちゃうのもいいかもしれません。

以下では .md, .txt の拡張子のファイルを開く際に markdown-mode にしてますが、これは人にとってお好みで、ですね。HTML への変換時は以下を使ってます。

  • HTML に変換してからブラウザで開く (markdown-export-and-preview)
    • Ctrl-c Ctrl-c v
  • 単に HTML に変換するだけ (markdown-export)
    • Ctrl-c Ctrl-c e

見出しやリンクを挿入する関数もありますが、ショートカットキー叩くより普通に入力したほうが早いので、あまりそっちは使ってませんw

ちなみにこの記事も Markdown 記法のテキストで作成 → コンバータで HTML に → Blogger 用に少し sed で整形、的なことやってます。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; [PKG機能利用] markdown-mode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(autoload 'markdown-mode "markdown-mode.el" "Major mode for editing Markdown files" t)
(setq auto-mode-alist (cons '("\\.md" . markdown-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.txt" . markdown-mode) auto-mode-alist))
(setq markdown-command "/usr/local/bin/markdown")
;; Markdown2HTML した際 (C-c C-c v や C-c C-c e)、参照する CSS の設定
(setq markdown-css-path "file://localhost/Users/morikawa/.emacs.d/local-lisp/markdown2html_mac.css")

Markdown 編集用・その二 (見出し検索用自作関数)

Markdown ネタをもう一つ。Markdown の見出しを Occur で引っ張ってくる自作関数 markdown-header-list を作って、テキスト内移動に使ってます。

一応、以下の Markdown の見出し記法 には一通り対応してます (まあヒットのさせ方が簡単ですからね…)。

# 見出し1
## 見出し2
### 見出し3
#### 見出し4
##### 見出し5
###### 見出し6

見出し1
=============

見出し2
-------------

私自身は Ctrl-c Ctrl-s のショートカットを設定してます。文章が長くなってきた時や、「全体構成どうなってたっけ?」という時に使ってます。(require を強引に呼んでて、もう少しスマートな書き方あるような気がする…。動くのでとりあえず良しとしてますが…)。

余談ですが、最近 rubikitch さんが all-ext.el をリリースされましたね (all-ext.el:対象行を絞り込んでからまとめて編集するM-x allを超強化!occurと融合&anything・helmと連携)。下記関数の用途は編集よりも移動なので Occur で OK なのですが、絞り込んだ結果の画面で直接編集できちゃうってのは凄いですね。そのうち活用したいなと。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; [編集支援] Markdown 書式の見出し検索
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun markdown-header-list ()
  "Show Markdown Formed Header list through temporary buffer."
  (interactive)
  (occur "^\\(#+\\|.*\n===+\\|.*\n\---+\\)")
  (other-window 1))
(require 'markdown-mode)
(define-key markdown-mode-map "\C-c\C-s" 'markdown-header-list)

ちなみに実際に使うとこんな感じ↓

anything, recentf-ext (+ kill-ring) 設定

とにかく一度使い慣れちゃうと離れられない anything, recentf-ext (あとついでに kill-ring) の設定です (rubiktch さんに感謝感謝)。おそらくこういうのも一つの「革新的」というものなんでしょうね。上手く一言で「こう素晴らしいんだよ」とは説明しづらいんですがとにかく「使ってみなヨ!」という機能ですね。

例のごとく list-packages から anything で始まるパッケージと, recentf-ext をさくっとインストールしてます。

とにかく anything にはすぐに起動して欲しいので "Ctrl-x X" 系のショートカットじゃなくて、Ctrl-o を割り当てちゃってます (多分何がしかのプリセットされてる関数があるんでしょうが上書き)。ファイルを開きたい、バッファを切り替えたいとかの際はとにかく Ctrl-o 押せば良い になってます。

使い始めてしばらくは (global-set-key (kbd "C-o") 'anything) としてたのですが、どうも recentf で保存されてるファイルの新しいものしか呼び出せないようで、最近呼び出す関数を anything-for-files にしたら(たぶん)古いものも呼び出せるようになりました。

あと、anything についてくる anything-show-kill-ring を M-y に設定しており、過去 kill-ring に保存した情報を引っ張り出せます (昔から色々実装がありましたが、今回こちらに乗り換えました)。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; [PKG機能利用] anything, recentf-ext, kill-ring
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; C-o で anything-for-files 起動
(global-set-key (kbd "C-o") 'anything-for-files)
;; recentf による保存数を 10000 に
(setq recentf-max-saved-items 10000)
;; 「バッファを替えた時ファイルを開いたとみなす」「Directoryも履歴に保存」する拡張
(require 'recentf-ext)
;; 遅延を短く
(setq anything-idle-delay 0.1)
(setq anything-input-idle-delay 0.1)
;; kill-ring の最大値。デフォルトは 30
(setq kill-ring-max 100)
;; M-y で kill-ring を表示
(global-set-key "\M-y" 'anything-show-kill-ring)

関連のドキュメントはネット上のあちこちにありますので詳しくはそちらをどうぞ。以下は今回私が参照したサイトです。

ちなみに今は anything を fork した helm というものもあるそうですが、ぱっとググった範囲ではわざわざ移行しなくてもな~、という感じなのでそのまま anything を使ってるのが現状です。とはいえ、後方互換で作ってもらってるのはありがたいですね。

popwin 設定

最近 近頃の開発環境 : Mosh、z、tmux、Emacs、Perl について - naoyaのはてなダイアリー から popwin.el を知って、以下のサイトを見ながら設定追加しました。

こちらも list-packages からインストールしてます。上記サイトでも紹介されてますが、ヘルプバッファ(*Help*)とか補完バッファ(*Completions*)とかデバッグバッファ(*Backtrace*)とか出たら出っぱなしでイライラしながらウィンドウを移動したり閉じたり、といったストレスが解消される、という地味で説明しづらいですが確かに快適になる機能です。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; [PKG機能利用] popwin
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'popwin)
(setq display-buffer-function 'popwin:display-buffer)
(setq popwin:popup-window-height 0.5)
(defvar popwin:special-display-config-backup popwin:special-display-config)
(setq popwin:special-display-config
      (append '(("*Remember*" :stick t)("*Org Agenda*")("*Backtrace*")
                ("*sdic*" :noselect))
              popwin:special-display-config))
(define-key global-map (kbd "C-x p") 'popwin:display-last-buffer)

screen: ミニバッファの保存や各ファイルに開いた際の行数のマークとかとか

anything でだいぶ楽にはなりましたが、screen もまた便利で昔から使ってます (端末多重接続ソフトウェアの GNU screen とは全然別物です。これはこれで個人的には使ってますが)。これも list-packages からインストールしてます。

基本明示的に呼び出して使うというものではなく、以前に Emacs 内でミニバッファに入力した内容や各ファイルの最終変更時の行数の記憶といったことをしてくれる機能で地味にかなり便利です。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; [PKG機能利用] session 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'session)
(add-hook 'after-init-hook 'session-initialize)
(setq session-save-print-spec '(t nil nil))

なお、最後の一行は以下サイトで紹介されていたもので、anything-show-kill-ring と screen を同時使用する際に必要な設定です。

Google Chrome のテキストエリアを外部エディタで編集

ブラウザ上でそれなりの量の文章をテキストエリアに直入力するのはちょっと嫌なので (手が滑って画面をリロードして全部消えちゃうとか…)、たいていは Emacs などのエディタ上でひと通り編集を行なってから貼り付けてます。

とはいえ、わざわざ Emacs にコピペするほどじゃないなと思ったんだけど、「あ、ここちょっと矩形切取したいな… or さくっと置換したいな」なんて事があったりもします。

そんなタイミングでサクッとEmacs とブラウザのテキストエリア上のテキストの同期をとれるようにしてくれるのが

になります。

以下の設定は Google Chrome のテキストエリアを外部エディタで編集する Edit with Emacs - 酒日記 はてな支店 をベースにしつつ、edit-server は list-packages でインストール、キーバインドは個人的に直感的なものに置き換えてます。

ブラウザ上のテキストエリア内編集時にもやもやしてる方は導入して損のない機能かなと。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; [PKG機能利用] Chrome のテキストエリア編集の為のエディットサーバ起動
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'edit-server)
(edit-server-start)
;; Chrome から呼び出した際のフレームサイズを edit-server.el デフォルトのものより
;; init.el で設定しているものを優先(デフォルトは幅 80, 高さ 25)
(setq edit-server-new-frame-alist nil)
;; 特定の URL から呼び出された場合のモード設定
(setq edit-server-url-major-mode-alist '(("mail\\.google\\.com" . mail-mode)))
;; Edit Server Mode のキー設定変更
;; - デフォルト
;;    - Ctrl-x # or Ctrl-c Ctrl-c: ブラウザのテキストエリアに編集内容貼付 (Emacs のウィンドウ閉)
;;    - Ctrl-x Ctrl-s:             ↑ 後に再度 Emacs を開く (一時保存)
;;    - Ctrl-x Ctrl-c:             編集を破棄
;;
;; - カスタム (普段の自分設定の Emacs に近い操作で)
;;    - Ctrl-x Ctrl-s:             ブラウザのテキストエリアに編集内容貼付 (Emacs のウィンドウ閉)
;;    - Ctrl-q:                    ↑ 後に再度 Emacs を開く (一時保存)
;;    - Ctrl-x k, Ctrl-x Ctrl-k:   編集を破棄
;; 
(define-key edit-server-edit-mode-map "\C-q"     'edit-server-save)
(define-key edit-server-edit-mode-map "\C-x\C-s" 'edit-server-done)
(define-key edit-server-edit-mode-map "\C-xk"    'edit-server-abort)
(define-key edit-server-edit-mode-map "\C-x\C-k" 'edit-server-abort)

Mac 用の特殊キーバインド (¥\ を入力)

ちょいちょい正規表現置換 query-replace-regexp を使うのですが、後方参照させたいのに何度 ¥( .. ¥) で括っても ¥1 に代入されない…。おかしいなぁ、と思っていたら、Mac だと ¥\ は違ったのねというオチ。

上記サイトで紹介されていた以下の設定で万事解決。\( .. \) で括ったものが \1 .. に代入されるようになりました。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; [基本] Mac 特殊キーバインド
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-key global-map [?¥] [?\\])

トラックパッドのスワイプで快適にスクロール

デフォルトだと、トラックパッドの上下のスワイプは過度にスクロールされてしまうので全然使えない感じだったのですが、

から設定を丸コピさせてもらって大変快適になりました。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; [基本] トラックパッド用のスクロール設定
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun scroll-down-with-lines ()
  "" (interactive) (scroll-down 3))
(defun scroll-up-with-lines ()
  "" (interactive) (scroll-up 3))
(global-set-key [wheel-up] 'scroll-down-with-lines)
(global-set-key [wheel-down] 'scroll-up-with-lines)
(global-set-key [double-wheel-up] 'scroll-down-with-lines)
(global-set-key [double-wheel-down] 'scroll-up-with-lines)
(global-set-key [triple-wheel-up] 'scroll-down-with-lines)
(global-set-key [triple-wheel-down] 'scroll-up-with-lines)

Dired: ディレクトリエディタ

ちょっとしたファイル操作は Emacs いじってる時はそのまま Emacs 上でやった方が楽だったりするので、古くからある Dired ですが今も使わせてもらってます。

しばらくはデフォルト設定で使ってたので、最近以下の記事を見つけて (記事自体は 5 年以上前のものですが)、設定追加しました。

より快適でいい感じです。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; [基本] Dired モードの設定
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(add-hook 'dired-load-hook
          '(lambda ()
             ;; ディレクトリを再帰的にコピー可能にする
             (setq dired-recursive-copies 'always)
             ;; lsのオプション 「l」(小文字のエル)は必須
             (setq dired-listing-switches "-FlhtA")
             ;; find-dired/find-grep-diredで、条件に合ったファイルをリストする形式
             (setq find-ls-option '("-print0 | xargs -0 ls -Flhatd"))
             ;; 無効コマンドdired-find-alternate-fileを有効にする
             (put 'dired-find-alternate-file 'disabled nil)))
;; ファイル・ディレクトリ名のリストを編集することで、まとめてリネーム可能にする
(require 'wdired)
;; wdiredモードに入るキー(下の例では「r」)
(define-key dired-mode-map "r" 'wdired-change-to-wdired-mode)
;; 新規バッファを作らずにディレクトリを開く(デフォルトは「a」)
(define-key dired-mode-map (kbd "RET") 'dired-find-alternate-file)
;; 「a」を押したときに新規バッファを作って開くようにする
(define-key dired-mode-map "a" 'dired-advertised-find-file)

外部 IME 使用中でも快適に使えるキーバインド

最近日本語入力には Google 日本語入力使ってますが、外部 IME だと Ctrl-x k みたいなキー入力は日本語入力オフになってないと最後のアルファベット入力ダメなんですよね (挙動としては当たり前ですが)。もう一度入力し直しだったり、先に日本語入力オフになってることを確認する事を心がけたりと結構面倒なので、よく使うやつには Ctrl-x Ctrl-k みたいなキーバインド追加したりしてます。

まっとうな解決策は以下で紹介されてるような IME パッチを適用することなんですけどね…。

ただ、Windows でも Emacs 使ってたり、リモートの Linux で SSH 端末経由で Emacs 立ち上げたりすることもあるので、そこら辺も含めて対応するのが面倒で、ついこういったアドホックな対応とっちゃってます。

「全然元のキーバインドと違うぢゃん」ってものもありますが、まあ結果結構ストレスは減ったのでよかったのかなと。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; [基本] グローバルキーマッピング (外部IMEの日本語オン/オフを切替えず使いたい関数用)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; kill buffer を Ctrl-x Ctrl-k で可能に (デフォルトは Ctrl-x k)
(global-set-key (kbd "C-x C-k") 'kill-buffer)

;; 別ウィンドウへの切り替えを Ctrl-x Ctrl-o で可能に (デフォルトは Ctrl-x o)
(global-set-key (kbd "C-x C-o") 'other-window)

;; 単一ウィンドウに戻すのを Ctrl-x Ctrl-1 で可能に (デフォルトは Ctrl-x 1)
(global-set-key (kbd "C-x C-1") 'delete-other-windows)

;; 縦ウィンドウ分割を Ctrl-x Ctrl-2 で可能に (デフォルトは Ctrl-x 2)
(global-set-key (kbd "C-x C-2") 'split-window-below)

;; 縦ウィンドウ分割を Ctrl-x Ctrl-3 で可能に (デフォルトは Ctrl-x 3)
(global-set-key (kbd "C-x C-3") 'split-window-right)

;; フレームの作成・削除を Ctrl-;, Ctrl-: で可能に (デフォルトは C-x 5 2, C-x 5 0)
(global-set-key (kbd "C-;") 'make-frame-command)
(global-set-key (kbd "C-:") 'delete-frame)

;; Ctrl-x Ctrl-d (デフォルトは Ctrl-x d) でも dired を起動する
(global-set-key (kbd "C-x C-d") 'dired)

まとめ

以上、書き並べてみたら結構な量になってしまいましたが、これら設定のお陰で Emacs Life はさらに快適になりましたね。

また良いなと思う機能など見つけましたらそのうち紹介します。

0 件のコメント:

コメントを投稿