WSL を使って Windows に快適なコマンドライン環境を構築する

unix 系の OS ではコマンドライン環境が充実しており、コマンドライン操作に慣れてしまえば GUI よりもストレスなく殆どの作業を行うことができる。

Windows にはコマンドライン環境が充実しているとは言えないが、近年搭載された WSL という機能を利用して、Windows 上に Linux をインストールすることができる様になった。

WSL を利用して快適なコマンドライン環境を手に入れよう。

# WSL環境の構築

WSL を快適に使うために、**Mintty, win32yank, AutoHotKey** 等を利用している。
WSL を含むこれらのインストール方法などはググればたくさん出てくるので詳しいインストール方法などは説明しない。

## WSL有効化 & ディストリビューションのインストール

https://docs.microsoft.com/ja-jp/windows/wsl/install-win10

Microsoft Store からインストールする方法以外に、自分で作成したイメージをインストールすることも可能。
https://github.com/microsoft/WSL-DistroLauncher

## WSLtty (Mintty) のインストール

Linux 環境を手に入れてもコマンドプロンプト上では強力な機能を使い倒すことが出来ない。
そこで WSL 向けに開発されたターミナルエミュレーターを利用する。
https://github.com/mintty/wsltty
release から最新のインストーラーでインストールすると良いでしょう。

## win32yank

コマンドラインからクリップボードを操作するコマンドとして Mac なら `pbcopy` `pbpaste` Linux なら `xclip` 等があるが、Windows では [win32yank](https://github.com/equalsraf/win32yank) がある。
release から最新を落としてパスを通せばよい。

WSL は exe ファイルを直接呼び出せるが、exe 本体は Windows ファイルシステム上に存在しないと正常に動作しない様なので、次のようにシンボリックリンクを張っている。

```
% ls -l /usr/local/bin/
lrwxrwxrwx 1 root root 13 Jan 22 13:05 win32yank -> win32yank.exe
lrwxrwxrwx 1 root root 64 Jan 22 13:04 win32yank.exe -> /mnt/c/Users/takezo/AppData/Local/WSL.opt/win32yank/win32yank.exe
```

## AutoHotKey

[AutoHotKey](https://www.autohotkey.com/) を利用して、Mintty のウィンドウがアクティブな場合、 `左Winキー + C` で選択範囲のコピー, `左Winキー + V` でクリップボードからペーストを行えるようにしている。

```ahk:AutoHotKey.ahk
*<#c::
	if (WinActive("ahk_class mintty")) {
		Send,^{Insert}
	} else {
		Send,^c
	}
	return
*<#v::
	if (WinActive("ahk_class mintty")) {
		Send,+{Insert}
	} else {
		Send,^v
	}
	return
```

## 起動スクリプト

```js:open-wsltty.js
var fs = new ActiveXObject("Scripting.FileSystemObject")
var WshShell = new ActiveXObject("WScript.Shell");
var env = WshShell.Environment('PROCESS');

var Distro = WScript.Arguments(0)

var Terminal = "%LOCALAPPDATA%\\wsltty\\bin\\mintty.exe"
var Icon = fs.getParentFolderName(WScript.ScriptFullName) + "\\\"" + Distro + ".ico\""
var Config = fs.getParentFolderName(WScript.ScriptFullName)
var Shell = "/usr/bin/zsh --login"
var Command = Terminal + " -i " + Icon + " --WSL=\"" + Distro + "\" --configdir=" + Config + " -~ " + Shell

env.item("WSLENV") = "PATH/lu:USERPROFILE/pu:LOCALAPPDATA/pu:PROGRAMFILES/pu:ANDROID_HOME/pu:NDK_ROOT/pu"

WshShell.Run("cmd /c start " + Command, 0);
```

### Mintty のオプション

`-i`: アイコンの指定
`--WSL`: ディストリビューションを指定
`--configdir`: [config](https://github.com/mintty/mintty/wiki/Tips) ファイルのディレクトリの指定

私は zsh を使っているので `/usr/bin/zsh --login` で zsh のログインシェルを起動している。
bash を使うなら `/bin/bash -l`

`WSLENV` 環境変数を使い、`PATH` `USERPROFILE` `LOCALAPPDATA` 等の Windows 上で定義されている環境変数を WSL へ渡している。

### スクリプトの呼び出し

次のようなショートカットやバッチファイルを作って起動する。

```
\path\to\open-wsltty.js "Ubuntu-18.04"
```


スタートメニューなどに置いておくとランチャーなどが拾ってくれるので便利
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083/6e3b7c31-36b9-79f6-8adc-83d33fda5f8a.png)

ちなみにランチャーは [Hain](https://hainproject.github.io/hain/) を `Ctrl + Space` で Mac っぽく使っている。

# WSLの設定

## WSLENV

`Windows -> WSL` 又は `WSL -> Windowsアプリ` を呼び出す際に、環境変数を共有するための特殊な環境変数。
https://docs.microsoft.com/ja-jp/windows/wsl/interop

## /etc/wsl.conf

WSL起動時のマウントオプションやネットワーク構成を設定できる。
https://docs.microsoft.com/ja-jp/windows/wsl/wsl-config

私はデフォルトのまま利用している。

# 備考

WSL1 はファイルI/O がとても遅い。
WSL2 はファイルI/O は改善するが、処理性能が若干落ちるらしい。