Up: 目次   [Index]


Vim の開發に關して

*develop.txt*   For Vim バージョン 8.1.  Last change: 2019 Aug 05


		  VIMリファレンスマニュアル    by Bram Moolenaar

Vim の開發

この文書は、Vim の更なる開發に參加しようといふ人にとつて重要なものです。

1. 設計上の目標|design-goals|
2. コーディングスタイル|coding-style|
3. 決定事項|design-decisions|
4. 想定してゐること|design-assumptions|

ソースコードの槪要については "src" ディレクトリの README.txt を見てください。

Vim はオープンソースソフトウェアです。誰でも Vim の開發に協力できます。パッチを送る時はなるべく "unified diff" 形式 ("diff -u" で作る) でお願ひします。GitHub 上でプルリクエストを作ることも可能ですが、必須ではありません。

http://vim.wikia.com/wiki/How_to_make_and_submit_a_patch

も見てください。

1. 設計上の目標

重要度の順に從つて書かれてゐます(大雜把ですが)。

Note:
かなりの項目が矛盾してゐることに注意してください。これは故意でさうしてゐます。それらの閒で、バランスを取つていかなければなりません。

VIM IS... VI COMPATIBLE

何よりもまづ、Vim は Vi の氣輕な置き換へとして使ふことができるべきであります。ユーザーが望むなら、オリジナルの Vi との區別がほとんど付かない互換モードで Vim を使ふことができます。

例外:

VIM IS... IMPROVED

Vim の改良點は、それをよりよい Vi にすべきであつて、まつたく違つたエディタにしてしまつてはなりません。擴張は "Vi の精神" に從つて行はれます。

VIM IS... MULTI PLATFORM

Vim は可能な限り、多くのプラットフォーム上の多くのユーザーの助けでありたい。

VIM IS... WELL DOCUMENTED

VIM IS... HIGH SPEED AND SMALL IN SIZE

Vim を使ふことでシステムリソースに大打擊を與へてはなりません。Vim を小さく、速く保ちませう。

VIM IS... MAINTAINABLE

VIM IS... FLEXIBLE

Vim は、そのユーザーに特定の作業パターンを强ひるよりは、ユーザーの好むスタイルでの作業を支援すべきです。これは大きな影響をもつ項目 (例へば、’compatible’ オプション) や、その他の詳細によつて實現されます。デフォルトは、多くのユーザーがそのままの Vim を樂しんで使へるやうに愼重に選ばれてゐます。コマンドとオプションは、Vim をユーザーの希望と環境に調整するために使はれます。

VIM IS... NOT

2. コーディングスタイル

Vim のソースコードに變更を加へる際に守るべきルールがあります。ソースを讀めるもの、保守できるものとして保つため、これらのルールに從つてください。

このリストは完全ではありません。より多くの例はソースコードを見てください。

MAKING CHANGES

コードに變更を加へる基本的なステップは:

  1. GitHub からコードを取得します。これによりあなたが變更したコードをメインのコードベースに同期するのがより簡單になります (あなたの變更がメインのコードベースに含まれるやうになるまで少しかかるかもしれません)。いくらか時閒を費やして git について學ぶ必要があります。git はあまりユーザーフレンドリーなツールではありません。
  2. ドキュメントを調整します。最初にこれをすることで、あなたの行ふ變更がユーザーに與へる影響について、おおまかな所見をもつことができます。
  3. ソースコードに變更を加へます。
  4. 變更がリストされた項目に影響を與へてゐないか ../doc/todo.txt をチェックします。
  5. "git diff" でパッチを作成します。GitHub でプルリクエストを作成しても良いのですが、重要なのはその diff です。
  6. 何が變更されたかのノートを作成します。問題點とその解決策について書かれてゐるのが望ましいでせう。|vim-dev| のメーリングリストに說明と diff を含めたメールを送るか GitHub でプルリクエストを作成します。

C COMPILER

サポートされてゐる最小の C コンパイラのバージョンは C89 (ANSI C とも呼ばれてゐる) です。C99 のやうな後繼の標準規格はあまりサポートされてゐません。もしくは少なくとも 100% サポートされてゐるわけではありません。したがつて C99 のいくつかの機能だけを使用し、その他の使用は (少なくとも現時點では) 禁止します。

現存するパッチに對してマージの問題を引き起こすため、C99 の機能を使ふ變更を至る所に入れてはいけません。新しくコードを書く場合、もしくは既存のコードを書き直す場合に限り使用しませう。

Comments

