PowerShellコンソール上で上下キーで選択可能なその場に現れるメニュー

  • 6
    いいね
  • 0
    コメント

PowerShell で、上下キーで選択できるメニューを作りたいと思ったので、作りました。

:page_facing_up: menu.psm1 (Gist)

文字列配列を渡して、文字列かインデックスで結果を受け取ることができるだけの、単純なコマンドです。

逐一画面をクリアして描画するのではなく、その場に現れて、選択したら消える感じになってます。…うまく表現できませんが、画像を見ていただいて、伝わるでしょうか。

・動いている様子
GIF.gif

・ファイル名一覧をパイプで受け取って表示してみる
1.png

・メニューの位置、幅を指定
2.png

・任意のカーソルを左に表示できる
3.png

・日本語が途切れても大丈夫(と思う)
4.png

使い方

  • menu (Show-Menuのエイリアス) に対し引数またはパイプで文字列配列を渡します
  • 上下キーで選択し、Enter キーで決定すると、結果が文字列で返ります。Esc キーでキャンセルすると、結果は null です
menu 1,2,3,4,5
"foo","bar","baz" | menu
$selected = "A","B","C","D" | menu  # 結果を変数へ
cd (ls -Directory | %{ $_.Name } | menu)  # 移動先フォルダを選ぶ
notepad (ls -File *.txt | menu)  # メモ帳でテキストファイルをどれか開く


  • -Index オプションを指定すると、結果は文字列でなく数値(選択した項目のインデックス)になります
"foo","bar","baz" | menu -Index  # 数値が返る (0~2)


  • -X-Y-W オプションで、メニューを表示する位置、メニューの幅を指定できます
ls | menu -X 2 -Y 1 -W 30


  • -Cursor オプションに指定した文字列を使って、選択項目にカーソルを表示できます
ls | menu -Cursor " > "


  • プロファイル等からグローバルスコープで $MenuPreference 変数を以下のように定義しておくと、メニューの色を設定できます
$MenuPreference = @{
    ForegroundColor = "Gray"               #非選択項目の文字色
    BackgroundColor = "Black"              #非選択項目の背景色
    SelectionForegroundColor = "DarkGray"  #選択項目の文字色
    SelectionBackgroundColor = "White"     #選択項目の背景色
}

仕組み

  • カーソルがウィンドウの下の方にあるとき、メニューが下方にはみ出るかもしれないので、コマンド実行した時点のカーソル位置からメニュー項目分だけ改行してスクロール
  • 最初に一度だけメニュー全体を出力
  • ↓↓↓ 以降キー入力待ちのループ ↓↓↓
  • 選択されている項目を描画する行にカーソルを設定して Write-Host で出力
  • 前回選択されていた項目は元の色で上書き
  • 選択項目が決定されたらメニューの範囲をウィンドウ背景色でクリアして、カーソルを元の位置に設定

参考にした記事

問題点とか気になっている点

  • ウィンドウの行数よりも項目数が多いと、上の方にはみ出してしまって見えなくなってしまう(カーソル選択自体は正常にできている)
    • スクロール処理面倒くさそう
  • 画面バッファの行数よりも項目数が多いとエラーになってしまう
    • しょうがないかなと思う