• Windows Terminal ベスト設定 第8回「スクロールバーマーカー、コンテキストメニュー」

今回は、Windows Terminalプレビュー版のみで、利用できるスクロールバーマーカーやコンテキストメニューなどの新しい機能を使えるようにしてみる。原稿執筆時点では、安定版(v1.17.11461.0)ではこれらの機能は利用できない。ただし、将来的には、安定版にも含まれると考えられる。コマンドラインやコマンド出力の位置をWindows Terminalが認識するため、シェルの使い勝手が上がる。

原稿執筆時点での最新版は、プレビュー版がv1.18.1462.0、安定版がv1.17.11461.0である。以下の記事は、上記のプレビュー版で確認を行なった。

現状、プレビュー版でのみ利用可能な新機能としては、

  • スクロールバーマーカー(v1.15以降のプレビュー版のみ対応。安定版には含まれない)
  • FTCSシェル統合機能(v1.18プレビュー版)
  • 右クリックメニュー(v1.18プレビュー版)

がある。スクロールバーマーカーに関しては、以前の記事第5回「Windows Terminal プレビュー版v1.15、安定版v1.14編」を参照してほしい。FTCSシェル統合機能は、同じくv1.15に最初に搭載されたFTCS_PROMPTを拡張したものだ。他の3つのエスケープシーケンスに対応し、プロンプト位置だけでなく、コマンドラインやコマンド出力の範囲を記憶できるようになった。なお、FTCSマークのエスケープシーケンスは、安定版でも動作する。

FTCSシェル統合機能は、FTCSマークを使ってコマンドラインとコマンド出力の部分をWindows Terminalに認識させる。その後、キーに割り当てたActionを使って、コマンドラインの選択やコマンド出力の選択などが可能になる。

右クリックメニューは、Windows Terminalウィンドウ内での右クリックでメニューを表示する機能。v1.17までは、マウスの右ボタンを扱っていなかった。この右クリックメニューは、Windowsでは「コンテキストメニュー」とも呼ばれ、右クリックする場所に応じて、メニューが変化する。Windows Terminalでは、FTCSシェル統合とリンクしており、右クリック位置に応じてコマンドラインやコマンド出力の選択が行える(写真01)。また、キーボードマーク機能(キーボードによるテキスト選択)で選択中の範囲があると、右クリックメニューの「検索機能」が利用できるようになる。

  • 写真01: WTプレビュー版の右クリックメニューは、クリックする位置で表示内容が変わる。マークモードを使ってWT内のテキストを選択していると「検索」機能が利用できるようになる

このようにスクロールバーマーカー、FTCSシェル統合機能、右クリックメニューは、相互に関係しており、まとめて設定する必要がある。

FTCSシェル統合機能とは?

FTCSマークと呼ばれるエスケープシーケンス(表01)をシェルのプロンプトなどで出力すると、その場所がWindows Terminalに記録される。その後、「スクロールバーマーカーに移動」アクションを使うことで、マークされた位置を表示させることができる。さらに、新設されたアクションを使うことで、コマンドライン、コマンド出力を選択してクリップボードにコピーできるようになる。これをFTCSシェル統合機能と呼ぶ。

  • ■表01

また、後述する右クリックメニューでは、FTCSシェル統合が設定されている場合に、その右クリック位置により、コマンドラインのコピーやコマンド出力のコピーが行えるようになる。

ただし、そのためには、シェルのプロンプトをカスタマイズして、FTCSマークに対応したエスケー夫シーケンスを出力するように書き換える必要がある。ただし、cmd.exeやPowerShell/Windows PowerShell、およびWSLのbashは、それぞれプロンプトメッセージのカスタマイズが可能である。

(表02)は、FTCSマークのエスケープシーケンスとシェルごとの表記方法をまとめたものだ。多くのシェルでは、Esc文字の簡略表記があるのだが、唯一Windows PowerShellにはこれがなく、ASCIIコードを使って文字コードを計算式として埋め込む必要がある。

  • ■表02

基本的には、どのシェルでも以下のパターンでプロンプト文字列を定義する。どの場合でも、既存の「プロンプト表示文字列」の前後を挟むようにFTCSマークを付加すればよい。


FTCS_COMMAND_FINISHED
FTCS_PROMPT
プロンプト表示文字列
FTCS_COMMAND_START

