# Vimで高速コーディングする方法

こんにちわ、ゴリラです。

Vimといえば高速でコーディングできるという印象を持っている方が多いのではないでしょうか? 今日は、Postfix Code Completion という手法をつかって早くコーディングする方法紹介します。

この方法を使えば次のgifのように、さくっとJSONを返すHTTPサーバーを立てられます。

sonictemplate-vim-sample.gif

# Postfix Code Completionとは

後置補完という補完手法です。 例えば、(a == b)に対してifを使いたい場合は(a == b).ifと入力して展開するとif (a == b) { }というふうに補完してくれます。

後ろのコードifが前のコード(a == b)に作用するという考え方です。 これを積極的に使用していくとより高速にコーディングできるようになります。

僕の場合は、割と後置補完だけではなくスニペットのように使っています。

# VimでPostfix Code Completionを使う方法

Vimではsonictemplate.vim (opens new window)というプラグインがサポートしています。 デフォルトではPostfixのパターンファイルが用意されています。<C-y><C-b>でパターンを展開できます。 もちろん自分でパターンファイルを用意することもできます。

まず、自前のテンプレートディレクトリを設定します。僕の場合は~/.vim/sonictemplate しています。

let g:sonictemplate_vim_template_dir = expand('~/.vim/sonictemplate')
1

次に、言語のディレクトリを作成します。ディレクトリ名はファイルタイプ名と同じにする必要があります。 jsならjavascriptというディレクトリを作成します。本記事ではGo言語のテンプレートを作っていきます。

$ mkdir ~/.vim/sonictemplate/go
1

次に、Postfixのパターンファイルを作ります。こちらもファイル名はファイルタイプと同じです。

$ vim ~/.vim/sonictemplate/go/go.stpl
1

このgo.stplにパターンを追記していきます。

# パターンの記述方法

次のように、1行目にパターンを2行目以降に展開後のコードを記述します。2行目以降はタブが必要です。

\(\S\+\)\.var$
	var {{$1}} = {{_cursor_}}
1
2

複数のパターンは空白行で区切られています。

\(\S\+\)\.var$
	var {{$1}} = {{_cursor_}}

\(\S\+\)\.iferr$
	if {{$1}} != nil {
		return {{$1}}
	}
	{{_cursor_}}
1
2
3
4
5
6
7
8

パターンは正規表現を使用する事ができます。そして展開したコードでは{{}}で囲ったプラグイン独自の構文を使用できます。 上記の例ではは後方参照(\(\S\+\)の部分)しています。は展開後カーソルの位置を指定しています。 {{}}を使った構文は他にもあります。ヘルプを参照してください。

# パターンの例

ぼくが使っているパターンをいくつか紹介します。

# dbを開く

  • パターン
db.open\.\(".*"\)\.\(".*"\)$
	db, err := sql.Open({{$1}}, {{$2}})
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	{{_cursor_}}
1
2
3
4
5
6
7
  • コード
// 展開前
db.open."sqlite3"."test.db"

// 展開後
db, err := sql.Open("sqlite3", "test.db")
if err != nil {
	log.Fatal(err)
}
defer db.Close()
1
2
3
4
5
6
7
8
9

# クエリを発行

  • パターン
db\.query\.\(.*\)$
	rows, err := db.Query({{$1}})
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()
	{{_cursor_}}
1
2
3
4
5
6
7
  • コード
// 展開前
db.query."select * from todos"

// 展開後
rows, err := db.Query("select * from todos")
if err != nil {
	log.Fatal(err)
}
defer rows.Close()
1
2
3
4
5
6
7
8
9

# JSONのエンコード

json\.encode\.\(\S\+\)\.\(\S\+\)$
	if err := json.NewEncoder({{$1}}).Encode({{$2}}); err != nil {
		{{_cursor_}}
	}
1
2
3
4
// 展開前
json.encode.writer.&gorilla

// 展開後
if err := json.NewEncoder(writer).Encode(&gorilla); err != nil {
	
}
1
2
3
4
5
6
7

# JSONのデコード

  • パターン
json\.decode\.\(\S\+\)\.\(\S\+\)$
	if err := json.NewDecoder({{$1}}).Decode({{$2}}); err != nil {
		{{_cursor_}}
	}
1
2
3
4
  • コード
// 展開前
json.decode.reader.&gorilla

// 展開後
if err := json.NewDecoder(reader).Decode(&gorilla); err != nil {
	
}
1
2
3
4
5
6
7

# append

  • パターン
\(\S\+\)\.append\.\(\S\+\)$
	{{$1}} = append({{$1}}, {{$2}})
	{{_cursor_}}
1
2
3
  • コード
// 展開前
gorillas.append.gorilla

// 展開後
gorillas = append(gorillas, gorilla)
1
2
3
4
5

# HTTPサーバー

  • パターン
http\.server\.\(\S\+\)$
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		{{_cursor_}}
	})
	log.Println("start http server :{{$1}}")
	log.Fatal(http.ListenAndServe(":{{$1}}", nil))
1
2
3
4
5
6
  • コード
// 展開前
http.server.8080

// 展開後
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
	
})
log.Println("start http server :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
1
2
3
4
5
6
7
8
9

# main

  • パターン
^main$
	package main
	
	func main() {
		{{_cursor_}}
	}
1
2
3
4
5
6
  • コード
// 展開前
main

// 展開後
package main

func main() {
	
}
1
2
3
4
5
6
7
8
9

# 最後に

いかがですか? この記事を見て少しでも早くコーディングできるようになったら嬉しいです。

では良いコーディングライフを〜