aboutsummaryrefslogtreecommitdiffstats
path: root/lua/conform
diff options
context:
space:
mode:
authorSteven Arcangeli <506791+stevearc@users.noreply.github.com>2023-12-06 22:20:29 -0800
committerGitHub <noreply@github.com>2023-12-06 22:20:29 -0800
commit659838ff4244ef6af095395ce68aaaf99fa8e696 (patch)
treeb92754f2de1a225187769ed2c30e01a3ea703b3c /lua/conform
parent8d0421a11b2944c6c059e0936a95182972921c30 (diff)
refactor!: formatter config functions take self as first argument (#233)
This is a breaking API change, but there is a shim in place that will keep existing functions working, just with a warning notification. Most people should not encounter this at all. For anyone overriding a formatter config value with a function that takes `(ctx)` as the parameter, it will need to be updated to take `(self, ctx)`.
Diffstat (limited to 'lua/conform')
-rw-r--r--lua/conform/formatters/autopep8.lua2
-rw-r--r--lua/conform/formatters/clang_format.lua2
-rw-r--r--lua/conform/formatters/darker.lua2
-rw-r--r--lua/conform/formatters/deno_fmt.lua2
-rw-r--r--lua/conform/formatters/markdown-toc.lua2
-rw-r--r--lua/conform/formatters/phpcbf.lua2
-rw-r--r--lua/conform/formatters/prettier.lua2
-rw-r--r--lua/conform/formatters/prettierd.lua2
-rw-r--r--lua/conform/formatters/stylua.lua2
-rw-r--r--lua/conform/formatters/uncrustify.lua2
-rw-r--r--lua/conform/formatters/yapf.lua2
-rw-r--r--lua/conform/formatters/zprint.lua2
-rw-r--r--lua/conform/init.lua26
-rw-r--r--lua/conform/runner.lua21
-rw-r--r--lua/conform/util.lua62
15 files changed, 90 insertions, 43 deletions
diff --git a/lua/conform/formatters/autopep8.lua b/lua/conform/formatters/autopep8.lua
index 3945e47..3d5b015 100644
--- a/lua/conform/formatters/autopep8.lua
+++ b/lua/conform/formatters/autopep8.lua
@@ -6,7 +6,7 @@ return {
},
command = "autopep8",
args = { "-" },
- range_args = function(ctx)
+ range_args = function(self, ctx)
return { "-", "--line-range", tostring(ctx.range.start[1]), tostring(ctx.range["end"][1]) }
end,
}
diff --git a/lua/conform/formatters/clang_format.lua b/lua/conform/formatters/clang_format.lua
index 44af877..2e68fc1 100644
--- a/lua/conform/formatters/clang_format.lua
+++ b/lua/conform/formatters/clang_format.lua
@@ -7,7 +7,7 @@ return {
},
command = "clang-format",
args = { "-assume-filename", "$FILENAME" },
- range_args = function(ctx)
+ range_args = function(self, ctx)
local start_offset, end_offset = util.get_offsets_from_range(ctx.buf, ctx.range)
local length = end_offset - start_offset
return {
diff --git a/lua/conform/formatters/darker.lua b/lua/conform/formatters/darker.lua
index 5f47e6b..9fe9b20 100644
--- a/lua/conform/formatters/darker.lua
+++ b/lua/conform/formatters/darker.lua
@@ -6,7 +6,7 @@ return {
description = "Run black only on changed lines.",
},
command = "darker",
- args = function(ctx)
+ args = function(self, ctx)
-- make sure pre-save doesn't lose changes while post-save respects
-- the revision setting potentially set in pyproject.toml
if vim.bo[ctx.buf].modified then
diff --git a/lua/conform/formatters/deno_fmt.lua b/lua/conform/formatters/deno_fmt.lua
index 7b48320..5e7f452 100644
--- a/lua/conform/formatters/deno_fmt.lua
+++ b/lua/conform/formatters/deno_fmt.lua
@@ -14,7 +14,7 @@ return {
description = "Use [Deno](https://deno.land/) to format TypeScript, JavaScript/JSON and markdown.",
},
command = "deno",
- args = function(ctx)
+ args = function(self, ctx)
return {
"fmt",
"-",
diff --git a/lua/conform/formatters/markdown-toc.lua b/lua/conform/formatters/markdown-toc.lua
index 129d50e..a7a9694 100644
--- a/lua/conform/formatters/markdown-toc.lua
+++ b/lua/conform/formatters/markdown-toc.lua
@@ -6,7 +6,7 @@ return {
},
command = "markdown-toc",
stdin = false,
- args = function(ctx)
+ args = function(self, ctx)
-- use the indentation set in the current buffer, effectively allowing us to
-- use values from .editorconfig
local indent = vim.bo[ctx.buf].expandtab and (" "):rep(vim.bo[ctx.buf].tabstop) or "\t"
diff --git a/lua/conform/formatters/phpcbf.lua b/lua/conform/formatters/phpcbf.lua
index 38f3155..6c6027e 100644
--- a/lua/conform/formatters/phpcbf.lua
+++ b/lua/conform/formatters/phpcbf.lua
@@ -9,7 +9,7 @@ return {
command = util.find_executable({
"vendor/bin/phpcbf",
}, "phpcbf"),
- args = function(ctx)
+ args = function(self, ctx)
return { "-q", "--stdin-path=" .. ctx.filename, "-" }
end,
stdin = true,
diff --git a/lua/conform/formatters/prettier.lua b/lua/conform/formatters/prettier.lua
index ea45ffb..52dda86 100644
--- a/lua/conform/formatters/prettier.lua
+++ b/lua/conform/formatters/prettier.lua
@@ -7,7 +7,7 @@ return {
},
command = util.from_node_modules("prettier"),
args = { "--stdin-filepath", "$FILENAME" },
- range_args = function(ctx)
+ range_args = function(self, ctx)
local start_offset, end_offset = util.get_offsets_from_range(ctx.buf, ctx.range)
return { "$FILENAME", "--range-start=" .. start_offset, "--range-end=" .. end_offset }
end,
diff --git a/lua/conform/formatters/prettierd.lua b/lua/conform/formatters/prettierd.lua
index 3cdc19e..386d441 100644
--- a/lua/conform/formatters/prettierd.lua
+++ b/lua/conform/formatters/prettierd.lua
@@ -7,7 +7,7 @@ return {
},
command = util.from_node_modules("prettierd"),
args = { "$FILENAME" },
- range_args = function(ctx)
+ range_args = function(self, ctx)
local start_offset, end_offset = util.get_offsets_from_range(ctx.buf, ctx.range)
return { "$FILENAME", "--range-start=" .. start_offset, "--range-end=" .. end_offset }
end,
diff --git a/lua/conform/formatters/stylua.lua b/lua/conform/formatters/stylua.lua
index d971932..25012bf 100644
--- a/lua/conform/formatters/stylua.lua
+++ b/lua/conform/formatters/stylua.lua
@@ -7,7 +7,7 @@ return {
},
command = "stylua",
args = { "--search-parent-directories", "--stdin-filepath", "$FILENAME", "-" },
- range_args = function(ctx)
+ range_args = function(self, ctx)
local start_offset, end_offset = util.get_offsets_from_range(ctx.buf, ctx.range)
return {
"--search-parent-directories",
diff --git a/lua/conform/formatters/uncrustify.lua b/lua/conform/formatters/uncrustify.lua
index 2782e96..aec93c2 100644
--- a/lua/conform/formatters/uncrustify.lua
+++ b/lua/conform/formatters/uncrustify.lua
@@ -5,7 +5,7 @@ return {
description = "A source code beautifier for C, C++, C#, ObjectiveC, D, Java, Pawn and Vala.",
},
command = "uncrustify",
- args = function(ctx)
+ args = function(self, ctx)
return { "-q", "-l", vim.bo[ctx.buf].filetype:upper() }
end,
}
diff --git a/lua/conform/formatters/yapf.lua b/lua/conform/formatters/yapf.lua
index fc3cfeb..63bff83 100644
--- a/lua/conform/formatters/yapf.lua
+++ b/lua/conform/formatters/yapf.lua
@@ -6,7 +6,7 @@ return {
},
command = "yapf",
args = { "--quiet" },
- range_args = function(ctx)
+ range_args = function(self, ctx)
return { "--quiet", "--lines", string.format("%d-%d", ctx.range.start[1], ctx.range["end"][1]) }
end,
}
diff --git a/lua/conform/formatters/zprint.lua b/lua/conform/formatters/zprint.lua
index 935a485..240b7ed 100644
--- a/lua/conform/formatters/zprint.lua
+++ b/lua/conform/formatters/zprint.lua
@@ -5,7 +5,7 @@ return {
description = "Formatter for Clojure and EDN.",
},
command = "zprint",
- range_args = function(ctx)
+ range_args = function(self, ctx)
return {
string.format(
"{:input {:range {:start %d :end %d :use-previous-!zprint? true :continue-after-!zprint-error? true}}}",
diff --git a/lua/conform/init.lua b/lua/conform/init.lua
index 50ae6ba..d980b8f 100644
--- a/lua/conform/init.lua
+++ b/lua/conform/init.lua
@@ -8,15 +8,16 @@ local M = {}
---@field available_msg? string
---@class (exact) conform.JobFormatterConfig
----@field command string|fun(ctx: conform.Context): string
----@field args? string|string[]|fun(ctx: conform.Context): string|string[]
----@field range_args? fun(ctx: conform.RangeContext): string|string[]
----@field cwd? fun(ctx: conform.Context): nil|string
+---@field command string|fun(self: conform.JobFormatterConfig, ctx: conform.Context): string
+---@field args? string|string[]|fun(self: conform.JobFormatterConfig, ctx: conform.Context): string|string[]
+---@field range_args? fun(self: conform.JobFormatterConfig, ctx: conform.RangeContext): string|string[]
+---@field cwd? fun(self: conform.JobFormatterConfig, ctx: conform.Context): nil|string
---@field require_cwd? boolean When cwd is not found, don't run the formatter (default false)
---@field stdin? boolean Send buffer contents to stdin (default true)
----@field condition? fun(ctx: conform.Context): boolean
+---@field condition? fun(self: conform.JobFormatterConfig, ctx: conform.Context): boolean
---@field exit_codes? integer[] Exit codes that indicate success (default {0})
----@field env? table<string, any>|fun(ctx: conform.Context): table<string, any>
+---@field env? table<string, any>|fun(self: conform.JobFormatterConfig, ctx: conform.Context): table<string, any>
+---@field options? table
---@class (exact) conform.LuaFormatterConfig
---@field format fun(self: conform.LuaFormatterConfig, ctx: conform.Context, lines: string[], callback: fun(err: nil|string, new_lines: nil|string[]))
@@ -33,8 +34,8 @@ local M = {}
---@class (exact) conform.FormatterConfigOverride : conform.JobFormatterConfig
---@field inherit? boolean
----@field command? string|fun(ctx: conform.Context): string
----@field prepend_args? string|string[]|fun(ctx: conform.Context): string|string[]
+---@field command? string|fun(self: conform.FormatterConfig, ctx: conform.Context): string
+---@field prepend_args? string|string[]|fun(self: conform.FormatterConfig, ctx: conform.Context): string|string[]
---@field options? table
---@class (exact) conform.FormatterMeta
@@ -606,6 +607,7 @@ end
---@param bufnr? integer
---@return conform.FormatterInfo
M.get_formatter_info = function(formatter, bufnr)
+ local util = require("conform.util")
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
@@ -639,19 +641,21 @@ M.get_formatter_info = function(formatter, bufnr)
local command = config.command
if type(command) == "function" then
- command = command(ctx)
+ command = util.compat_call_with_self(formatter, config, command, ctx)
end
if vim.fn.executable(command) == 0 then
available = false
available_msg = "Command not found"
- elseif config.condition and not config.condition(ctx) then
+ elseif
+ config.condition and not util.compat_call_with_self(formatter, config, config.condition, ctx)
+ then
available = false
available_msg = "Condition failed"
end
local cwd = nil
if config.cwd then
- cwd = config.cwd(ctx)
+ cwd = util.compat_call_with_self(formatter, config, config.cwd, ctx)
if available and not cwd and config.require_cwd then
available = false
available_msg = "Root directory not found"
diff --git a/lua/conform/runner.lua b/lua/conform/runner.lua
index 9571588..8137ad1 100644
--- a/lua/conform/runner.lua
+++ b/lua/conform/runner.lua
@@ -8,25 +8,26 @@ local M = {}
---@class (exact) conform.RunOpts
---@field exclusive boolean If true, ensure only a single formatter is running per buffer
+---@param formatter_name string
---@param ctx conform.Context
---@param config conform.JobFormatterConfig
---@return string|string[]
-M.build_cmd = function(ctx, config)
+M.build_cmd = function(formatter_name, ctx, config)
local command = config.command
if type(command) == "function" then
- command = command(ctx)
+ command = util.compat_call_with_self(formatter_name, config, command, ctx)
end
---@type string|string[]
local args = {}
if ctx.range and config.range_args then
- ---@cast ctx conform.RangeContext
- args = config.range_args(ctx)
+ args = util.compat_call_with_self(formatter_name, config, config.range_args, ctx)
elseif config.args then
- if type(config.args) == "function" then
- args = config.args(ctx)
+ local computed_args = config.args
+ if type(computed_args) == "function" then
+ args = util.compat_call_with_self(formatter_name, config, computed_args, ctx)
else
---@diagnostic disable-next-line: cast-local-type
- args = config.args
+ args = computed_args
end
end
@@ -262,14 +263,14 @@ local function run_formatter(bufnr, formatter, config, ctx, input_lines, opts, c
return
end
---@cast config conform.JobFormatterConfig
- local cmd = M.build_cmd(ctx, config)
+ local cmd = M.build_cmd(formatter.name, ctx, config)
local cwd = nil
if config.cwd then
- cwd = config.cwd(ctx)
+ cwd = util.compat_call_with_self(formatter.name, config, config.cwd, ctx)
end
local env = config.env
if type(env) == "function" then
- env = env(ctx)
+ env = util.compat_call_with_self(formatter.name, config, env, ctx)
end
local buffer_text
diff --git a/lua/conform/util.lua b/lua/conform/util.lua
index bbb711a..0ff54de 100644
--- a/lua/conform/util.lua
+++ b/lua/conform/util.lua
@@ -10,11 +10,11 @@ end
---Search parent directories for a relative path to a command
---@param paths string[]
---@param default string
----@return fun(ctx: conform.Context): string
+---@return fun(self: conform.FormatterConfig, ctx: conform.Context): string
---@example
--- local cmd = require("conform.util").find_executable({ "node_modules/.bin/prettier" }, "prettier")
M.find_executable = function(paths, default)
- return function(ctx)
+ return function(self, ctx)
for _, path in ipairs(paths) do
local normpath = vim.fs.normalize(path)
local is_absolute = vim.startswith(normpath, "/")
@@ -46,9 +46,9 @@ M.find_executable = function(paths, default)
end
---@param files string|string[]
----@return fun(ctx: conform.Context): nil|string
+---@return fun(self: conform.FormatterConfig, ctx: conform.Context): nil|string
M.root_file = function(files)
- return function(ctx)
+ return function(self, ctx)
local found = vim.fs.find(files, { upward = true, path = ctx.dirname })[1]
if found then
return vim.fs.dirname(found)
@@ -101,8 +101,8 @@ M.wrap_callback = function(cb, wrapper)
end
---Helper function to add to the default args of a formatter.
----@param args string|string[]|fun(ctx: conform.Context): string|string[]
----@param extra_args string|string[]|fun(ctx: conform.Context): string|string[]
+---@param args string|string[]|fun(self: conform.FormatterConfig, ctx: conform.Context): string|string[]
+---@param extra_args string|string[]|fun(self: conform.FormatterConfig, ctx: conform.Context): string|string[]
---@param opts? { append?: boolean }
---@example
--- local util = require("conform.util")
@@ -113,12 +113,12 @@ end
--- })
M.extend_args = function(args, extra_args, opts)
opts = opts or {}
- return function(ctx)
+ return function(self, ctx)
if type(args) == "function" then
- args = args(ctx)
+ args = M.compat_call_with_self("unknown", self, args, ctx)
end
if type(extra_args) == "function" then
- extra_args = extra_args(ctx)
+ extra_args = M.compat_call_with_self("unknown", self, extra_args, ctx)
end
if type(args) == "string" then
if type(extra_args) ~= "string" then
@@ -143,7 +143,7 @@ M.extend_args = function(args, extra_args, opts)
end
---@param formatter conform.FormatterConfig
----@param extra_args string|string[]|fun(ctx: conform.Context): string|string[]
+---@param extra_args string|string[]|fun(self: conform.FormatterConfig, ctx: conform.Context): string|string[]
---@param opts? { append?: boolean }
---@example
--- local util = require("conform.util")
@@ -183,4 +183,46 @@ M.buf_get_changedtick = function(bufnr)
end
end
+---Returns true if the function takes no args or has self as the first arg
+---@param name string
+---@param fn function(...: any): T
+---@return boolean
+local function has_self_arg(name, fn)
+ local first_arg_name = nil
+ debug.sethook(function()
+ local info = debug.getinfo(3)
+ if info.name ~= "pcall" then
+ return
+ end
+ first_arg_name = debug.getlocal(2, 1)
+ error()
+ end, "c")
+ pcall(fn)
+ debug.sethook()
+
+ return first_arg_name == "self" or first_arg_name == nil
+end
+
+---@generic T
+---@param formatter_name string
+---@param self any
+---@param fn fun(...: any): T
+---@param ... any
+---@return T
+M.compat_call_with_self = function(formatter_name, self, fn, ...)
+ local has_self = has_self_arg(formatter_name, fn)
+ if has_self then
+ return fn(self, ...)
+ else
+ vim.notify_once(
+ string.format(
+ "[conform] formatter %s should take 'self' as the first argument for args, range_args, cwd, condition, and env functions (see :help conform-self-args)\nCompatibility will be dropped on 2024-03-01",
+ formatter_name
+ ),
+ vim.log.levels.WARN
+ )
+ return fn(...)
+ end
+end
+
return M