NushellでAWS CLIの入力補完を行う方法

2024.03.05

しばたです。

2019年に最初のプレビューリリース(Ver.0.2.0)が公開されてから定期的にNushellの更新を追いかけ続けています。

残念ながら「バージョンごとの破壊的変更がかなり強烈」だったのと「私にとっての必須機能が足りなかった」ため現在までメインで使うには至っていません。

Nushellの入力補完

私にとっての必須機能の一つが入力補完で、この機能自体は2022年にリリースされたVer.0.60.0でサポートされ始めたものの、当時は補完のパターンを全て関数で記述する必要がある簡素なものでした。

その後、Ver.0.68.0から補完に外部プロセスの利用(External Completers)がサポートされる様になり、修正を繰り返しながら現在に至っています。

NushellでAWS CLIの入力補完を行う

2024年3月時点の最新バージョンはVer.0.90.1になっており「今ならやりたいことを実現できるのでは?」と思い試したところ良い結果を得られたので本記事で共有することにしました。

1. 検証環境

本記事の内容は以下の環境で動作確認しています。

  • Windows 11
  • Nushell Ver.0.90.1
# versionコマンドの結果
~> version
╭────────────────────┬──────────────────────────────────────────╮
│ version            │ 0.90.1                                   │
│ branch             │                                          │
│ commit_hash        │ c2992d5d8b8541b64e9fc1440ed2917fc9b757f7 │
│ build_os           │ windows-x86_64                           │
│ build_target       │ x86_64-pc-windows-msvc                   │
│ rust_version       │ rustc 1.73.0 (cc66ad468 2023-10-03)      │
│ rust_channel       │ 1.73.0-x86_64-pc-windows-msvc            │
│ cargo_version      │ cargo 1.73.0 (9c4383fb5 2023-08-26)      │
│ build_time         │ 2024-02-07 02:25:09 +00:00               │
│ build_rust_channel │ release                                  │
│ allocator          │ mimalloc                                 │
│ features           │ default, sqlite, trash, which, zip       │
│ installed_plugins  │                                          │
╰────────────────────┴──────────────────────────────────────────╯

前述の通りNushellはバージョン毎での破壊的変更がかなり強烈でした。
今後のリリースにおいてはそうでもないかもしれませんが、本記事で試した内容が以降のバージョンで使えなくなる可能性がある点は予めご了承ください。
(一応Ver.1.0までのロードマップを公開済みなのでそこまで強烈な破壊的変更は少なくなっていると信じたいです)

2. External Completers設定

Nushell 0.90.1では設定ファイルconfig.nuに入力補完に使う外部プロセスを使う設定を指定することができます。

ドキュメントにはcarapaceを使う例が記載されており、carapaceコマンドを実行して補完文字列を取得する処理をクロージャで定義してやります。

config.nu

# carapaceを使って入力補完を行うクロージャ
let carapace_completer = {|spans: list<string>|
    # 補完文字列を取得するコマンドを実行
    carapace $spans.0 nushell ...$spans | from json
}

# $env.config で入力補完の利用を指定
$env.config = {
    # ・・・省略・・・
    completions: {
        # ・・・省略・・・
        external: {
            enable: true
            max_results: 100
            # ここに入力補完を行うクロージャを指定する。未使用時は null 
            completer: $carapace_completer
        }
    }
    # ・・・省略・・・
}

spans引数には入力中の文字列がListの形で引き渡され、最初の要素である$spans.0にはコマンド名が設定されます。

クロージャの戻り値には最低限valueを含むテーブル *1を返してやる必要があります。
上述のcarapaceでAWS CLIの入力補完を再現すると以下の様な結果が求められることが分かります。

# "aws ec"まで入力した体でcarapaceを使った場合の実行例 : valueとdisplayを持つテーブルを返す
~> carapace aws nushell aws ec | from json
╭───┬───────────────────────┬──────────────────────╮
│ # │         value         │       display        │
├───┼───────────────────────┼──────────────────────┤
│ 0 │ ec2                   │ ec2                  │
│ 1 │ ec2-instance-connect  │ ec2-instance-connect │
│ 2 │ ecr                   │ ecr                  │
│ 3 │ ecr-public            │ ecr-public           │
│ 4 │ ecs                   │ ecs                  │
╰───┴───────────────────────┴──────────────────────╯

ここまでわかればcarapace以外のツールでも応用可能でしょう。
実際ドキュメントはFish Shellを補完ツールとして使うFish completerの例も記載されています。

# Fishを補完ツールとして使用する例 : valueとdescriptionを持つテーブルを返す形になっている
let fish_completer = {|spans|
    fish --command $'complete "--do-complete=($spans | str join " ")"'
    | $"value(char tab)description(char newline)" + $in
    | from tsv --flexible --no-infer
}

3. AWS CLIの入力補完を設定する

carapaceは標準でAWS CLIの入力補完をサポートしており、carapaseを導入するだけでNushellでも入力補完を実現できます。

ただ、Nushellcarapaceaws_completerと複数プロセスを経由するため結果を得るのに体感できるレベルでラグが発生してしまいました。
このためAWS CLIの補完は独自に記述し直接aws_completerコマンドを呼び出す形する方がお勧めできます。

今回は以下の様にcarapace以外にAWS CLI専用のaws_completerを用意し

  • AWS CLIの利用時はaws_completerを使う
  • それ以外のコマンドではcarapace_completerを使う

形にしました。

config.nu

# AWS CLI用のcompleter
let aws_completer = {|spans: list<string>|
    with-env {COMP_LINE: ($spans | str join " ")} {
        aws_completer
            | $"value(char newline)" + $in
            | from tsv --flexible --no-infer
    }
}
# carapaceを呼び出すcompleter
let carapace_completer = {|spans: list<string>|
    carapace $spans.0 nushell ...$spans | from json
}
# AWS CLIだけaws_completerを使う
let external_completer = {|spans: list<string>|
    match $spans.0 {
        aws => $aws_completer
        _ => $carapace_completer
    } | do $in $spans
}

$env.config = {
    # ・・・省略・・・
    completions: {
        # ・・・省略・・・
        external: {
            # 入力補完を行うクロージャを指定
            completer: $external_completer
        }
    }
    # ・・・省略・・・
}

結果AWS CLIの入力補完をいい感じに行える様になりました。

(AWS CLIの入力補完がいい感じに!)

ちなみにVer.0.90.1からCtrl + nを押すことでIDEメニュー形式の補完表示にすることも可能になっています。

(いわゆるIntelliSenseっぽい表示も可能)

最後に

以上となります。

個人的に一番の鬼門だった入力補完でやりたいことが実現できて非常に嬉しいです。
これからはNushellをメインで使い続けることができるか本気で試していこうと思います。

脚注

  1. 調べた限り、他にdisplay, desription, styleといった要素を設定可能な模様