• "UP THE LINE" 時間線を遡って

PowerShellには、入力行を編集する「PSReadLine」という機能が搭載されている。このPSReadLineは、Linuxのbashに「inspired」されたreadline実装だとしている。

readlineは、GNUで開発された。もともとはbashの一部だったが、のちに独立したライブラリになり、他のプログラムなどからも使われるようになった。

その起源は、1980年台初頭にベル研で開発され、1983年に公開されたKornShell(ksh)にあると思われる。kshは、行編集機能をEmacsやviのキー割り当てで行うことができた。

ksh以前、cshなどは、履歴置換コマンドで、履歴を書き換える必要があった。これは、ラインエディタでの行編集に似ている。

kshは当初、オープンソースではなくAT&TがUNIX用ソフトウェアとして販売されていたと記憶する。このため、kshを使うことができるユーザーは非常に限られていた。しかし、そのために、多くのオープンソース系シェルでは、kshのような行編集機能を実装することが目標となった。

いまではLinuxで広く使われているbashは、1988年にGNU/FSF(Free Software Foundation)で開発が始まり、1989年にベータ版が公開された。readlineがbashから独立したライブラリとして公開されたのは1994年からである。

readlineは、GPL(GNU General Public License)であるため、Windows同梱ソフトウェアには取り込むことができず、Microsoftは、似たようなプログラムをC#で開発した。これがPSReadLineである。PowerShell専用であるため、GNU readlineとは異なる部分もあれば、同じようにemacsやviのキー割り当てで行編集が行える。

まず、キー割り当て(EditMode)の変更だが、PSReadLineには、“emacs”、“vi”、“Windows”の3つのEditModeが設定できる。“Windows”は、PSReadLineのデフォルトモードである。


set-PSReadLineOption -EditMode emacs | vi | windows

で行う。キー割り当てに関しては、“Get-PSReadLineKeyHandler”で一覧を得ることが可能だ。

PSReadLineには、200弱の関数があり、その大半はキー割り当てで利用できる。前記の3つEditModeでは、PSReadLineの関数とキー割り当ては異なっており、どのEditModeでもすべての関数にキーが割り当てられているわけではない。このため、EditModeによって、使える機能、使えない機能がある。最も関数のキー割り当てが少ないのがWindows EditMode(モード)であり、最も多いのはviモードである。ただし、viモードには、コマンドモードとインサートモードがあり、vi固有の動作のための関数も多い。

キー割り当てが適当で、それなりに使えるのがemacsモードだ。もし、emacsとviの「宗教戦争」に「参戦」していないなら、emacsモードを選択するのがよい。筆者は、Linuxのエディタとしてはvimをつかっているのだが、PowerShellの行内編集では、emacsモードを使っている。viでは起動時にコマンドモードでh/j/k/lでカーソルが動き、Escで挿入モードからコマンドモードに「抜ける」という感覚があって、カーソルを動かす前にEscを打つのに何かモヤモヤしたものを感じてしまう。

どのモードにも多数の機能はあるものの必要なものだけを使えば良い。筆者がよく使うキー割り当てのリストを(表01)に示す。なお、この表では、カーソルキーやHOMEキー(行先頭への移動)のような自然と理解できるコマンドは省略してある。

  • ■表01

コマンドや履歴を編集するとき、カーソルキーだけを使うのも1つの方法だが、文字検索や単語間移動を使うとキーストロークを減らすことができる。コマンドラインは原則スペースで区切るため、単語関連のコマンドは、オプション文字やパラメーターが対応する。一文字ごとに削除やカーソル移動するよりも、引数単位で削除、カーソル移動した方が手数が少ない。これはコマンドラインが複数行にまたがるぐらい長くなると、より強く利点を感じる。

行内文字検索を使うことで目的の場所へすばやく移動できる。このとき、事前にAlt+0からAlt+9の数字と符号(Alt+ハイフン)で、行内文字検索コマンドを繰り返し行うことができる。たとえば、以下のような行の末尾にカーソルがあるとき、


gci -Recurse -filter *.txt|sls -list "readline"|fl fileName,LineNumber,Line

中央の「-list」の“l”にカーソルを移動させたい場合、以下の4つのキーを打鍵する(文字検索は大文字小文字を区別する)。


Alt+-、Alt+4、Ctrl+]、l

とする。Ctrl+]は、前方(行末尾に向かっての検索)だが、繰り返し数を負数にすることで逆方向への検索になる。「Alt+-、Alt+4」は、Altキーを押したまま「-4」と打ってかまわない。

PSReadLineではユーザーが関数へのキー割り当てを変更できる。emacsモードでは、対応するカッコへのカーソル移動関数(GotoBrace)は未割り当てだが、以下のコマンドでGotoBrace(対応するカッコへの移動)の割り当てができる。ただし、筆者の環境では、カッコと波カッコでは動作したが角カッコでは動作しなかった。


Set-PSReadLineKeyHandler -Chord 'ctrl+}' -Function GotoBrace

ViEditVisually関数は、事前に環境変数「EDITOR」にエディタの実行パスを割り当てておく。たとえば、Visual Studio Codeなら


$env:EDITOR=$env:LOCALAPPDATA+ "\Programs\Microsoft VS Code\Code.exe"

などとする(VSCodeのインストール方法でパスは異なることがある)。その後、PowerShellからCtrl+x、Ctrl+eと順に打鍵すれば、入力行をVS Codeエディタで編集できる。編集後に上書き保存してVS Codeを終了させると、コマンドラインに編集後のコマンドが入る。

また、関数名にkillを含むコマンドは、キルリング(Kill Ring)と呼ばれる領域に削除した文字列がkillコマンドごとに入る。kill系コマンドは、単語移動や行頭、行末移動(Home、End)と組み合わせて使うことで、前後の単語の削除や行全体の削除として利用できる。

キルリングはCtrl+yで取り出すことができ、Alt+yでキルリングの先頭を1つ前にkillした文字列に切り替えることができる。

履歴も直前のコマンドでなければ、上カーソルキー連打で遡るよりも、Ctrl+rで文字列を入れて検索する方が速い。文字列を入れたあとはCtrl+rの連打で同じ文字列を含むコマンドを過去方向に辿っていける。行きすぎてしまったらCtrl+sで1つ戻ることができる。

今回のタイトルネタは、ロバート・シルバーバーグの「時間線を遡って」(原題 UP THE LINE,Robert Silverberg 1969)である。邦訳は東京創元社SF文庫(1974年)である。原題と邦題からわかるように、この作品では、過去に向かうことを「UP」と呼んでいる。コマンドラインでは、画面にあるすでに実行されたコマンドの出力は上にあり、下が現在(最新)という並びと同じだからだ。現在は新訳「時間線をのぼろう」に切り替わっているようだが、筆者は旧訳でしか読んでいない。というのもこの作品、性的な描写が描写も多く、新訳を読むのがちょっと「怖い」のである。