🐭

【coc.nvim】マウスクリックで定義にジャンプする 【ビルトインLSP】

2024/07/24に公開

はじめに

coc.nvim or ビルトインLSP

この記事のコードは一応はcoc.nvim向けに書いていますが、コード中のCocActionAsync("jumpDefinition")の部分をビルトインLSP側の対応する処理で置き換えることで、ビルトインLSPを使っている方も同様の設定ができると思います。

目的

LSPの便利な機能のひとつといえば、定義ジャンプですね。大規模なコードを触っていると、この関数やこのクラスはどこでどう定義されているんだっけ?と思うことはよくあります。そんな時、定義ジャンプ機能を使えば関数の定義をすばやく確認することができます。

さて、NeoVimで定義ジャンプを行う場合、ジャンプしたい関数にカーソルを移動してから定義ジャンプのキーマップを入力することになると思うのですが、(あなたがカーソル移動を使いこなすVimの達人でない限り)これには少々時間がかかると思います。目標の識別子をマウスクリックするだけで定義にジャンプできればよりスピーディにコーディングができそうですね。

この記事では、マウスクリックによる定義ジャンプを実現する設定を、Luaで記述することを目指します。

設定

マウスを有効にする

まずは、以下のようにしてマウスを有効化しなければなりません。

.config/nvim/init.lua
local set = vim.opt
set.mouse = 'a'

マウスクリックで定義にジャンプする

マウスが有効になったら特殊なキー<LeftMouse>にキーマップを設定することで、左クリックにキーマップを設定できます。

以下のようにして、定義ジャンプを左クリックに割り当てます。

.config/nvim/init.lua
function _G.jump_def_of_clicked()
  -- マウスの位置情報を取得する
  local mousepos = vim.fn.getmousepos()
  -- マウスの位置情報からクリックされたウィンドウのタイプを取得する
  local window_type = vim.fn.win_gettype(mousepos.winid)
  -- window_type == '' なら 通常の(編集可能な)ウィンドウがクリックされた
  -- (筆者は barbar.nvim を使用しているため) mousepos.winrow == 0 なら barbar.nvim のラベルがクリックされた
  -- 通常のウィンドウの、ラベル以外の箇所がクリックされた場合、以下を実行する
  if window_type == '' and mousepos.winrow ~= 0 then
    -- 定義ジャンプを実行する
    vim.cmd('call CocActionAsync("jumpDefinition")')
  end
end

-- Mouse button mappings
local opts = { silent = true, noremap = true }
vim.keymap.set("n", "<LeftMouse>", "<LeftMouse><Cmd>lua _G.jump_def_of_clicked()<CR>", opts)

おわりに

以上で設定が完了しました。今回記述した設定の全体像は以下の通りです。

local set = vim.opt
set.mouse = 'a'

function _G.jump_def_of_clicked()
  -- マウスの位置情報を取得する
  local mousepos = vim.fn.getmousepos()
  -- マウスの位置情報からクリックされたウィンドウのタイプを取得する
  local window_type = vim.fn.win_gettype(mousepos.winid)
  -- window_type == '' なら 通常の(編集可能な)ウィンドウがクリックされた
  -- (筆者は barbar.nvim を使用しているため) mousepos.winrow == 0 なら barbar.nvim のラベルがクリックされた
  -- 通常のウィンドウの、ラベル以外の箇所がクリックされた場合、以下を実行する
  if window_type == '' and mousepos.winrow ~= 0 then
    -- 定義ジャンプを実行する
    vim.cmd('call CocActionAsync("jumpDefinition")')
  end
end

-- Mouse button mappings
local opts = { silent = true, noremap = true }
vim.keymap.set("n", "<LeftMouse>", "<LeftMouse><Cmd>lua _G.jump_def_of_clicked()<CR>", opts)

おまけ 右クリックでジャンプする場合

左クリックの代わりに右クリックでジャンプしたい場合、設定は以下のようになります。mousemodelextendに設定して右クリック時のポップアップを無効化しなければならない点と、<RightMouse><LeftMouse>…にマップする必要がある点に注意が必要です。

local set = vim.opt
set.mouse = 'a'
set.mousemodel = 'extend'

function _G.jump_def_of_clicked()
  -- マウスの位置情報を取得する
  local mousepos = vim.fn.getmousepos()
  -- マウスの位置情報からクリックされたウィンドウのタイプを取得する
  local window_type = vim.fn.win_gettype(mousepos.winid)
  -- window_type == '' なら 通常の(編集可能な)ウィンドウがクリックされた
  -- (筆者は barbar.nvim を使用しているため) mousepos.winrow == 0 なら barbar.nvim のラベルがクリックされた
  -- 通常のウィンドウの、ラベル以外の箇所がクリックされた場合、以下を実行する
  if window_type == '' and mousepos.winrow ~= 0 then
    -- 定義ジャンプを実行する
    vim.cmd('call CocActionAsync("jumpDefinition")')
  end
end

-- Mouse button mappings
local opts = { silent = true, noremap = true }
vim.keymap.set("n", "<RightMouse>", "<LeftMouse><Cmd>lua _G.jump_def_of_clicked()<CR>", opts)

Discussion