慣習的に Vim では /* コメント */ を使用します。特にファイルと函數のヘッダに關してはこれを維持するつもりです。新しいコードもしくは變更される行については、// コメント を使用してもよいでせう。特にコードの後ろに續くコメントなど:

int some_var;  // ここで一行コメントは有用

Enums

列擧型の末尾の要素にコンマ (trailing comma) が付いてゐてもよいでせう。C89 では認められてゐませんでした。

Types

"long long" は使用してもよく、64 bit を想定してゐます。printf では %lld を使用してください。同じやうに "long long unsigned" では %llu を使用してください。

使用してはいけないもの

これらの C99 の機能は、コンパイラのサポートが不十分なため使用してはいけません:

USE OF COMMON FUNCTIONS

よく使はれる函數のうち、特別な Vim バージョンを持つものがあります。これらは理由があつて導入されたものなので、常に Vim バージョンを使ふやうに意識しませう。

標準的な名前Vim での名前Vim 版での違ひ
free()vim_free()NULL の解放をチェックする
malloc()alloc()アウトオブメモリの狀況をチェックする
malloc()lalloc()alloc() に似てゐるが、long 型の引數を持つ
strcpy()STRCPY()char_u *引數を、(char *) へキャストする
strchr()vim_strchr()スペシャルキャラクタを受け入れる
strrchr()vim_strrchr()スペシャルキャラクタを受け入れる
isspace()vim_isspace()128 以上のキャラクタを扱ふことができる
iswhite()vim_iswhite()Tab とスペースに對してのみ TRUE
memcpy()mch_memmove()オーバーラップしたコピーを扱ふ
bcopy()mch_memmove()オーバーラップしたコピーを扱ふ
memset()vim_memset()全てのシステムで一定である

NAMES

函數の名前に 31 文字より長い名前は使へません (VMSのために)。

"delete" や "this" といふ名前の變數を使はないでください。C++ で問題となります。

Vim をできる限り多くのシステム上で實行できるやうにするといふ必要上、システムによつてすでに定義されてゐる名前を使ふことは避けなければなりません。以下は問題となることが知られてゐる名前のリストです。名前は regexp パターンとして與へられてゐます。

is.*()POSIX, ctype.h
to.*()POSIX, ctype.h
d_.*POSIX, dirent.h
l_.*POSIX, fcntl.h
gr_.*POSIX, grp.h
pw_.*POSIX, pwd.h
sa_.*POSIX, signal.h
mem.*POSIX, string.h
str.*POSIX, string.h
wcs.*POSIX, string.h
st_.*POSIX, stat.h
tms_.*POSIX, times.h
tm_.*POSIX, time.h
c_.*POSIX, termios.h
MAX.*POSIX, limits.h
__.*POSIX, system
_[A-Z].*POSIX, system
E[A-Z0-9]*POSIX, errno.h
.*_tPOSIX, for typedefs, *_T を使ふこと
waittypes.h とコンフリクトするため、函數の引數として使はない
indexグローバル宣言を覆ひ隱す
timeグローバル宣言を覆ひ隱す
newC++ の豫約語
clearMac curses.h
echoMac curses.h
instrMac curses.h
metaMac curses.h
newwinMac curses.h
nlMac curses.h
overwriteMac curses.h
refreshMac curses.h
scrollMac curses.h
typeaheadMac curses.h
basename()GNU 文字列函數 (GNU string function)
dirname()GNU 文字列函數 (GNU string function)
get_env_value()Linux システム函數

VARIOUS

型の定義に使ふ名前は最後を "_T" にします:

typedef int some_T;

マクロ定義はすべて大文字にします:

#define SOME_THING

機能に關する定義は "FEAT_" で始めます:

#define FEAT_FOO

’\"’ は使はないでください。これを扱へないコンパイラがあります。’"’ はうまく機能します。

次は使つてはいけません:

#if HAVE_SOME

あるコンパイラはこれを扱へず、"HAVE_SOME" が定義されてゐないと訴へます。

次を使ひます:

#ifdef HAVE_SOME

または

#if defined(HAVE_SOME)

STYLE

一般的なルール: 1 行に 1 つのステートメント。

閒違ひ:    if (cond) a = 1;

OK:        if (cond)
               a = 1;
閒違ひ:    while (cond);

OK:        while (cond)
              ;
閒違ひ:    do a = 1; while (cond);

OK:        do
               a = 1;
           while (cond);
閒違ひ:    if (cond) {
              cmd;
              cmd;
           } else {
              cmd;
              cmd;
           }