プロンプトが始まるところは、直前のコマンドの終了になるため、最初に「FTCS_COMMAND_FINISHED」を置く。その後「FTCS_PROMPT」に続いてプロンプト文字列を置く。コマンドラインでは、このあとからコマンドが開始されるため、最後に「FTCS_COMMAND_START」出力する。「FTCS_COMMAND_START」は、コマンドラインの末尾部分になるが、ここは通常エンターキーなどが使われて、次の行からコマンド出力が始まる。ここにエスケープシーケンスを挟むのは困難だが、Windows Terminalでは、Enterキーを押したあとの改行部分からをコマンド出力の最初と判断するようだ。

事前設定

まずは、Windows Terminal プレビュー版で、スクロールバーマーカーを表示する設定を有効にしておこう。これを表示させておく、以後のシェル統合のとき、コマンドを入力した位置にマーカーが表示されるようになる。

同時に「右クリックメニュー」を有効化し、常にスクロールバーが表示されるようにしておく。

それには、Windows Terminalのsettings.jsonを書き換える必要がある(リスト01)。

■リスト01


"profiles": 
    {
        "defaults": 
        {
            // 上記の記述がある場所に、ここから先を挿入する
            "experimental.rightClickContextMenu": true,
            "experimental.showMarksOnScrollbar": true,
            "scrollbarState": "visible",

このリストの追加部分は、右クリックメニューの有効化、スクロールバーマーカーの表示を有効化するもの。3行目は、スクロールバーを常に表示するものだ(この行はなくてもよい)。

スクロールバーマーカーを有効化すると、スクロールバーマーカーの位置まで画面をスクロールさせるアクションが使えるようになる。そのためには、キー割り当てを変更する必要がある。ここでは、(表03)のようなキー割り当てを行う。

  • ■表03

それには、settings.jsonの“actions:”に(リスト02)のようなキーボード割り当てを追加する。

■リスト02


"actions": 
    [
        // 上記の記述がある場所に、ここから先を挿入する
        // 前のコマンドを選択(前方。過去の側)">"
        {"keys":"ctrl+shift+comma","command":{"action":"selectCommand","direction":"prev"}},
        // 次のコマンドを選択(後方、最近に近い側)"<"
        {"keys":"ctrl+shift+period","command":{"action":"selectCommand","direction":"next"}},
        // 前のコマンド出力を選択
        {"keys":"ctrl+shift+[","command":{"action":"selectOutput","direction":"prev"}},
        // 次のコマンド出力を選択
        {"keys":"ctrl+shift+]","command":{"action":"selectOutput","direction":"next"}},
        // コンテキストメニューを出す
        {"keys":"ctrl+shift+z","command":"showContextMenu"},
        // 前のスクロールバーマーカーに移動
        {"keys":"alt+shift+up","command":{"action":"scrollToMark","direction":"previous"}},
        // 次のスクロールバーマーカーに移動
        {"keys":"alt+shift+down","command":{"action":"scrollToMark","direction":"next"}},
        // 現在の位置をマーク
        {"keys":"ctrl+shift+s","command":{"action":"addMark","color":"#FF0000"}},
        // カーソル移動モード
        {"keys":"ctrl+shift+m","command":"markMode" },
        // コピー
        {"keys":"ctrl+shift+c", "command":{"action":"copy","singleLine":false}},
        // ペースト
        {"keys":"ctrl+shift+v","command":"paste"},

settings.jsonの設定については、記事末にある本連載の過去記事を参照されたい。

シェル統合 cmd.exeの場合

cmd.exeでは、環境変数PROMPTでプロンプト文字列を定義できる。これは、「設定 ⇒ システム ⇒ バージョン情報 ⇒ システムの詳細設定 ⇒ 環境変数ボタン」で行う。Windows 11のコントロールパネルの「システム」は、上記の「設定 ⇒ システム ⇒ バージョン情報」を開くリンクである。

cmd.exeの場合、初期化スクリプト(Batchファイル)を実行する方法もあるのだが、レジストリにスクリプトファイル名を指定する必要があり、目的別に初期化スクリプトを切り替えるなどが面倒になる。

Windows Terminalを使う場合には、プロファイルの起動コマンドで初期化スクリプトを指定すると扱いが簡単になる。この場合、目的別に複数のWindows Terminalプロファイルを作成すればよい。

具体的には、適当なフォルダに「WTCMD.BAT」ファイルを作成し、その中に(リスト03)のプロンプト設定をBatchファイル内に記述しておく。PROMPTコマンドの特殊文字などについては、オンラインヘルプ(prompt /?)で表示できる。

■リスト03


@echo off
VER
PROMPT $e]133;D$e\$e]133;A$e\$P $G$e]133;B$e\

