Windows
Linux
fish
WSL

Windows & WSL Linux & Hyper & Fish & PhraseExpress

目的

 WSL(Windows Subsystem for Linux)の登場により、開発環境としてのWindowsの利便性は格段に向上しつつある。

 今回は、WSL上のLinuxとWindowsを相互に行き来しながら開発するために、細かい環境を整えたので、些末な内容だが共有する。

WSLインストール

 以下の記事を参照して導入する。
 Windows 10でLinuxプログラムを利用可能にするWSL(Windows Subsystem for Linux)をインストールする(バージョン1803対応版)

Hyperターミナルのインストール

注意:この記述はすでに古い。いずれ削除予定。現在は後述する # 追記:新たな選択肢 - WSLtty の方を参照してほしい。

Hyper

を導入する。

Hyperの環境設定で、以下の行を設定する。これで、Hyperで起動するシェルはWSL環境でデフォルト扱い(複数のLinuxがインストールされている場合の話)になっているLinux環境のシェルになる。

shell: 'C:\\Windows\\System32\\bash.exe',

image.png

WindowsのファイルパスをWSL環境のパスに変換する

Windowsのエクスプローラからフォルダなどをターミナルウィンドウにドラッグ&ドロップすると、Windows形式のファイルパスがターミナルに入力される。これを、WSL形式のパスに変換するシェル関数を用意した。

cdw () {
    cd "$(echo $1 | sed -e 's/\(.\):/\/mnt\/\L\1/' -e 's/\\/\//g')"
}

これを.bashrcなどに記載しておく。

そして、 $ cdw と打ってから、Windowsのエクスプローラのフォルダをドラッグアンドドロップする。(Windows形式の)パスが入力されるので、そのままエンターキーを押すと、望みのパスに問題なく移動することができる。

cdw.gif

 これが、普通のコマンドプロンプトだと、「パスにスペースが含まれるフォルダ」はダブルクォーテーションでパスが囲まれて入力されるのでうまくいく。しかし、「パスにスペースが含まれないフォルダ」はダブルクォーテーションに囲まれずにパスが入力されるために、\が解釈時点で捨てられてしまう挙動によって正しく動作しない現象に悩まされた。
 Hyperターミナルソフトは、どのようなフォルダでも常にシングルクォーテーションで囲むという一貫した動作であったので、今回はWindowsにおけるターミナルソフトはHyperに落ち着いた。この問題が解決する以外にも、Hyperには多くの魅力があると感じた。

スニペットツール

 スニペットツールとは、TextExpanderに代表される、いわゆる短い省略形をタイプするだけで、長いテキストに展開してくれる入力補助ツールだ。
 TextExpanderだと、Hyperとの組み合わせではうまく動作しなかったため、最近マルチプラットフォーム化を果たした競合ソフトであるPhraseExpressに乗り換えた。こちらはHyperでうまく動作する。
 TextExpanderはサブスクリプション課金形式に移行したことで世の不満が出ているようだ。個人的にそれくらい大目に見ればいいとは思うが、PhraseExpressの方が(特にWindows版は)多機能に感じる。今後はPhraseExpressの方がシェアを伸ばすかもしれない。

追記:PhrageExpressとHyperの組み合わせでは、ある程度以上の長さのスニペットの展開でエラーが起きるようだ。

WSL環境以外のシェルから、WSLデフォルトLinuxのシェル環境のコマンドを利用する

 コマンドプロンプト/PowerShell/MSYS いずれからでも、

$ wsl ls

 などと、wslの後に実行したコマンドを続けることで、WSL環境でデフォルト指定のLinux環境のコマンドを実行できる。

追記:新たな選択肢 - WSLtty

https://github.com/mintty/wsltty

WSLに特化したターミナル。前述のcdwなど必要なく、そのままターミナルにフォルダを放り込めば、/mnt/c/形式としてパスを入力してくれる。
スニペットソフトの対応については、こちらはPhrageExpressが全くダメで、逆にTextExpanderでは(長いスニペットも含め)全く問題なかった。現在はWSLttyとTextExpanderに落ち着いている。

WSL環境から、指定したディレクトリパスをWindowsエクスプローラで表示する

judge2020 という人が作った下記のシェルスクリプトが便利だ。

https://gist.github.com/judge2020/4450bc62df8adeeb29f02bd5524ab3db

$ explorer .

 で現在のカレントディレクトリをエクスプローラで開くことができる。

WebStormなどの統合開発環境でWSLシェルを利用する

WebStormなど、内部でターミナルを用意している開発環境では、大抵は使用したいシェルを指定できる。

image.png

 Node.jsなど、Windowsではあまりサポートが充実していない環境はWSLのLinuxで構築してしまい、WebStormからはWSLシェルを指定することで、Windowsへの親和性が薄い開発環境も問題なく利用することができる。

WSL環境で立てたローカルサーバーはWindows側からアクセスできる

例えば、WSL環境にNode製のhttpサーバーであるhttp-serverをインストールし、以下のようにすると。

$ http-server
Starting up http-server, serving ./
Available on:
  http://192.168.91.1:8080
  http://192.168.217.1:8080
  http://172.24.87.1:8080
  http://127.0.0.1:8080
  http://192.168.100.8:8080