OK:        if (cond)
           {
              cmd;
              cmd;
           }
           else
           {
              cmd;
              cmd;
           }

ブロックが 1 行の場合は、波括弧を省くことができます。if/else の 1 つのブロックに波括弧がある場合、他のブロックにも波括弧があると通常は見榮えが良くなります:

OK:         if (cond)
               cmd;
            else
               cmd;

OK:         if (cond)
            {
               cmd;
            }
            else
            {
               cmd;
               cmd;
            }

函數宣言には ANSI スタイルを使ひ、戾り値の型は獨立した行にインデントをつけて書いてください。

閒違ひ: int function_name(int arg1, int arg2)

OK:     /*
         * Explanation of what this function is used for.
         * この函數が何に使はれるかの說明。
         *
         * Return value explanation.
         * 戾り値の說明。
         */
            int
        function_name(
            int     arg1,           // short comment about arg1
            int     arg2)           // short comment about arg2
        {
            int     local;          // comment about local

            local = arg1 * arg2;

SPACES AND PUNCTUATION

函數名とブラケットの閒にスペースを入れないでください:

閒違ひ:	func (arg);
OK:     func(arg);

if, while, switch などの後にはスペースを入れてください。

閒違ひ: if(arg)         for(;;)
OK:     if (arg)        for (;;)

コンマ、セミコロンの後にはスペースを入れてください:

閒違ひ: func(arg1,arg2);        for (i = 0;i < 2;++i)
OK:     func(arg1, arg2);       for (i = 0; i < 2; ++i)

’=’, ’+’, ’/’ などの前と後には、スペースを入れてください。

閒違ひ: var=a*5;
OK:     var = a * 5;

一般的なこと: コードの行をグループ分けするために空行を使ひます。行グループのすぐ上にコメントを入れます。かうすることによつて、何が行はれるのかをより簡單に知ることができます。

OK:     /* Prepare for building the table. */
        /* テーブルの作成の準備 */
        get_first_item();
        table_idx = 0;

        /* Build the table */
        /* テーブルの作成 */
        while (has_item())
            table[table_idx++] = next_item();

        /* Finish up. */
        /* 仕上げ */
        cleanup_items();
        generate_hash(table);

3. 決定事項

折疊(folding)

同じバッファにいくつもの折疊狀態を設定可能にします。例へば、あるウィンドウに函數を折疊んだ狀態で表示し、他のウィンドウで函數の中身を表示するなど。

折疊はテキストを表示する方法です。テキストを變更すべきではありません。したがつてバッファ內のテキストをウィンドウに表示する際のフィルタとして實行されます。

ウィンドウの名前

"ウィンドウ" といふ單語は一般にいくつかの意味で使はれてゐます。スクリーン上のウィンドウ、xterm のウィンドウ、Vim のバッファを表示するウィンドウなど。

混亂を避けるため、時にウィンドウと呼ばれる他の物には別の名前が付けられてゐます。ここに關聯する物の槪觀を示します。

スクリーン (screen)

ディスプレイ全體。GUI では例へば 1024x768 ピクセルの畫面。Vim シェルはスクリーン全體を使ふことも一部を使ふこともできます。

シェル (shell)

Vim アプリケーション。スクリーン全體 (例へばコンソールで實行した時)、あるいはその一部 (xterm や GUI)。

ウィンドウ (window)

バッファの表示畫面。Vim は複數のウィンドウを持つことができます。ウィンドウはコマンドラインやメニューバー、ツールバーなどといつしよに表示されます。これらはシェルに納まります。

スペルチェック

Vim にスペルチェックを追加することになつたとき、利用可能なスペルチェックのライブラリやプログラムについての調査が行はれました。その結果は殘念なことに、Vim 內でスペルチェックエンジンとして使へるものはないとわかりました。これには樣々な理由があります:

スペル候補

候補の作成には 2 つの基本的なメカニズムがあります:

  1. 誤つた單語を少し變更して、正しい單語とマッチするかチェックする。あるいは、正しい單語全てに對し、それを少し變更して誤つた單語とマッチするかチェックする。變更とは、文字の削除・文字の插入・2 つの文字の交換などです。
  2. 誤つた單語と正しい單語のリストの兩方に soundfolding (撥音が近い單語を同じグループとみなすこと) を行つて、そこでマッチを見つける。1 番目のメカニズムと同樣にいくつか變更をしてもよいでせう。

最初のメカニズムはタイプミスを見つけるのには良いです。ハッシュテーブルの實驗と、他のスペルチェッカのソリューションを見ると、これには trie (ツリー構造の一種) が最適であるとの結論になりました。メモリ使用量の削減と、賢い變更を試みるといふことの兩方の面でです。例へば、文字を插入するときは正しい單語につながる文字だけを試せば良いです。他の (ハッシュテーブルを使つた) メカニズムは、單語のすべての位置でありうるすべての文字を試さねばなりません。また、ハッシュテーブルを使ふには、單語の境界が個別に認識されなければならないのに對し、trie はそれを要求しません。そのためメカニズムがより單純になります。

ある單語の撥音は知つてゐるけれどもスペルは知らないといふ場合に soundfolding は有用です。例へば、"dictionary" といふ單語を "daktonerie" と書いてしまふかもしれません。これを最初の方法で訂正しようとすると變更回數が非常に多くなつてしまひ、正しいスペルを見つけるのは困難になります。それに對し、これらの單語に soundfolding を行ふと "tktnr" と "tkxnry" になり、2 文字しか違ひません。

soundfold の同値 (音が似てゐる單語) により單語を見つけるには、全ての soundfolded words のリストが必要です。どれが最良の方法かを探すための實驗が行はれました。案:

  1. 修正候補を探すときに、その場で sound folding を行ふ。つまり正しい單語の trie をたどりながら、各單語を soundfolding し、それがスペルミスしてゐる單語からどれだけ異なるかをチェックします。これはメモリ效率の面でとても優れてゐますが、時閒は長くかかります。英語の場合、高速な PC で 2 秒ほどかかります。これは對話的な利用として受け入れることができます。しかしいくつかの言語 (ドイツ語、カタルニャ語など) に對しては 10 秒以上かかり、受け入れがたいです。バッチ處理 (自動訂正) に使ふには全ての言語で遲すぎます。
  2. soundfold された單語に對して trie を使ひ、soundfolding なしのときとまつたく同じやうに檢索できるやうにします。そのためには、soundfold された各單語に對し、正しい單語のリストを記憶しておく必要があります。さうすると照合がとても高速になりますが、1MB 〜 10MB のオーダーの大量のメモリを必要とします。ある言語の場合は元の單語のリストよりも多くなります。
  3. 2 番目の案と同樣ですが、接辭壓縮を使ひ soundfold した基本單語だけを保存することによりメモリ消費量を減らします。これは Aspell が採用してゐる方法です。不利な點は、誤つた單語を soundfold する前に接辭を取り除いておかねばならないことです。そのため、單語の先頭・末尾における誤りに對しては對應できません。また、誤つた單語が正しい單語から大きく異なるときは遲くなります。

我々が採用したのは、2 番目のメカニズムを使ひ、別ファイルを使ふ方法です。かうすることによつて、十分なメモリを持つてゐるユーザーはとてもよい候補を得ることができるし、メモリが不足してゐるユーザーやスペルチェックだけで候補は出さなくてよいといふユーザーはそれほどメモリを使はなくて濟みます。

單語の頻度

候補をソートするにはどの單語が共通であるかを知ると役に立ちます。理論的には單語の頻度は單語とともに辭書の中に保持することができます。しかしさうすると、單語につき回數を保持しなければなりません。これは單語ツリー壓縮を大いに劣化させます。また、全ての言語に對して單語の頻度を保守するのは大變な作業です。また、テキストに既に出てきてゐる單語を優先するとよいでせう。このやうにして特定のテキスト內に表れる單語は候補の中で優先度が高くなります。

實裝されたのは、表示中に單語を數へることです。ハッシュテーブルを使つてその單語の回數を高速に檢索します。回數は接辭ファイルで COMMON アイテムにリストされてゐる單語から初期化されます。そのため新規ファイルの編輯を始めたときも機能します。

これは理想的ではありません。Vim が長時閒稼動してゐるほど回數は大きくなるためです。しかし實用的には單語の回數を使はない場合と比べて注目に値するほどの改善です。

4. 想定してゐること

變數のサイズ:

char8 bit signed
char_u8 bit unsigned
int32 or 64 bit signed (限定された機能については 16 ビットもありうる)
unsigned32 or 64 bit unsigned (16 ビットについては int と同樣)
long32 or 64 bit signed, can hold a pointer

Note:
いくつかのコンパイラは長すぎる行は文字列をうまく扱へないことに注意していください。C89 の標準規格では 509 文字までに制限されてゐます。


Up: 目次   [Index]