コマンドプロンプトでの入力補完。

管理者モードのコマンドプロンプトでプロンプトを変える。AutoRun の設定をするときに regedit を開いたわけですが、HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processorキーには他に CompletionChar というキーがあります。うちではこの値は 0x40 になっています。

この CompletionChar はファイル名の補完機能の設定で、たとえばカレントディレクトリにabc.txtcde.txtxyz.txtがあったとき、a<TAB>と押せば abc.txt が補完され、x<TAB>と押せば xyz.txt が補完されます。

キーにはこのCompletionCharの他に、PathCompletionCharというのもあります。どちらもデフォルト値は 0x09 (TAB) に設定されているようです。が、自分のところでは両方ともに 0x40 です。なんで 0x40 なのかわかりません。上記のページでは 0x40 は "key" となっていて、詳しい説明がありません。が、動作としてはTABキーで補完してくれるので気にしないようにします。

ところで、CMD.EXEの補完機能は結構貧弱ですが、これをbash的な行編集機能にするためのClinkというアプリケーションがあるようです。

===
Clink combines the native Windows shell cmd.exe with the powerful command line editing features of the GNU Readline library, which provides rich completion, history, and line-editing capabilities. Readline is best known for its use in the well-known Unix shell Bash, the standard shell for Mac OS X and many Linux distributions.
===

ということで、CMD.EXEがかなりいい感じになるようです。
ClinkはインストーラーでインストールするとAutoRun値を書き換えてしまうようなので、ZIP形式をダウンロードして c:\Apps ディレクトリに配置します。

次に、前記事で書いた cmdrc.bat の最終行に次の行を加えます。
c:\Apps\clink_0.4.9\clink_x64.exe inject

ただ…せっかく指定したコマンドプロンプトのエスケープシーケンス (色) が消えてしまいました。すごく残念。なにかやりようはないかしら。でも、CTRL-Dでコマンドプロンプトを閉じることができるのは素晴らしいです。

結局cmdrc.batを以下のように変更しました。

@echo off
doskey /macrofile=%userprofile%\cmd.rc

c:\Apps\clink_0.4.9\clink_x64.exe inject

openfiles > NUL 2>&1

