Next: , Previous: Major Mode Conventions, Up: Major Modes


22.1.2 メジャーモードの例

基本(fundamental)モードを除くと、 テキスト(text)モードはもっとも単純なモードです。 上に述べた慣習の例示として、text-mode.elの抜粋をあげておきます。

     
     ;; モード固有の構文テーブルを作る
     (defvar text-mode-syntax-table nil
       "Syntax table used while in text mode.")
     
     (if text-mode-syntax-table
     
         ()              ; 構文テーブルが既存ならば変更しない
       (setq text-mode-syntax-table (make-syntax-table))
       (modify-syntax-entry ?\" ".   " text-mode-syntax-table)
       (modify-syntax-entry ?\\ ".   " text-mode-syntax-table)
       (modify-syntax-entry ?' "w   " text-mode-syntax-table))
     
     (defvar text-mode-abbrev-table nil
       "Abbrev table used while in text mode.")
     (define-abbrev-table 'text-mode-abbrev-table ())
     
     
     (defvar text-mode-map nil)   ; モード固有のキーマップを作る
     
     (if text-mode-map
     
         ()              ; キーマップが既存ならば変更しない
       (setq text-mode-map (make-sparse-keymap))
       (define-key text-mode-map "\t" 'indent-relative)
       (define-key text-mode-map "\es" 'center-line)
       (define-key text-mode-map "\eS" 'center-paragraph))

つぎは、テキスト(text)モードのメジャーモード関数の完全な定義です。

     (defun text-mode ()
       "Major mode for editing text intended for humans to read...
      Special commands: \\{text-mode-map}
     Turning on text-mode runs the hook `text-mode-hook'."
       (interactive)
       (kill-all-local-variables)
       (use-local-map text-mode-map)
       (setq local-abbrev-table text-mode-abbrev-table)
       (set-syntax-table text-mode-syntax-table)
       (make-local-variable 'paragraph-start)
       (setq paragraph-start (concat "[ \t]*$\\|" page-delimiter))
       (make-local-variable 'paragraph-separate)
       (setq paragraph-separate paragraph-start)
       (setq mode-name "Text")
       (setq major-mode 'text-mode)
     
     
       (run-hooks 'text-mode-hook))      ; 最後に、フックによるモードの
                                         ;   カスタマイズをユーザーに許す

3つのlispモード(lispモード、emacs-lispモード、lisp対話モード)には、 テキスト(text)モードより多くの機能があり、 それに応じてコードもより複雑です。 これらのモードの書き方を例示する lisp-mode.elからの抜粋をあげておきます。

     
     ;; モード固有の構文テーブルを作成する
     (defvar lisp-mode-syntax-table nil "")
     (defvar emacs-lisp-mode-syntax-table nil "")
     (defvar lisp-mode-abbrev-table nil "")
     
     
     
     (if (not emacs-lisp-mode-syntax-table) ; 構文テーブルが既存ならば
                                            ;   変更しない
         (let ((i 0))
           (setq emacs-lisp-mode-syntax-table (make-syntax-table))
     
     
     
     
           ;; 0までの文字に、単語構成文字ではないが
           ;; シンボル名構成文字であるクラスを設定する
           ;; (文字0は、ASCII文字集合では48)
           (while (< i ?0)
             (modify-syntax-entry i "_   " emacs-lisp-mode-syntax-table)
             (setq i (1+ i)))
           ...
     
           ;; 他の文字の構文を設定する
           (modify-syntax-entry ?  "    " emacs-lisp-mode-syntax-table)
           (modify-syntax-entry ?\t "    " emacs-lisp-mode-syntax-table)
           ...
           (modify-syntax-entry ?\( "()  " emacs-lisp-mode-syntax-table)
           (modify-syntax-entry ?\) ")(  " emacs-lisp-mode-syntax-table)
           ...))
     
     ;; lispモード向けの略語表を作る
     (define-abbrev-table 'lisp-mode-abbrev-table ())

3つのlispモードは多くのコードを共有しています。 つぎの関数はさまざまな変数に設定します。 lispモードの各メジャーモード関数が呼び出します。

     (defun lisp-mode-variables (lisp-syntax)
       (cond (lisp-syntax
     	  (set-syntax-table lisp-mode-syntax-table)))
       (setq local-abbrev-table lisp-mode-abbrev-table)
       ...

forward-paragraphなどの関数は、 変数paragraph-startの値を使います。 Lispのコードは普通のテキストとは異なるので、 Lispを扱えるように変数paragraph-startを特別に設定する必要があります。 また、Lispではコメントの字下げは特殊な形なので、 各lispモードには独自のモード固有のcomment-indent-functionが必要です。 これらの変数に設定するコードが、 lisp-mode-variablesの残りの部分です。

       (make-local-variable 'paragraph-start)
       (setq paragraph-start (concat page-delimiter "\\|$" ))
       (make-local-variable 'paragraph-separate)
       (setq paragraph-separate paragraph-start)
       ...
       (make-local-variable 'comment-indent-function)
       (setq comment-indent-function 'lisp-comment-indent))

各lispモードでは、キーマップが多少異なります。 たとえば、lispモードではC-c C-zrun-lispにバインドしますが、 他のlispモードではそうしません。 つぎのコードは、共通するコマンドを設定します。

     (defvar shared-lisp-mode-map ()
       "Keymap for commands shared by all sorts of Lisp modes.")
     
     (if shared-lisp-mode-map
         ()
        (setq shared-lisp-mode-map (make-sparse-keymap))
        (define-key shared-lisp-mode-map "\e\C-q" 'indent-sexp)
        (define-key shared-lisp-mode-map "\177"
                    'backward-delete-char-untabify))

つぎはlispモード向けのキーマップを設定するコードです。

     (defvar lisp-mode-map ()
       "Keymap for ordinary Lisp mode...")
     
     (if lisp-mode-map
         ()
       (setq lisp-mode-map (make-sparse-keymap))
       (set-keymap-parent lisp-mode-map shared-lisp-mode-map)
       (define-key lisp-mode-map "\e\C-x" 'lisp-eval-defun)
       (define-key lisp-mode-map "\C-c\C-z" 'run-lisp))

最後に、emacs-lispモードのメジャーモード関数の完全な定義を示します。

     (defun lisp-mode ()
       "Major mode for editing Lisp code for Lisps other than GNU Emacs Lisp.
     Commands:
     Delete converts tabs to spaces as it moves back.
     Blank lines separate paragraphs.  Semicolons start comments.
     \\{lisp-mode-map}
     Note that `run-lisp' may be used either to start an inferior Lisp job
     or to switch back to an existing one.
     
     Entry to this mode calls the value of `lisp-mode-hook'
     if that value is non-nil."
       (interactive)
       (kill-all-local-variables)
     
     
     
     
     
       (use-local-map lisp-mode-map)          ; モードのキーマップを選択する
       (setq major-mode 'lisp-mode)           ; これによりdescribe-mode
                                              ; 説明文を探し出せる
       (setq mode-name "Lisp")                ; モード行に表示される
       (lisp-mode-variables t)                ; さまざまな変数を定義する
       (setq imenu-case-fold-search t)
       (set-syntax-table lisp-mode-syntax-table)
     
     
       (run-hooks 'lisp-mode-hook))           ; フックによるモードの
                                              ; カスタマイズをユーザーに許す