summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Arcangeli <stevearc@stevearc.com>2023-11-04 13:24:48 -0700
committerSteven Arcangeli <stevearc@stevearc.com>2023-11-04 13:31:35 -0700
commit0bbe83830be5a07a1161bb1a23d7280310656177 (patch)
treec08a901c6ace758e9cfcaff49f5ba78837f79e40
parent893b139e6dcdb55dee4c98215d9217d3a1ec69eb (diff)
feat: allow formatters_by_ft to be a function (#174)
-rw-r--r--README.md10
-rw-r--r--doc/conform.txt10
-rw-r--r--lua/conform/formatters/injected.lua8
-rw-r--r--lua/conform/health.lua8
-rw-r--r--lua/conform/init.lua55
-rw-r--r--scripts/options_doc.lua10
6 files changed, 69 insertions, 32 deletions
diff --git a/README.md b/README.md
index caf0a8c..96fb8d1 100644
--- a/README.md
+++ b/README.md
@@ -372,9 +372,17 @@ require("conform").setup({
formatters_by_ft = {
lua = { "stylua" },
-- Conform will run multiple formatters sequentially
- python = { "isort", "black" },
+ go = { "goimports", "gofmt" },
-- Use a sub-list to run only the first available formatter
javascript = { { "prettierd", "prettier" } },
+ -- You can use a function here to determine the formatters dynamically
+ python = function(bufnr)
+ if require("conform").get_formatter_info("ruff_format", bufnr).available then
+ return { "ruff_format" }
+ else
+ return { "isort", "black" }
+ end
+ end,
-- Use the "*" filetype to run formatters on all filetypes.
["*"] = { "codespell" },
-- Use the "_" filetype to run formatters on filetypes that don't
diff --git a/doc/conform.txt b/doc/conform.txt
index f5dede6..e30eef4 100644
--- a/doc/conform.txt
+++ b/doc/conform.txt
@@ -17,9 +17,17 @@ OPTIONS *conform-option
formatters_by_ft = {
lua = { "stylua" },
-- Conform will run multiple formatters sequentially
- python = { "isort", "black" },
+ go = { "goimports", "gofmt" },
-- Use a sub-list to run only the first available formatter
javascript = { { "prettierd", "prettier" } },
+ -- You can use a function here to determine the formatters dynamically
+ python = function(bufnr)
+ if require("conform").get_formatter_info("ruff_format", bufnr).available then
+ return { "ruff_format" }
+ else
+ return { "isort", "black" }
+ end
+ end,
-- Use the "*" filetype to run formatters on all filetypes.
["*"] = { "codespell" },
-- Use the "_" filetype to run formatters on filetypes that don't
diff --git a/lua/conform/formatters/injected.lua b/lua/conform/formatters/injected.lua
index 21a9830..7028a8b 100644
--- a/lua/conform/formatters/injected.lua
+++ b/lua/conform/formatters/injected.lua
@@ -170,7 +170,13 @@ return {
num_format = num_format + 1
last_start_lnum = start_lnum
local input_lines = util.tbl_slice(lines, start_lnum, end_lnum)
- local formatter_names = conform.formatters_by_ft[lang]
+ local ft_formatters = conform.formatters_by_ft[lang]
+ local formatter_names
+ if type(ft_formatters) == "function" then
+ formatter_names = ft_formatters(ctx.buf)
+ else
+ formatter_names = require("conform").resolve_formatters(ft_formatters, ctx.buf, false)
+ end
local format_opts = { async = true, bufnr = ctx.buf, quiet = true }
local idx = num_format
log.debug("Injected format %s:%d:%d: %s", lang, start_lnum, end_lnum, formatter_names)
diff --git a/lua/conform/health.lua b/lua/conform/health.lua
index 7132007..3a1c9f6 100644
--- a/lua/conform/health.lua
+++ b/lua/conform/health.lua
@@ -12,8 +12,14 @@ local function get_formatter_filetypes(name)
local conform = require("conform")
local filetypes = {}
for filetype, formatters in pairs(conform.formatters_by_ft) do
+ if type(formatters) == "function" then
+ formatters = formatters(0)
-- support the old structure where formatters could be a subkey
- if not vim.tbl_islist(formatters) then
+ elseif not vim.tbl_islist(formatters) then
+ vim.notify_once(
+ "Using deprecated structure for formatters_by_ft. See :help conform-options for details.",
+ vim.log.levels.ERROR
+ )
---@diagnostic disable-next-line: undefined-field
formatters = formatters.formatters
end
diff --git a/lua/conform/init.lua b/lua/conform/init.lua
index 23c3818..32f24eb 100644
--- a/lua/conform/init.lua
+++ b/lua/conform/init.lua
@@ -56,8 +56,9 @@ local M = {}
---@field end integer[]
---@alias conform.FormatterUnit string|string[]
+---@alias conform.FiletypeFormatter conform.FormatterUnit[]|fun(bufnr: integer): string[]
----@type table<string, conform.FormatterUnit[]>
+---@type table<string, conform.FiletypeFormatter>
M.formatters_by_ft = {}
---@type table<string, conform.FormatterConfigOverride|fun(bufnr: integer): nil|conform.FormatterConfigOverride>
@@ -78,20 +79,6 @@ M.setup = function(opts)
M.notify_on_error = opts.notify_on_error
end
- for ft, formatters in pairs(M.formatters_by_ft) do
- ---@diagnostic disable-next-line: undefined-field
- if formatters.format_on_save ~= nil then
- vim.notify(
- string.format(
- 'The "format_on_save" option for filetype "%s" is deprecated. It is recommended to put this logic in the autocmd, see :help conform-autoformat',
- ft
- ),
- vim.log.levels.WARN
- )
- break
- end
- end
-
local aug = vim.api.nvim_create_augroup("Conform", { clear = true })
if opts.format_on_save then
if type(opts.format_on_save) == "boolean" then
@@ -214,7 +201,6 @@ local function get_matching_filetype(bufnr)
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
@@ -254,16 +240,23 @@ M.list_formatters_for_buffer = function(bufnr)
end
table.insert(filetypes, "*")
for _, ft in ipairs(filetypes) do
- ---@type conform.FormatterUnit[]
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
- ---@diagnostic disable-next-line: undefined-field
- ft_formatters = ft_formatters.formatters
- end
+ if type(ft_formatters) == "function" then
+ dedupe_formatters(ft_formatters(bufnr), formatters)
+ else
+ -- support the old structure where formatters could be a subkey
+ if not vim.tbl_islist(ft_formatters) then
+ vim.notify_once(
+ "Using deprecated structure for formatters_by_ft. See :help conform-options for details.",
+ vim.log.levels.ERROR
+ )
+ ---@diagnostic disable-next-line: undefined-field
+ ft_formatters = ft_formatters.formatters
+ end
- dedupe_formatters(ft_formatters, formatters)
+ dedupe_formatters(ft_formatters, formatters)
+ end
end
end
@@ -301,11 +294,12 @@ local function range_from_selection(bufnr, mode)
}
end
+---@private
---@param names conform.FormatterUnit[]
---@param bufnr integer
---@param warn_on_missing boolean
---@return conform.FormatterInfo[]
-local function resolve_formatters(names, bufnr, warn_on_missing)
+M.resolve_formatters = function(names, bufnr, warn_on_missing)
local all_info = {}
local function add_info(info, warn)
if info.available then
@@ -372,7 +366,7 @@ M.format = function(opts, callback)
local explicit_formatters = opts.formatters ~= nil
local formatter_names = opts.formatters or M.list_formatters_for_buffer(opts.bufnr)
local formatters =
- resolve_formatters(formatter_names, opts.bufnr, not opts.quiet and explicit_formatters)
+ M.resolve_formatters(formatter_names, opts.bufnr, not opts.quiet and explicit_formatters)
local any_formatters = not vim.tbl_isempty(formatters)
if not explicit_formatters and opts.lsp_fallback == true and M.will_fallback_lsp(opts) then
@@ -464,7 +458,7 @@ M.format_lines = function(formatter_names, lines, opts, callback)
local errors = require("conform.errors")
local log = require("conform.log")
local runner = require("conform.runner")
- local formatters = resolve_formatters(formatter_names, opts.bufnr, not opts.quiet)
+ local formatters = M.resolve_formatters(formatter_names, opts.bufnr, not opts.quiet)
if vim.tbl_isempty(formatters) then
callback(nil, lines)
return
@@ -499,7 +493,7 @@ M.list_formatters = function(bufnr)
bufnr = vim.api.nvim_get_current_buf()
end
local formatters = M.list_formatters_for_buffer(bufnr)
- return resolve_formatters(formatters, bufnr, false)
+ return M.resolve_formatters(formatters, bufnr, false)
end
---List information about all filetype-configured formatters
@@ -507,8 +501,15 @@ end
M.list_all_formatters = function()
local formatters = {}
for _, ft_formatters in pairs(M.formatters_by_ft) do
+ if type(ft_formatters) == "function" then
+ ft_formatters = ft_formatters(0)
+ end
-- support the old structure where formatters could be a subkey
if not vim.tbl_islist(ft_formatters) then
+ vim.notify_once(
+ "Using deprecated structure for formatters_by_ft. See :help conform-options for details.",
+ vim.log.levels.ERROR
+ )
---@diagnostic disable-next-line: undefined-field
ft_formatters = ft_formatters.formatters
end
diff --git a/scripts/options_doc.lua b/scripts/options_doc.lua
index 6f850ef..72acca4 100644
--- a/scripts/options_doc.lua
+++ b/scripts/options_doc.lua
@@ -3,9 +3,17 @@ require("conform").setup({
formatters_by_ft = {
lua = { "stylua" },
-- Conform will run multiple formatters sequentially
- python = { "isort", "black" },
+ go = { "goimports", "gofmt" },
-- Use a sub-list to run only the first available formatter
javascript = { { "prettierd", "prettier" } },
+ -- You can use a function here to determine the formatters dynamically
+ python = function(bufnr)
+ if require("conform").get_formatter_info("ruff_format", bufnr).available then
+ return { "ruff_format" }
+ else
+ return { "isort", "black" }
+ end
+ end,
-- Use the "*" filetype to run formatters on all filetypes.
["*"] = { "codespell" },
-- Use the "_" filetype to run formatters on filetypes that don't