aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Arcangeli <506791+stevearc@users.noreply.github.com>2023-09-17 10:02:10 -0700
committerGitHub <noreply@github.com>2023-09-17 10:02:10 -0700
commit1abbb82bb8e519e652d8b31b12a311872e9090d1 (patch)
treee4b612223d04d357ce5b61f8380d76ac7729b5e1
parent6d74e6c70b13a39384996268deaf4140443d6121 (diff)
feat: make lsp_fallback behavior more intuitive (#59)
When lsp_fallback = true AND the only formatters for the buffer are from the "*" or "_" filetype, format with LSP instead of the "*"/"_" formatters.
-rw-r--r--README.md17
-rw-r--r--doc/conform.txt13
-rw-r--r--lua/conform/init.lua71
-rw-r--r--scripts/options_doc.lua7
4 files changed, 73 insertions, 35 deletions
diff --git a/README.md b/README.md
index eceb89d..fb2a923 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,7 @@ Lightweight yet powerful formatter plugin for Neovim
- [list_formatters(bufnr)](#list_formattersbufnr)
- [list_all_formatters()](#list_all_formatters)
- [get_formatter_info(formatter, bufnr)](#get_formatter_infoformatter-bufnr)
+ - [will_fallback_lsp(options)](#will_fallback_lspoptions)
- [Acknowledgements](#acknowledgements)
<!-- /TOC -->
@@ -241,12 +242,9 @@ require("conform").setup({
-- Use a sub-list to run only the first available formatter
javascript = { { "prettierd", "prettier" } },
-- Use the "*" filetype to run formatters on all filetypes.
- -- Note that if you use this, you may want to set lsp_fallback = "always"
- -- (see :help conform.format)
["*"] = { "codespell" },
- -- Use the "_" filetype to run formatters on all filetypes
- -- that don't have other formatters configured. Again, you may want to
- -- set lsp_fallback = "always" when using this value.
+ -- Use the "_" filetype to run formatters on filetypes that don't
+ -- have other formatters configured.
["_"] = { "trim_whitespace" },
},
-- If this is set, Conform will run the formatter on save.
@@ -384,6 +382,15 @@ Get information about a formatter (including availability)
| --------- | -------------- | ------------------------- |
| formatter | `string` | The name of the formatter |
| bufnr | `nil\|integer` | |
+
+### will_fallback_lsp(options)
+
+`will_fallback_lsp(options): boolean` \
+Check if the buffer will use LSP formatting when lsp_fallback = true
+
+| Param | Type | Desc |
+| ------- | ------------ | ------------------------------------ |
+| options | `nil\|table` | Options passed to vim.lsp.buf.format |
<!-- /API -->
## Acknowledgements
diff --git a/doc/conform.txt b/doc/conform.txt
index bb3d90d..76b0714 100644
--- a/doc/conform.txt
+++ b/doc/conform.txt
@@ -21,12 +21,9 @@ OPTIONS *conform-option
-- Use a sub-list to run only the first available formatter
javascript = { { "prettierd", "prettier" } },
-- Use the "*" filetype to run formatters on all filetypes.
- -- Note that if you use this, you may want to set lsp_fallback = "always"
- -- (see :help conform.format)
["*"] = { "codespell" },
- -- Use the "_" filetype to run formatters on all filetypes
- -- that don't have other formatters configured. Again, you may want to
- -- set lsp_fallback = "always" when using this value.
+ -- Use the "_" filetype to run formatters on filetypes that don't
+ -- have other formatters configured.
["_"] = { "trim_whitespace" },
},
-- If this is set, Conform will run the formatter on save.
@@ -149,6 +146,12 @@ get_formatter_info({formatter}, {bufnr}): conform.FormatterInfo *conform.get_for
{formatter} `string` The name of the formatter
{bufnr} `nil|integer`
+will_fallback_lsp({options}): boolean *conform.will_fallback_lsp*
+ Check if the buffer will use LSP formatting when lsp_fallback = true
+
+ Parameters:
+ {options} `nil|table` Options passed to |vim.lsp.buf.format|
+
--------------------------------------------------------------------------------
FORMATTERS *conform-formatters*
diff --git a/lua/conform/init.lua b/lua/conform/init.lua
index aadec4d..7c81e1e 100644
--- a/lua/conform/init.lua
+++ b/lua/conform/init.lua
@@ -145,6 +145,24 @@ M.setup = function(opts)
end, { desc = "Show information about Conform formatters" })
end
+---Get the configured formatter filetype for a buffer
+---@param bufnr? integer
+---@return nil|string filetype or nil if no formatter is configured
+local function get_matching_filetype(bufnr)
+ if not bufnr or bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+ local filetypes = vim.split(vim.bo[bufnr].filetype, ".", { plain = true })
+ table.insert(filetypes, "_")
+ for _, filetype in ipairs(filetypes) do
+ ---@type conform.FormatterUnit[]
+ local ft_formatters = M.formatters_by_ft[filetype]
+ if ft_formatters then
+ return filetype
+ end
+ end
+end
+
---@private
---@param bufnr? integer
---@return conform.FormatterUnit[]
@@ -154,7 +172,6 @@ M.list_formatters_for_buffer = function(bufnr)
end
local formatters = {}
local seen = {}
- local filetypes = vim.split(vim.bo[bufnr].filetype, ".", { plain = true })
local function dedupe_formatters(names, collect)
for _, name in ipairs(names) do
@@ -171,10 +188,15 @@ M.list_formatters_for_buffer = function(bufnr)
end
end
- table.insert(filetypes, "_")
- for _, filetype in ipairs(filetypes) do
+ local filetypes = {}
+ local matching_filetype = get_matching_filetype(bufnr)
+ if matching_filetype then
+ table.insert(filetypes, matching_filetype)
+ end
+ table.insert(filetypes, "*")
+ for _, ft in ipairs(filetypes) do
---@type conform.FormatterUnit[]
- local ft_formatters = M.formatters_by_ft[filetype]
+ local ft_formatters = M.formatters_by_ft[ft]
if ft_formatters then
-- support the old structure where formatters could be a subkey
if not vim.tbl_islist(ft_formatters) then
@@ -183,20 +205,9 @@ M.list_formatters_for_buffer = function(bufnr)
end
dedupe_formatters(ft_formatters, formatters)
- break
end
end
- local ft_formatters = M.formatters_by_ft["*"]
- if ft_formatters then
- -- support the old structure where formatters could be a subkey
- if not vim.tbl_islist(ft_formatters) then
- ---@diagnostic disable-next-line: undefined-field
- ft_formatters = ft_formatters.formatters
- end
- dedupe_formatters(ft_formatters, formatters)
- end
-
return formatters
end
@@ -294,17 +305,23 @@ M.format = function(opts, callback)
local lsp_format = require("conform.lsp_format")
local runner = require("conform.runner")
+ local explicit_formatters = opts.formatters ~= nil
local formatter_names = opts.formatters or M.list_formatters_for_buffer(opts.bufnr)
local any_formatters_configured = formatter_names ~= nil and not vim.tbl_isempty(formatter_names)
local formatters =
resolve_formatters(formatter_names, opts.bufnr, not opts.quiet and opts.formatters ~= nil)
- local resolved_names = vim.tbl_map(function(f)
- return f.name
- end, formatters)
- log.debug("Running formatters on %s: %s", vim.api.nvim_buf_get_name(opts.bufnr), resolved_names)
-
local any_formatters = not vim.tbl_isempty(formatters)
+ if not explicit_formatters and opts.lsp_fallback == true and M.will_fallback_lsp(opts) then
+ -- use the LSP formatter when the configured formatters are from the fallback "_" filetype
+ any_formatters = false
+ else
+ local resolved_names = vim.tbl_map(function(f)
+ return f.name
+ end, formatters)
+ log.debug("Running formatters on %s: %s", vim.api.nvim_buf_get_name(opts.bufnr), resolved_names)
+ end
+
if any_formatters then
local mode = vim.api.nvim_get_mode().mode
if not opts.range and mode == "v" or mode == "V" then
@@ -492,6 +509,20 @@ M.get_formatter_info = function(formatter, bufnr)
}
end
+---Check if the buffer will use LSP formatting when lsp_fallback = true
+---@param options? table Options passed to |vim.lsp.buf.format|
+---@return boolean
+M.will_fallback_lsp = function(options)
+ options = options or {}
+ if not options.bufnr or options.bufnr == 0 then
+ options.bufnr = vim.api.nvim_get_current_buf()
+ end
+ local matching_filetype = get_matching_filetype(options.bufnr)
+ local has_primary_formatters = matching_filetype and matching_filetype ~= "_"
+ local lsp_clients = require("conform.lsp_format").get_format_clients(options)
+ return not has_primary_formatters and not vim.tbl_isempty(lsp_clients)
+end
+
M.formatexpr = function(opts)
-- Change the defaults slightly from conform.format
opts = vim.tbl_deep_extend("keep", opts or {}, {
diff --git a/scripts/options_doc.lua b/scripts/options_doc.lua
index bce6908..b68614e 100644
--- a/scripts/options_doc.lua
+++ b/scripts/options_doc.lua
@@ -7,12 +7,9 @@ require("conform").setup({
-- Use a sub-list to run only the first available formatter
javascript = { { "prettierd", "prettier" } },
-- Use the "*" filetype to run formatters on all filetypes.
- -- Note that if you use this, you may want to set lsp_fallback = "always"
- -- (see :help conform.format)
["*"] = { "codespell" },
- -- Use the "_" filetype to run formatters on all filetypes
- -- that don't have other formatters configured. Again, you may want to
- -- set lsp_fallback = "always" when using this value.
+ -- Use the "_" filetype to run formatters on filetypes that don't
+ -- have other formatters configured.
["_"] = { "trim_whitespace" },
},
-- If this is set, Conform will run the formatter on save.