ichiroc subset

書きながら考える・考えをまとめる場所

Emacs Mode Tutorial 訳 ( Emacs メジャーモード作成チュートリアル)

Mode Tutorial 英語の練習で訳す。 下にGPL2って書いてあったから、ライセンスは問題ないはず。 訳ししだいアップデートしてく形で。

ModeTutorial

An Emacs language mode creation tutorial A mode tutorial by ScottAndrewBorton, originally located http://two-wugs.net/emacs/mode-tutorial.html

ScottAndrewBorton による Emacs 言語メジャーモード作成チュートリアル。

I’ve written several Emacs modes for various obscure or in-house tool languages. When starting my first mode, I found that there weren’t a lot of lucid explanations of how to write a mode intended for language editing. Even Writing GNU Emacs Extensions ISBN 1565922611 (alternate, search) doesn’t cover topics like syntax highlighting and indentation. And generic-mode, distributed with recent versions of Emacs, doesn’t handle indentation.

私はマイナーだったり、社内向けのツールだったりした言語のために、多種多様な Emacs のメジャーモードを書いてきました。 私がメジャーモードを書き始めた時、言語を編集する為のメジャーモードを書く方法の説明は、豊富でない事に気がつきました。

Writing GNU Emacs (GNU Emacs拡張ガイド―Emacs Lispプログラミング)でさえ、シンタックスハイライトとインデントのトピックをカバーしていませんでした。 そして最近のバージョン*1で追加された generic-mode はインデントを扱っていません。

Here, I walk through my wpdl-mode.el, a mode for editing Workflow Process Definition Language files. I simply go through each line of the mode, and explain what it does. It may also be helpful to refer to this WPDL example[1], to see how the concepts are being applied. Hopefully wpdl-mode is clear and simple enough for you to learn the basics of writing your own mode.

ここに wpdl-mode.el の手順を説明します。 ワークフロープロセスを定義する言語ファイルを編集するためのメジャーモードです。 単純にメジャーモードの各行を1行ずつ、何をしているのかを説明します。 WPDL の例に言及することで、考えをコードにどのように適用していくのかの助けになるかも知れません。 wpdl-mode がわかりやすく、あなたが必要なメジャーモードを書く基本を学ぶのに、十分であることを望みます。

The following information was written with GNU Emacs versions 20 or 21 in mind. NB: Since I am not a professional Emacs hacker, some of this might be a case of the blind leading the blind. More experienced Emacs guys may take offense at the style or terminology, and will hopefully correct my ignorance. Thanks to readers on comp.emacs and gnu.emacs.help who have already contributed suggestions! – ScottAndrewBorton

これ以降の情報は GNU Emacs 20 または 21 で書かれることを想定しています。 NB:私はプロフェッショナルなEmacsハッカーではないから、いくつかは分かってない部分があるかもしれません。 もっと経験豊富なEmacsユーザはスタイルや用語の使い方等について、腹をたてるかも知れません。 そして私の間違いを修正してくれることを望みます。

Note that the tutorial builds a new mode from the ground up. If the modes are relatively simple, then starting out with a GenericMode or a DerivedMode makes more sense. Even if you decide to write most of the code yourself, starting out with SampleMode might be a good idea. What the tutorial does and none of the other suggestions is explaining things. This is very important; so if you are curious to learn, then perhaps the tutorial is actually better for you. It even delves into such topics as RegexpOpt. I recommend that.

このチュートリアルは1から新しいメジャーモードを作成します。 もしこのメジャーモードが思ったよりも簡単だったら、GenericMode や DeriveMode もさわってみてください。

もしも、自分自身でコードを書こうと思っていたとしても、サンプルのメジャーモードで始めて見るのは良いアイデアかもしれません。 このチュートリアルは、他の人がどう言うかは知りませんが、説明するべきことを説明します。これはとても重要です。 もしあなたが学ぶこと自体に興味を持っていれば、多分このチュートリアルは貴方にとって有用でしょう。 RegexpOpt のようなトピックにも掘り下げています。これはお薦めの機能です。

Basic mode setup (基本)

(defvar wpdl-mode-hook nil)

First, we define some variables that all modes should define. ‘wpdl-mode-hook’ allows the user to run their own code when your mode is run.

