ViVi Home > さくさくエディタ > チュートリアル > Zen-Coding for C系言語


 

 

Zen-Coding for C系言語

 

イントロダクション

Zen-Coding は独特の短い記法で構文を指定し、コマンドによりテキストを入力する方式です。

Zen-Coding for C系言語 を使うと、for文、if文、while文、do-while文、return文、構造体・クラス定義、typedef文、namespace文 などを少ないストロークで、非常に簡単かつ高速に入力できます。

展開ルールはユーザがテキストファイルで指定することができます。詳しくは こちら を参照してください。
ZenCoding for C系言語 をマスターして、3倍速いコーディングを身につけてください。

使用方法

使い方はいたって簡単。i a != b の様に構文指定子、パラメータ直後で Ctrl + ,(カンマ)を入力するだけです。

    i a != b(カーソル)
    
        ↓ Ctrl + ,(カンマ)を押下
    
    if (a != b) {
        (カーソル)
    }

パラメータは構文により様々で、たいていの場合省略可能です。
構文指定子は、for文 ならば f、if文なら i とキーワードの最初の文字を指定します。
typedef unsigned char uchar; のように複数のキーワードから成る場合は、tuc にように各キーワードの先頭文字を並べます。

展開例

for 文

f または for に続けて、ループ変数、初期値、比較演算子、最終値、増減などを指定可能です。
以下の例で、型名が「int」になっていますが、JavaScript タイプの場合は「var」が生成されます。
for文に限っては、php, JavaScript, python, Ruby に対応しています。

展開前展開後説明
ffor (int i = 0; i < N; ++i) {
  (カーソル)
}
int i を 0 から N-1 までループ
f jfor (int j = 0; j < N; ++j) {
  (カーソル)
}
f の直後にループ変数を指定
f i 100for (int i = 0; i < 100; ++i) {
  (カーソル)
}
ループ回数指定
f i 10 100for (int i = 10; i < 100; ++i) {
  (カーソル)
}
ループ初期値、最終値指定
f i 100 10for (int i = 100; --i > 10; ) {
  (カーソル)
}
初期値>最終値 の場合
f i Nfor (int i = 0; i < N; ++i) {
  (カーソル)
}
変数指定時
f i first != lastfor (int i = first; i != last; ++i) {
  (カーソル)
}
ループ初期値、比較演算子、最終値指定
f i v.size()for (int i = 0; i < v.size(); ++i) {
  (カーソル)
}
最終値を式で指定
f i first lastfor (int i = first; i < last; ++i) {
  (カーソル)
}
初期値、最終値を式で指定
f i first last -for (int i = first; --i > last; ) {
  (カーソル)
}
- でデクリメント指定
f;for (;;) {
  (カーソル)
}
無限ループ

php 向け

展開前展開後説明
ffor ($i = 0; $i < N; ++$i) {
  (カーソル)
}
$i を 0 から N-1 までループ
f jfor ($j = 0; $j < N; ++$j) {
  (カーソル)
}
f の直後にループ変数($は省略可能)を指定
f $kfor ($k = 0; $k < N; ++$k) {
  (カーソル)
}
f の直後にループ変数を指定

JavaScript 向け

展開前展開後説明
ffor (var i = 0; i < N; ++i) {
  (カーソル)
}
i を 0 から N-1 までループ
f jfor (var j = 0; j < N; ++j) {
  (カーソル)
}
f の直後にループ変数(は省略可能)を指定
f kfor (var k = 0; k < N; ++k) {
  (カーソル)
}
f の直後にループ変数を指定

python 向け

展開前展開後説明
ffor i in range(N):
  (カーソル)
i を 0 から N-1 までループ
f kfor k in range(N):
  (カーソル)
ループ変数指定
f 100for i in range(N):
  (カーソル)
ループ回数指定

Ruby 向け

展開前展開後説明
ffor i in 1..N do
  (カーソル)
end
i を 0 から N-1 までループ
f kfor k in 1..N do
  (カーソル)
end
変数指定
f 100 for k in 1..100 do
  (カーソル)
end
繰り返し回数指定
f 10..20 for k in 10..20 do
  (カーソル)
end
繰り返し範囲指定

if 文

i(または if)条件式 を if (条件式) { } に、
ie 条件式 を if (条件式) { } else { } に展開します。
条件式は省略可能で、省略すると true が挿入されます。

