初心者

NeovimでGitHub Copilot (Chat)の活用

菅野

こんにちは、開発部長の菅野です。セットアップマニュアルシリーズ第4弾。今回はNeovimでGithub Copilotを利用する方法を詳しく紹介します。Copilot利用はハッキリ言ってVSCodeを使った方が圧倒的に楽だと思いますが、私のようにvimで何とかしたい人に少しでもお役に立てれば幸いです。

Neovimについての詳しい説明はこちら!

はじめに

GitHubCopilotのプラグインは、Vimscriptで書かれた公式のgithub/copilot.vimとLuaで書かれた後発のzbirenbaum/copilot.luaがあります。とりあえず手っ取り早くGitHubCopilotでのコード補完を行いたいなら公式のプラグインを入れて:Copilot setupすればすぐに使えます。特に設定も不要です。

しかし、LSPと連携したい、とか、cmpのコード補完とCopilotのコード補完を使い分けたい、といった場合は公式のcopilot.vimプラグインでは実現できません。

本記事ではこの課題を解決するLua製プラグイン「copilot.lua」の導入方法と「CopilotChat」の設定方法を解説します。

対象

以下のような方を対象としています。

  • 既にNeovimの環境はあるが、GitHub Copilotを使ったことがない
  • GitHub Copilot ChatをNeovimで使いたい
  • GitHub Copilot Chatを日本語で対話できるようにしたい

GitHub Copilot自体の説明や導入方法は割愛させて頂きます。

前提となるプラグインについて

この記事はtelescope、nvim-cmp、maisonなどLSP関連プラグインが導入されていることを前提としています。Neovimへのプラグイン導入方法はセットアップマニュアルシリーズ第2弾の記事をご覧ください。

環境

  • macOS:Sequoia 15.4.1
  • Neovim:v0.11.0

第2弾から半年以上経過してるので、バージョンも変わっています。古い場合は最新にしましょう。Homebrewで入れてるのであれば簡単に最新にアップグレードできるはずです。

copilot.lua

以下のような流れになります。

  1. Masonでcopilot-language-serverのインストール
  2. copilot.luaの設定
  3. nvim-cmpとcopilot-cmpの設定

copilot-language-serverのインストール

Masonは既にインストールされてる前提とします。:Masonで起動してcopilot-language-serverを選んだらiでインストールしましょう。

copilot.luaの設定

次はcopilot.luaの設定です。私は以下のように設定しています。

注意点があります。それはcopilot.vimでは:Copilot setupで初期設定しますが、copilot.luaでは:Copilot authで初期設定します。既にcopilot.vimで初期設定済みであれば、copilot.luaに変えた時に初期設定しなおす必要はありません。

return {
  'zbirenbaum/copilot.lua',
  cmd = 'Copilot',
  event = 'InsertEnter',
  config = function()
    require('copilot').setup({
      suggestions = { enable = false },
      panels = { enable = false },
      server_opts_overrides = {
        trace = 'verbose',
        cmd = {
          vim.fn.expand("~/.local/share/nvim/mason/bin/copilot-language-server"),
          "--stdio"
        },
      },
      filetypes = { ["*"] = true },
    })
  end
}
~/.config/nvim/lua/plungins/copilot.lua

ポイントは3つです。

suggestionsとpanelsの無効化

suggestions = { enable = false },
panels = { enable = false },
Lua

このあとcmpと統合するために無効化します。これをしないとcmpで候補が出るのと同時にcopilotからsuggestionされてしまいます。

LSPの設定

server_opts_overrides = {
  trace = 'verbose',
  cmd = {
    vim.fn.expand("~/.local/share/nvim/mason/bin/copilot-language-server"),
    "--stdio"
  },
},
Lua

インストールしたcopilot-language-serverのパスを指定します。これでよりシームレスに動作する、はず!(まだあまり実感できてないです)

ファイルタイプの指定

filetypes = { ["*"] = true },
Lua

これが結構ハマりどころです。私はyamlを有効にしたかったのですがデフォルトではyamlは無効になっています。私は使いたいファイルタイプが多岐にわたるので全部有効にしてますが、決まってるのであれば使うのだけtrueにして、あとは全部falseにした方が良いと思います。

nvim-cmpとcopilot-cmpの設定

nvim-cmpのsourcesにcopilotを追加して、copilot-cmpのインストールを追加します。copilot-cmpの設定を色々書き込む場合はcopilot-cmp用の別ファイルを作ることをオススメします。

