読者です 読者をやめる 読者になる 読者になる

意識の高いLISPマシン

藤原惟/すかいゆき(@sky_y)の技術用ブログ

Emacsのkey-combo.el: haskell-mode用設定のメモ

Emacs Haskell

id:uk-ar さんのkey-combo.elを設定しました。

key-comboを使って読みやすいコードを書く (Emacs Advent Calendar 8日目) - むしゃくしゃしてやった

その際、haskell-mode用のローカルkey-combo設定がうまくできなかったのですが、
解決したので、その顛末をメモ書きしておきます。

前提

私はinit-loader.elで設定ファイルを分割しています。
設定ファイルは以下の順番で読み込まれます。

  • init.el
    • load-pathの設定
    • init-loaderのロード
    • 変数の設定: custom-set-variables

haskell-modeのインデント設定とadd-hook

haskell-modeではインデントの種類を3種類から選べます。
そのためにhaskell-mode-hookに追加する必要がありますが、
私の環境ではなぜかadd-hook関数で以下のように書いても正しく読み込まれませんでした。

;; 36_haskell.el
;; NG: 有効にならない
(add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)

haskell-modeでインデント設定が正しくない場合、
インデントしようとするとヘルプ画面が出て設定の仕方を教えてくれます。
渋々、出てきたヘルプ通りにinit.elで直接custom-set-variablesを使って書くと、
正しくインデント設定が読み込まれました。

;; init.elの最後
(custom-set-variables
;; ...
 '(haskell-mode-hook 'turn-on-haskell-indentation)
;; ...
)

これが、災いの元でした。

add-hookが上書きされてしまう

init.elの最後でcustom-set-variablesでhookを設定してしまうと、
add-hook関数で追加しても設定が上書きされてしまいます。

;; 36_haskell.el
;; NG: init.elで上書きされて動かない
(add-hook 'haskell-mode-hook
	  '(lambda ()
	     (key-combo-define-local (kbd "-") '("-" " -> " "--"))
	     (key-combo-define-local (kbd "<") '("<" " <- " " <= " " =<< " "<<" "<"))
	     (key-combo-define-local (kbd ">") '(">" " >= " " >>= " ">"))
	     (key-combo-define-local (kbd "=") '("=" " = " " == " "=="))
	     (key-combo-define-local (kbd ":") '(":" " :: " "::"))
	     ))

key-comboも正しくadd-hookさせる

そこで、以下のように書き換えます。

;; 36_haskell.el

;; key-comboの設定用関数
(defun my-haskell-key-combo ()
  (key-combo-define-local (kbd "-") '("-" " -> " "--"))
  ;; (key-combo-define-local (kbd "<=") '("<="))
  (key-combo-define-local (kbd "<") '("<" " <- " " <= " " =<< " "<<" "<"))
  (key-combo-define-local (kbd ">") '(">" " >= " " >>= " ">"))
  (key-combo-define-local (kbd "=") '("=" " = " " == " "=="))
  (key-combo-define-local (kbd ":") '(":" " :: " "::"))
  )

;; 後でまとめてadd-hookするための関数
(defun my-haskell-add-hook ()
  (turn-on-haskell-indentation)
  (font-lock-mode)
  (my-haskell-key-combo)
  )
;; init.elの最後
(custom-set-variables
 '(haskell-mode-hook 'my-haskell-add-hook)
  )

これで、無事にkey-comboがうまく動きました。