まず、すべてのメジャーモードが定義すべき幾つかの変数を定義します。 'wpdl-mode-hook' はメジャーモードが実行されるときに、ユーザに任意のコードを実行できるようにします。

(defvar wpdl-mode-map
  (let ((map (make-keymap)))
    (define-key map "\C-j" 'newline-and-indent)
    map)
  "Keymap for WPDL major mode")

Now we create a keymap. This map, here called ‘wpdl-mode-map’, allows both you and users to define their own keymaps. The keymap is immediately set to a default keymap. Then, using ‘define-key’, we insert an example keybinding into the keymap, which maps the ‘newline-and-indent’ function to Control-j (which is actually the default binding for this function, but is included anyway as an example). Of course, you may define as many keybindings as you wish.

キーマップを作りました。'wpdl-mode-map' と名付けられたこのキーマップは、 あなたとユーザに好きなキーマップを定義できるようにします。 このキーマップは即座にデフォルトキーマップにセットされます。 そして 'define-key' を使用して、サンプルのキーバインディングをキーマップに入れました。 'newline-and-indent' を Control-j にマップしています。 (これは実際にはデフォルトでバインディングされています。しかし例として含めました。) もちろん、あなたの望むとおりにキーバインドを定義できます。

If your keymap will have very few entries, then you may want to consider ‘make-sparse-keymap’ rather than ‘make-keymap’.

もしもキーマップがとても少なくなるのなら、 'make-sparse-keymap' が使えるか見てみてください。

;;;###autoload
(add-to-list 'auto-mode-alist '("\\.wpd\\'" . wpdl-mode))

Here, we append a definition to ‘auto-mode-alist’. This tells emacs that when a buffer with a name ending with .wpd is opened, then wpdl-mode should be started in that buffer. Some modes leave this step to the user.

ここで 'auto-mode-alist' に定義を追加しました。 Emacs に .wpd で終わるファイル名を開いたら, wpdl-mode を開始するようにしています。 他のメジャーモードの中には、このステップをユーザに任せる事もあります。

Syntax highlighting using keywords (キーワードを使用したシンタックスハイライト)

(defconst wpdl-font-lock-keywords-1 (list
   '("\\<\\(A\\(CTIVITY\\|PPLICATION\\)\\|DATA\\|END_\\(A\\(CTIVITY\\|PPLICATION\\)\\|DATA\\|MODEL\\|PARTICIPANT\\|T\\(OOL_LIST\\|RANSITION\\)\\|WORKFLOW\\)\\|MODEL\\|PARTICIPANT\\|T\\(OOL_LIST\\|RANSITION\\)\\|WORKFLOW\\)\\>" . font-lock-builtin-face)
   '("\\('\\w*'\\)" . font-lock-variable-name-face))
  "Minimal highlighting expressions for WPDL mode")

Now we have defined our minimal set of keywords for emacs to highlight. A ‘font-lock-keyword’ variable is a list of keywords to highlight. There are many ways to specify this list. I have used the form (matcher . facename). With this form, I have specified a pattern to match, and then a face name to use for the actual highlighting.

そして、ハイライトさせたいキーワードのセットを定義しました。 'font-lock-keyword' 変数はハイライトさせるキーワードのリストです。 これには様々な定義方法が有ります。 私は (macher . facename) の形式を使いました。 このフォームでは、指定したパターンにマッチすると、指定したフェイスが使用されます。

There are two elements to my list: the first element matches WPDL language keywords, and the second element matches WPDL identifier names (variable names). I have selected the appropriate font-lock face names for each type of keyword (‘font-lock-builtin-face’ and ‘font-lock-variable-name-face’, respectively).

私が定義したリストには2つの要素があります。 最初の要素は、WPDL のキーワードにマッチします。 二番目のはWPDLのID名(変数名)にマッチします。 それぞれのキーワードに適切な font-lock face を指定しました。 (font-lock-builtin-face’ と‘font-lock-variable-name-face’と respectively です)

For my keyword list, I’ve selected those WPDL keywords which would benefit most from being highlighted: keywords that delimit blocks of information. One may notice that the regexp used to specify these keywords is optimized. I did not have to do this by hand. Emacs provides the ‘regexp-opt’ function to save you from the tedious work of creating complicated regexps. ‘regexp-opt’ takes a list of strings and an additional optional argument. This optional argument controls whether or not we want to wrap the entire regexp in parens. In our case, we do. For example, the following expression:

ハイライトされることで助けになると思われる、WPDLキーワードをこのリストに指定しました。 キーワードは情報のブロックの区切りになります。 これらのキーワードの正規表現が最適化していることに注意してください。 これは手で書いたものではありません。 Emacs は複雑な正規表現を作成するという、ひどい仕事からあなたを救うため regexp-opt 関数を提供しています。 regexp-opt は文字列のリストと、追加のオプション引数を受け取ります。 オプション引数では正規表現全体をカッコでラップするかどうかを制御します。今回のケースでも指定しました。 例に、下の式を見てください。

(regexp-opt '("PARTICIPANT" "END_PARTICIPANT" "MODEL" "END_MODEL"
"WORKFLOW" "END_WORKFLOW" "ACTIVITY" "END_ACTIVITY" "TRANSITION"
"END_TRANSITION" "APPLICATION" "END_APPLICATION" "DATA" "END_DATA"
"TOOL_LIST" "END_TOOL_LIST") t)

Results in this regexp:

結果はこのようになります

"\\(A\\(CTIVITY\\|PPLICATION\\)\\|DATA\\|END_\\(A\\(CTIVITY\\|PPLICATION\\)\\|DATA\\|MODEL\\|PARTICIPANT\\|T\\(OOL_LIST\\|RANSITION\\)\\|WORKFLOW\\)\\|MODEL\\|PARTICIPANT\\|T\\(OOL_LIST\\|RANSITION\\)\\|WORKFLOW\\)"

Because font-lock is so resource-intensive, providing optimized regexps to font-lock should provide a boost in performance.

font-lock はリソースを消費するので、最適化されたfont-lockの正規表現は パフォーマンスを引き上げるでしょう。

Finally, the regexp is wrapped in < and >. These indicate that the regexp should only match keywords if they are surrounded by either a space or a beginning/end-of-file. This ensures that, for example, the keyword if is not highlighted in the word difference.

最後に、正規表現を < と > で囲みます。

これはスペースか、ファイルの最初か最後で囲われている時だけ、キーワードがマッチするようことを意味します。 これは、例えば、キーワード if が単語 difference の中でハイライトされない事を保証します。

(defconst wpdl-font-lock-keywords-2
  (append wpdl-font-lock-keywords-1
          (list
           '("\\<\\(AUTHOR\\|C\\(ONDITION\\|REATED\\)\\|DE\\(FAULT_VALUE\\|SCRIPTION\\)\\|EXTENDED_ATTRIBUTE\\|FROM\\|I\\(MPLEMENTATION\\|N_PARAMETERS\\)\\|JOIN\\|NAME\\|O\\(THERWISE\\|UT_PARAMETERS\\)\\|PERFORMER\\|ROUTE\\|S\\(PLIT\\|TATUS\\)\\|T\\(O\\(OLNAME\\)?\\|YPE\\)\\|VENDOR\\|WPDL_VERSION\\)\\>" . font-lock-keyword-face)
           '("\\<\\(TRUE\\|FALSE\\)\\>" . font-lock-constant-face)))
  "Additional Keywords to highlight in WPDL mode")

Now I’ve defined the second level of highlighting. Note that the second level is appended to the first level, resulting in a single keyword variable that matches everything in both levels. Here I’ve specified even more keywords, along with two common WPDL constant values, TRUE and FALSE.

ハイライトの第二レベルまでを定義出来ました。 第二レベルは第一レベルに追加している事に気をつけてください。 一つのキーワードは両方のレベルにマッチします。 そして、ここに共通のWPDL定数値、TRUEとFALSEを指定しておきました。

(defconst wpdl-font-lock-keywords-3
  (append wpdl-font-lock-keywords-2
          (list
           '("\\<\\(A\\(ND\\|PPLICATIONS\\)\\|BOOLEAN\\|HUMAN\\|INTEGER\\|NO\\|OR\\(GANISATIONAL_UNIT\\)?\\|R\\(EFERENCE\\|OLE\\)\\|S\\(TRING\\|YNCHR\\)\\|UNDER_REVISION\\|WORKFLOW\\|XOR\\)\\>" . font-lock-constant-face)))
  "Balls-out highlighting in WPDL mode")

I’ve now defined more WPDL constants. This completes the list of WPDL keywords.

更にWPDL定数を定義しました。これでWPDLキーワードリストは完了です。

(defvar wpdl-font-lock-keywords wpdl-font-lock-keywords-3
  "Default highlighting expressions for WPDL mode")

Here I’ve defined the default level of highlighting to be the maximum. This is just my preference – the user can change this variable (if the user knows how! This might be something to put in the documentation for your own mode).

ここにデフォルトのハイライトレベルを最大で定義しました。 これは個人的な設定です。ユーザはこの変数を変更出来ます。 (もしも知っていたらね!あなたのメジャーモードにはドキュメントを何か置くかもしれません)

Indentation (インデント)

WPDL features a Pascal-like syntax. This provides a natural basis for indentation. Blocks of information can be indented away from their parent. Fortunately, this doesn’t seem to be too difficult to accomplish with Emacs – the indentation code for wpdl-mode is only 28 lines long. Here is some example WPDL code, including indentation:

WPDL はパスカルライクな文法を特徴としています。 この文法はインデントの為の自然な土台を提供します。 インフォメーションブロックは彼らの親によってインデントされます。 幸運にも、Emacsではそれほど難しい事ではありません。work-modeのは28行しかありません。 ここにインデントを含めたWPDLのを例を示します。

WORKFLOW   'In_the_Mail_Room'
    CREATED 1998-07-15
    NAME    "In the Mail Room"

    ACTIVITY    'MailRoom'
        NAME    "Mail Room"
        TOOL_LIST 
            'scan_document'
            'identify_document'
            'send_document'
        END_TOOL_LIST
        PERFORMER 'Joe'
    END_ACTIVITY

END_WORKFLOW

I have identified five rules for indenting WPDL code. The rules are as follows:

以下にWPDLをインデントする5つのルールを定義しました。

  1. If we are at the beginning of the buffer, indent to column 0.
  2. If we are currently at an END_ line, then de-indent relative to the previous line.
  3. If we first see an END line before our current line, then we should indent our current line to the same indentation as the END line.
  4. If we first see a “start line” like PARTICIPANT, then we need to increase our indentation relative to that start line.
  5. If none of the above apply, then do not indent at all.
  1. もしも、バッファの先頭だった場合はインデントを0にする
  2. もしも、END_ の行にいる場合は、前の行に対してインデントを減らす
  3. もしも、END が前の行にあった後の最初の行の場合、 END 行のインデントと同じインデントをする
  4. もしも、PARTICIPANT のような "start line" の場合,start line に対してインデント量を増やす
  5. もしも、上記のいずれにも当てはまらなかったら、インデントを行わない

The following WPDL code example, with comments, may clarify these ideas:

次のWDPLのサンプルコードとコメントを見た方が、分かりやすいかも知れません。

// My activity              // Rule 1 applies
ACTIVITY    'MailRoom'      // Rule 5 applies
    NAME    "Mail Room"     // Rule 4 (based on "ACTIVITY")
    TOOL_LIST               // Rule 4 (based on "ACTIVITY")
        'scan_document'     // Rule 4 (based on "TOOL_LIST")
        'identify_document' // Rule 4 (based on "TOOL_LIST")
        'send_document'     // Rule 4 (based on "TOOL_LIST")
    END_TOOL_LIST           // Rule 2
    PERFORMER 'Joe'         // Rule 3
END_ACTIVITY                // Rule 2
(defun wpdl-indent-line ()
  "Indent current line as WPDL code"
  (interactive)
  (beginning-of-line))

We start by defining a single function for determining how a given line should be indented. It may be helpful to make the function interactive, to aid you in testing your indentation function. Making the function interactive allows you to call the function directly using `M-x your-function’. Also, we set the point to the beginning of the line.

与えられた行をどのようにインデントすべきかを決定する、関数を定義しました。 interactive で定義した方が、インデント関数のテストの役に立つかもしれません。 interactive 関数で作成すれば、ダイレクトに M-x your-function として呼び出すことができます。 それと、ポイントを行の始めにセットしておきました。

(if (bobp)  ; Check for rule 1
      (indent-line-to 0)

The first indentation-related thing we do is to check to see if this is the first line in the buffer, using the function ‘bobp’. If it is, we set the indentation level to 0, using ‘indent-line-to’. ‘indent-line-to’ indents the current line to the given column. Please note that if this condition is true, then the rest of the indentation code is not considered.

最初のインデントに関する行うことは、もし、このバッファの最初の行にいるかどうかを bobp 関数を使用してチェックすることです。 もしそうなら、'indent-line-to' 関数を使用して、インデントレベルを0にセットします。 'indent-line-to' は引数の値に現在の行をインデントします。 もしも条件が成立したら、インデントコードの rest *2 は考慮されない事に気をつけてください。

(let ((not-indentedt) cur-indent))

Now we declare two variables. We will store the value of our intended indentation level for this line in ‘cur-indent’. Then, when all of the indentation options have been considered (rules 2-5), we will finally make the indentation. The use of ‘not-indented’ will become clear later.

2つの変数を定義しました。 'cur-indent' にこの行のインデントレベルの値を格納するようにします。 すべてのインデントルール(2から5)の評価が済んだら、ようやくインデントをすることができます。 'not-indented' の値の使用方法は後ほど明らかになります。

        (if (looking-at "^[ \t]*END_") ; Check for rule 2
            (progn
              (save-excursion
                (forward-line -1)
                (setq cur-indent (- (current-indentation) default-tab-width)))

If we are not at the beginning of the buffer, then we start to consider other indentation options. What we do here is to check to see if we are at the end of a block. In WPDL, blocks are ended by keywords that start with END. So, we check to see if we are on such a line by using the ‘looking-at’ function, using a regexp that will detect if we are at a line that starts with END. Remember, we are at the beginning of the line, so we need to include any spaces or tabs in the regexp.

バッファの先頭にいなければ、インデントルールの評価を始めます。 ここでは、ブロックの終了にいるかどうかを確認します。 WPDL ではブロックは END で始まるキーワードで終了します。 なので、 lookinng-at 関数と、正規表現を使用して、END で始まる行にいるかどうかを確認します。 行頭にいることも考えると、スペースやタブも含める必要があります。

If we see that we are at the end of a block, we then set the indentation level. We do this by going to the previous line (using the ‘forward-line’ function), and then use the ‘current-indentation’ function to see how that line is indented. Then we set ‘cur-indent’ with the value of the previous line’s indentation, minus the ‘default-tab-width’.

もしもブロックの最後にいる場合は、インデントレベルを設定する必要があります。 これは前の行を利用して行います( 'forward-line' 関数を使います)。 'current-indentation' 関数を使い前行がどれくらいインデントされているか確認します。 そして、前行のインデントの値に 'default-tab-width' の値を引いた値を 'cur-indent' に設定します。

              (if (< cur-indent 0)
                  (setq cur-indent 0)))

We also include a safety check, so that we don’t try to indent past the left margin.

安全チェックも含めました。 左の欄外にはインデントをしません。

        (save-excursion 
          (while not-indented
            (forward-line -1)
            (if (looking-at "^[ \t]*END_") ; Check for rule 3
                (progn
                  (setq cur-indent (current-indentation))
                  (setq not-indented nil))
              ; Check for rule 4
              (if (looking-at "^[ \t]*\\(PARTICIPANT\\|MODEL\\|APPLICATION\\|WORKFLOW\\|ACTIVITY\\|DATA\\|TOOL_LIST\\|TRANSITION\\)")
                  (progn
                    (setq cur-indent (+ (current-indentation) default-tab-width))
                    (setq not-indented nil))
                (if (bobp) ; Check for rule 5
                    (setq not-indented nil)))))))

If we are not looking at an END_ line, then we iterate backward through the code to find an “indentation hint”. An indentation hint is some token in our file which can tell us how to indent the line we are on now. The rules I have provided earlier tell us what the indentation hints are. At this point, we only need to find the hints for rules 3-5, as the first two rules have already been covered by previous code.

もしも END_ が見つからない場合は、インデントのヒントが見つかるまで、前の行に移動します。 インデントのヒントとは、今いる場所は、どんなインデントにするべきかを、教えてくれる文です。

There aren’t any new Emacs lisp functions introduced here. The only thing worth noting is the use of ‘not-indented’ as a sentinel value for our while loop.

ここでは何も新しい関数はありません。 唯一注目に値することはループ中の各行での 'not-indented' 変数の使い方です。

      (if cur-indent
          (indent-line-to cur-indent)
        (indent-line-to 0))))) ; If we didn't see an indentation hint, then allow no indentation

Finally, we execute the actual indentation, if we have actually identified an indentation case. We have (most likely) already stored the value of the indentation in ‘cur-value’. If ‘cur-indent’ is empty, then we always indent to column 0.

もしもインデントケースを見つけられれたら、ようやくインデントを実行します。 すでに cur-value にインデントの値が保存されています。 もしも cur-indent が空なら、インデントは0に設定します。

And that concludes the indentation code for WPDL. Exercise: This indentation code is rather simple. In which cases would the code fail to create proper indentation of WPDL code?

そしてWPDLのコードのインデントを決定します。 エクササイズ: このインデントコードは比較的シンプルです。 適切なインデントに失敗するのは、どのようなケースでしょう?

The syntax table (シンタックステーブル)

Now we will set up a syntax table for WPDL. A syntax table tells Emacs how it should treat various tokens in your text for various functions, including movement within the buffer and syntax highlighting. For example, how does Emacs know to move forward by one word (as used in the ‘forward-word’ function)? The syntax table gives Emacs this kind of information. The syntax table is also used by the syntax highlighting package. It is for this reason that we want to modify the syntax table for wpdl-mode.

次に WPDL のシンタックステーブルをセットアップします。 シンタックステーブルとは,テキスト中にある,様々な移動機能やシンタックスハイライト等の意味を持つ部品を,どのように扱うべきかをEmacsに教えるものです。 例えば、どのように Emacs が前方への単語移動をするか( forward-word で使われています )分かりますか? シンタックステーブルは、そういった情報を Emacs に提供します。 またシンタックスハイライトのパッケージとしても使われます。 wpdl-mode のシンタックステーブルを編集する必要があるのは、そうした訳です。

(defvar wpdl-mode-syntax-table
  (let ((st (make-syntax-table)))

We will use the ‘make-syntax-table’ function to create an empty syntax table. This function creates a syntax table that is a good start for most modes, as it either inherits or copies entries from the standard syntax table.

空のシンタックステーブルを作成するためには、 make-syntax-table を使います。 この関数は標準のシンタックステーブルを継承、またはコピーするような、 ほとんどのメジャーモードのシンタックステーブルの土台にちょうど良いです。

   (modify-syntax-entry ?_ "w" st)

The first modification we make to the syntax table is to declare the underscore character ‘_’ as being a valid part of a word. So now, a string like foo_bar will be treated as one word rather than two (the default Emacs behavior). We do this because we want to make it easier to treat WPDL variable names (which use underscores by convention), and, more importantly, keywords, as single words. NB: Treating underscores as non-whitespace is non-standard Emacs behavior. Here, I feel justified in including this modification, since so many WPDL keywords include underscores.

シンタックステーブルを作るための、最初の編集はアンダースコアを単語の一部として定義する事です。 そして今、 foo_bar のような文字列は、2つの単語ではなく(Emacsのデフォルトの挙動です)、1つの単語として扱われるようにしました。 WPDL の変数名(規約によりアンダースコアを使います),そして更に重要な,キーワードを一つの単語とする事で、より簡単に操作出来るようにしたかった為です。 NB: アンダースコアを、スペースのように扱うのは、Emacs の標準的な挙動ではありません。 ここで、この更新を加えた方が良いと考えたのは、多くのWPDLキーワードはアンダースコアを含むためです。

The ‘modify-syntax-entry’ function takes a character as its first argument, a syntax class as its second argument, and the syntax table to be modified as the third argument. In Emacs Lisp, characters are represented by using the '?' symbol followed by the actual character, so we use ?_ to represent the underscore. The syntax class indicates how a particular character is treated. Example syntax classes include “punctuation character,” “open parenthesis indicator”, and “word constituent.” 'w' is the symbol for “word constituent.”

modify-syntax-entry 関数は最初の引数にキャラクタをとります。 2つ目の引数にはシンタックスクラスを、そして3つ目の引数には編集するシンタックステーブルをとります。 Emacs Lisp では、キャラクタは '?' のシンボルの後に実際の文字が並んで表現されます。 だから ?_ はアンダースコアを表します。 シンタックスクラスは,特定の文字をどのように扱うべきかを決めます。 例のシンタックスクラスは '句読点文字' , '開き括弧' , そして '文字要素' を含みます。 'w' は文字要素のシンボルです。

    (modify-syntax-entry ?/ ". 124b" st)
    (modify-syntax-entry ?* ". 23" st)
    (modify-syntax-entry ?\n "> b" st)

WPDL comments are just like C++ comments. So, our goal is to program C++ comments into the WPDL syntax table. To do this, we need to use some extra syntax class parameters called syntax flags. Some syntax classes have these extra parameters to further refine the place of the character within the classes. The syntax class used here is '.', which means “punctuation character.”

WPDL コメントは C++ のコメントに似ています。 だから、C++ のコメントを WPDL シンタックステーブルに埋め込むことをゴールとします。 それをするには、シンタックスフラグと呼ぶ、特別なシンタックスクラスパラメータをいくつか使う必要があります。 いくつかのシンタックスクラスは、クラス内のキャラクタの配置をよりいっそう向上させるため、これらの特別なパラメータを持っています。 シンタックスクラスは '句読点文字' を意味する '.' を使用します。

If we consult the Emacs lisp programming guide and see what the syntax flags mean, we will see that we have made the following adjustments to the syntax table:

もしも Emacs lisp プログラミングガイドに助けを求めて、、シンタックスフラグとはなにかを調べたなら、 この後に続いて書いてある、シンタックステーブルの細かな調整のためと書いてあるでしょう。

1) That the character '/' is the start of a two-character comment sequence ('1'), that it may also be the second character of a two-character comment-start sequence ('2'), that it is the end of a two-character comment-start sequence ('4'), and that comment sequences that have this character as the second character in the sequence is a “b-style” comment ('b'). It’s a rule that comments that begin with a “b-style” sequence must end with either the same or some other “b-style” sequence.

1) '/' は2文字のコメント文字列*3の始まりにあたります('1')。 また、2文字のコメント開始文字列の2番目かも知れません('2')。 2文字のコメント文字列開始の終わりかも知れません('4')。 そして、このコメント文字列が、コメント文字列内で2番目にある場合は "b-style" コメントです('b')。 "b-style" 文字列で始まっているコメントは、同じか、別の "b-style" 文字列で終わる必要があります。

2) That the character '*' is the second character of a two-character comment-start sequence ('2') and that it is the start of a two-character comment-end sequence ('3').

2) '*' は2文字のコメント開始文字列の2番目にあたります('2')。そして、コメント終了文字列の最初でもあります('3')。

3) That the character '\n' (which is the newline character) ends a “b-style” comment.

3) '\n'(改行文字) は 'b-style' コメントを終了させます。

Now we have programmed our comment style into the syntax table. The syntax highlighting mechanism (font-lock) will now read the syntax table and highlight WPDL comments accordingly.

これでシンタックステーブルにコメントスタイルをプログラムできました。 シンタックスハイライトの仕組み(font-lock)は、シンタックステーブルを読み取り、 それに従って、WPDLコメントをハイライトしてくれるでしょう。

   st)
  "Syntax table for wpdl-mode")

These lines finish the definition of the syntax table, including the document string.

これらの行では doc-string を含めた形で、シンタックステーブルの定義を終了します。

The entry function (エントリー関数)

Finally, we will create the function that will be called by Emacs when the mode is started.

ようやく、メジャーモードが開始した時に Emacs に呼ばれる関数を作ります。

(defun wpdl-mode ()
  "Major mode for editing Workflow Process Description Language files"
  (interactive)
  (kill-all-local-variables)
  (set-syntax-table wpdl-mode-syntax-table)
  (use-local-map wpdl-mode-map)

Here we define our entry function, give it a documentation string, make it interactive, and call our syntax table creation function. We also set our keymap for the mode.

メジャーモードの入口となるエントリー関数を定義します。 ドキュメントを設定して、インタラクティブにして、そしてシンタックステーブルを作成する関数を呼び出します。 メジャーモード用のキーマップも設定します。

(set (make-local-variable 'font-lock-defaults) '(wpdl-font-lock-keywords))

Now we are specifying the font-lock (syntax highlighting) default keywords. Note that if the user has specified her own level of keyword highlighting by redefinine ‘wpdl-font-lock-keywords’, then that will be used instead of the default.

font-lock (シンタックスハイライト) のデフォルトのキーワードを指定します。 もしもユーザがキーワードハイライトのレベルを、'wpdl-font-lock-keywords'で再定義している場合は、 そちらが使われることに注意してください。

(set (make-local-variable 'indent-line-function) 'wpdl-indent-line)  

Here we register our line indentation function with Emacs. Now Emacs will call our function every time line indentation is required (like when the user calls ‘indent-region’).

Emacs でインデントする関数を登録します。 これで Emacs が各行でインデントが必要になった時(ユーザが 'indent-region' を呼んだ時など)に、この関数が呼ばれるようになります。

  (setq major-mode 'wpdl-mode)
  (setq mode-name "WPDL")
  (run-hooks 'wpdl-mode-hook))

The last steps in the entry function are to set the ‘major-mode’ variable with the value of our mode, to set the ‘mode-name’ variable (which determines what name will appear in the status line and buffers menu, for example), and to finally call ‘run-hooks’ so that the user’s own mode hooks will be called.

エントリー関数最後のステップは 'major-mode' 変数にモード名をセットすることです。 (ステータスラインやバッファメニューで表示される名前を解決します。) そしてようやく 'run-hooks' を呼びました。 ユーザが指定したフックがここで呼ばれます。

The most important line (最重要な行)

(provide 'wpdl-mode)

Finally, we use ‘provide’ to expose our mode to the Emacs environment. Users will most likely want to use the ‘require’ function in the .emacs file to load the mode into the environment.

ようやく provide' を使いました。 Emacs にこのメジャーモードの存在を知らせるためです。 通常、ユーザは Emacs にメジャーモードを読み込ませる為に、.emacs で 'require' をします。

A word about style (スタイル)

The Emacs lisp manual has a section about style called “Tips and Conventions”, including a section about major mode style called “Major Mode conventions”. In addition to following these guidelines, you may want to use the CheckDoc tool to help you get your style issues under control, especially concerning the format of the initial comment block.

Emacs マニュアルには、「メジャーモードの慣習」というセクションを含む、 「ティップと慣習」というセクションがあります。このガイドラインに加えて、 制御しているスタイルの問題、特にコメントブロックのフォーマットに関して、 文書チェックツールを使いたいかも知れません。

Implementation alternatives (別実装)

Stefan Monnier, an Emacs maintainer, has suggested alternative approaches for indentation and the entry function. His SampleMode gives an outline of these alternative approaches. For example, our entry function could be greatly simplified by deriving wpdl-mode from fundamental-mode, see DerivedMode. The code to do this is given here:

EmacsメンテなのStefan Moniierは、インデントとエントリー関数定義に別のアプローチを提案してくれました。 彼のサンプルはそのアプローチの概要を示しています。 例えば、エントリー関数定義は fundamental-mode を継承することで劇的にシンプルになりました。 コードは下記です。

This can replace (defun wpdl-mode ()... このコードは (defun wpdl-mode () .. に置き換え可能です。

(define-derived-mode wpdl-mode fundamental-mode "WPDL"
  "Major mode for editing Workflow Process Description Language files."
  (set (make-local-variable 'font-lock-defaults) '(wpdl-font-lock-keywords))
  (set (make-local-variable 'indent-line-function) 'wpdl-indent-line))

*1: 22?

*2:空白?

*3:// あるいは/ / の事と思われる