return {
  {
    'hrsh7th/nvim-cmp',
    event = 'InsertEnter',
    config = function()
      -- 中略
      cmp.setup {
      
      -- 中略
        
        sources = {
          { name = 'copilot' }, -- ⇐コレ追加
          { name = 'nvim_lsp' },
          { name = 'luasnip' },
          { name = 'path' },
        },
      }
    end,
  },
  -- 以下追加
  {
    'zbirenbaum/copilot-cmp',
    config = function()
      require('copilot_cmp').setup()
    end
  },
}
~/.config/nvim/lua/plugings/cmp.lua

これで補完候補にCopilotが追加されるようになったはずです。

Copilot Chat

こちらも設定を晒しちゃいます。

return {
  {
    'CopilotC-Nvim/CopilotChat.nvim',
    dependencies = {
      { 'zbirenbaum/copilot.lua' }, -- or github/copilot.vim
      { 'nvim-lua/plenary.nvim' }, -- for curl, log wrapper
    },
    build = 'make tiktoken',
    opts = {
      -- See Configuration section for options
    },
    -- See Commands section for default commands if you want to lazy load on them
    config = function()
      require('CopilotChat').setup({
        prompts = {
          Explain = {
              prompt = '選択したコードの説明を日本語で書いてください',
              mapping = '<leader>ce',
          },
          Review = {
              prompt = 'コードを日本語でレビューしてください',
              mapping = '<leader>cr',
          },
          Fix = {
              prompt = 'このコードには問題があります。バグを修正したコードを表示してください。説明は日本語でお願いします',
              mapping = '<leader>cf',
          },
          Optimize = {
              prompt = '選択したコードを最適化し、パフォーマンスと可読性を向上させてください。説明は日本語でお願いします',
              mapping = '<leader>co',
          },
          Docs = {
              prompt = '選択したコードに関するドキュメントコメントを日本語で生成してください',
              mapping = '<leader>cd',
          },
          Tests = {
              prompt = '選択したコードの詳細なユニットテストを書いてください。説明は日本語でお願いします',
              mapping = '<leader>ct',
          },
          Commit = {
              prompt = require('CopilotChat.config.prompts').Commit.prompt,
              mapping = '<leader>cco',
              selection = require('CopilotChat.select').gitdiff,
          },
        },
      })
    end,

    -- See Commands section for default commands if you want to lazy load on them
    keys = {
      {
        '<leader>cc',
        function()
          require('CopilotChat').toggle()
        end,
        desc = 'CopilotChat - Toggle',
      },
      {
        '<leader>cch',
        function()
          local actions = require('CopilotChat.actions')
          require('CopilotChat.integrations.telescope').pick(actions.help_actions())
        end,
        desc = 'CopilotChat - Help actions',
      },
      { '<leader>ccp',
        function()
          local actions = require('CopilotChat.actions')
          require('CopilotChat.integrations.telescope').pick(actions.prompt_actions())
        end,
        desc = 'CopilotChat - Prompt actions',
      },
    },
  },
}

設定のポイント

デフォルトだと英語で回答されちゃうので、プロンプトに送るテキストを日本語にしたのと、telescopeと連携させて使いやすくしました。

使い方

私のキーマップだと<leader>+ccでプロンプト起動ですが、私はあまり使いません。よく使うのは<leader>+ccpでtelescopeのプロンプト表示です。

コードを範囲指定することで、Copilot Chatにコードの内容を渡せます。 ただし少しコツが必要です。私は以下の方法でやってますが、もっと他に良い方法があるかもしれません。

1 <leader>ccでプロンプトを出す

先に右ウィンドウにプロンプトを表示させます。

2 対象を範囲選択する

元のコードが表示されてる左のウィンドウに移動して、プロンプトに投げたい対象範囲を指定した状態で、右のプロンプトウィンドウに切り替えます。

3 <leader>ccpでやりたいことを選ぶ

この状態で<leader>ccpでtelescopeの画面を出して、やりたいことを選択すればOK

こんな感じで表示されます

まとめ

さて、如何でしたでしょうか?

素直にVSCodeを使えばもっと直感的に操作できて楽なはずですが、やっぱり使い慣れて愛着のあるvimから中々離れられません。VSCodeならCopilotが一部制限があるとはいえ、無料で使えますし、もはやviへの愛が無いとやってられない感は正直ありますが、vimmerの方々へ少しでもお役に立てたら光栄です。

最後に今回の内容も以下に公開しておきますのでよかったら参考にしてください。

-初心者
-,