167 lines
4.0 KiB
Lua
167 lines
4.0 KiB
Lua
-- LSP: Auto-format on save
|
|
-- https://github.com/rafi/vim-config
|
|
|
|
-- This is part of LazyVim's code, with my modifications.
|
|
-- See: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/lsp/format.lua
|
|
|
|
local M = {}
|
|
|
|
---@type PluginLspOpts
|
|
M.opts = nil
|
|
|
|
function M.enabled()
|
|
return M.opts.autoformat
|
|
end
|
|
|
|
function M.toggle()
|
|
if vim.b.autoformat == false then
|
|
vim.b.autoformat = nil
|
|
M.opts.autoformat = true
|
|
else
|
|
M.opts.autoformat = not M.opts.autoformat
|
|
end
|
|
local msg = M.opts.autoformat and 'Enabled' or 'Disabled'
|
|
vim.notify(
|
|
msg .. ' format on save',
|
|
vim.log.levels.INFO,
|
|
{ title = 'Format' }
|
|
)
|
|
end
|
|
|
|
---@param opts? {force?:boolean}
|
|
function M.format(opts)
|
|
local buf = vim.api.nvim_get_current_buf()
|
|
if vim.b.autoformat == false and not (opts and opts.force) then
|
|
return
|
|
end
|
|
|
|
local formatters = M.get_formatters(buf)
|
|
local client_ids = vim.tbl_map(function(client)
|
|
return client.id
|
|
end, formatters.active)
|
|
|
|
if #client_ids == 0 then
|
|
return
|
|
end
|
|
|
|
if M.opts.format_notify then
|
|
M.notify(formatters)
|
|
end
|
|
|
|
vim.lsp.buf.format(vim.tbl_deep_extend('force', {
|
|
bufnr = buf,
|
|
filter = function(client)
|
|
return vim.tbl_contains(client_ids, client.id)
|
|
end,
|
|
}, require('rafi.lib.utils').opts('nvim-lspconfig').format or {}))
|
|
end
|
|
|
|
---@param formatters LazyVimFormatters
|
|
function M.notify(formatters)
|
|
local lines = { '# Active:' }
|
|
|
|
for _, client in ipairs(formatters.active) do
|
|
local line = '- **' .. client.name .. '**'
|
|
if client.name == 'null-ls' then
|
|
line = line
|
|
.. ' ('
|
|
.. table.concat(
|
|
vim.tbl_map(function(f)
|
|
return '`' .. f.name .. '`'
|
|
end, formatters.null_ls),
|
|
', '
|
|
)
|
|
.. ')'
|
|
end
|
|
table.insert(lines, line)
|
|
end
|
|
|
|
if #formatters.available > 0 then
|
|
table.insert(lines, '')
|
|
table.insert(lines, '# Disabled:')
|
|
for _, client in ipairs(formatters.available) do
|
|
table.insert(lines, '- **' .. client.name .. '**')
|
|
end
|
|
end
|
|
|
|
vim.notify(table.concat(lines, '\n'), vim.log.levels.INFO, {
|
|
title = 'Formatting',
|
|
on_open = function(win)
|
|
local scope = { scope = 'local', win = win }
|
|
vim.api.nvim_set_option_value('conceallevel', 3, scope)
|
|
vim.api.nvim_set_option_value('spell', false, scope)
|
|
local buf = vim.api.nvim_win_get_buf(win)
|
|
vim.treesitter.start(buf, 'markdown')
|
|
end,
|
|
})
|
|
end
|
|
|
|
-- Gets all lsp clients that support formatting.
|
|
-- When a null-ls formatter is available for the current filetype,
|
|
-- only null-ls formatters are returned.
|
|
function M.get_formatters(bufnr)
|
|
local ft = vim.bo[bufnr].filetype
|
|
-- check if we have any null-ls formatters for the current filetype
|
|
local null_ls = package.loaded['null-ls']
|
|
and require('null-ls.sources').get_available(ft, 'NULL_LS_FORMATTING')
|
|
or {}
|
|
|
|
---@class LazyVimFormatters
|
|
local ret = {
|
|
---@type lsp.Client[]
|
|
active = {},
|
|
---@type lsp.Client[]
|
|
available = {},
|
|
null_ls = null_ls,
|
|
}
|
|
|
|
local clients
|
|
if vim.lsp.get_clients ~= nil then
|
|
clients = vim.lsp.get_clients({ bufnr = bufnr })
|
|
else
|
|
---@diagnostic disable-next-line: deprecated
|
|
clients = vim.lsp.get_active_clients({ bufnr = bufnr })
|
|
end
|
|
for _, client in ipairs(clients) do
|
|
if M.supports_format(client) then
|
|
if (#null_ls > 0 and client.name == 'null-ls') or #null_ls == 0 then
|
|
table.insert(ret.active, client)
|
|
else
|
|
table.insert(ret.available, client)
|
|
end
|
|
end
|
|
end
|
|
|
|
return ret
|
|
end
|
|
|
|
-- Gets all lsp clients that support formatting
|
|
-- and have not disabled it in their client config
|
|
---@param client lsp.Client
|
|
function M.supports_format(client)
|
|
if
|
|
client.config
|
|
and client.config.capabilities
|
|
and client.config.capabilities['documentFormattingProvider'] == false
|
|
then
|
|
return false
|
|
end
|
|
return client.supports_method('textDocument/formatting')
|
|
or client.supports_method('textDocument/rangeFormatting')
|
|
end
|
|
|
|
---@param opts PluginLspOpts
|
|
function M.setup(opts)
|
|
M.opts = opts
|
|
vim.api.nvim_create_autocmd('BufWritePre', {
|
|
group = vim.api.nvim_create_augroup('rafi_format', {}),
|
|
callback = function()
|
|
if M.opts.autoformat then
|
|
M.format()
|
|
end
|
|
end,
|
|
})
|
|
end
|
|
|
|
return M
|