summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Arcangeli <stevearc@stevearc.com>2024-07-13 14:28:18 -0700
committerSteven Arcangeli <stevearc@stevearc.com>2024-07-19 08:41:31 -0700
commit0b3d25969e2da2f5de90cc02ccd6446aa68dd895 (patch)
treeed78bf0fae463a6f7bb1be08757a6ea5a5b6c3d7
parent3a0e9b44076514ffba6c81ca28685107928b55f7 (diff)
feat: format parameter to only run the first available formatter
-rw-r--r--README.md1
-rw-r--r--doc/conform.txt73
-rw-r--r--lua/conform/formatters/injected.lua20
-rw-r--r--lua/conform/init.lua34
-rw-r--r--lua/conform/types.lua9
5 files changed, 85 insertions, 52 deletions
diff --git a/README.md b/README.md
index 9b42903..f5b4258 100644
--- a/README.md
+++ b/README.md
@@ -609,6 +609,7 @@ Format a buffer
| | | > `"prefer"` | use only LSP formatting when available |
| | | > `"first"` | LSP formatting is used when available and then other formatters |
| | | > `"last"` | other formatters are used then LSP formatting when available |
+| | stop_after_first | `nil\|boolean` | Only run the first available formatter in the list. Defaults to false. |
| | quiet | `nil\|boolean` | Don't show any notifications for warnings or failures. Defaults to false. |
| | range | `nil\|conform.Range` | Range to format. Table must contain `start` and `end` keys with {row, col} tuples using (1,0) indexing. Defaults to current selection in visual mode |
| | id | `nil\|integer` | Passed to vim.lsp.buf.format when using LSP formatting |
diff --git a/doc/conform.txt b/doc/conform.txt
index 002e46c..589289b 100644
--- a/doc/conform.txt
+++ b/doc/conform.txt
@@ -132,11 +132,12 @@ setup({opts}) *conform.setu
This can also be a function that returns the table.
{default_format_opts} `nil|conform.DefaultFormatOpts` The default
options to use when calling conform.format()
- {timeout_ms} `nil|integer` Time in milliseconds to block for
- formatting. Defaults to 1000. No effect if async =
- true.
- {lsp_format} `nil|conform.LspFormatOpts` Configure if and when LSP
- should be used for formatting. Defaults to "never".
+ {timeout_ms} `nil|integer` Time in milliseconds to block for
+ formatting. Defaults to 1000. No effect if
+ async = true.
+ {lsp_format} `nil|conform.LspFormatOpts` Configure if and
+ when LSP should be used for formatting.
+ Defaults to "never".
`"never"` never use the LSP for formatting (default)
`"fallback"` LSP formatting is used when no other formatters
are available
@@ -145,8 +146,10 @@ setup({opts}) *conform.setu
other formatters
`"last"` other formatters are used then LSP formatting
when available
- {quiet} `nil|boolean` Don't show any notifications for
- warnings or failures. Defaults to false.
+ {quiet} `nil|boolean` Don't show any notifications for
+ warnings or failures. Defaults to false.
+ {stop_after_first} `nil|boolean` Only run the first available
+ formatter in the list. Defaults to false.
{format_after_save} `nil|conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts`
If this is set, Conform will run the formatter
asynchronously after save. It will pass the table
@@ -166,20 +169,23 @@ format({opts}, {callback}): boolean *conform.forma
Parameters:
{opts} `nil|conform.FormatOpts`
- {timeout_ms} `nil|integer` Time in milliseconds to block for
- formatting. Defaults to 1000. No effect if async = true.
- {bufnr} `nil|integer` Format this buffer (default 0)
- {async} `nil|boolean` If true the method won't block. Defaults to
- false. If the buffer is modified before the formatter
- completes, the formatting will be discarded.
- {dry_run} `nil|boolean` If true don't apply formatting changes to
- the buffer
- {undojoin} `nil|boolean` Use undojoin to merge formatting changes
- with previous edit (default false)
- {formatters} `nil|string[]` List of formatters to run. Defaults to all
- formatters for the buffer filetype.
- {lsp_format} `nil|conform.LspFormatOpts` Configure if and when LSP
- should be used for formatting. Defaults to "never".
+ {timeout_ms} `nil|integer` Time in milliseconds to block for
+ formatting. Defaults to 1000. No effect if async =
+ true.
+ {bufnr} `nil|integer` Format this buffer (default 0)
+ {async} `nil|boolean` If true the method won't block.
+ Defaults to false. If the buffer is modified before
+ the formatter completes, the formatting will be
+ discarded.
+ {dry_run} `nil|boolean` If true don't apply formatting
+ changes to the buffer
+ {undojoin} `nil|boolean` Use undojoin to merge formatting
+ changes with previous edit (default false)
+ {formatters} `nil|string[]` List of formatters to run. Defaults
+ to all formatters for the buffer filetype.
+ {lsp_format} `nil|conform.LspFormatOpts` Configure if and when
+ LSP should be used for formatting. Defaults to
+ "never".
`"never"` never use the LSP for formatting (default)
`"fallback"` LSP formatting is used when no other formatters are
available
@@ -188,19 +194,22 @@ format({opts}, {callback}): boolean *conform.forma
formatters
`"last"` other formatters are used then LSP formatting when
available
- {quiet} `nil|boolean` Don't show any notifications for warnings
- or failures. Defaults to false.
- {range} `nil|conform.Range` Range to format. Table must contain
- `start` and `end` keys with {row, col} tuples using (1,0)
- indexing. Defaults to current selection in visual mode
+ {stop_after_first} `nil|boolean` Only run the first available
+ formatter in the list. Defaults to false.
+ {quiet} `nil|boolean` Don't show any notifications for
+ warnings or failures. Defaults to false.
+ {range} `nil|conform.Range` Range to format. Table must
+ contain `start` and `end` keys with {row, col}
+ tuples using (1,0) indexing. Defaults to current
+ selection in visual mode
{start} `integer[]`
{end} `integer[]`
- {id} `nil|integer` Passed to |vim.lsp.buf.format| when using
- LSP formatting
- {name} `nil|string` Passed to |vim.lsp.buf.format| when using
- LSP formatting
- {filter} `nil|fun(client: table): boolean` Passed to
- |vim.lsp.buf.format| when using LSP formatting
+ {id} `nil|integer` Passed to |vim.lsp.buf.format| when
+ using LSP formatting
+ {name} `nil|string` Passed to |vim.lsp.buf.format| when
+ using LSP formatting
+ {filter} `nil|fun(client: table): boolean` Passed to |vim.ls
+ p.buf.format| when using LSP formatting
{callback} `nil|fun(err: nil|string, did_edit: nil|boolean)` Called once
formatting has completed
Returns:
diff --git a/lua/conform/formatters/injected.lua b/lua/conform/formatters/injected.lua
index 4dbf1eb..6cfd387 100644
--- a/lua/conform/formatters/injected.lua
+++ b/lua/conform/formatters/injected.lua
@@ -284,13 +284,21 @@ return {
---@type string[]
local formatter_names
if type(ft_formatters) == "function" then
- formatter_names = ft_formatters(ctx.buf)
- else
- local formatters = require("conform").resolve_formatters(ft_formatters, ctx.buf, false)
- formatter_names = vim.tbl_map(function(f)
- return f.name
- end, formatters)
+ ft_formatters = ft_formatters(ctx.buf)
end
+ local stop_after_first = ft_formatters.stop_after_first
+ if stop_after_first == nil then
+ stop_after_first = conform.default_format_opts.stop_after_first
+ end
+ if stop_after_first == nil then
+ stop_after_first = false
+ end
+
+ local formatters =
+ conform.resolve_formatters(ft_formatters, ctx.buf, false, stop_after_first)
+ formatter_names = vim.tbl_map(function(f)
+ return f.name
+ end, formatters)
local idx = num_format
log.debug("Injected format %s:%d:%d: %s", lang, start_lnum, end_lnum, formatter_names)
log.trace("Injected format lines %s", input_lines)
diff --git a/lua/conform/init.lua b/lua/conform/init.lua
index acd8c8c..208edc7 100644
--- a/lua/conform/init.lua
+++ b/lua/conform/init.lua
@@ -198,7 +198,7 @@ end
---@private
---@param bufnr? integer
----@return conform.FiletypeFormatterInternal[]
+---@return string[]
M.list_formatters_for_buffer = function(bufnr)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
@@ -301,8 +301,9 @@ end
---@param names conform.FiletypeFormatterInternal
---@param bufnr integer
---@param warn_on_missing boolean
+---@param stop_after_first boolean
---@return conform.FormatterInfo[]
-M.resolve_formatters = function(names, bufnr, warn_on_missing)
+M.resolve_formatters = function(names, bufnr, warn_on_missing, stop_after_first)
local all_info = {}
local function add_info(info, warn)
if info.available then
@@ -329,6 +330,10 @@ M.resolve_formatters = function(names, bufnr, warn_on_missing)
end
end
end
+
+ if stop_after_first and #all_info > 0 then
+ break
+ end
end
return all_info
end
@@ -353,7 +358,6 @@ end
---@param callback? fun(err: nil|string, did_edit: nil|boolean) Called once formatting has completed
---@return boolean True if any formatters were attempted
M.format = function(opts, callback)
- ---@type {timeout_ms: integer, bufnr: integer, async: boolean, dry_run: boolean, lsp_format: "never"|"first"|"last"|"prefer"|"fallback", quiet: boolean, formatters?: string[], range?: conform.Range, undojoin: boolean}
opts = opts or {}
local has_explicit_formatters = opts ~= nil and opts.formatters ~= nil
if not has_explicit_formatters then
@@ -361,6 +365,7 @@ M.format = function(opts, callback)
end
opts = vim.tbl_extend("keep", opts, M.default_format_opts)
+ ---@type {timeout_ms: integer, bufnr: integer, async: boolean, dry_run: boolean, lsp_format: "never"|"first"|"last"|"prefer"|"fallback", quiet: boolean, stop_after_first: boolean, formatters?: string[], range?: conform.Range, undojoin: boolean}
opts = vim.tbl_extend("keep", opts, {
timeout_ms = 1000,
bufnr = 0,
@@ -369,6 +374,7 @@ M.format = function(opts, callback)
lsp_format = "never",
quiet = false,
undojoin = false,
+ stop_after_first = false,
})
-- For backwards compatibility
@@ -394,8 +400,12 @@ M.format = function(opts, callback)
local runner = require("conform.runner")
local formatter_names = opts.formatters or M.list_formatters_for_buffer(opts.bufnr)
- local formatters =
- M.resolve_formatters(formatter_names, opts.bufnr, not opts.quiet and has_explicit_formatters)
+ local formatters = M.resolve_formatters(
+ formatter_names,
+ opts.bufnr,
+ not opts.quiet and has_explicit_formatters,
+ opts.stop_after_first
+ )
local has_lsp = has_lsp_formatter(opts)
---@param err? conform.Error
@@ -483,12 +493,6 @@ M.format = function(opts, callback)
end
end
----@class conform.FormatLinesOpts
----@field timeout_ms nil|integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
----@field bufnr nil|integer use this as the working buffer (default 0)
----@field async nil|boolean If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded.
----@field quiet nil|boolean Don't show any notifications for warnings or failures. Defaults to false.
-
---Process lines with formatters
---@private
---@param formatter_names string[]
@@ -498,18 +502,20 @@ end
---@return nil|conform.Error error Only present if async = false
---@return nil|string[] new_lines Only present if async = false
M.format_lines = function(formatter_names, lines, opts, callback)
- ---@type {timeout_ms: integer, bufnr: integer, async: boolean, quiet: boolean}
+ ---@type {timeout_ms: integer, bufnr: integer, async: boolean, quiet: boolean, stop_after_first: boolean}
opts = vim.tbl_extend("keep", opts or {}, {
timeout_ms = 1000,
bufnr = 0,
async = false,
quiet = false,
+ stop_after_first = false,
})
callback = callback or function(_err, _lines) end
local errors = require("conform.errors")
local log = require("conform.log")
local runner = require("conform.runner")
- local formatters = M.resolve_formatters(formatter_names, opts.bufnr, not opts.quiet)
+ local formatters =
+ M.resolve_formatters(formatter_names, opts.bufnr, not opts.quiet, opts.stop_after_first)
if vim.tbl_isempty(formatters) then
callback(nil, lines)
return
@@ -545,7 +551,7 @@ M.list_formatters = function(bufnr)
bufnr = vim.api.nvim_get_current_buf()
end
local formatters = M.list_formatters_for_buffer(bufnr)
- return M.resolve_formatters(formatters, bufnr, false)
+ return M.resolve_formatters(formatters, bufnr, false, false)
end
---List information about all filetype-configured formatters
diff --git a/lua/conform/types.lua b/lua/conform/types.lua
index 2f051ca..9b775a9 100644
--- a/lua/conform/types.lua
+++ b/lua/conform/types.lua
@@ -79,6 +79,7 @@
---@field undojoin? boolean Use undojoin to merge formatting changes with previous edit (default false)
---@field formatters? string[] List of formatters to run. Defaults to all formatters for the buffer filetype.
---@field lsp_format? conform.LspFormatOpts Configure if and when LSP should be used for formatting. Defaults to "never".
+---@field stop_after_first? boolean Only run the first available formatter in the list. Defaults to false.
---@field quiet? boolean Don't show any notifications for warnings or failures. Defaults to false.
---@field range? conform.Range Range to format. Table must contain `start` and `end` keys with {row, col} tuples using (1,0) indexing. Defaults to current selection in visual mode
---@field id? integer Passed to |vim.lsp.buf.format| when using LSP formatting
@@ -89,6 +90,14 @@
---@field timeout_ms? integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
---@field lsp_format? conform.LspFormatOpts Configure if and when LSP should be used for formatting. Defaults to "never".
---@field quiet? boolean Don't show any notifications for warnings or failures. Defaults to false.
+---@field stop_after_first? boolean Only run the first available formatter in the list. Defaults to false.
+
+---@class conform.FormatLinesOpts
+---@field timeout_ms? integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
+---@field bufnr? integer use this as the working buffer (default 0)
+---@field async? boolean If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded.
+---@field quiet? boolean Don't show any notifications for warnings or failures. Defaults to false.
+---@field stop_after_first? boolean Only run the first available formatter in the list. Defaults to false.
---@class (exact) conform.setupOpts
---@field formatters_by_ft? table<string, conform.FiletypeFormatter> Map of filetype to formatters