これをWindows Terminalのプロファイルの「コマンドライン」で、以下のように指定する(写真02)。なお、ここでは、WTCMD.BATファイルのパスを“%userprofile%\Documents\WTCMD.BAT”と仮定する。


%SystemRoot%\System32\cmd.exe /K %userprofile%\Documents\WTCMD.BAT
  • 写真02: cmd.exeの場合、プロファイル設定の「コマンドライン」で、プロンプトなどを設定するスクリプト「%userprofile%\Documents\WTCMD.BAT」を実行させている

PowerShellの場合

PowerShell、Windows PowerShellでは、プロンプトは、Promptと呼ばれる関数で定義する。関数内で直接コンソールに出力してもいいが、関数値として何かを返さないとデフォルトのプロンプトが出力されてしまう。

こちらも同様にスクリプトファイルを作成してもいいが、PowerShellの起動時に、自動的に実行される自動実行スクリプト(PowerShellではこれをPROFILEと呼ぶ)に記述しておくのが簡単だ。これは、PowerShell内で、$PROFILE自動変数にフルパスが定義されているので、メモ帳(notepad.exe)などのテキストエディタを使って「notepad.exe $PROFILE」で編集できる。プロファイルにリスト04にあるPrompt関数追加する。

■リスト04


function prompt() { 
    $OSC="$([char]27)]"                 # OSC
    $ST="$([char]27)\"                  # ST
    $VR=$PSVersionTable.PSVersion       # Version
    $promptString ="${OSC}133;D${ST}"   # FTCS_COMMAND_FINISHED
    $promptString+="${OSC}133;A${ST}"   # FTCS_PROMPT
    $promptString+="PS$($VR.Major).$($VR.Minor)> "   # Prompt
    $promptString+="${OSC}133;B${ST}"   # FTCS_COMMAND_START
    return $promptString
}
set-PSReadLineOption -PromptText "> "

bashの場合

WSLのbashでは、ユーザーのホームディレクトリにある「.bashrc」(~/.bashrc)を書き換えてプロンプトを設定する。bashでは、環境変数PS1でプロンプトを設定する。  ここでは、Ubuntuディストリビューションの標準状態の~/.bashrcを前提にした。細かい部分は、ディストリビューションによっても異なり、/etc/bashrcなどで設定しているディストリビューションもある。

どの場合でも、.bashrc終了時のPS1がプロンプト文字列になるため、.bashrcの最後に(リスト05)の1行を追加する。

■リスト05


PS1="\e]133;C\a\e]133;A\a${PS1}\e]133;B\a"

なお、このリストでは、OSCエスケープシーケンスの終了をSTではなく、Ctrl+B(BEL)にしている。bashの文字列では、\文字を使うエスケープが多用されているのだが、シングルクオートではエスケープの意味がなく、ダブルクオートのときに有効になる。.bashrc内では、あとから書き換えることを想定してシングルクオートとダブルクオートによる代入があり、単独の\文字が複数回評価されると後続文字のエスケープになってしまうことがあり、STシーケンスの最後の\文字を“\\\\”と記述しなければ、正しく解釈されない可能性がある。しかし、STのもう1つの形式としてBEL文字(Ctrl+B)を使うとこの問題を回避できる。“\a”は、BEL文字を表すBashの逆スラッシュ・エスケープ表現である(man bashに解説がある)。

今回解説した設定を行うことで、コマンドラインの位置にマーカーが表示され、簡単に戻ることができる。ついうっかり、大量の出力を出してしまったときでも先頭に戻るのが簡単になる。また、コマンドラインやコマンド出力を右クリックメニューなどから簡単に選択できるほか、キーボードによるマークモードを併用して、コンソールに表示された文字列を選択して検索させることも可能になる。まとめて設定するとWindows Terminalの使い勝手がかなり向上する。

>> Windows Terminal ベスト設定 連載バックナンバー
https://news.mynavi.jp/tag/winterminal/