さて前回のコレから5年が経過しています...
コンセプト
- とりあえずこれくらいやればLSP動くよ〜という紹介
- 脱 coc.nvim
- LSは手動で管理するので、mason.nvim みたいなのは使わない
- Python の LSP を最低限の設定で動かして、Ruff で Lint/Format する
環境
brew install nvim したもの
$ nvim -version NVIM v0.10.0 Build type: Release LuaJIT 2.1.1716656478
今回登場するプラグイン
- folke/lazy.nvim
- プラグインマネージャ
- neovim/nvim-lspconfig
- ビルドインLSPクライアントの設定
- hrsh7th/nvim-cmp
- 補完エンジンのコア(以下のcpm-シリーズと合わせて使う)
- hrsh7th/cmp-nvim-lsp
- LSPからの補完
- hrsh7th/cmp-buffer
- バッファからの補完
- hrsh7th/cmp-path
- path補完
- L3MON4D3/LuaSnip
- スニペットのコア
- saadparwaiz1/cmp_luasnip
- dense-analysis/ale
- 毎度おなじみ非同期Linter実行ツール
プラグイン管理
folke/lazy.nvim でいきます。
Mac の場合は、~/.local/share/nvim/lazy
配下に git clone した plugin が置かれます。
vim.loader.enable() local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" if not vim.loop.fs_stat(lazypath) then vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable", -- latest stable release lazypath, }) end vim.opt.rtp:prepend(lazypath) require("lazy").setup({ "neovim/nvim-lspconfig", "hrsh7th/nvim-cmp", "hrsh7th/cmp-nvim-lsp", "hrsh7th/cmp-buffer", "hrsh7th/cmp-path", "saadparwaiz1/cmp_luasnip", "L3MON4D3/LuaSnip", "dense-analysis/ale", })
LSPと補完の設定
なんでも良いんですけど、惰性で、jedi-language-server を使っています。
コンセプト
- 各プロジェクトの .venv 配下を見せたい
- $PROJECT_VENV を direnv で制御している
- 各Pythonプロジェクトのrootに、以下のような .envrc を置いておく
export VENV_DIR=".venv" export PROJECT_ROOT=`pwd` export PROJECT_VENV=${PROJECT_ROOT}/${VENV_DIR} export PATH=${PROJECT_VENV}/bin:$PATH
init.lua
-- lspのハンドラーに設定 capabilities = require("cmp_nvim_lsp").default_capabilities() -- lspの設定後に追加 vim.opt.completeopt = "menu,menuone,noselect" local cmp = require"cmp" cmp.setup({ snippet = { expand = function(args) require("luasnip").lsp_expand(args.body) end, }, mapping = cmp.mapping.preset.insert({ ["<C-p>"] = cmp.mapping.select_prev_item(), ["<C-n>"] = cmp.mapping.select_next_item(), ["<C-d>"] = cmp.mapping.scroll_docs(-4), ["<C-f>"] = cmp.mapping.scroll_docs(4), ["<C-Space>"] = cmp.mapping.complete(), ["<C-e>"] = cmp.mapping.close(), ["<CR>"] = cmp.mapping.confirm({ select = true }), }), sources = cmp.config.sources({ { name = "nvim_lsp" }, { name = "luasnip" }, }, { { name = "buffer" }, }) }) -- python の path の切り替え local function expand(str) return vim.fn.expand(str) end local project_venv = expand('$PROJECT_VENV') .. '/bin/python3' if vim.fn.executable(project_venv) == 1 then vim.g.python3_host_prog = project_venv else local home_python = expand('$HOME/nvim-python/.venv/bin/python3') vim.g.python3_host_prog = home_python end -- lspconfig の有効化 require'lspconfig'.jedi_language_server.setup{}
pip
- neovim を忘れずに
- これは各プロジェクトの venv でのpipです
$ pip install jedi-language-server neovim
動作イメージ
Linter / Formatter
コンセプト
- ruff で良いかなと
- ただ、none-ls みたいなやつに、linter / formatter を統合するのにちょっと抵抗感があって、ale にしています
init.lua
-- ale vim.g.ale_linters = { python = {'ruff'}, } vim.g.ale_fixers = { python = {'ruff'}, } vim.g.ale_fix_on_save = 1
pip
- これは各プロジェクトの venv でのpipです
pip install ruff
動作イメージ
こんな感じで怒られる&保存するとfixされる
今回のinit.luaの全体
- 今回紹介したプラグイン周りの全体像はこんな感じ。
- 見ての通り最低限なので、ぼちぼち育てていきます。
vim.cmd('let $LANG = "en_US.UTF-8"') vim.loader.enable() local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" if not vim.loop.fs_stat(lazypath) then vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable", -- latest stable release lazypath, }) end vim.opt.rtp:prepend(lazypath) require("lazy").setup({ "neovim/nvim-lspconfig", "hrsh7th/nvim-cmp", "hrsh7th/cmp-nvim-lsp", "hrsh7th/cmp-buffer", "hrsh7th/cmp-path", "saadparwaiz1/cmp_luasnip", "L3MON4D3/LuaSnip", "dense-analysis/ale", }) -- lspのハンドラーに設定 capabilities = require("cmp_nvim_lsp").default_capabilities() -- lspの設定後に追加 vim.opt.completeopt = "menu,menuone,noselect" local cmp = require"cmp" cmp.setup({ snippet = { expand = function(args) require("luasnip").lsp_expand(args.body) end, }, mapping = cmp.mapping.preset.insert({ ["<C-p>"] = cmp.mapping.select_prev_item(), ["<C-n>"] = cmp.mapping.select_next_item(), ["<C-d>"] = cmp.mapping.scroll_docs(-4), ["<C-f>"] = cmp.mapping.scroll_docs(4), ["<C-Space>"] = cmp.mapping.complete(), ["<C-e>"] = cmp.mapping.close(), ["<CR>"] = cmp.mapping.confirm({ select = true }), }), sources = cmp.config.sources({ { name = "nvim_lsp" }, { name = "luasnip" }, }, { { name = "buffer" }, }) }) -- python の path の切り替え local function expand(str) return vim.fn.expand(str) end local project_venv = expand('$PROJECT_VENV') .. '/bin/python3' if vim.fn.executable(project_venv) == 1 then vim.g.python3_host_prog = project_venv else local home_python = expand('$HOME/nvim-python/.venv/bin/python3') vim.g.python3_host_prog = home_python end -- lspconfig の有効化 require'lspconfig'.jedi_language_server.setup{} -- ale vim.g.ale_linters = { python = {'ruff'}, } vim.g.ale_fixers = { python = {'ruff'}, } vim.g.ale_fix_on_save = 1