Neovim+LSP 환경에서의 Codelens integration

요약
CodeLens는 대개 편집 문서와 관련된 부가기능을
제공하는 데 유용하게 사용할 수 있다. 예를 들면 Rust 코드를 편집할 때 테스트
코드 상단에 Run test
를 표시하고, 그걸 누르면 바로 테스트가 실행되는데 이것이
바로 CodeLens를 이용한 기능이다.
이번 글에서는 Neovim에서 CodeLens를 활용해서 새로운 기능을 추가하는 방법에 대해 설명한다.
목표: CodeLens로 뭘 하겠다고?
연관문서 검색 기능을 원래 Neovim의 custom command로 구현하고 있었다. 이를테면 노트 위에 커서를 두고 :MyS 명령을 실행하면 연관문서를 보여주는 방식.
이 부분을 CodeLens로 바꾸면 유저 입장에서 해당 기능이 존재한다는 것을 좀 더 직관적으로 파악할 수 있어서 편할 것 같다고 생각했다.
다만 CodeLens로 바꾸는 과정에서 핵심 문제는 Custom command에서 구현했던 여러 custom handler를 CodeLens 구현에서 어떻게 적용하냐는 점이었다. 즉 연관 문서 목록을 서버에서 받아다가 화면에 표시하는 로직을 어떻게 설정하냐는 것.
가정
CodeLens에 대한 구체적인 구현이나 설명은 이 문서에서 다루고자 하는 범위 밖이라 과감하게 스킵한다. 즉, 이미 CodeLens를 제공하는 language server는 이미 주어져 있다고 가정한다. 이 글에서의 CodeLens는 단순히 서버에서 ‘이 CodeLens는 XYZ Command를 ABC Arguments로 실행하는 거랍니다’ 라고 간주해도 충분하다.
1단계: CodeLens 표시하기
Neovim의 LspAttach 이벤트에 빌붙어서, Codelens를 표시하고 업데이트하도록 구현한다.
vim.api.nvim_create_autocmd('LspAttach', {
callback = function(ev)
-- Show codelens
vim.api.nvim_create_autocmd({'TextChanged', 'InsertLeave'}, {
callback = function(_)
vim.lsp.codelens.refresh()
end
})
vim.lsp.codelens.refresh()
end,
})
2단계: command 실행을 client에서 낚아채기
Neovim의 codelens
구현
에 의하면 codelens의 실행은 client._exec_cmd
함수에서 담당한다. (참고로
master branch이기 때문에 stable branch의 구현은 약간 다를 수 있지만 의미는
동일했다)
Neovim의 해당 함수
구현
에 의하면 가장 간편한 방법은 client.commands[cmdname]
에 내가 원하는 구현을 끼워넣는
것이다. 즉, 다음과 같이 구현하면 된다.
local configs = require("lspconfig.configs")
-- My own lsp server for markdown
if not configs.lsp_md then
configs.lsp_md = {
default_config = {
-- cmd_cwd, cmd, filetypes, root_dir, single_file_support 등등 설정
commands = {
['cmd1'] = function(args, client_info) -- cmd1은 server에서 전달한 command 이름
-- args는 server에서 전달한 arguments, client_info는 client_id와 buf number 등이 들어감
local client = vim.lsp.get_active_clients()[client_info.client_id]
client.request('workspace/executeCommand',
args,
function (_, resp, ctx, _)
-- 내가 원하는 callback을 여기서 구현. 이를테면 lopen이라던가, telescope 창을 연다던가
end
)
end,
-- 다른 command들도 여기에 이어서 선언한다.
}
},
}
end
3단계: CodeLens 실행하기
아… 지금은 아직 귀찮아서 그냥 해당 CodeLens 위에서 :lua vim.lsp.codelens.run()
을 실행한다. 단축키 설정을 하기만 하면 된다.
결론
기존의 Custom command와 비교하면, Language Server에서 바로 어떤 기능이 있는지 편집기 위에서 보여줄 수 있으니까 더 좋은것 같기도?