【Sublime Text3】行末にセミコロンを追加するショートカットを作成

#はじめに
[Atomで行末にセミコロンを追加する](https://qiita.com/hatta/items/3724f28908ea3fe6f479)ということをされている方がおられましたので、Sublime Text3ではどうなのかと思ったところ意外と検索しても見つからなかったので方法を考えてみました。

環境
OS: MacOS High Sierra
Sublime Text3: Version 3.0, Build 3143

#目標
- cmd + ; で行末にセミコロンを追加して改行する。
- ctrl + ; でカーソルの現在位置を変えずに行末にセミコロンを追加する。
- 以下のような状況で ctrl + ; を入力した場合、カーソルの現在位置を変えず次の行の行末にセミコロンを追加する。

```javascript
$("#id").on('click', function() {
	|
})
```

↓

```javascript
$("#id").on('click', function() {
	|
});
```

#方法
キーバインドの設定では複数のコマンドを実行させることはできないので、マクロを用意してそれをキーバインドで呼び出します。

マクロは Tools -> Record Macro で作成しました。
Record Macro -> 操作を実行 -> Stop Recording Macro -> Save Macro... で保存できます。

以下のような sublime-macro ファイルがPreferences -> Browse Packages -> Userディレクトリ内に保存されますので、操作を記録する代わりにこれらのファイルを作成して上記のディレクトリに保存すればよいでしょう。

####行末にセミコロンを追加して改行
操作：[ cmd + → ] -> [ ; ] -> [ enter ]

```add-semicolon-to-eol-and-enter.sublime-macro
[
	{
		"args":
		{
			"to": "eol"
		},
		"command": "move_to"
	},
	{
		"args":
		{
			"characters": ";"
		},
		"command": "insert"
	},
	{
		"args":
		{
			"characters": "\n"
		},
		"command": "insert"
	}
]
```

####カーソルの現在位置を変えずに行末にセミコロンを追加
操作：[ cmd + F2 ] -> [ cmd + → ] -> [ ; ] -> [ shift + F2 ] -> [ cmd + F2 ]

```add-semicolon-to-eol.sublime-macro
[
	{
		"args": null,
		"command": "toggle_bookmark"
	},
	{
		"args":
		{
			"to": "eol"
		},
		"command": "move_to"
	},
	{
		"args":
		{
			"characters": ";"
		},
		"command": "insert"
	},
	{
		"args": null,
		"command": "prev_bookmark"
	},
	{
		"args": null,
		"command": "toggle_bookmark"
	}
]
```

####次の行の行末にセミコロンを追加
操作：[ ↓ ] -> [ cmd + → ] -> [ ; ] -> [ ↑ ] -> [ Tab ]

```add-semicolon-to-next-line.sublime-macro
[
	{
		"args":
		{
			"by": "lines",
			"forward": true
		},
		"command": "move"
	},
	{
		"args":
		{
			"to": "eol"
		},
		"command": "move_to"
	},
	{
		"args":
		{
			"characters": ";"
		},
		"command": "insert"
	},
	{
		"args":
		{
			"by": "lines",
			"forward": false
		},
		"command": "move"
	},
	{
		"args": null,
		"command": "reindent"
	}
]
```

なお、「カーソルの現在位置を変えずに行末にセミコロンを追加」ではカーソルの現在位置を記録するのに（手抜きで）ブックマークを使っています（現在位置をブックマーク -> 行末に移動 -> セミコロン追加 -> ブックマークした位置に戻る -> ブックマークを削除）。そのためカーソルの現在位置と行末の間にブックマークが存在しているとうまく動作しませんが、そのような状況はあまりないと思われるため目をつぶることにしました。

あとはキーバインドでマクロを呼び出すようにすれば完成です。

メニューから
Sublime Text -> Preferences -> Key Bindings
を選択すると Default と User の2つの keymap ファイルが開きますので、 User の方に以下の記載を追加します。

```
    // cmd + ; で行末にセミコロンを追加して改行するマクロを起動
    {
        "keys": ["super+;"],
        "command": "run_macro_file",
        "args": {
            "file": "Packages/User/add-semicolon-to-eol-and-enter.sublime-macro"
        }
    },
    // カーソルが行末にあるときは ctrl + ; で次の行にセミコロンを追加するマクロを起動
    {
        "keys": ["ctrl+;"],
        "command": "run_macro_file",
        "args": {
            "file": "Packages/User/add-semicolon-to-next-line.sublime-macro"
        },
        "context": [
            { "key": "following_text", "operator": "regex_match", "operand": "$" }
        ]
    },
    // カーソルが行末にないときは ctrl + ; で行末にセミコロンを追加するマクロを起動
    {
        "keys": ["ctrl+;"],
        "command": "run_macro_file",
        "args": {
            "file": "Packages/User/add-semicolon-to-eol.sublime-macro"
        },
        "context": [
            { "key": "following_text", "operator": "not_regex_match", "operand": "$" }
        ]
    },

```

 ctrl + ; でセミコロンを現在の行に追加するのか、次の行に追加するのかは単純にカーソルが行末にあるかどうかで判断しています。

#終わりに
あまり需要はないかもしれませんが、私はちょっとややこしい文を書くときはセミコロンを先に打っておきたい派なので重宝しそうです。
また、キーバインドでマクロを呼び出す方法は色々と応用が利くのではないかと思います。