🧰

[Neovim]null_ls.nvimを用いてNeovim上でLinter/Formtterを動かす🌵

2022/10/15に公開

null_ls.nvimでLinter/Formatterを動かす

この記事の概要


BuiltinLSP+Lspsaga.nvim+null-ls.nvimでeslintを動かしているところ
ここ1~2年、Neovimでは、Neovimに組み込みのLSP(BuiltinLSP:Language Server Protcol)クライアントを用いて各種のコーディング支援機能(コード補完/定義ジャンプ/コード診断など)を活用することが大きなトレンドとなっています✍
BuiltinLSPを用いると、各種Language Server(例えば、Typescriptであればtsserver)が提供するコーディング支援機能をNeovim上でリアルタイムに利用することができます。

ところで、Language Serverを活用してVim/Neovimを丸ごとIDEのように拡張するメジャーなプラグインとしては、Coc.nvimが存在します。
Coc.nvimを用いた場合、LSPとは別の各種LinterやFormatterを用いる際は、coc-extensionsと呼ばれる、Coc.nvimが独自に提供する拡張機能を用いることで簡単に利用できました。

しかし、BuitinLSPを活用した場合に、各言語に固有のLinterやFormatter(Ex. eslint rubocop prettier など)を利用するには、別途専用のプラグインを導入し、セッティングする必要があります。

今回は、Neovim上で、ローカルに存在する各言語のLinterやFormatterを非同期的に動作させ、BuiltinLSPと組み合わせた利用を可能にするプラグインである、null_ls.nvimのセッティングをします💪


null_ls.nvimの概要

こんにちは!食パンと申します🌵
普段はNeovimをBuitinLSPなどを活用しつつカスタマイズして、IDEのようにしつつ、メインエディタとして利用しています。

今回の記事ではnull_ls.nvimのセッティングを簡単に解説します。

冒頭で説明したとおり、BuitlinLSPを用いてNeovimをセッティングしていく場合、(Coc.nvimを利用した場合とやや異なり)各言語固有のLinter/Formatterを使いたい場合には、別途それらを非同期で動かすプラグインを導入しなければなりません。

そのようなプラグインには、例えばiamcco/diagnostic-languageserverdense-analysis/aleなどがありますが、なかでも今回ご紹介するnull_ls.nvimは、Neovim専用のLua言語製プラグインで特に注目されています。

null_ls.nvimは、Lua言語を用いて、NeovimをLanguageServerのように動作させ、(LSPの形式に沿わない)各種LinterやFormatterの出力を、NeovimのLSPクライアントに注入(inject)するプラグインです。
これにより、必ずしもLSPの形式に沿わない各言語に固有の支援ツールの出力を、Neovim上でBuiltinLSPと一緒に扱えるようになります。

…言葉で説明すると少しややこしい感じがしますが、実際の設定はとても簡単です💪

なお、本記事におけるNeovimおよびNeovim BuiltinLSPの設定は、前回投稿した記事の内容を前提としています。
具体的には、おおむね、

  • BuiltinLSP
    • lspconfig+mason.nvim+mason-lspconfig
    • nvim-cmpetc...
  • パッケージマネージャー
    • packer.nvim
  • 設定記述
    • init.lua

といった構成になってます。
詳細については、下記記事をご参照下さい👓

https://zenn.dev/fukakusa_kadoma/articles/99e8f3ab855a56


null_ls.nvimのセットアップ

まずはPackerを用いてプラグインをインストール(:PackerInstall or :PackerSync)します。

lua/plugins.lua
 --null_ls.nvimをインストール
  use({
    "jose-elias-alvarez/null-ls.nvim",
    requires = { "nvim-lua/plenary.nvim" },
  })

インストールできたら、新たに分割した設定ファイルを作るか、init.luaに次のように記載し、null_ls.nvimを初期化します。

今回は一例として、Node.jsを導入した環境下で、Javascript/Typescriptを書くことを想定し、グローバル(またはプロジェクトのローカル)にインストールしたeslintpretterをnull-lsで利用してみたいと思います。

plugin/null-ls.rc.lua

local status, null_ls = pcall(require, "null-ls")
if (not status) then return end

(省略...)

null_ls.setup({ -- nul-lsを初期化
    -- sources={}の中に利用したいLinter/Formatterを記載(後述)
    sources = {
    -- 例:ローカルおよびグローバルのeslintのコード診断機能をnull-lsで利用
        null_ls.builtins.diagnostics.eslint.with({ 
        prefer_local = "node_modules/.bin", --プロジェクトローカルがある場合はそれを利用
    }),
    --例:ローカルおよびグローバルのPrettierをFormatに利用
        null_ls.builtins.formatting.prettier,
    },
    debug = false,
  (省略...)
})

以上のように記載し、
npm install -g eslint prettier
でグローバル環境(これはもちろんプロジェクトローカルでもOKです)にeslint prettierをインストールすると、あとは自動的にnull-lsがこれらを認識し、Neovim上で非同期で実行してくれます。

EslintのDiagnostic


tsservereslintの出力をtelescope.nvimで一覧表示しているところ
これらの出力結果は、BuiltinLSPのDiagnosticsなどに表示され、とても自然に利用することができます🎉
また、PrettierなどのFormatterは、BuiltinLSP標準のFormat機能を用いる場合に使用されます。

なお、null_ls.nvimがどのLinterやFormatterに対応しているかは、リポジトリのドキュメントに記載されてるBuiltin-Sourcesに記載されており、こちらを参考にしつつ用いたいLinter/Formatterをsourcesオブジェクトに記述すればOKです。

基本的には、
null_ls.builtins.diagnostics|formatting|code_actions|.〇〇(LinterやFormatterの名前)
という書式になっており、慣れればすぐに目当ての記載を探せるようになります🌵

また、保存時(:w)の自動フォーマット(Formatting on save)の設定などについても、リポジトリのWiki欄があるので、必要な方は別途設定されると大変便利かと思います。
https://github.com/jose-elias-alvarez/null-ls.nvim/wiki
https://github.com/jose-elias-alvarez/null-ls.nvim/wiki/Formatting-on-save

最後の、私自身のnul-ls.rc.luaの設定ファイルを置いておきます。
なにかしら参考になりましたら幸いです😊
https://github.com/Nyowa450/Neovim-with-lua/blob/main/plugin/null-ls.rc.lua

それでは、良き(Neo)Vimライフを!🌵

Discussion