🧊

`CopilotChat.nvim`で、独自のコンテキスト変数を定義する

CopilotC-Nvim/CopilotChat.nvim: Chat with GitHub Copilot in Neovim https://github.com/CopilotC-Nvim/CopilotChat.nvim/tree/main

今期イチオシのプラグインなので。

コンテキストとは

https://github.com/CopilotC-Nvim/CopilotChat.nvim/tree/main?tab=readme-ov-file#contexts

プロンプト中に使える特別な文字列で、たとえば、

#buffer

関数をリストアップして説明して。

ってすると、いま開いてるファイル(バッファ)の中身を見て、答えてくれる。

デフォルトでもいくつか定義されてて、よく使うのはこのあたり。

  • #files: 今ひらいてるソースを起点に、配下のファイル全部の中身
  • #file:../foo/bar.js: 単一ファイルの中身

git ls-filesしたい

#filesは便利ではあるものの、そのチャットを開いた元ファイルがディレクトリの起点になっちゃう。

なので、具体的にどのファイルがコンテキストに載ったのかがわからないのが不安になるし、毎回それを意識したくない。

というか、だいたいGitのルートから全部載せてくれてもいいのに・・・ってケースもある。

というわけで、#git_filesを独自のコンテキストとして実装したのが以下。

{
    -- ...
    contexts = {
        git_files = {
            resolve = function()
                local context = require("CopilotChat.context")
                local utils = require("CopilotChat.utils")

                local cmd = {
                    "git",
                    "rev-parse",
                    "--show-toplevel",
                }
                local out = utils.system(cmd)
                local git_root = out.stdout:gsub("\n$", "")

                local files = utils.scan_dir(git_root)

                utils.schedule_main()
                files = vim.tbl_filter(
                    function(file)
                        return file.ft ~= nil
                    end,
                    vim.tbl_map(function(file)
                        return {
                            name = utils.filepath(file),
                            ft = utils.filetype(file),
                        }
                    end, files)
                )

                return vim.iter(files)
                    :map(function(file)
                        return context.get_file(file.name, file.ft)
                    end)
                    :filter(function(file_data)
                        return file_data ~= nil
                    end)
                    :totable()
            end,
        },
    },
},

やってることは単純で、

これだけ。

utils.scan_dirは、内部的にrgコマンドを優先的に使うらしく、いくつかのオプションは渡せるみたいだった。

https://github.com/CopilotC-Nvim/CopilotChat.nvim/blob/03d1aba3270169e2c06edb0043b1d232e4f43dce/lua/CopilotChat/utils.lua#L551