[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

12. モードとキーバインドの基礎と Elisp (2004/02/03)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=about%20mode"
"MeadowMemo/モードとキーバインドの基礎とElisp"へのコメント(無し)
検索全文Elisp


この章で紹介していること

この章では,モードの基礎知識と関連した Elisp を紹介します.モードについてよく分 からない方は,関連する Elisp は読み飛ばしてください.



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

12.1 モードとは何? (2004/01/24)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=mode"
"MeadowMemo/モードとは何?"へのコメント(無し)
検索全文Elisp

モードとは何なのか

Meadow ではファイルを開くと, 必ず何らかの「モード」になります.

「モード」とは「あるファイルを編集するのに適した環境」のことです.

例えば,「 emacs-lisp-mode 」というモードがあります.これは文字通り, Emacs Lisp を書くためのモードです.これにより,キーワードに色が付き,キーバインドも変わり, 様々な機能が利用できるようになります.

このように,あるファイルを編集するのに適した環境がモードなのです.

今のモードを知る方法

今のファイルが, どういうモードにあるかはモードラインの真中あたりに表示されていま す.例えば, HTML ファイルを開くと,私の設定では

(yahtml Encoded-kbd Fill)

と表示されます.この () の中がモード名を表しています.この例だと 3 つのモードがあ ります.

3 つの内で,一番最初のものがメジャーモード,それ以降のものがマイナーモードと呼ば れます.この例だと, yahtml というメジャーモード, Encoded-kbd と Fill というマイ ナーモードになっていることが分かります.

マイナーモードであっても,ここに文字を表示しないことがあります.そのため,実際に は 3 つ以上のモードを使っているかもしれません.

メジャーモードとマイナーモード

メジャーモードとはそのバッファの基本となるモードであり,主なキーバインドなどを設 定しています.このメジャーモードがないということは絶対にありません.また,基本的 には複数のメジャーモードを使うことはできません.

一方,マイナーモードはメジャーモードに付け加えるオプション機能です.したがって, マイナーモードはオン/オフの切り替えが可能です.そのため,一個もない場合もありま すし,複数あることもあります.

モードの詳細を知る

今使っているモードはモードラインでも分かりますが,M-x describe-mode と入力 することで,より詳しく見ることができます.

M-x describe-mode を実行すると,メジャーモード,マイナーモード,それぞれに キーバインドが割り当てられていることに気付くと思います.当然,メジャーモード,マ イナーモードのキーバインドが重なってしまうこともありますが,あくまで基本はメジャー モードです.そのため,同一のキーバインドであれば,メジャーモードの方のみが有効に なります.

さらに,キーバインドにはグローバル・マップというものもあります.これはモードを問 わずに設定できるキーバインドです.例えば,C-a などの Meadow の基本的なキー バインドなどはすべてグローバル・マップで定義されています.これら 3 つのキーバイ ンドの優先順位は,

メジャーモード > グローバル・マップ > マイナーモード

です.

12.1.1 ファイル名とモードの関連付け (2004/01/21)  



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

12.1.1 ファイル名とモードの関連付け (2004/01/21)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=connect%20mode"
"MeadowMemo/ファイル名とモードの関連付け"へのコメント(無し)
検索全文Elisp

ファイルを開くと必ず何らかのメジャーモードになります.メジャーモードとファイル名 の関連は「 auto-mode-alist 」という変数で定義されています.これを,変更すると, 指定した拡張子や名前を持つファイルに任意のメジャーモードを設定することができます.

実際の設定サンプルです.

 
(setq auto-mode-alist (append (list
                               '(".gnus" . emacs-lisp-mode)
                               '(".abbrev_defs" . emacs-lisp-mode)
                               '("\\.el$" . emacs-lisp-mode)
                               '("\\.txt$" . text-mode)
                              auto-mode-alist)))

実に単純ですね.ファイル名そのままか正規表現を書いておけばいいだけです.よく分か らなければ, text-mode の行を参考にすれば,任意の拡張子とモードの関連付けができ ると思います.

また, ruby のスクリプトのように先頭行でインタープリタを指定しているようなものは, 以下のようにも設定できます.ただし,上記設定があればそちらが優先されます.

 
(setq interpreter-mode-alist
      (append '(("ruby" . ruby-mode))
                 interpreter-mode-alist))



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

12.2 フックの意味と探し方 (2004/01/24)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=search%20hook"
"MeadowMemo/フックの意味と探し方"へのコメント(無し)
検索全文Elisp

フックの働き

まずは. c-mode の関数を見てみましょう

 
(defun c-mode ()
  (interactive)
  (c-initialize-cc-mode)
  (kill-all-local-variables)
  (set-syntax-table c-mode-syntax-table)
  (setq major-mode 'c-mode
        mode-name "C"
        local-abbrev-table c-mode-abbrev-table)
  (use-local-map c-mode-map)
  (c-common-init)
  (setq comment-start "/* "
        comment-end   " */"
        c-conditional-key c-C-conditional-key
        c-class-key c-C-class-key
        c-baseclass-key nil
        c-comment-start-regexp c-C++-comment-start-regexp
        imenu-generic-expression cc-imenu-c-generic-expression
        imenu-case-fold-search nil
        )
  (run-hooks 'c-mode-common-hook) ←ここでフックが実行される
  (run-hooks 'c-mode-hook) ←ここでフックが実行される
  (c-update-modeline))

プログラムは基本的には上から順番に実行されます.だから,この c-mode という関数が 実行されると, 上から順に実行されていきます. 細かい内容はどうでもいいですが, 最後 の方に (run-hooks 'c-mode-common-hook) という行があるのに注目してください.

ここで, フックが実行されます. このフックには,設定や関数など実行して欲しい命令を 入れておくことができます.

そうすると, c-mode が上から実行されてきて,ここで自分の設定が評価できるわけです.

例えば,

 
(add-hook 'c-mode-common-hook
          (lambda ()
            (setq imenu-case-fold-search t)))

のように,「 c-mode-common-hook 」に「 (setq imenu-case-fold-search t) 」を追加する と,「 imenu-case-fold-search 」が「 t 」になります.

一方,普通に

 
(setq imenu-case-fold-search t)

としてしまうと,「 c-mode 」では「 imenu-case-fold-search 」を「 nil 」に設定している ので, c-mode になった時に「 imenu-case-fold-search 」が「 nil 」になってしまいます.

このため,フックは各メジャーモード毎に設定を変えたい時や,モードにより設定が変更 されてしまうものを再設定する時に利用されます.

フックの探し方

では, どうしたらフックがあることがわかるのか. それは, readme などのドキュメント になければ, ソースを読むのです. そのためには, まず関数のあるファイルを探す必要が あります (11.4.1 ヘルプ機能 ― help-for-help (2005/02/28)を参照). あとは読んで探しましょう (^_^;) 大体,-hook という名前で終わっているので,検索すれば簡単に見つかります.



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

12.3 モード毎に設定する方法 (2004/02/03)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=setup%20mode"
"MeadowMemo/モード毎に設定する方法"へのコメント(無し)
検索全文Elisp

12.2 フックの意味と探し方 (2004/01/24) で自分が設定したいモードのフックは見つけられます ね.モードごとの設定は,そのフックを用いて行います.

ここでは,簡単な例としてタブ幅の設定を例にあげます.タブ幅の設定は

 
;;タブ幅を 4 に設定
(setq-default tab-width 4)

と書きます. C モードのみで有効にするには

 
;;C モード でのみタブ幅を 4 にしたい
(add-hook 'c-mode-hook
          (lambda ()
          ;; ここに設定を追加していく
            (setq tab-width 4)
            ))

と書きます.

add-hook は c-mode-hook に設定を追加します.

この hook の使い方は設定をする時に多用しますので, ぜひ覚えておきましょう.



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

12.4 キーバインドについて (2004/02/03)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=special%20keybind"
"MeadowMemo/キーバインドについて"へのコメント(無し)
検索全文Elisp

キーバインドの設定方法や特殊なキーについて説明します.

まず, Emacs では慣習として C-c + 英数字キー はユーザが自由に使うことので きるキーバインドとなってます.だから,C-c a といったキーバインドはユーザが 任意に設定できます.と言いたいんですが,実際にはそんな慣習を守っていないものも多 く,結構使われてしまっている場合もあります.

他によく使われるキーとしては C-x があります.これは,C-x C-f など Emacs の標準のキーに多く使われています.

C-mC-[ なども特殊で,以下のような割り当てになっています.

12.4.1 文字の入力 ― タブ,制御記号の入力方法 (2003/06/08)  
12.4.2 キーバインドの設定方法 ― モード別/グローバル (2004/02/03)  



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

12.4.1 文字の入力 ― タブ,制御記号の入力方法 (2003/06/08)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=control%20char"
"MeadowMemo/文字の入力―タブ,制御記号の入力方法"へのコメント(無し)
検索全文Elisp

最初に紹介したように, Emacs では各ファイル形式に適したモードに自動的になります. C を書く時には C-mode になりますし, emacs-lisp なら emacs-lisp-mode になります.

ところが,これらのプログラムを書くモードでは TAB はインデントに割り当てら れており,TABキーでタブ自身を入力することはできません,

では,どうやってタブを入力するかというと,C-q TAB あるいは C-q C-i とする必要があります.

こんな風に C-q に続けて入力するとそのキー入力をそのまま出力されます.

このため,改ページ記号として使われる ^L (Ctrl + l) は C-q C-lとして入力で きますし,他の制御文字も同じように入力できます.



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

12.4.2 キーバインドの設定方法 ― モード別/グローバル (2004/02/03)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=change%20keybind"
"MeadowMemo/キーバインドの設定方法―モード別/グローバル"へのコメント(無し)
検索全文Elisp

モード毎のキーバインドの設定方法

まずは,メジャーモードとマイナーモードにキーバインドを割り当てる方法です.メジャー モードとマイナーモードでの,キーバインドの割り当て方は同じ方法でできます.

それでは,もう一度, 12.2 フックの意味と探し方 (2004/01/24)の関数をよく見てください.

 
  (use-local-map c-mode-map)

という行がありますね. この c-mode-map が, c-mode のキーバインドを格納しておく変 数なのです. これとフックを使うと, 各モードごとのキーバイドを設定できます.

例えば C-c > に indent-region を割り当てるには

 
(add-hook 'c-mode-hook
          '(lambda ()
             (define-key c-mode-map "\C-c>" 'indent-region)))

とします.あるいは c-mode-map を書かずに

 
(add-hook 'c-mode-hook
          '(lambda ()
            (local-set-key "\C-c>" 'indent-region)))

としてもできます.マイナーモードでも方法は同じで,「 c-mode-hook 」と 「 c-mode-map 」が変わるだけです.

グローバルマップでのキーバインド設定方法

グローバル・マップに割り当てるには

 
(global-set-key "\M-g" 'goto-line)

とします.グローバル・マップではフックが不要なので簡単ですね.

逆に解除は

 
(global-unset-key "\M-g")

とします.

.emacs に書かずに M-x global-set-keyM-x global-unset-key として も設定できます.ただし,これだと次回起動時には消えてしまいますので,テストに用い るといいでしょう.

特殊なキーの設定サンプル

以下は特殊なキーの設定サンプルです.ここにある left などの文字は M-x help-for-help k に続けて,キーを入力すると確認できます.

 
(global-set-key [f1] 'help-for-help)
;;RET に newline-and-indent を割り当てる
(global-set-key "\C-m" 'newline-and-indent)
;;右カーソルキーに forward-char を割り当てる
(global-set-key '[right] 'forward-char)
;;左カーソルキーに backward-char を割り当てる
(global-set-key '[left] 'backward-char)
;; Insert キー
(define-key global-map [insert] 'overwrite-mode)
;; 無変換キー
(define-key global-map [noconvert] 'overwrite-mode)
;; 変換キー,全角/半角キー
(define-key global-map [kanji] 'overwrite-mode)
;; Home キー
(define-key global-map [home] 'overwrite-mode)
;; End キー
(define-key global-map [end] 'overwrite-mode)
;; PgUp キー
(define-key global-map [prior] 'overwrite-mode)
;; PgDn キー
(define-key global-map [next] 'overwrite-mode)



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

12.5 ファイル毎に設定する方法 (2003/04/12)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=config%20perfile"
"MeadowMemo/ファイル毎に設定する方法"へのコメント(無し)
検索全文Elisp

モードごとではなく, ファイルごとに設定したい場合はそのファイルに設定を書きこむこ ともできます. 例えば html ファイルなら以下のように書いておきます.

 
<!-- Local Variables: -->
<!-- buffer-file-coding-system: euc-jp -->
<!-- End: -->

これで, このファイルは euc-jp として扱われます.

ただし,ファイルの末尾に書くようにしてください.そうしないと,ないものと見なされ る可能性があります.



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

12.6 フックがない時の設定方法 − defadvice (2004/01/21)

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=defadvice"
"MeadowMemo/フックがない時の設定方法−defadvice"へのコメント(無し)
検索全文Elisp

プログラムによってはフックが用意されていないこともよくあります.こんな時には,ソー スを修正してフックを追加してしまうという方法もありますが,もっといい方法がありま す.それはアドバイスの利用です.

アドバイスとは文字通り,ある関数を実行する時にアドバイスを与えることができます.

例えば,下カーソルでの移動時に,カーソルを常に行末へ持っていきたいとします.この 下カーソルでの移動は M-x help-for-help k 下カーソル で確認すると, next-line という関数で実行されていることが分かります.同じように,カーソルを行末 へ移動する関数は end-of-line (C-e) だと分かります.

だから, next-line という関数が終わった後で, end-of-line を実行すれば,やりたい ことができそうです.しかし, next-line にはフックがありません.そこで,アドバイ スを使って設定します.

その方法は

 
(defadvice next-line
  (after go-end-line activate)
  (end-of-line))

のようにします.

まず defadvice でアドバイスを作ります.次の next-line は今アドバイスを作成しよう としている関数です.

その後の () の中にある, after は関数 next-line の実行後に処理を行うことを意味し ます.関数の処理を行う前に実行したいなら, before を使います.

go-end-line はアドバイスの名前です.好きなものをつけて構いません.

最後の activate は作成時にアドバイスを有効にすることを意味します.

そして, end-of-line の部分が追加したいコマンドです.ここに,コマンドや設定などを 書いていくことで,任意のタイミングで設定を行うことができます.

また,「 activate 」 がないとアドバイスの定義だけを行い,有効にはなりません.

そのため,その場合には

 
;; next-line に対するアドバイスを有効にする
(ad-activate 'next-line)
;; 指定した正規表現に一致するアドバイスを有効にする
(ad-activate-regexp "go-end-line")

のようにアドバイスを有効にする必要があります.

逆にアドバイスを無効にするのは

 
;; next-line に対するアドバイスを無効にする
(ad-deactivate 'next-line)
;; 指定した正規表現に一致するアドバイスを無効にする
(ad-deactivate-regexp "go-end-line")

です.

これぐらいで大概の場所で任意の関数を実行することができます.

アドバイスに関して,引数などもっと詳しいことは マニュアル をどうぞ.



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端] [?]

12.7 特定キーの入力でコマンド実行

URL="http://www.bookshelf.jp/cgi-bin/goto.cgi?file=meadow&node=key-chord"
"MeadowMemo/特定キーの入力でコマンド実行"へのコメント(無し)
検索全文Elisp
要約

コントロールキーを使わなくても,例えば,hjと入力するだけで undo できます.

情報源

tototoshiの日記 で知りました.

何が問題なのか?

コントロールキーの使いすぎで小指が痛いとか,コマンドの実行にコントロールやメタキー を使うのが面倒,よく入力する単語でもいちいち全部入力するのは面倒なものです.

何ができるのか?

例えば,hj と連続して素早く入力すると,undo を実行できたりします.もちろん, コマンドは自由に選択できます.

設定済みMeadowでは

インストールしていません.

インストール方法

http://www.emacswiki.org/emacs/key-chord.el からダウンロードしてロードパ スの通ったところに置きます.

設定方法

まず,以下を .emacs に追加します

 
(require 'key-chord)
(key-chord-mode 1)

ただ,これだけでは何の意味もありません.この後に,どういうキーでどういうコマンド を実行させるかを指定します.

例えば,key-chord.el にもあるように,上の設定の後に,下記を .emacs に追加します

 
(key-chord-define-global "hj" 'undo)

こうすると,素早く hj と入力すると, undo を実行できます.hj を変えれば, 他の文字でも可能です.

ただし,2文字が必要ですし,よく出てくるような組み合わせ(子音+母音など)だと,普段 の文字入力でも使いますので,どういう文字を使うかは注意が必要です.

また,下記のようにすることで,コマンド実行だけでなく,文字入力をさせることもでき ますし,あるモードだけで設定することもできます.

 
(key-chord-define-global "qq" "the ")
(key-chord-define c++-mode-map ";;" "\C-e;")

コメント

うまくキーを決めることができると面白いですね.


[ << ] [ >> ]           [表紙] [目次] [索引] [検索] [上端 / 下端] [?]