WindowsでCmderとPowershellによる快適なコマンド環境を整える

![2021-04-08_13h48_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1036918/ae4c44f9-2a90-f2dd-4df7-09aa6b1c272c.png)

# 前提

- Windowsで便利なコマンド環境を整えたい
- コマンドプロンプト嫌い
- タブ化必須
- `git`, `vim`必須
- `Windows Terminal`詳しくない
    - `ConEmu`, `Cmder` に結構前からお世話になってきた人間なので、、

# 概要

以下が全部できるWindowsコマンド環境を、整える方法をまとめる。

- 画面: タブ化、分割、透過
- `git`と`vim`の操作
    - `git`コマンド補助ツール(`posh-git`)
- 基本的なアプリケーションのコマンドからの起動
    - ファイルエクスプローラ
    - テキストエディタ
    - IDE(VisualStudioとか)
    - gitクライアントアプリ
- `ssh`
- コンピュータ管理系
    - プロセス・サービス管理
    - パフォーマンスカウンター
    - イベントログ

以上ができたらWindowsコマンド環境としてとりあえず満足。
`Windows Terminal`にまだ詳しくない自分にとっては、
`Cmder`+`Powershell`環境が以下の点でベスト。

- `git`と`vim`が内蔵されている
- `git`の強力な補助ツール`posh-git`が簡単に導入できる
- windows関連の命令に強い(プロセス、サービス、カウンター、イベントログ)
- (個人的にPowershellのオブジェクト指向っぽいところ好き)

これを手軽に実現する手順と、よく悩みがちなところの解決方法をまとめる。

# 環境構築手順

## 概要

1. Cmderのダウンロードと設定調整
1. CmderのPowershellプロファイル`user_profile.ps1`のカスタマイズ
1. Cmder内蔵vimの動作確認と`.vimrc`について
1. `git`コマンド補助ツール `posh-git`導入
1. 各アプリケーションとの連携

## Cmderのダウンロードと設定調整