展開前展開後説明
iif (true) {
  (カーソル)
}
if 文のひな形生成
i a != bif (a != b) {
  (カーソル)
}
条件式指定で if 文を生成
ieif (true) {
  (カーソル)
} else {
  
}
if-else 文のひな形生成
ie a != bif (a != b) {
  (カーソル)
} else {
  
}
条件式指定で if-else 文を生成
eelse {
  (カーソル)
}
else 節生成
eielse if (true) {
  (カーソル)
}
else if 文のひな形生成
ei a != belse if (a != b) {
  (カーソル)
}
条件式指定で else if 文を生成

while 文

w 条件式 を if (条件式) { } に展開します。
条件式は省略可能で、省略すると true が挿入されます。

展開前展開後説明
wwhile (true) {
  (カーソル)
}
while 文のひな形生成
w first != lastwhile (first != last) {
  (カーソル)
}
条件式指定で while 文を生成

do-while 文

d 条件式 をdo { } while (条件式); に展開します。
条件式は省略可能で、省略すると true が挿入されます。

展開前展開後説明
ddo {
  (カーソル)
} while( true );
while 文のひな形生成
d first != lastdo {
  (カーソル)
} while( first != last );
条件式指定で while 文を生成

return 文、break文

展開前展開後説明
rreturn;(カーソル)return 文を生成します。
r truereturn true;(カーソル)返り値付き return 文を生成します。
bbreak;(カーソル)break 文を生成します。

class, struct 定義

展開前展開後説明
sstruct Name {
  (カーソル)
};
構造体定義のひな形生成
s MyStructstruct MyStruct {
  (カーソル)
};
構造体定義のひな形生成
cclass Name {
  (カーソル)
};
クラス定義のひな形生成
c MyClassstruct MyClass {
  (カーソル)
};
クラス定義のひな形生成

typedef struct 定義

展開前展開後説明
tstypedef struct {
  (カーソル)
} Name;
構造体定義のひな形生成
ts MyStructtypedef struct {
  (カーソル)
} MyStruct;
構造体定義のひな形生成

typedef unsigned タイプ

展開前展開後説明
tuctypedef unsigned char uchar;(カーソル)符号なし8ビット型定義を生成
tustypedef unsigned short ushort;(カーソル)符号なし16ビット型定義を生成
tuitypedef unsigned int uint;(カーソル)符号なし32ビット型定義を生成

typedef const char タイプ

展開前展開後説明
tcctypedef const char cchar;(カーソル)const char 型定義を生成

#include, #define、#if 文生成

展開前展開後説明
##include "(カーソル)#include 文を生成
#i#include "(カーソル)#include 文を生成
#<#include <(カーソル)#include 文を生成
#d#define (カーソル)#define 文を生成
#0#if 0(カーソル)#if 文を生成
#e#endif(カーソル)#endif 文を生成
#el#else(カーソル)#else 文を生成
#ei#elif(カーソル)#elif 文を生成

main() 関数

展開前展開後説明
imint main()
{
  (カーソル)
  return 0;
}
main関数のひな形生成
imaint main(int argc, char *argv[])
{
  (カーソル)
  return 0;
}
引数付きmain関数のひな形生成

その他

展開前展開後説明
////---(70個)---(カーソル)// に続く70個の - 生成

Java 向け

展開前展開後説明
sopSystem.out.println("(カーソル)");print文生成

テキストファイルによる、展開パターン指定

設定ファイルを用意しておき、下記の書式で展開パターンを指定可能とします。

  構文指定子(タブ)展開後テキスト

「\c」は展開後のカーソル位置を表します。「\c」が無い場合はカーソルは末尾に設定されます。
改行は「\n」で指定します。「\t」でタブを指定することも可能です。「\」そのものを入力したい場合は「\\」と記述します。

パラメータを展開する部分は「\{」と「\}」でマークします。その中にパラメータが省略された場合のテキストを記述します。
s や c など既に定義済みのものを指定した場合、ファイルによる指定の方が優先されます。

例:
  sop(タブ)System.out.println("\c");
  w(タブ)while (\{true\}) {\n\t\c\n}

より詳しい例は、アーカイブに同梱されている ZenCoding.txt を参照してください。

