Cmderでオシャレにcmd.exeを使う -前編-
Cmderを使ってWindowsのcmd.exe
を快適にカッコよく使えるようにしてみました。
この写真で実行しているのはcmd.exe
です。
cmd.exe
でもCmder上で実行すると、ここまでオシャレになります。
Table of Contents
はじめに
経緯
今仕事ではWindows中心の開発をしています。
しかしWindowsはターミナルがイケていません… コマンドプロンプトを開くのは辛い。
Ubuntuではターミナル中心の快適な生活をしていました。
Windowsでも同様のことがしたい… それを目標に色々試しもしていました。
過去にチャレンジしたもの
『無理してcmd.exe
を使う必要はあるのか?』と思われるかもしれません。
cmd.exe
を脱却するために過去試したものを紹介します。
簡素な説明ですが、一度でも利用したことのある方なら伝わると思っています。
WSL
最近有名なWindows Subsystem for Linuxです。
Linux環境が提供されているのはありがたいことですが、Windows上のシステムと連携すると複雑になります。
今どちらのOSに対して作業をしているのか..を意識する必要があるため好きになれませんでした。
PowerShell
Windows公式でcmd.exe
とも互換性ある…らしいですが色々思うように動かなかったのでやめました。
そこまで色々試していないので、単に私の勉強不足かもしれませんが..。
git bash
Gitをインストールすると標準で搭載されているアレです。
以前にgit bashを快適に使うための記事を書きました。
WSLよりはWindowsシステム寄りではありますが、動いているのはbashであるのでどちらつかずな部分があります。
例えばcd $(fzf)
みたいなコマンドを実行できません。
Cmderとの出会い
Cmderについては次章で説明します。
試してみようと思ったのは以下の記事を目にしたからです。
決めては以下の2点です。
- 記事の文書に共感を覚えた (勝手ながらシンパシーを感じました 😄)
- 更新日時が最近
特に以下の点が心に刺さりました。
- Powerlineも使える環境にする
- カッコよくて見やすいターミナル、コンソールを目指す
前提条件
以下を知っている前提で進めます。
Cmderのインストール
公式サイトは以下です。
Chocolateyでインストールする場合は、C:\tools\Cmder
にインストールされます。
$ choco install cmder
Powerlineの導入
デフォルトもそこそこオシャレですが、情報を増やしたいのでPowerlineを導入します。
Powerline対応フォントのインストール
Powerline対応フォントをインストールします。
私はSource Code Pro for Powerlineを使用しています。
フォントのインストール方法が分からない...
フォントのインストール(Windows 10/8/7/Vista)
Cmder-powerline-promptの導入
CmderでPowerlineを有効にできるプロジェクトをCloneしてきます。
プロジェクトディレクトリ内のLuaファイルをCmderのconfigディレクトリ配下に移動します。
$ cp *.lua %cmder_root%\config\
設定をPowerline対応フォントに変更
フォントをPowerline対応フォントにします。
Boldは個人的な好みです。
Monospaceは日本語によるレイアウト崩れを防ぐために外しています。
コマンドの強化
cmd.exe
やCmderに内包されるgit-for-windows
のコマンドでは不十分のため色々インストールします。
Scoopで以下をインストールしました。
インストールコマンド
$ scoop install ^
sudo ^
bat ^
fd ^
7zip ^
fzf ^
less ^
ripgrep ^
make
インストールしたけど消してしまったもの
以下のツールは見送りました。
Windows上ではexeファイル実行時のラグが大きく、我慢できなかったからです。
- diff-so-fancy
Cmderの設定変更
代表的な設定をいくつか晒します。
背景の設定
記事の冒頭にあるスクリーンショットで移っていたフクロウの画像を背景に設定しています。
フクロウの画像はWallpaperCaveのものを使わせて頂きました。
cmd.exe直後のディレクトリをホームディレクトリに
起動直後は%USERPROFILE%
にいるのが便利だと思うので変更します。
赤枠下の部分にあるStartup dir...
ボタンを押してホームディレクトリを選ぶと、自動で入力されます。
なお、Cmder
では%home%
もホームディレクトリとして認識されます。
プロンプトの改善
デフォルトのMonokaiテーマ + Powerlineだけでもオシャレですが更に格好良くしましょう。
本節で紹介されているソースコードについて
Cmder-powerline-promptプロジェクトが更新された場合、正常に動作することを保証しません。
プロンプトのλを$にする
λだとLinuxユーザには馴染みが無く、半角文字でないことが仇となることがあるため変更します。
%cmder_root%\config\powerline_core.lua
を以下のように変更しましょう。
if not plc_prompt_lambSymbol then
- plc_prompt_lambSymbol = "λ"
+ plc_prompt_lambSymbol = "$"
end
本記事執筆時は115行目でした。
\vendor\clink.lua は変更しなくてもいいの...?
変更の必要はありません。
Google検索で調べるとclink.lua
を変更せよという記事が沢山出てきますが、それらはPowerlineを導入していない場合です。
Cmder-powerline-prompt
を導入している場合、プロンプトの設定はpowerline_core.lua
で上書きされるためclink.lua
を変更しても何も変わりません。
コマンドをプロンプト1行目に入力する
デフォルトだとコマンド入力はプロンプトに情報が表示された次の行(2行目)になります。
これをLinuxやコマンドプロンプトのように1行目で入力できるようにします。
%cmder_root%\config\powerline_core.lua
を以下のように変更しましょう。
-- Symbols
- newLineSymbol = "\n"
+ newLineSymbol = ""
本記事執筆時は100行目付近でした。
newLineSymbol
を空にするのは違和感ありますが、挙動は意図したとおりになったため目を瞑ります。
Gitリポジトリの情報を更に詳しく表示する
2018/11/27: より新しく優れた情報が展開されています
デフォルトだとブランチ名、変更や競合の有無が表示されます。
追加で以下の情報も表示できるようにしてみました。
- 追加/削除/変更の件数
- リモートリポジトリとの差 (ahead/behind)
改修後のイメージです。
%cmder_root%\config\powerline_git.lua
にいくつか改修を加えます。
色設定の追加/変更
aheadとbehindを追加して、全体の色設定を微調整します。
powerline_git.luaのsegmentColors
local segmentColors = {
clean = {
fill = colorGreen,
text = colorWhite
},
dirty = {
fill = colorRed,
text = colorWhite
},
conflict = {
fill = colorYellow,
text = colorWhite
},
ahead = {
fill = colorBlue,
text = colorWhite
},
behind = {
fill = colorMagenta,
text = colorWhite
}
}
ステータス取得関数の変更
追加、編集、削除、管理対象外のファイル数を取得できるように変更します。
powerline_git.luaのget_git_status()
function get_git_status()
local file = io.popen("git --no-optional-locks status --porcelain | awk '{print $1\"\\n\"}' | sort | uniq -c 2>nul")
local add, modify, delete, unknown = 0, 0, 0, 0
for line in file:lines() do
num, kind = string.match(line, ".+(%d+) (.+)")
if kind == "A" then
add = num
elseif kind == "M" then
modify = num
elseif kind == "D" then
delete = num
elseif kind == "??" then
unknown = num
end
end
file:close()
return add, modify, delete, unknown
end
Stagingエリアに追加済かの判定について
リモートリポジトリとの差分を取得する関数の作成
新しくgit_ahead_behind_module
関数を作成します。
powerline_git.luaのgit_ahead_behind_module()
function git_ahead_behind_module()
local file = io.popen("git rev-list --count --left-right @{upstream}...HEAD 2>nul")
for line in file:lines() do
ahead, behind = string.match(line, "(%d+).+(%d+)")
end
file:close()
return ahead, behind
end
各種情報をプロンプトに表示する
上記を利用してinit
関数を編集します。
powerline_git.luaのinit()
local function init()
segment.isNeeded = get_git_dir()
if segment.isNeeded then
-- if we're inside of git repo then try to detect current branch
local branch = get_git_branch(git_dir)
if branch then
-- Has branch => therefore it is a git folder, now figure out status
-- local gitStatus = get_git_status()
local add, modify, delete, unknown = get_git_status()
local ahead, behind = git_ahead_behind_module()
local gitConflict = get_git_conflict()
segment.text = " "..plc_git_branchSymbol.." "..branch.." "
segment.textColor = segmentColors.clean.text
segment.fillColor = segmentColors.clean.fill
if gitConflict then
segment.textColor = segmentColors.conflict.text
segment.fillColor = segmentColors.conflict.fill
if plc_git_conflictSymbol then
segment.text = segment.text..plc_git_conflictSymbol
end
return
end
if add ~= 0 then
segment.textColor = segmentColors.dirty.text
segment.fillColor = segmentColors.dirty.fill
segment.text = segment.text.."+"..add.." "
end
if modify ~= 0 then
segment.textColor = segmentColors.dirty.text
segment.fillColor = segmentColors.dirty.fill
segment.text = segment.text.."*"..modify.." "
end
if delete ~= 0 then
segment.textColor = segmentColors.dirty.text
segment.fillColor = segmentColors.dirty.fill
segment.text = segment.text.."-"..delete.." "
end
if unknown ~= 0 then
segment.textColor = segmentColors.dirty.text
segment.fillColor = segmentColors.dirty.fill
segment.text = segment.text.."?"..unknown.." "
end
if ahead ~= "0" then
segment.textColor = segmentColors.ahead.text
segment.fillColor = segmentColors.ahead.fill
segment.text = segment.text.."↓ "..ahead.." "
end
if behind ~= "0" then
segment.textColor = segmentColors.behind.text
segment.fillColor = segmentColors.behind.fill
segment.text = segment.text.."↑ "..behind.." "
end
end
end
end
コードが醜いですって? Lua書いたのは初めてなので勘弁してください 🙇♂️
リポジトリディレクトリでのもっさり感を軽減する
普通のディレクトリではサクサクですが、Gitリポジトリ内ではプロンプトの表示がもっさりします。
調べたところ、私には不要なコマンドが毎回実行されていました。
%cmder_root%\vendor\clink.lua
の一部をコメントアウトします。
clink.prompt.register_filter(set_prompt_filter, 1)
- clink.prompt.register_filter(hg_prompt_filter, 50)
- clink.prompt.register_filter(git_prompt_filter, 50)
- clink.prompt.register_filter(svn_prompt_filter, 50)
+ -- clink.prompt.register_filter(hg_prompt_filter, 50)
+ -- clink.prompt.register_filter(git_prompt_filter, 50)
+ -- clink.prompt.register_filter(svn_prompt_filter, 50)
clink.prompt.register_filter(percent_prompt_filter, 51)
hgはMercurial、svnはSVNですがどちらも使用していません。
以下のIssueが参考になりました。
マシン間の同期
Cmderはポータビリティがあるため、以下のディレクトリをGitやDropboxなどで同期しておけばOKです。
Cmder/config
Cmder/bin
clink.luaについて
clink.lua
はvendor
配下にあるため、上記2ディレクトリを設定しても同期されません。
そもそもvendor
配下を同期すべきかという話にもなりますので、同期せずに初回だけ対応としています。
コメントアウトだけですので。
トラブルシューティング
ハマった事例をいくつか紹介します。
aliasしたコマンドに引数が渡らない場合
末尾に$*
が付いていることを確認しましょう。
Linuxとは違い、そのままでは引数は渡されません。
- 🆖
alias ll=ls -l
- 🆗
alias ll=ls -l $*
aliasしたコマンドがPipeの先で上手く動かない
事象は把握しましたが関係する情報は見つけられていません。
alias sort="C:\tools\cmder\vendor\git-for-windows\usr\bin\sort.exe"
とした場合- 🆖
ll | sort
- 🆗
ll | C:\tools\cmder\vendor\git-for-windows\usr\bin\sort.exe
- 🆖
historyの結果をgrepできない
デフォルトで設定されているaliasが引数(Pipe)に対応していません。
以下のようにaliasを設定しましょう。
- 🆖
history=cat "%CMDER_ROOT%\config\.history"
- 🆗
history=cat "%CMDER_ROOT%\config\.history" $*
Vimに色が付かない
set termguicolors
の設定を削除したら解消しました。
正確な原因は分かっていません..。
tigの表示がおかしい
マルチバイト文字の無いリポジトリなら set LANG=ISO-8859-1
した後にtig実行で解決します。
しかし、マルチバイト文字があると文字化けします..。
tig2.4.1で改修されていそうですが、git bashに同梱されているtigが2.4.0のため確認できていません。
bat出力結果の色がおかしい
git bashのless(MSYSのless)が使用されている場合、色付けに対応していないのが原因です。
Scoopでlessをインストールすると解消されます。
一部のKey Bindingが変更できない
これも情報源を見つけることができていません。
私はAutoHotKeyを使用しているので、変更できない設定はそちらで対応してしまいました。
findやsortのオプションが指定できない
findやsortはc:\Windows\System32\
配下のコマンドが優先されます。
それらはLinuxのfindやsortとオプションが異なるため、指定できないように見えます。
aliasの設定もできなかったので、今のところスマートな解決方法は見つかっていません。
総括
Cmderを使ってWindowsのcmd.exe
をオシャレに使う方法を紹介しました。
タイトルからも分かるように今回前編です。
後ほど執筆予定の後編では、自作コマンドを駆使してイケてるLinux環境に負けないカスタマイズの仕方を紹介します。