Hit CTRL-C to stop the server

問題なくWindows側のWebブラウザで http://localhost:8080 とアクセスできる。

WSLでのSSHポートフォワーディングはWindowでも利用できる。

 WSLでSSHポートフォワーディングしたポートは、実はWindowsからも利用することができる。これならば、SSH関連はMSYSやWindows系の独自のSSHツールよりも、より安定したWSL Linux側のSSHに完全に任せることができるだろう。

例えば、rmateという仕組みを使い、ローカルマシンのWSL LinuxからSSH接続したサーバー上のファイルを、ローカルマシンWindowsのVisual Studio Codeで編集することができる。

(設定方法については他の人のQiita記事「Vagrant上のファイルをVScodeで編集 for Mac」などを参照のこと。MacやVagrantに限らず設定は基本同じである)

on WSL Linux

$ ssh -i ~/.ssh/hoge.pem centos@example.com -R 52698:localhost:52698

on Windows VS Code

image.png

on Server Linux

$ rmate hoge.txt

fishシェル

 個人的にBashよりもFishを好むため、以下のような環境を整えた。

常時Fishにする

以下のシェルスクリプトを.bashrcなどに記載しておくことで、シェル起動時に即座にfishに切り替わる。

# Fish
if [ -z "$FISH" ] && [ "${FISH:-A}" = "${FISH-A}" ]; then # if $FISH is undefined
  export FISH=1
fi
if [ $((FISH)) != 0 ]; then
    case $- in
        *i*) exec fish;;
        *) return;;
    esac
fi

bashに戻りたい場合は、下記コマンドを実行する。

set -x FISH 0; bash

bashから再びfishに切り替えたい場合は、下記コマンドを実行する。

FISH=1 fish

自分は、これらのコマンドの入力が面倒と感じ、PhraseExpressでそれぞれf2bb2fとしてスニペット登録している。

Fishでもcdwコマンドを使う

以下を、~/.config/fish/config.fishに記載する。

function cdw
    cd (wslpath $argv[1])
end

 wslpathコマンドは、Windows10 1803アップデートから含まれるようになった、Windows形式のファイルパスをWSL形式に変換するコマンドである。しかし、コマンドプロンプトやBashでは、このwslpathは完ぺきな利便性を提供してくれないように感じる。Bashの方で、sedコマンドを利用したcdwコマンドを自前で用意(といってもどこかのStackOverflowを参考にした)したのは、そのためである。
 しかし、HyperとFishの組み合わせであれば、wslpathコマンドはうまく機能する。
 Bashの時と同様に、エクスプローラからフォルダをドラッグ&ドロップして、cdw移動することができる。

Fishプロンプトカスタマイズ

 余談に近くなるが、個人で使っているプロンプトカスタマイズである。Gitのカレントブランチなどの情報も表示されるので、多少は便利かと思う(どこかでググった情報を参考にしたが、失念してしまった)。

# Fish Command Prompt Custumize
function fish_prompt --description 'Write out the prompt'
    # Just calculate these once, to save a few cycles when displaying the prompt
    if not set -q __fish_prompt_hostname
    set -g __fish_prompt_hostname (hostname|cut -d . -f 1)
    end

    if not set -q __fish_prompt_normal
    set -g __fish_prompt_normal (set_color normal)
    end

    if not set -q __git_cb    set __git_cb ":"(set_color brown)(git branch ^/dev/null | grep \* | sed 's/* //')(set_color normal)""
    end
    switch $USER
    case root

    if not set -q __fish_prompt_cwd
        if set -q fish_color_cwd_root            set -g __fish_prompt_cwd (set_color $fish_color_cwd_root)        else            set -g __fish_prompt_cwd (set_color $fish_color_cwd)
        end
    end
    printf '%s@%s:%s%s%s%s# ' $USER $__fish_prompt_hostname "$__fish_prompt_cwd" (prompt_pwd) "$__fish_prompt_normal" $__git_cb

    case '*'
    if not set -q __fish_prompt_cwd
        set -g __fish_prompt_cwd (set_color $fish_color_cwd)
    end

    printf '%s@%s:%s%s%s%s > ' $USER $__fish_prompt_hostname "$__fish_prompt_cwd" (prompt_pwd) "$__fish_prompt_normal" $__git_cb

    end
end

以下のような感じになる。

image.png

ディスクIO性能について

 詳しくは調べられていないが、WSL環境はディスクIOの性能に課題があるようだ。
 特にIO処理が多く伴うnode.jsのnpmやyarnのでのパッケージインストールではMacと比べて大幅に遅いなど、まだ問題点は散見される。
https://github.com/yarnpkg/yarn/issues/990
 これについては、とりあえずWindows Defenderなどのファイルアクセスをいちいちチェックするようなアンチウイルスソフトの監視で開発系のディレクトリを除外設定すると、だいぶ改善する模様。

まとめ

 *nix環境との互換とGUIソフトウェアの充実、セットアップの利便性という点で、今まではmacOSが開発環境として好まれていた。
 だがこの状況もやがて変わり、Windowsが死角のない最強開発プラットフォームの座に再び返り咲くと筆者は考える。