1. [Cmder公式](https://cmder.net/) から **Full版** をダウンロード (`Download Full`)
1. 好きな場所にzipを展開(自分はドライブ直下)
    - 自分はドライブ直下に展開するので、`C:\cmder` のようなフォルダが出来上がる
1. cmderフォルダ配下の`cmder.exe`を右クリックし、`タスクバーにピン留めする`を行っておく
    - 注意: cmderから起動される実体は内蔵されている`ConEmu`なので、起動中のアプリからピン留めしようとすると`ConEmu`の方がピン留めされてしまう
    - そのため、`cmder.exe` ファイルを右クリックして、このexe自体をピン留めしておく必要がある
1. Cmderを初起動
    - 注意: 最初はダウンロードしたexeなので実行がブロックされていることがあり、その場合は気にせず実行許可する。
    - 注意: 内蔵されているdllやexeについても実行がブロックされていることがある
        - その場合、 **起動後に警告ダイアログが開く** ので、`Unblock and Continue`を選択する
1. Cmderの設定: `Win + Alt + p`、もしくは右下のメニューボタン(三本線ボタン)からSettingsを押し、設定画面を開く
    - 設定を変更したら、最後に`Save settings`ボタンを押すことを忘れずに！
    - `Powershell`をデフォルト起動シェルにする
        - General: Choose your startup task
            - `Powershell::Powershell as Admin` に設定
        - 一度`Save settings`で保存し、`Ctrl + T`を押して新タブを開く
            - `Startup command`が`Powershell::Powershell as Admin`になっていることを確認し、`Start`を押す
        - 1つめのタブは`Cmder as Admin`(コマンドプロンプト)で開かれていたが、これ以降デフォルトで`Powershell`が開かれるようになる
        - 以降は`Powershell`が開かれている前提の話
    - タブの調整: General - Tab bar
        - スマートタブ化(`Ctrl + tab`を押した時のタブ遷移を使用順にする)
            - `Lazy tab switch`をオフ、`Recent mode`をオン
        - タブ表示を画面トップへ変更
            - `Tabs on bottom`をオフ
            - デフォルトでボトムにあるのはなぜなのか、、
    - シェルを画面分割で複数開いているとき、カーソルホバーしている画面が自動でアクティブになるのを止める
        - 個人的にはこれを不便に感じることの方が多かった
        - Keys & Macro - Mouse
            - `Active split/pane on mouse hover`をオフ
    - lsを打った時など、文字幅が行によってズレる場合の対処
        - コンピュータやフォントによってこの現象が起こったり起こらなかったり
        - General - Fonts
            - 以下の双方をオフにすると改善することがある
                - `Adjust font size for monitor DPI`
                - `Compress long strings to fit space`
    - ショートカットキー設定: Keys & Macro
        - 画面分割
            - `Ctrl + T`を押したときに、`New console split`を`Layered`ではなくて`To bottom`や`To right`にすれば分割できるが、面倒
            - 以下の2つを指定すると便利、`duplicate`でフィルタするとすぐ見つかる
                - 下半分に画面分割: `Split: Duplicate active shell split to bottom`
                    - 自分は`Ctrl + Shift + B`
                - 右半分に画面分割: `Split: Duplicate active shell split to right`
                    - 自分は`Ctrl + Shift + R`
        - 透明度調整
            - もし透明度を時々調整したくなるなら、以下の2つを指定すると便利、`trans`でフィルタするとすぐ見つかる
                - 透明度アップ: `Transparency: more translucent`
                    - 自分は`Alt + WheelUp`
                - 透明度ダウン: `Transparency: more opaque`
                    - 自分は`Alt + WheelDown`

## CmderのPowershellプロファイルのカスタマイズ

CmderのPowershellのプロファイル: `cmder\config\user_profile.ps1`
注意: プロファイルを更新したら、`.$PROFILE`コマンドを実行するか、
もしくはシェルを開きなおさないと反映されない。(Cmder自体を開きなおす必要はないよ！)

- 上プロファイルをエディタで開く
    - 内蔵`vim`がすぐ動く場合はそれで良いが、デフォルトだとvimにパスが通っていないこともあるので注意
- プロンプトのカスタマイズ
    - `[ScriptBlock]$PrePrompt`をカスタマイズすることで自由に変えられる
    - 自分の場合

```powershell
[ScriptBlock]$PrePrompt = {
    Write-Host "[" -ForegroundColor "White" -NoNewline
    Write-Host "PS" -ForegroundColor "Blue" -NoNewline
    Write-Host "] " -ForegroundColor "White" -NoNewline
    Write-Host "[" -ForegroundColor "White" -NoNewline
    Write-Host "$((Get-Date).ToString("MM/dd HH:mm:ss"))" -ForegroundColor "Blue" -NoNewline
    Write-Host "] " -ForegroundColor "White" -NoNewline
}
```

- 文字コードのおまじない
    - できるだけ`utf-8`にしておくと吉
    - 特に`LANG`環境変数は`vim`や`git`の日本語文字化けを防ぐための必須設定
    - ただし、ここで頑張っても、`cat`等のコマンドはデフォルトでutf-8の日本語が文字化けする
        - OSのデフォルトEncoding`[System.Text.Encoding]::Default`が`shift_jis`なので仕方ない
        - `cat hoge.txt -Encoding UTF8` のようにEncodingを指定する必要がある
    - また、`Powershell`のクセとして、パイプやリダイレクトが`utf-16`になるのも仕方ない
        - リダイレクトは`>`ではなくて、`Out-File`コマンドを使えば`cat`と同様Encodingを指定できる

```powershell
Set-Item env:LANG -Value ja_JP.UTF-8
chcp 65001
[System.Console]::OutputEncoding = [text.encoding]::UTF8
```

## Cmder内蔵vimの動作確認と.vimrc

### viやvimコマンドが実行できない場合

プロファイル(`cmder\config\user_profile.ps1`)に以下の処理を追加する。

```powershell
try {
    Get-command -Name "vim" -ErrorAction Stop > $null
} catch {
    new-alias -name "vim" -value $($ENV:CMDER_ROOT + "\vendor\git-for-windows\usr\bin\vim.exe")
    new-alias -name "vi" -value vim
}
```

原因不明だが、デフォルトで`vim`が動作するときと、これを指定しないと動作しないときがある。
今までセットアップした環境では体感半々くらい、、なぜだろう、、

### 日本語が文字化けする

プロファイル設定の欄に書いた`Set-Item env:LANG -Value ja_JP.UTF-8`を書き忘れているか、
プロファイルが未反映(`.$PROFILE`を実行してリロードしましょう)の可能性が高い。

### `.vimrc`を使う

自分のホームディレクトリ配下に`.vimrc`ファイルを作成すれば自動で読み込まれる。

例: gitのコミットメッセージの80文字自動改行をオフにする
(先に次章の`posh-git`導入を済ませてもらったほうが良いかも)

- `.vimrc`ファイルに以下を設定する

```vim
set tw=200
autocmd FileType gitcommit localset tw=0
```

- gitのコミットメッセージを編集するvim画面で、`:set tw?`を実行し、設定が反映されていればok

## gitコマンド補助ツールposh-gitを入れる

デフォルトで`git`が内蔵されているので、`git`コマンドが動作するはず。
あとはコマンド補助ツールを導入して便利にする。

- gitリポジトリのあるフォルダに移動すると、以下のような警告文が出る
    - `警告: Missing git support, install posh-git with 'Install-Module posh-git' and restart cmder.`
- これに従い、`Install-Module posh-git`をするだけで良いはず、、なのだが、、いくつか詰まりポイントがある

<details>
<summary>うまくいかないケースと対処方法</summary>
<div>

- `続行するには NuGet プロバイダーが必要です...`
    - これ関連は基本`Y`で続行すればいい
- `警告: URI 'https://ooxx/ooxx' から '' へダウンロードできません。...`
    - 2020年あたりで`Powershell Gallery`へのアクセスのTLS基準が厳しくなったらしく、古くから使っている環境だと、こうなることがある
    - * これについてはいろいろな方が対処方法を公開して下さっているので、詳しくはそちらを探してみてください
    - `[Net.ServicePointManager]::SecurityProtocol`を実行して、値に`Tls12`が含まれていなかった場合は、以下で治るはず
        1. `[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12`を実行して一時的に用いるTLSバージョンを上げる
        1. `Install-Module PowerShellGet -RequiredVersion 2.2.4 -SkipPublisherCheck`を実行して`PowerShellGet`をアップデートする
- うまくインストールできたはずだが、`[(main)]`のようなstatus情報がプロンプトの後ろに表示されてしまう
    - 最近よくこうなる気がする、、本来はPrePromptの後ろに表示されるべきだが、なぜかプロンプト全体の末尾に表示されてしまう
    - Cmder側の問題なのか、posh-git側の問題なのか、、
    - とりあえず`Write-VcsStatus`関連の問題であり、以下により治せる
        - `cmder\vender\psmodules\Cmder.ps1`ファイルの`checkGit`関数を以下のように修正する

```diff_powershell
- Write-VcsStatus
+ Write-Host -NoNewline "$(Write-VcsStatus)"
```

- `警告: posh-git requires Git x.x or better. You have y.y`
    - `git --exec-path`を実行し、`cmder\vendor`配下のパスになっていない場合、`git`が他にもインストールされており、そちらへのパスが優先されてしまっている可能性が高い
    - システム環境変数やユーザー環境変数に他の`git`のパスが通っていないかどうかを確認する
    - 他の`git`へパスが通ってしまっている場合は、その環境変数が本当に必要なのかどうか確認し、必要ないならパスから削除する
        - 他のシェルとgitを使い分けたい場合であれば、そちらのプロファイル上でプロセス限定でパスに設定するとか
- その他うまくいかない場合、以下をいろいろ試してみる
    - `Powershell`の`ExecutionPolicy`を調整する
        - Cmderから起動される`Powershell`はProcessスコープでBypassになっているので問題ないはずだが、他のスコープの設定が問題になることがあるかも？
    - `Powershell`の権限が管理者ではない
        - 普通にCmderを起動すると、最初のタブは管理者権限になるが、それ以降開いたタブは管理者権限にならない
            - `Powershell as Admin`で開いても管理者権限にならない、なぜだろう、、
        - なので、管理者権限が必要な操作を行う場合は1つめのタブで操作するか、もしくはcmder自体を右クリックから「管理者として実行」を押して起動しておけば、新たに開くタブも全部管理者権限で開ける
    - `cmder\vendor\`配下のexeやスクリプト系のファイルブロックを解除してみる
        - ファイルのプロパティを確認すると結構ブロックされていたりする、ブロックされていても問題ないことも多いが、これで解決することもあるかも？

</div>
</details>

## 各アプリケーションとの連携

プロファイル`cmder\config\user_profile.ps1`に設定を書くことで、
ユーザー環境変数等々を変更しなくても気軽にパスを通せる。

- コマンドエイリアス設定: `New-Alias`コマンド
    - SublimeText3: `New-Alias subl "C:\Program Files\Sublime Text 3\subl.exe"`
        - 手軽なエディタに
        - 使用例
            - `subl hoge.txt`: ファイルを開く
            - `subl -n hoge.txt`: 新しいウィンドウでファイルを開く
            - `subl .`: 今いるフォルダ毎開く
    - SublimeMerge: `New-Alias smerge C:\Program Files\Sublime Merge\smerge.exe`
        - gitクライアントアプリ
        - `smerge .`: 今いるフォルダのgitリポジトリを開く(`.git`フォルダが直下に存在するフォルダに対して使う)
        - `-n`などのオプションは SublimeText3 と同様の感覚で使える
    - VisualStudioCode: `New-Alias vscode "~\AppData\Local\Programs\Microsoft VS Code\Code.exe"`
        - つよつよエディタ
    - VisualStudio: `New-Alias vs "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.exe"`
        - IDE
        - バージョンやCommunityかProfessionalかでもパスが変わるので要確認
        - `vs hoge.sln`: ソリューションを開く
    - DB Browser for SQLite: `New-Alias sqlite "C:\Program Files\DB Browser for SQLite\DB Browser for SQLite.exe"`
        - SqliteのGUIアプリ
    - jupyter-notebook: `New-Alias ju jupyter-notebook`
        - `python`と`jupyter-notebook`をインストール済みならパスは既に通っていると思う
        - それでも、よく使うものは短めのエイリアスをセットしておくと捗る
- 関数定義: `function`定義
    - 特定の引数を取らせたい場合はエイリアス設定ではなくて関数定義を行う
    - `function st {git status}`
        - `st`と打つだけで`git status`コマンドを実行させる
    - `function editProfile {subl -n C:\cmder\config\user_profile.ps1}`
        - コンフィグファイルのパスを覚えるくらいなら、関数化しておくのが便利
        - 自分は`jupyter-notebook`や`keyhack`のコンフィグ設定等々も同様に関数登録してある
- シェル環境変数のパスを追加: `$Env:Path += ";C:\hoge"`
    - 例: 自作関数群にパスを通す
        - `$Env:Path += ";$(cvpa ~)\Documents\WindowsPowerShell\MyPowerShellScripts"`
            - `cvpa ~`について
                - 環境変数設定は文字列として追加するだけなので、ホームディレクトリ`~`はそのままでは使えない
                - `cvpa`(`Convert-Path`)コマンドでパス解決して文字列に埋め込めばいい
                - `C:\Users\ooxx\...`のように直接書いてしまってもよいが、できればユーザー名に依存しない設定にしておくのが吉

# 出来上がった環境を使う！

以上で構築完了。

## 最初に目指した環境になっているかどうか確認

- 画面: タブ化、分割、透過
    - Cmderが全部かなえてくれた
    - ショートカットキーまで設定してあれば自由自在
- `git`と`vim`の操作
    - Cmderに内蔵されていてすぐ使える
    - `posh-git`便利
- 基本的なアプリケーションのコマンドからの起動
    - ファイルエクスプローラ
        - `ii .`コマンド
    - テキストエディタ
        - エイリアス等をプロファイルで設定しておくだけ
    - IDE(VisualStudioとか)
        - エイリアス等をプロファイルで設定しておくだけ
    - gitクライアントアプリ
        - エイリアス等をプロファイルで設定しておくだけ
- `ssh`
    - 最近のWindowsはデフォルトでOpenSSH入っているので普通に`ssh`コマンド使える
    - 問題があったらCmderからbashを立ち上げて`ssh`すればいい
- コンピュータ管理系
    - プロセス・サービス管理
        - `ps`, `kill` `Get-Service`, `Restart-Service`, `Stop-Service`, ...
        - `Get-WmiObject Win32_Process | ?{$_.Name -match "powershell"} | fl -Property Name,CommandLine,ProcessId`
            - powershellやpythonなど同名で複数プロセスが立ち上がっている時に、コマンドラインから特定プロセスのIdを見つけたいときによく使う
    - パフォーマンスカウンター
        - `Get-Counter`
    - イベントログ
        - イベントログリスト: `Get-EventLog -List`
        - Applicationログ最新5個: `Get-EventLog Application -Newest 5`
        - フォーマットして表示: `Get-EventLog Application -Newest 5 | fl`
        - 直近のErrorログを確認: `Get-EventLog Application -Newest 1000 | ?{$_.EntryType -eq "Error"}`

## その他tips

- ヘルプ: `Get-Help`コマンド
- tab補完
    - コマンド名、オプション名、値等々かなり補完してくれるので積極活用
    - `posh-git`が入っていれば、`git`コマンドやブランチ名などもかなり補完してくれる、捗る
- `Ctrl + space`補完
    - 補完候補一覧を全部表示してくれる、候補をカーソルで選べる。ファイルパスの補完に便利
- 履歴から補完: 途中まで打って`F8`
- 履歴から検索: `Ctrl + r`を打って検索ワードを入力、`Ctrl + r`を連打すれば次々検索
- コピー、ペースト
    - `Ctrl+c`, `Ctrl+v`も使えるが、実は要らない(人によってはむしろオフにした方がよいかも)
    - 実はドラッグしたら自動でコピーされているので、`Ctrl+c`を押す必要がない
        - ドラッグもダブルクリック1回で単語選択、2回で行選択が使える
    - ペーストは右クリックで可能
- プロンプトのカレントパスのコピー不具合
    - よくある不具合例
        - 別タブのプロンプトからカレントパスをコピーしてきて、同じパスへcdしようとすると、ドライブ名がおかしいと言われる
    - プロンプトのカレントパスにはドライブ文字の前に謎の文字コードが入り込んでいる！！
    - カレントパスをコピーしたい場合は、`pwd`か`cvpa .`コマンドの出力値を用いるのが良い