if %ERRORLEVEL% == 0 (
  rem 管理者モードの処理
  rem CRIMSON
  rem set PROMPT=$e[38;2;220;20;60m$p# $e[0m
  set PROMPT=$p# 
  set clink.prompt_colour=4
) else (
  rem 通常モードの処理
  rem deepskyblue
  rem set PROMPT=$e[38;2;0;191;255m$p$$ $e[0m
  set PROMPT=$p$$ 
  set clink.prompt_colour=3
)

これだと基本的な16色しか指定できないので、ちょっとつまらないんですが仕方ないですね。

管理者モードのコマンドプロンプトでプロンプトを変える。

コマンドプロンプトの色を変える。では、有無を言わさず自分が開くコマンドプロンプトのプロンプトを変えてしまう方法を書きました。

ところで自分が使用するNetBSDやLinuxやCygwin上では zsh を使用していて、suでrootになったときにはプロンプトを赤色に変更しています。通常のプロンプトはネイビーというかブルー系です。これは、うっかりミスをできるだけ防ぐように、という工夫です。

これを管理者モードのコマンドプロンプトでも実現できないか、と考えるわけです。

コマンドプロンプトの色を変える。

Windowsでコマンドプロンプトを使っていると通常は文字の色が全部白のため、スクロールバックしたときなどにどれがコマンドなのかがわかりにくくなります。

コマンドプロンプトを管理者モードで起動する方法。

「コマンドプロンプト」をタスクバーにピン留めしておいて、コマンドプロンプトを右クリックしてメニューを出して、さらに「コマンドプロンプト」の上で右クリックするともう一つメニューが出ます。



コマンドプロンプトにかぎらず他のアプリもこの方法で管理者モードで起動できます。

スタートメニューの場合には、アイコンを右クリックしてから「その他」を選択すると「管理者として実行」メニューが出ます。

コマンドプロンプトでエイリアスを使う。

Windowsのコマンドプロンプトでは、ドライブごとにカレントディレクトリを記憶している関係なのか、たとえばc:\tempからd:\appsに移動したいときに

c:\temp>cd d:\apps
c:\temp>

などとしても、カレントディレクトリはc:\tempのまま。d:ドライブに移動すると、d:ドライブではd:\appsに移動しているという実装になっています。つまり、カレントディレクトリはドライブごとに管理されています。

コマンドプロンプトの実体であるcmd.exeの組み込みコマンドcd (chdir)では、

cd /?

などとするとヘルプが表示され、その中に/dオプションがあることがわかります。これはドライブも含めて移動するオプションで、

c:\temp>cd /d d:\apps
d:\apps>

とすればカレントドライブもカレントディレクトリも同時に変更され、現在位置が d:\apps になります。

ところでWindows10では doskey というユーティリティがあり、これを使うとUNIX上のシェルのようにエイリアスを使用することができるようになります。

D:\apps>doskey /?
コマンド ラインの編集、Windows コマンドの再呼び出し、マクロの作成を行います。

DOSKEY [/REINSTALL] [/LISTSIZE=サイズ] [/MACROS[:ALL | :実行ファイル名]]
  [/HISTORY] [/INSERT | /OVERSTRIKE] [/EXENAME=実行ファイル名]
  [/MACROFILE=ファイル名][マクロ名=[テキスト]]

  /REINSTALL               Doskey の新しいコピーを組み込みます。
  /LISTSIZE=サイズ         コマンド履歴バッファーのサイズを設定します。
  /MACROS                  すべての Doskey マクロを表示します。
  /MACROS:ALL              Doskey マクロを含むすべての実行可能ファイルの
                           すべての Doskey マクロを表示します。
  /MACROS:実行ファイル名
                           指定した実行可能ファイルのすべての Doskey マクロを
                           表示します。
  /HISTORY                 メモリ内のすべてのコマンドを表示します。
  /INSERT                  入力したテキストが古いテキストに挿入されるように
                           指定します。
  /OVERSTRIKE              入力したテキストが古いテキストを上書きするように
                           指定します。
  /EXENAME=実行ファイル名  実行可能ファイルを指定します。
  /MACROFILE=ファイル名    作成するマクロ ファイル名を指定します。
  マクロ名                 作成するマクロ名を指定します。
  テキスト                 登録するコマンドを指定します。

上下方向キーはコマンドを再度呼び出します。Esc はコマンド ラインをクリア
します。F7 はコマンド履歴を表示します。Alt+F7 はコマンド履歴をクリアします。
F8 はコマンド履歴を検索します。F9 は数字によるコマンドを選択します。
Alt+F10 はマクロ定義をクリアします。

以下は、DOSKEY のマクロ定義で使用する特殊コードです:
$T     コマンド セパレーターです。マクロ中で複数のコマンドを定義できます。
$1-$9  バッチ パラメーターです。バッチ ファイル中の %1-%9 と同じ意味です。
$*     コマンド ライン上のマクロ名に続くテキストで置き換えられるシンボルです。

これを利用してコマンドプロンプトで doskey cd=cd /d $* とすれば、cd の動作が cd /d に展開されるのでドライブも一緒に変更できるようになります。

さらにこれをコマンドプロンプト起動時に自動的に設定するには、regeditを利用して HKEY_CURRENT_USER\Software\Microsoft\Command ProcessorAutoRunというキーを作り、そこに初期設定として実行したい内容を記述したバッチファイルを設定しておきます。

登録するバッチファイルは以下のような感じで作成しておきます。

@echo off
Doskey cd=cd /d $*
Doskey history=doskey /history
Doskey vim="C:\Program Files\Vim\vim.exe" $*

なんて感じで。

また、別なやり方として、ホームディレクトリにDOSKEYマクロファイルを置く方法もあります。ファイル名は cmd.rc で、以下のような内容を記述します。AutoRun には doskey /macrofile=%userprofile%\cmd.rcなどとします。

CD=CD /D $*
H=doskey /history
HISTORY=doskey /history
ALIASES=doskey /macros

こちらのほうが、よりUNIX的な感じがしますね。

よくわからないコマンドプロンプト。

ちょっとCMD.EXEシリーズ。

なにがわからないかというと、空白文字の扱い。

たとえば a.bat という名前で次の内容のファイルを作ります。

@echo %1

これを、a.bat あいうえお_かきくけこ と引数を与えて実行します。 "_" は全角空白に置き換えてください。

すると、 "あいうえお" が返ってきます。つまり全角空白がデリミタ (区切り文字) として処理されています。

次にコマンドプロンプトで直接

set a=あいうえお かきくけこ
echo %a%
あいうえお かきくけこ

今度は全角空白がデリミタではなく文字として扱われています。

これはかなり困った仕様で、バッチファイルに「ファイル名に全角空白文字を含んだファイル」を食わせると、勝手に分解してしまうのです。その結果、「指定されたファイルが見つかりません」エラーになります。全角空白をデリミタとして処理してしまうということを知らないと、なにがおかしいのかまったく見当もつかない状態になります。

これを防ぐにはダブルクォーテーションで文字列を囲うという方法があるのですが、その方法はドラッグ&ドロップでバッチファイルに食わせるときには使えません。つまり自動的には行ってくれません。それを解決するには、引数で与えられたファイル名をバッチファイル内部でダブルクォーテーションで囲い直す、などという処理が必要になってきます。

ところがたちの悪いことに、バッチファイルに「ファイル名に半角空白文字を含んだファイル」をドラッグ&ドロップで食わせると、コマンドプロンプトがバッチファイル内で自動的にダブルクォーテーションで囲ってしまうのです。するとどういうことが起こるかというと、「すでにダブルクォーテーションで囲われている文字列をさらにダブルクォーテーションで囲う」ということになり、結果「ダブルクォーテーションで囲われていない」のと同じ状態になってしまうのです。

それからファイル名に "&" の文字を含んでいるファイルをバッチファイルに食わせると、 "&" 以降を別のコマンドとして実行しようとしますので、これも注意が必要です。

はぁ…。

NeovimをVisual Studio 2017でコンパイルする。

必要要件

  • Windowsのシステムロケールを「英語(米国)」に変更しておく。
  • Git for Windowsをインストールし、パスを通しておく。
  • CMakeをインストールし、パスを通しておく。
  • 必要に応じてPython2、Python3、RubyおよびNode.jsをインストールし、パスを通しておく。特にShougo/dein.vimを使う場合にはPython3は必須となる。
  • gettext0.19.8.1-iconv1.15-shared-64.zipをダウンロードしておく。
  • Neovimインストーラを作成する場合にはNSISをインストールしておく。
パスについては、
setx GITPATH=C:\Program Files\Git\bin;C:\Program Files\Git\usr\bin;C:\Program Files\Git\mingw64\bin
setx CMAKEPATH=C:\Program Files\CMake\bin
setx PATH=%PATH%;%GITPATH%;%CMAKEPATH%
などとしておきます。こうしておくと、Git for Windowsに同梱されているMSYS系のコマンド (cpやpatchなど) が使えるようになります。CygwinやMSYSなどを別途インストールしておく必要はありません。

ビルドオプション

以下の条件でビルドします。
  • x64-Release
  • +iconv、+tui、-acl、-jemalloc
  • 作業は %USERPROFILE%/build ディレクトリで行う。
  • インストール先は c:\Apps\Neovim とする。
  • MSBuild を使うので、作業は「VS2017用 x64 Native Toolsコマンドプロンプト」で行う。(iconvは除く)

準備: libiconvのコンパイル

cd %USERPROFILE%\build
git clone https://github.com/kiyolee/libiconv-win-build
cd libiconv-win-build/build-VS2017-MT
  1. ここにある libiconv.sln をダブルクリックしてVS2017を起動する。
  2. このままビルドすると「Windows SDKバージョンが違う」というエラーが出るので、それぞれのプロジェクトのプロパティから変更する。
  3. 「Release」「x64」を選択してビルドする。

準備: 依存ライブラリのコンパイル

cd %USERPROFILE%\build
git clone https://github.com/neovim/neovim
cd neovim
mkdir .deps
mkdir build
cd .deps
"\Program Files\CMake\bin\CMAKE.exe" -G "Visual Studio 15 2017 Win64" ..\third-party
MSbuild ALL_BUILD.vcxproj /p:Configuration=Release
2018/5/1現在のmasterでは libuv にパッチが追加されたもののパッチできないため、libuv のコンパイルが失敗します。その場合にはなんとか自力で (libuv.vcprojなどを見ながら手動で) コンパイルしておきます。
ここまででツリー構造は以下のようになっているはずです。.deps以下にディレクトリが作られ、依存ライブラリはここにコピーされています。

build -+- neovim -+- .deps -- usr -+- bin
       |          |                +- include
       |          |                +- lib
       |          |
       |          +- build
       |
       +- libiconv-win-build -+- include -- iconv.h
                              +- build-VS2017-MT -- x64 -- Release -+- libiconv.dll
                                                                    +- libiconv.lib
                                                                    +- iconv.exe

ここで、iconvのヘッダファイルとDLLをコピーします。
cd %USERPROFILE%\build\neovim\.deps
copy ..\..\libiconv-win-build\include\iconv.h usr\include
copy ..\..\libiconv-win-build\build-VS2017-MT\x64\Release\iconv.exe usr\bin
copy ..\..\libiconv-win-build\build-VS2017-MT\x64\Release\libiconv.dll usr\bin
copy ..\..\libiconv-win-build\build-VS2017-MT\x64\Release\*.lib usr\lib

また、ダウンロードしてある gettext0.19.8.1-iconv1.15-shared-64.zip を展開して libintl-8.dll を取り出し、usr\bin にコピーしておきます。

準備: cmakeファイルの変更

cmakeが libiconv と libintl を見つけられるようにcmakeファイルを変更します。
--- cmake\FindIconv.cmake.orig Wed Apr 18 18:08:38 2018
+++ cmake\FindIconv.cmake Wed Apr 18 18:05:32 2018
@@ -8,7 +8,7 @@
 include(LibFindMacros)
 
 find_path(ICONV_INCLUDE_DIR NAMES iconv.h)
-find_library(ICONV_LIBRARY NAMES iconv)
+find_library(ICONV_LIBRARY NAMES iconv libiconv libiconv-2)
 
 set(Iconv_PROCESS_INCLUDES ICONV_INCLUDE_DIR)
 if(ICONV_LIBRARY)
--- cmake\FindLibIntl.cmake.orig Wed Apr 18 18:08:28 2018
+++ cmake\FindLibIntl.cmake Wed Apr 18 18:04:29 2018
@@ -27,7 +27,7 @@
 )
 
 find_library(LibIntl_LIBRARY
-    NAMES intl libintl
+    NAMES intl libintl libintl-8
 )
 
 if (LibIntl_INCLUDE_DIR)

パッチは %USERPROFILE%\neovim ディレクトリで行います。上記のdiffを cmake.patch という名前で保存し、
cd %USERPROFILE%\neovim
patch -p0 < cmake.patch
でパッチがあたります。patch コマンドはGit for Windowsに含まれています。

Neovimをビルドする

cd %USERPROFILE%\build\neovim\build
"\Program Files\CMake\bin\CMAKE.exe" -DCMAKE_BUILD_TYPE=RelWithDebInfo -CMAKE_INSTALL_PREFIX=\Apps\Neovim -G "Visual Studio 15 2017 Win64" ..
MSbuild ALL_BUILD.vcxproj /p:Configuration=Release
ConfigurationRelease もしくは RelWithDebInfo を指定します。

Neovimをデプロイする

前の記事ではちまちまコピーしていたのでいっそ cp なんかを使ってスクリプトでも作ろうかと思ったのですが、INSTALL.vcxproj を使います。
cd %USERPROFILE%\build\neovim\build
MSbuild INSTALL.vcxproj /p:Configuration=Release
これで -CMAKE_INSTALL_PREFIX= で指定した場所にデプロイされます。ここでは c:\Apps\Neovim になっています。

Neovimインストーラを作成する

NSIS (Nullsoft Scriptable Install System) を使って、Neovim.exeという形でインストーラを作成できます。NSISはインストールしておけばパスを通す必要はないようです。
cd %USERPROFILE%\build\neovim\build
MSbuild PACKAGE.vcxproj /p:Configuration=Release
これで %USERPROFILE%\buildNeovim.exe が生成されます。 これは-CMAKE_INSTALL_PREFIX= で指定した場所ではなく、c:\Program Files\Neovim にインストールされるようです。
また証明書のついていないインストーラなので、セキュリティポリシーを上げたWindowsではインストールできないかもしれません。

以上で一通りNeovimのビルドは終わりです。
Have a good Neovim life!

SWDなら3線でいいとはいうものの。

 安価で優秀なデバッグプローブはないかしら、と探したら、 Raspberry Pi Debug Probe というのがあったんですが、これは3線がにゅるんと出てるだけです。 もちろんSWDなら3線を繋げばいいのではありますが、汎用的に考えるなら5x2のリボンケーブルコネクタが欲し...