vim tips

今回はtipsと実例。というか半分ギャグ。
先のエントリで出てきた

int aCount = 0;
int bCount = 0;
int cCount = 0;
int dCount = 0;
/* 略 */
int ZCount = 0;

をまじで実装してみようかと。

まずはtips

先のエントリを書いた時に実際使ったのだが、今回のコマンドは"ga"


"g"始まりのコマンドはどうも多すぎて掴みきれないのだが、いくつか有用なのを拾っていこう。
ということでご紹介。


"ga"はカーソルの下の文字の文字コードを拾ってきます。
例えば"a"の上にカーソルを合わせて"ga"とすると
「<a> 97, 16進数 61, 8進数 141」
などの表示が一番下のラインに表示されます。
別にこれは半角だけではないのです。
例えば「例」は
「<例> 20363, 16進数 4f8b, 8進数 47613」
基本的にUnicodeっぽい。


まぁ、実際に使うような時って結構稀なんだけどね。

修行開始。

ということで先のエントリ

int aCount = 0;
int bCount = 0;
int cCount = 0;
int dCount = 0;
/* 略 */
int ZCount = 0;

をマジで実装。


なるべくvimっぽさを出そうとは思うのですが...どうにも...。


まずヘッダとか
流石にこれは普通に入力

#include <stdio.h>

int main( int argc, char** argv )
{

ここから怒涛の変数宣言。
Ctrl-Aは数字のインクリメントはできても英字はインクリメントできない。
ので、フィルターに頼ってみるのだが、いかんせん連番(?)の英字を出力するコマンドを思いつかない。
ということで、やや泥臭いのだがseqとtrで

:.!seq 0 9 | tr "0-9" "a-z"<Enter>
Go<Esc>
:./seq 0 9 | tr "0-9" "k-z"<Enter>
Go<Esc>
:./seq 0 9 | tr "0-9" "u-z"<Enter>
d3k			-- 最後'z'が余るので

改行は便宜上なので以外でEnterキーを押す必要はないです。
とりあえずこれでaからzをゲット。
コマンドラインコマンドは履歴から探ると早い。


AからZも欲しいところ。
ということで

25k			-- 'a'まで移動
yGP			-- 'a'-'z'を複製
v25j~			-- 大文字へ

これで'A'-'Z'と'a'-'z'をゲット。


で、これは後々使いたいので名前付きレジスタにヤンクしておこう

"ly51j			-- レジスタlにヤンク


で、ここから加工開始。
なんとなく矩形選択使いたいので使います。

<C-v>G			-- 矩形選択
ACount = 0;<Esc>	-- 選択範囲の後ろに"Count = 0;"を追加
gv			-- 再選択
Iint <Esc>		-- 選択範囲の前に"int "を追加

ということで宣言&初期化完了


"Go"で再び単純入力開始。

int i,j;
for( i = 1; i < argc; i++ ) {
        if( argv[i][0] == '-' ) {
                for( j = 0; argv[i][j] != '\0'; j++ ) {
                        switch( argv[i][j] ) {

そして怒涛のcaseの嵐。
とりあえず雛形は

				case 'a':
					aCount++;
					break;

かな。


ということで

"lp			-- レジスタlに保存しておいたものをプット
:.,$s/\(.\)/case '\1':\r\1Count++;\rbreak;/
			-- 現在行から最後までを置換。
			-- \rは環境によっては改行になってくれないかも。

完全黒魔術ですが

case 'A':
ACount++;
break;

が完成。
インデントが死んでますが、それは最後にまとめて直すので気にしない。


みたび直接入力

			} //switch終了
		} //for(j)終了
	} //if終了
} //for(i)終了

ということでカウントアップは終了。


これから表示。
例のごとく雛形

if( aCount != 0 ) {
	printf( "a:%d\n", aCount );
}


及び黒魔術

"lp
:.,$s/\(.\)/if( \1Count != 0 ) {\rprintf( "\1:%di\n", \1Count );\r}/


またも直接入力

return 0;
}

で完成!!
黒魔術ばかりだ。


とりあえずコンパイル...。
...まじで動いたよ...(汗
これ提出しようかな。
ソースコード379行


で、このままだと流石にインデントがあれなので修正。
vimには整形機能がついてるので使っちゃいましょう。

gg=G			-- ソース全体を整形しなおす。

便利!!


ということで完成したソース

#include <stdio.h>

int main( int argc, char** argv )
{
	int ACount = 0;
	int BCount = 0;
	/* 略 */
	int ZCount = 0;
	int aCount = 0;
	int bCount = 0;
	/* 略 */
	int zCount = 0;
	int i,j;
	for( i = 1; i < argc; i++ ) {
		if( argv[i][0] == '-' ) {
			for( j = 0; argv[i][j] != '\0'; j++ ) {
				switch( argv[i][j] ) {
					case 'A':
						ACount++;
						break;
					case 'B':
						BCount++;
						break;
					/* 略 */ 
					case 'Z':
						ZCount++;
						break;
					case 'a':
						aCount++;
						break;
					case 'b':
						bCount++;
						break;
					/* 略 */
					case 'z':
						zCount++;
						break;
				}
			}
		}
	}
	if( ACount != 0 ) {
		printf( "A:%d\n", ACount );
	}
	if( BCount != 0 ) {
		printf( "B:%d\n", BCount );
	}
	/* 略 */
	if( ZCount != 0 ) {
		printf( "Z:%d\n", ZCount );
	}
	if( aCount != 0 ) {
		printf( "a:%d\n", aCount );
	}
	/* 略 */
	if( zCount != 0 ) {
		printf( "z:%d\n", zCount );
	}
	return 0;
}

もはや狂気の沙汰。
でもちゃんと動きます(w


結局vimの機能のうち使った機能っていうと...

  • ヤンク/プット (y/p)
  • キャピタル変換 (~)
  • フィルタ (:!)
  • 置換 (:s)
  • 矩形選択 ()

むぅ...。
まだまだだなぁ...。