展開パターンを指定するテキストファイルを作成したら、文字エンコーディングUTF-8で適当なディレクトリに保存します。 次に、設定>全体設定 メニューを実行し、全体設定ダイアログを開き、Zen-Coding ファイル:の部分に作成したファイルフルパスを入力します。 直ぐ横の【参照…】ボタンを押すと、ファイルツリーからフィルを選択することも出来ます。

他の方式との比較・評価

Zen-Coding は定型的なテキストを短いストロークで高速に入力するためのものです。
同様の目的を持つ機能・手法としては、(1) テキストファイル挿入、(2) 短文入力、(3) vi の abbreviations、(4) snipets, (5) マクロ関数 などがあります。以下比較します。

テキストファイル挿入

エディタによっては、テキストファイルをカーソル位置に挿入する機能があります。
この機能を使えば、定形テキストをカーソル位置に読み込むことが可能です。
しかし、「ファイル挿入」コマンド実行 → ファイル選択 という操作は Zen-Coding に比べるとステップが多く、 パラメータ指定による柔軟なテキスト生成が不可能です。

短文入力

エディタによっては、登録テキストをカーソル位置に挿入する機能があります。
この方法はテキストファイル挿入よりはステップが少ない場合が多いですが、 やはり、パラメータ指定による柔軟なテキスト生成が不可能です。

vi の abbreviations

vi には abbreviations(短縮入力)という機能があり、「.virc」ファイルに展開元、展開後テキストを記述しておくことで、 キーワードなどを短いテキストで入力することが可能です。
しかし、テキスト展開がスペース(半角空白)キーのために i、a などといったよく使う1文字を展開元として指定すると、 i という文字そのものを入力出来ないという不都合が起こります。
また、直後が空白でないといけないため、「return;」を「ret」で入力するということも出来ません (厳密には不可能ではないが、末尾に余分な空白が付加されてします)。
また、ファイル挿入・短文入力同様にパラメータ指定による柔軟なテキスト生成が不可能です。

snipets

Zen-Coding と snipets は非常によく似ています。本稿と実質的に同じ機能を snipets と呼んでいる例もあるかもしれませんが、 筆者は、定型文を指定する時にパラメータを指定する方式が Zen-Coding であり、 展開前にはパラメータを指定せず展開後にパラメータ変更機能をサポートするものが snipets だと考えています。

例えば、本方式で「f」を展開すると「for (int i = 0; i < N; ++i) { }」となります。 変数名を「i」ではなく「k」にしたい場合は「f k」とします。
それに対して snipets では 「for (int i = 0; i < N; ++i) { }」を生成した後、「i」の部分一箇所を「k」に変更すると、 全ての「i」が「k」に変わる機能を提供しているものが主流です。
つまり、パラメータ的な部分を展開前に指定するか、展開後に指定するかという違いです。

この違いは一長一短です。
一般論を言えば、展開後を想像しパラメータを指定する必要があるので、Zen-Coding の方が若干敷居が高いかもしれません。 しかし、修正箇所への移動操作を考えると、Zen-Coding の方式の方が速くテキストを入力可能です。 それに間違った場合は undo で元に戻してパラメータを修正し再度展開することも可能なので、 事前にパラメータを指定することはそれほど高い敷居ではないと考えます。
また、テキストバッファに特殊な属性を付加する必要が無いので、実装的には Zen-Coding の方がはるかに簡単です。 スクリプト・マクロを使えばどのようなエディタにも簡単に Zen-Coding を実装可能だと考えます。

マクロ関数

筆者の知り合いに競技プログラミングを行っている人がいて、彼は速くコーディングするために以下のようなマクロを定義しています。

#define    rep(i,a,b)     for(int i = (a); i != (b); ++i)

この方式に比べると、Zen-Coding の打鍵回数は約2分の1です。 場合によってはいくつかのパラメータを省略出来る場合がありますし、デクリメントする場合にも対応しています。
また、この方式では他人がソースを読むにはマクロ定義を知っていないといけないという問題があります。 Zen-Coding であれば、展開後のソースは通常の文法に従ったものなので、誰でも直ぐにソースを理解することが可能です。

結論

Zen-Coding は定型的なテキストを短いストロークで高速に入力するため非常に優れた方式です。 しかも、自分で展開ルールを追加することも簡単だ。使わないと損だぜ。