BigQuery の LSP を .bq ファイルでのみ動作させる nvim-lspconfig
@dr666m1 さんが公開されている BigQuery(標準 SQL)の LSP を nvim-lsp
に設定してご機嫌に使わせていただいている(↓記事参照)のですが、.sql
ファイル一律に動作してしまうと困ることもありそうなので、その対策をしておきます。
以下、↑記事と同様の設定が済んでいる前提となります。
はじめに
色々方法はあると思うのですが、今回は以下の方針で対処してみます。
- BigQuery 標準 SQL のファイルは、拡張子
.bq
で保存するものとする -
.bq
ファイルを SQL ファイルとして認識させる - さらに、
.bq
を開いた時のみ LSP を動作させる
.bq ファイルを SQL ファイルとして認識させる
neovim のファイルタイプの認識については、:help filetype
に記載のある通りです。runtimepath
内の ftdetect
サブディレクトリに含まれる .vim
ファイルが設定として読み込まれる様ですので、こんな感じでファイルを置いてあげれば .bq
ファイルを SQL ファイルとして認識する様になります。
au BufNewFile,BufRead *.bq setf sql
.bq ファイルを開いた時のみ LSP を動作させる lspconfig
:help lspconfig-setup
を見ると、root_dir
と言うオプションがあることがわかります。この設定は、本来同じプロジェクト内(git リポジトリ内など)のファイルを開く際に、すでに起動している LSP を使いまわすための設定の様です(:help lspconfig-root-detection
参照)。
root_dir
オプションの型は、
function(filename, bufnr)
となっていますので、ファイル名とバッファ番号を引数として受け取る「関数」を設定することになります。また、この関数の返却値は
Returns either a filepath (string) or nil.
The language server will only start if the function returns a filepath.
とのことですので、これを上手く使って、
- 起動したい場合には適切な
filepath
- 起動したくない場合には
nil
を、それぞれ返してあげれば良さそうです。こんな感じ。
local lspConfig = require('lspconfig')
local lspInstaller = require("nvim-lsp-installer")
local serverOpts = {} -- key: server-name, value: options
local function rootOfFileWith(pattern, singleFileSupport)
return function(filename, _)
if not(string.match(filename, pattern)) then return nil end
local gitAncestor = lspConfig.util.find_git_ancestor(filename)
local singleFileDir = singleFileSupport and lspConfig.util.path.dirname(filename) or nil
return gitAncestor or singleFileDir
end
end
serverOpts['bqls'] = {
root_dir = rootOfFileWith("%.bq$", true),
single_file_support = false,
}
lspInstaller.on_server_ready(function(server)
local opts = {
on_attach = on_attach, -- e.g.
}
if serverOpts[server.name] then
for k, v in pairs(serverOpts[server.name]) do opts[k] = v end
end
server:setup(opts)
vim.cmd [[ do User LspAttachBuffers ]]
end)
rootOfFileWith
と言う関数で、root_dir
に設定する関数を作成しています。作成した関数内では、ファイル名に対して正規表現マッチをかけて、マッチしない場合は nil
を返す様な処理にしています。lua の正規表現は少し個性的ですね。私は、基本的に .bq
ファイルを git 管理しているので、素直にリポジトリのルートディレクトリを返すような設定にしています。
なお、single_file_support
が true
になっていると、root_dir
の返却値に関わらず LSP が起動してしまうので、false
に設定しておきます。代わりに、rootOfFileWith
関数の singleFileSupport
引数に true
を渡すことで、リポジトリルートが見つからなかった場合に単にそのファイルがあるディレクトリを返す様になっており、git 外のファイルでも動作する様にしています。
ちなみに、lua には三項演算子が無いようで、A and B or C
が三項演算子の代わりになっています。きゅ〜と。
おわりに
最近の私は、BigQuery 叩く時くらいしか SQL を書かないので、いったんこの設定で過ごしてみます。他の SQL 用 LSP を併用する場合にも、同じ様な方法で排他制御できるのではないかと思います。
Discussion