Compare commits
11
Commits
c41b19222d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
132a3d0630 | ||
|
|
48da2ebd5e | ||
|
|
368ee5d3e6 | ||
|
|
f3b96fa221 | ||
|
|
1983f353b2 | ||
|
|
abce2be529 | ||
|
|
ae0d37dd43 | ||
|
|
40133b4bf3 | ||
|
|
ddb854253d | ||
|
|
882a4449e5 | ||
|
|
3ba75eeae8 |
@@ -0,0 +1,7 @@
|
|||||||
|
column_width = 120
|
||||||
|
line_endings = "Unix"
|
||||||
|
indent_type = "Spaces"
|
||||||
|
indent_width = 4
|
||||||
|
quote_style = "AutoPreferDouble"
|
||||||
|
call_parentheses = "Always"
|
||||||
|
collapse_simple_statement = "Never"
|
||||||
@@ -1,9 +1,17 @@
|
|||||||
# mason-conform.nvim
|
# mason-conform.nvim
|
||||||
|
|
||||||
Auto install formatters registered with `conform.nvim` via [Mason](https://github.com/williamboman/mason.nvim).
|
Automatically install formatters registered with [conform.nvim](https://github.com/stevearc/conform.nvim) via [Mason](https://github.com/williamboman/mason.nvim).
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
|
||||||
|
- Neovim 0.11+
|
||||||
|
- [mason.nvim](https://github.com/mason-org/mason.nvim) 2.x
|
||||||
|
- [conform.nvim](https://github.com/stevearc/conform.nvim) (9.x or newer)
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
|
|
||||||
|
With [lazy.nvim](https://github.com/folke/lazy.nvim):
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
require("lazy").setup({
|
require("lazy").setup({
|
||||||
"williamboman/mason.nvim",
|
"williamboman/mason.nvim",
|
||||||
@@ -12,6 +20,16 @@ require("lazy").setup({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
With Neovim's built-in package manager (`:h vim.pack`, Neovim 0.12+):
|
||||||
|
|
||||||
|
```lua
|
||||||
|
vim.pack.add({
|
||||||
|
{ src = "https://github.com/mason-org/mason.nvim" },
|
||||||
|
{ src = "https://github.com/stevearc/conform.nvim" },
|
||||||
|
{ src = "https://github.com/zapling/mason-conform.nvim" },
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
# Setup
|
# Setup
|
||||||
|
|
||||||
It's crucial to setup plugins in the following order:
|
It's crucial to setup plugins in the following order:
|
||||||
@@ -26,15 +44,45 @@ access the mason registry.
|
|||||||
# Configuration
|
# Configuration
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
require("mason-conform").setup()
|
require("mason-conform").setup({
|
||||||
|
ignore_install = {'prettier'} -- List of formatters to ignore during install
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
All the `formatters_by_ft` shapes supported by conform are understood:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
require("conform").setup({
|
||||||
|
formatters_by_ft = {
|
||||||
|
-- Plain list
|
||||||
|
lua = { "stylua" },
|
||||||
|
-- List with inline format options (`lsp_format`, `stop_after_first`, ...)
|
||||||
|
python = { "autopep8", lsp_format = "fallback" },
|
||||||
|
-- Legacy nested list ("run the first available formatter")
|
||||||
|
markdown = { { "prettierd", "prettier" }, "cbfmt" },
|
||||||
|
-- Function returning a list (conform "first available" recipe)
|
||||||
|
javascript = function(bufnr)
|
||||||
|
return { require("conform").get_formatter_info("prettier", bufnr).available and "prettier" or "prettierd" }
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Functions are evaluated without a buffer so that every candidate formatter can
|
||||||
|
be discovered and installed. A function that requires a buffer is skipped
|
||||||
|
instead of raising an error.
|
||||||
|
|
||||||
# Available formatters
|
# Available formatters
|
||||||
|
|
||||||
Only formatters that are available in the [mason registry](https://github.com/mason-org/mason-registry)
|
Only formatters that are available in the [mason registry](https://github.com/mason-org/mason-registry)
|
||||||
can be downloaded automatically. If the formatter is available in the registry and it's not being
|
can be downloaded automatically. If the formatter is available in the registry and it's not being
|
||||||
downloaded, this plugin might be missing a `conform` => `mason` mapping in the file [lua/mason-conform/mapping.lua](lua/mason-conform/mapping.lua).
|
downloaded, this plugin might be missing a `conform` => `mason` mapping in the file [lua/mason-conform/mapping.lua](lua/mason-conform/mapping.lua).
|
||||||
|
|
||||||
|
# Healthcheck
|
||||||
|
|
||||||
|
Run `:checkhealth mason-conform` to verify that Neovim, `mason.nvim` and `conform.nvim` are set up
|
||||||
|
correctly, and to see which configured formatters cannot be installed automatically.
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
`mason-conform.nvim` is a blatant copy of [mason-nvim-lint](https://github.com/rshkarin/mason-nvim-lint)
|
`mason-conform.nvim` is a blatant copy of [mason-nvim-lint](https://github.com/rshkarin/mason-nvim-lint)
|
||||||
|
|||||||
@@ -1,36 +1,25 @@
|
|||||||
local registry = require("mason-registry")
|
|
||||||
local mapping = require("mason-conform.mapping")
|
|
||||||
|
|
||||||
local function auto_install()
|
local function auto_install()
|
||||||
local formatters_by_ft = require("conform").formatters_by_ft;
|
local config = require("mason-conform").config
|
||||||
|
local mapping = require("mason-conform.mapping")
|
||||||
|
local install = require("mason-conform.install")
|
||||||
|
|
||||||
local formatters_to_install = {}
|
local ignored = {}
|
||||||
for _, formatters in pairs(formatters_by_ft) do
|
for _, name in ipairs(config.ignore_install) do
|
||||||
for _, formatter in pairs(formatters) do
|
ignored[name] = true
|
||||||
-- Support case where the user has defined multiple formatters
|
end
|
||||||
-- for said filetype. E.g javascript = { { "prettierd", "prettier" } }
|
|
||||||
if type(formatter) == "table" then
|
for _, name in ipairs(require("mason-conform.formatters").configured()) do
|
||||||
for _, f in pairs(formatter) do
|
if not ignored[name] then
|
||||||
formatters_to_install[f] = 1
|
local package = mapping.conform_to_package[name]
|
||||||
end
|
if package ~= nil then
|
||||||
else
|
install.try_install(package)
|
||||||
formatters_to_install[formatter] = 1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for conformFormatter, _ in pairs(formatters_to_install) do
|
|
||||||
local package = mapping.conform_to_package[conformFormatter]
|
|
||||||
if package ~= nil then
|
|
||||||
require("mason-conform.install").try_install(package)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if registry.refresh then
|
---Refresh the mason registry, then install every configured formatter that is
|
||||||
return function()
|
---missing. Returns immediately; installation happens on the main loop.
|
||||||
registry.refresh(vim.schedule_wrap(auto_install))
|
return function()
|
||||||
end
|
require("mason-registry").refresh(vim.schedule_wrap(auto_install))
|
||||||
else
|
|
||||||
return auto_install
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
local M = {}
|
||||||
|
|
||||||
|
---Collect formatter names from a single `formatters_by_ft` entry.
|
||||||
|
---
|
||||||
|
---A conform filetype formatter can be any of:
|
||||||
|
--- * a list of formatter names, optionally followed by string-keyed format
|
||||||
|
--- options (e.g. `{ "stylua", lsp_format = "fallback" }`)
|
||||||
|
--- * a function `fun(bufnr): string[]`, used by the "run the first available
|
||||||
|
--- formatter" recipe
|
||||||
|
--- * the legacy nested list `{ { "prettierd", "prettier" } }`
|
||||||
|
---
|
||||||
|
---Only the array part of the table is traversed, so format options such as
|
||||||
|
---`lsp_format` and `stop_after_first` are ignored.
|
||||||
|
---@param value any
|
||||||
|
---@param out table<string, boolean>
|
||||||
|
local function collect_entry(value, out)
|
||||||
|
local list = value
|
||||||
|
if type(list) == "function" then
|
||||||
|
-- A function may depend on a buffer and/or on run-time availability.
|
||||||
|
-- We don't have a buffer to pass here, so evaluate it best-effort and
|
||||||
|
-- silently skip it when it cannot be called without one.
|
||||||
|
local ok, result = pcall(list)
|
||||||
|
if not ok or type(result) ~= "table" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
list = result
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(list) ~= "table" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, formatter in ipairs(list) do
|
||||||
|
if type(formatter) == "table" then
|
||||||
|
-- Legacy "run the first available formatter" syntax.
|
||||||
|
collect_entry(formatter, out)
|
||||||
|
elseif type(formatter) == "string" then
|
||||||
|
out[formatter] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---List every formatter configured in conform's `formatters_by_ft`.
|
||||||
|
---
|
||||||
|
---Understands all `formatters_by_ft` shapes supported by conform, including
|
||||||
|
---functions returning a list and the legacy nested "run the first available"
|
||||||
|
---syntax.
|
||||||
|
---@return string[] names Sorted, de-duplicated formatter names.
|
||||||
|
function M.configured()
|
||||||
|
local out = {}
|
||||||
|
for _, entry in pairs(require("conform").formatters_by_ft or {}) do
|
||||||
|
collect_entry(entry, out)
|
||||||
|
end
|
||||||
|
|
||||||
|
local names = {}
|
||||||
|
for name in pairs(out) do
|
||||||
|
names[#names + 1] = name
|
||||||
|
end
|
||||||
|
table.sort(names)
|
||||||
|
return names
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
local M = {}
|
||||||
|
|
||||||
|
---@return boolean
|
||||||
|
local function check_mason()
|
||||||
|
local ok, mason_version = pcall(require, "mason.version")
|
||||||
|
if not ok then
|
||||||
|
vim.health.error("mason.nvim was not found. Is it installed and loaded?")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if mason_version.MAJOR_VERSION ~= 2 then
|
||||||
|
vim.health.error(("mason.nvim v2 is required (found v%d)."):format(mason_version.MAJOR_VERSION))
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
vim.health.ok("mason.nvim v2")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.check()
|
||||||
|
vim.health.start("mason-conform.nvim")
|
||||||
|
|
||||||
|
if vim.fn.has("nvim-0.11") == 1 then
|
||||||
|
vim.health.ok("Neovim v0.11+")
|
||||||
|
else
|
||||||
|
vim.health.error("Neovim v0.11 or higher is required.")
|
||||||
|
end
|
||||||
|
|
||||||
|
local mason_installed = check_mason()
|
||||||
|
|
||||||
|
if mason_installed then
|
||||||
|
local registry_ok = pcall(require, "mason-registry")
|
||||||
|
if registry_ok then
|
||||||
|
vim.health.ok("mason registry is accessible")
|
||||||
|
else
|
||||||
|
vim.health.error("mason-registry could not be loaded.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local conform_ok = pcall(require, "conform")
|
||||||
|
if not conform_ok then
|
||||||
|
vim.health.error("conform.nvim was not found. Is it installed and loaded?")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
vim.health.ok("conform.nvim")
|
||||||
|
|
||||||
|
local formatters = require("mason-conform.formatters").configured()
|
||||||
|
if #formatters == 0 then
|
||||||
|
vim.health.warn("No formatters are configured in conform's formatters_by_ft, so there is nothing to install.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
vim.health.ok(("%d formatter(s) configured in formatters_by_ft"):format(#formatters))
|
||||||
|
|
||||||
|
local mapping = require("mason-conform.mapping")
|
||||||
|
local unmapped = {}
|
||||||
|
for _, name in ipairs(formatters) do
|
||||||
|
if mapping.conform_to_package[name] == nil then
|
||||||
|
unmapped[#unmapped + 1] = name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #unmapped > 0 then
|
||||||
|
vim.health.info(
|
||||||
|
("No mason package mapping for: %s. These will not be installed automatically."):format(
|
||||||
|
table.concat(unmapped, ", ")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
local ignored = {}
|
||||||
|
for _, name in ipairs(require("mason-conform").config.ignore_install) do
|
||||||
|
ignored[#ignored + 1] = name
|
||||||
|
end
|
||||||
|
if #ignored > 0 then
|
||||||
|
vim.health.info(("Ignored by 'ignore_install': %s"):format(table.concat(ignored, ", ")))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
@@ -1,7 +1,20 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
function M.setup()
|
---@class MasonConformConfig
|
||||||
require "mason-conform.auto_install" ()
|
---@field ignore_install string[] Formatters that should never be installed automatically.
|
||||||
|
|
||||||
|
---@type MasonConformConfig
|
||||||
|
M.config = {
|
||||||
|
ignore_install = {},
|
||||||
|
}
|
||||||
|
|
||||||
|
---@param opts? MasonConformConfig Options overriding the defaults.
|
||||||
|
function M.setup(opts)
|
||||||
|
vim.validate("opts", opts, "table", true)
|
||||||
|
|
||||||
|
M.config = vim.tbl_deep_extend("force", { ignore_install = {} }, opts or {})
|
||||||
|
|
||||||
|
require("mason-conform.auto_install")()
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
@@ -1,31 +1,19 @@
|
|||||||
local registry = require "mason-registry"
|
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local function resolve_package(mason_package_name)
|
---@param pkg Package The mason package to install.
|
||||||
local Optional = require "mason-core.optional"
|
---@param version? string Pin the installation to a specific version.
|
||||||
|
|
||||||
local ok, pkg = pcall(registry.get_package, mason_package_name)
|
|
||||||
if ok then
|
|
||||||
return Optional.of_nilable(pkg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function install_package(pkg, version)
|
local function install_package(pkg, version)
|
||||||
local linter_name = pkg.name
|
vim.notify(("[mason-conform] installing %s"):format(pkg.name))
|
||||||
|
|
||||||
vim.notify(("[mason-conform] installing %s"):format(linter_name))
|
pkg:install({ version = version }):once(
|
||||||
|
|
||||||
return pkg:install({ version = version }):once(
|
|
||||||
"closed",
|
"closed",
|
||||||
vim.schedule_wrap(function()
|
vim.schedule_wrap(function()
|
||||||
if pkg:is_installed() then
|
if pkg:is_installed() then
|
||||||
vim.notify(("[mason-conform] %s was successfully installed"):format(linter_name))
|
vim.notify(("[mason-conform] %s was successfully installed"):format(pkg.name))
|
||||||
else
|
else
|
||||||
vim.notify(
|
vim.notify(
|
||||||
("[mason-conform] failed to install %s. Installation logs are available in :Mason and :MasonLog")
|
("[mason-conform] failed to install %s. Installation logs are available in :Mason and :MasonLog"):format(
|
||||||
:format(
|
pkg.name
|
||||||
linter_name
|
|
||||||
),
|
),
|
||||||
vim.log.levels.ERROR
|
vim.log.levels.ERROR
|
||||||
)
|
)
|
||||||
@@ -34,27 +22,30 @@ local function install_package(pkg, version)
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Install the mason package if it exists in the registry and is not already
|
||||||
|
---installed or installing.
|
||||||
|
---@param mason_package_name string Mason package identifier, optionally `name@version`.
|
||||||
function M.try_install(mason_package_name)
|
function M.try_install(mason_package_name)
|
||||||
local Package = require "mason-core.package"
|
local Package = require("mason-core.package")
|
||||||
|
local registry = require("mason-registry")
|
||||||
local package_name, version = Package.Parse(mason_package_name)
|
local package_name, version = Package.Parse(mason_package_name)
|
||||||
|
|
||||||
resolve_package(package_name)
|
local ok, pkg = pcall(registry.get_package, package_name)
|
||||||
:if_present(
|
if not ok or pkg == nil then
|
||||||
function(pkg)
|
vim.notify(
|
||||||
if not pkg:is_installed() then
|
("[mason-conform] Formatter %q is not available in the mason registry. Make sure it is a valid formatter name, or add it to 'ignore_install' to silence this warning."):format(
|
||||||
install_package(pkg, version)
|
package_name
|
||||||
end
|
),
|
||||||
end
|
vim.log.levels.WARN
|
||||||
)
|
)
|
||||||
:if_not_present(function()
|
return
|
||||||
vim.notify(
|
end
|
||||||
("[mason-conform] Formatter %q is not a valid entry in ensure_installed. Make sure to only provide valid formatter names.")
|
|
||||||
:format(
|
if pkg:is_installed() or pkg:is_installing() then
|
||||||
package_name
|
return
|
||||||
),
|
end
|
||||||
vim.log.levels.WARN
|
|
||||||
)
|
install_package(pkg, version)
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
+133
-18
@@ -1,9 +1,12 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
-- conform formatter to mason package mapping
|
---Conform formatter name -> mason package name.
|
||||||
-- https://mason-registry.dev/registry/list
|
---https://mason-registry.dev/registry/list
|
||||||
|
---@type table<string, string>
|
||||||
M.conform_to_package = {
|
M.conform_to_package = {
|
||||||
-- alejandra
|
["air"] = "air",
|
||||||
|
["alejandra"] = "alejandra",
|
||||||
|
["ansible-lint"] = "ansible-lint",
|
||||||
["asmfmt"] = "asmfmt",
|
["asmfmt"] = "asmfmt",
|
||||||
["ast-grep"] = "ast-grep",
|
["ast-grep"] = "ast-grep",
|
||||||
-- astyle
|
-- astyle
|
||||||
@@ -11,71 +14,145 @@ M.conform_to_package = {
|
|||||||
-- autocorrect
|
-- autocorrect
|
||||||
["autoflake"] = "autoflake",
|
["autoflake"] = "autoflake",
|
||||||
["autopep8"] = "autopep8",
|
["autopep8"] = "autopep8",
|
||||||
-- awk
|
|
||||||
-- bean-format
|
-- bean-format
|
||||||
["beautysh"] = "beautysh",
|
["beautysh"] = "beautysh",
|
||||||
["bibtex-tidy"] = "bibtex-tidy",
|
["bibtex-tidy"] = "bibtex-tidy",
|
||||||
-- biome-check
|
-- bicep; it exists on Mason, but as LSP (exec: `bicep-lsp`)
|
||||||
["biome"] = "biome",
|
["biome"] = "biome",
|
||||||
|
-- biome-check
|
||||||
|
-- biome-organize-imports
|
||||||
["black"] = "black",
|
["black"] = "black",
|
||||||
["blade-formatter"] = "blade-formatter",
|
["blade-formatter"] = "blade-formatter",
|
||||||
["blue"] = "blue",
|
["blue"] = "blue",
|
||||||
|
-- bpfmt
|
||||||
|
["bsfmt"] = "brighterscript-formatter",
|
||||||
["buf"] = "buf",
|
["buf"] = "buf",
|
||||||
["buildifier"] = "buildifier",
|
["buildifier"] = "buildifier",
|
||||||
|
-- cabal_fmt
|
||||||
|
-- caramel_fmt
|
||||||
["cbfmt"] = "cbfmt",
|
["cbfmt"] = "cbfmt",
|
||||||
["clang_format"] = "clang-format",
|
-- cedar
|
||||||
|
["clang-format"] = "clang-format",
|
||||||
|
["cljfmt"] = "cljfmt",
|
||||||
-- cljstyle
|
-- cljstyle
|
||||||
["cmake_format"] = "cmakelang",
|
["cmake_format"] = "cmakelang",
|
||||||
|
-- codeql; it exists on Mason, but as LSP (exec: `codeql`)
|
||||||
["codespell"] = "codespell",
|
["codespell"] = "codespell",
|
||||||
|
-- commitmsgfmt
|
||||||
|
["crlfmt"] = "crlfmt",
|
||||||
|
-- crystal
|
||||||
["csharpier"] = "csharpier",
|
["csharpier"] = "csharpier",
|
||||||
|
-- css_beautify
|
||||||
-- cue_fmt
|
-- cue_fmt
|
||||||
|
-- d2
|
||||||
["darker"] = "darker",
|
["darker"] = "darker",
|
||||||
-- dart_format
|
-- dart_format
|
||||||
|
["dcm_fix"] = "dcm",
|
||||||
|
["dcm_format"] = "dcm",
|
||||||
["deno_fmt"] = "deno",
|
["deno_fmt"] = "deno",
|
||||||
-- dfmt
|
-- dfmt
|
||||||
|
-- dioxus
|
||||||
["djlint"] = "djlint",
|
["djlint"] = "djlint",
|
||||||
|
["docformatter"] = "docformatter",
|
||||||
|
["dockerfmt"] = "dockerfmt",
|
||||||
|
-- docstrfmt
|
||||||
|
["doctoc"] = "doctoc",
|
||||||
["dprint"] = "dprint",
|
["dprint"] = "dprint",
|
||||||
["easy-coding-standard"] = "easy-coding-standard",
|
["easy-coding-standard"] = "easy-coding-standard",
|
||||||
|
-- efmt
|
||||||
["elm_format"] = "elm-format",
|
["elm_format"] = "elm-format",
|
||||||
-- erb_format
|
["erb_format"] = "erb-formatter",
|
||||||
|
-- erlfmt
|
||||||
["eslint_d"] = "eslint_d",
|
["eslint_d"] = "eslint_d",
|
||||||
["fantomas"] = "fantomas",
|
["fantomas"] = "fantomas",
|
||||||
|
["findent"] = "findent",
|
||||||
-- fish_indent
|
-- fish_indent
|
||||||
["fixjson"] = "fixjson",
|
["fixjson"] = "fixjson",
|
||||||
-- fnlfmt
|
-- fnlfmt
|
||||||
|
-- forge_fmt
|
||||||
|
-- format-dune-file
|
||||||
|
-- format-queries
|
||||||
["fourmolu"] = "fourmolu",
|
["fourmolu"] = "fourmolu",
|
||||||
|
["fprettify"] = "fprettify",
|
||||||
|
-- gawk
|
||||||
["gci"] = "gci",
|
["gci"] = "gci",
|
||||||
["gdformat"] = "gdtoolkit",
|
["gdformat"] = "gdtoolkit",
|
||||||
|
["gdscript-formatter"] = "gdscript-formatter",
|
||||||
["gersemi"] = "gersemi",
|
["gersemi"] = "gersemi",
|
||||||
|
-- ghokin
|
||||||
|
-- gleam
|
||||||
|
-- gluon_fmt
|
||||||
-- gn
|
-- gn
|
||||||
-- gofmt
|
-- gofmt
|
||||||
["gofumpt"] = "gofumpt",
|
["gofumpt"] = "gofumpt",
|
||||||
["goimports-reviser"] = "goimports-reviser",
|
|
||||||
["goimports"] = "goimports",
|
["goimports"] = "goimports",
|
||||||
|
["goimports-reviser"] = "goimports-reviser",
|
||||||
|
-- gojq
|
||||||
|
["golangci-lint"] = "golangci-lint",
|
||||||
["golines"] = "golines",
|
["golines"] = "golines",
|
||||||
["google-java-format"] = "google-java-format",
|
["google-java-format"] = "google-java-format",
|
||||||
|
-- grain_format
|
||||||
|
["hcl"] = "hclfmt",
|
||||||
|
-- hindent
|
||||||
|
-- hledger-fmt
|
||||||
|
-- html_beautify
|
||||||
["htmlbeautifier"] = "htmlbeautifier",
|
["htmlbeautifier"] = "htmlbeautifier",
|
||||||
|
-- hurlfmt
|
||||||
|
-- imba_fmt
|
||||||
-- indent
|
-- indent
|
||||||
-- init
|
-- init
|
||||||
-- injected
|
-- injected
|
||||||
|
-- inko
|
||||||
["isort"] = "isort",
|
["isort"] = "isort",
|
||||||
|
-- janet-format
|
||||||
["joker"] = "joker",
|
["joker"] = "joker",
|
||||||
["jq"] = "jq",
|
["jq"] = "jq",
|
||||||
|
-- js_beautify
|
||||||
["jsonnetfmt"] = "jsonnetfmt",
|
["jsonnetfmt"] = "jsonnetfmt",
|
||||||
-- just
|
-- just
|
||||||
|
["kcl"] = "kcl",
|
||||||
|
["kdlfmt"] = "kdlfmt",
|
||||||
|
-- keep-sorted
|
||||||
|
["ktfmt"] = "ktfmt",
|
||||||
["ktlint"] = "ktlint",
|
["ktlint"] = "ktlint",
|
||||||
|
["kulala-fmt"] = "kulala-fmt",
|
||||||
["latexindent"] = "latexindent",
|
["latexindent"] = "latexindent",
|
||||||
|
-- leptosfmt
|
||||||
|
-- liquidsoap-prettier
|
||||||
|
-- llf
|
||||||
|
["lua-format"] = "luaformatter",
|
||||||
|
["luafmt"] = "luafmt",
|
||||||
|
-- mago_format
|
||||||
|
-- mago_lint
|
||||||
["markdown-toc"] = "markdown-toc",
|
["markdown-toc"] = "markdown-toc",
|
||||||
["markdownlint-cli2"] = "markdownlint-cli2",
|
-- markdownfmt
|
||||||
["markdownlint"] = "markdownlint",
|
["markdownlint"] = "markdownlint",
|
||||||
|
["markdownlint-cli2"] = "markdownlint-cli2",
|
||||||
["mdformat"] = "mdformat",
|
["mdformat"] = "mdformat",
|
||||||
|
["mdsf"] = "mdsf",
|
||||||
["mdslw"] = "mdslw",
|
["mdslw"] = "mdslw",
|
||||||
-- mix
|
-- mix
|
||||||
-- nixfmt
|
-- mojo_format
|
||||||
|
-- nginxfmt
|
||||||
|
-- nickel; it exists on Mason, but as LSP (exec: `nls`)
|
||||||
|
-- nimpretty
|
||||||
|
["nixfmt"] = "nixfmt",
|
||||||
["nixpkgs_fmt"] = "nixpkgs-fmt",
|
["nixpkgs_fmt"] = "nixpkgs-fmt",
|
||||||
|
["nomad_fmt"] = "nomad",
|
||||||
|
-- nph
|
||||||
|
["npm-groovy-lint"] = "npm-groovy-lint",
|
||||||
|
-- nufmt
|
||||||
["ocamlformat"] = "ocamlformat",
|
["ocamlformat"] = "ocamlformat",
|
||||||
-- opa_fmt
|
-- ocp-indent
|
||||||
|
-- odinfmt
|
||||||
|
["opa_fmt"] = "opa",
|
||||||
|
["ormolu"] = "ormolu",
|
||||||
|
["oxfmt"] = "oxfmt",
|
||||||
|
["oxlint"] = "oxlint",
|
||||||
-- packer_fmt
|
-- packer_fmt
|
||||||
|
["palantir-java-format"] = "palantir-java-format",
|
||||||
|
["panache"] = "panache",
|
||||||
|
["panache-fix"] = "panache",
|
||||||
-- pangu
|
-- pangu
|
||||||
-- perlimports
|
-- perlimports
|
||||||
-- perltidy
|
-- perltidy
|
||||||
@@ -87,51 +164,89 @@ M.conform_to_package = {
|
|||||||
["prettier"] = "prettier",
|
["prettier"] = "prettier",
|
||||||
["prettierd"] = "prettierd",
|
["prettierd"] = "prettierd",
|
||||||
["pretty-php"] = "pretty-php",
|
["pretty-php"] = "pretty-php",
|
||||||
|
["prettypst"] = "prettypst",
|
||||||
-- puppet-lint
|
-- puppet-lint
|
||||||
|
["purs-tidy"] = "purescript-tidy",
|
||||||
|
-- pycln
|
||||||
|
["pyink"] = "pyink",
|
||||||
|
["pymarkdownlnt"] = "pymarkdownlnt",
|
||||||
|
["pyproject-fmt"] = "pyproject-fmt",
|
||||||
|
-- python-ly
|
||||||
|
["pyupgrade"] = "pyupgrade",
|
||||||
|
["reformat-gherkin"] = "reformat-gherkin",
|
||||||
["reorder-python-imports"] = "reorder-python-imports",
|
["reorder-python-imports"] = "reorder-python-imports",
|
||||||
-- rescript-format
|
-- rescript-format
|
||||||
|
-- roc
|
||||||
|
-- rstfmt
|
||||||
["rubocop"] = "rubocop",
|
["rubocop"] = "rubocop",
|
||||||
["rubyfmt"] = "rubyfmt",
|
["rubyfmt"] = "rubyfmt",
|
||||||
-- ruff
|
["ruff"] = "ruff",
|
||||||
["ruff_fix"] = "ruff",
|
["ruff_fix"] = "ruff",
|
||||||
["ruff_format"] = "ruff",
|
["ruff_format"] = "ruff",
|
||||||
|
["ruff_organize_imports"] = "ruff",
|
||||||
["rufo"] = "rufo",
|
["rufo"] = "rufo",
|
||||||
["rustfmt"] = "rustfmt",
|
["rumdl"] = "rumdl",
|
||||||
|
-- runic
|
||||||
|
-- ["rustfmt"] = "rustfmt", Deprecated by mason
|
||||||
["rustywind"] = "rustywind",
|
["rustywind"] = "rustywind",
|
||||||
-- scalafmt
|
-- scalafmt
|
||||||
["shellcheck"] = "shellcheck",
|
["shellcheck"] = "shellcheck",
|
||||||
["shellharden"] = "shellharden",
|
["shellharden"] = "shellharden",
|
||||||
["shfmt"] = "shfmt",
|
["shfmt"] = "shfmt",
|
||||||
|
["sleek"] = "sleek",
|
||||||
|
-- smlfmt
|
||||||
|
["snakefmt"] = "snakefmt",
|
||||||
["sql_formatter"] = "sql-formatter",
|
["sql_formatter"] = "sql-formatter",
|
||||||
["sqlfluff"] = "sqlfluff",
|
["sqlfluff"] = "sqlfluff",
|
||||||
["sqlfmt"] = "sqlfmt",
|
["sqlfmt"] = "sqlfmt",
|
||||||
|
["sqruff"] = "sqruff",
|
||||||
-- squeeze_blanks
|
-- squeeze_blanks
|
||||||
|
-- standard-clj
|
||||||
["standardjs"] = "standardjs",
|
["standardjs"] = "standardjs",
|
||||||
["standardrb"] = "standardrb",
|
["standardrb"] = "standardrb",
|
||||||
["stylelint"] = "stylelint",
|
["stylelint"] = "stylelint",
|
||||||
-- styler
|
-- styler
|
||||||
|
-- stylish-haskell
|
||||||
["stylua"] = "stylua",
|
["stylua"] = "stylua",
|
||||||
|
["superhtml"] = "superhtml",
|
||||||
|
-- swift
|
||||||
-- swift_format
|
-- swift_format
|
||||||
-- swiftformat
|
["swiftformat"] = "swiftformat",
|
||||||
|
["swiftlint"] = "swiftlint",
|
||||||
|
-- syntax_tree
|
||||||
["taplo"] = "taplo",
|
["taplo"] = "taplo",
|
||||||
["templ"] = "templ",
|
["templ"] = "templ",
|
||||||
-- terraform_fmt
|
["terraform_fmt"] = "terraform",
|
||||||
-- terragrunt_hclfmt
|
-- terragrunt_hclfmt
|
||||||
|
["tex-fmt"] = "tex-fmt",
|
||||||
["tlint"] = "tlint",
|
["tlint"] = "tlint",
|
||||||
|
-- tofu_fmt
|
||||||
|
["tombi"] = "tombi",
|
||||||
|
-- treefmt
|
||||||
-- trim_newlines
|
-- trim_newlines
|
||||||
-- trim_whitespace
|
-- trim_whitespace
|
||||||
-- twig-cs-fixer
|
["twig-cs-fixer"] = "twig-cs-fixer",
|
||||||
|
-- typespec
|
||||||
["typos"] = "typos",
|
["typos"] = "typos",
|
||||||
-- typstfmt
|
["typstyle"] = "typstyle",
|
||||||
|
-- ufmt
|
||||||
-- uncrustify
|
-- uncrustify
|
||||||
["usort"] = "usort",
|
["usort"] = "usort",
|
||||||
["xmlformat"] = "xmlformatter",
|
-- v
|
||||||
|
["verible"] = "verible",
|
||||||
|
["vsg"] = "vsg",
|
||||||
|
["xmlformat"] = "xmlformatter", -- Deprecated in conform.nvim; redirects to xmlformatter
|
||||||
|
["xmlformatter"] = "xmlformatter",
|
||||||
-- xmllint
|
-- xmllint
|
||||||
|
-- xmlstarlet
|
||||||
["yamlfix"] = "yamlfix",
|
["yamlfix"] = "yamlfix",
|
||||||
["yamlfmt"] = "yamlfmt",
|
["yamlfmt"] = "yamlfmt",
|
||||||
["yapf"] = "yapf",
|
["yapf"] = "yapf",
|
||||||
|
-- yew-fmt
|
||||||
["yq"] = "yq",
|
["yq"] = "yq",
|
||||||
-- zigfmt
|
-- zigfmt
|
||||||
|
-- ziggy
|
||||||
|
-- ziggy_schema
|
||||||
["zprint"] = "zprint",
|
["zprint"] = "zprint",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,182 @@
|
|||||||
|
-- Smoke test for mason-conform.nvim with stubbed mason/conform.
|
||||||
|
-- Run from the repository root: nvim -l tests/smoke_test.lua
|
||||||
|
local script = (arg and arg[0]) or "tests/smoke_test.lua"
|
||||||
|
local root = script:match("^(.*)/tests/") or "."
|
||||||
|
package.path = ("%s/lua/?.lua;%s/lua/?/init.lua;"):format(root, root) .. package.path
|
||||||
|
|
||||||
|
local failures = {}
|
||||||
|
local function check(cond, msg)
|
||||||
|
if not cond then
|
||||||
|
failures[#failures + 1] = msg
|
||||||
|
print("FAIL: " .. msg)
|
||||||
|
else
|
||||||
|
print("ok: " .. msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---- stubs -------------------------------------------------------------
|
||||||
|
local notifications = {}
|
||||||
|
local install_calls = {}
|
||||||
|
local installed = {}
|
||||||
|
local installing = {}
|
||||||
|
|
||||||
|
package.preload["conform"] = function()
|
||||||
|
return {
|
||||||
|
formatters_by_ft = {
|
||||||
|
lua = { "stylua" },
|
||||||
|
python = { "autopep8", lsp_format = "fallback", stop_after_first = true },
|
||||||
|
markdown = { { "prettierd", "prettier" }, "cbfmt" },
|
||||||
|
javascript = function()
|
||||||
|
error("needs a buffer")
|
||||||
|
end,
|
||||||
|
go = function()
|
||||||
|
return { "gofumpt" }
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
package.preload["mason-registry"] = function()
|
||||||
|
local registry = {}
|
||||||
|
function registry.refresh(cb)
|
||||||
|
if cb then
|
||||||
|
cb(true, {})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function registry.get_package(name)
|
||||||
|
if name == "not-in-registry" then
|
||||||
|
error(('Cannot find package "%q".'):format(name))
|
||||||
|
end
|
||||||
|
local pkg = { name = name }
|
||||||
|
function pkg:is_installed()
|
||||||
|
return installed[name] or false
|
||||||
|
end
|
||||||
|
function pkg:is_installing()
|
||||||
|
return installing[name] or false
|
||||||
|
end
|
||||||
|
function pkg:install(opts)
|
||||||
|
install_calls[#install_calls + 1] = { name = name, version = opts and opts.version }
|
||||||
|
local handle = {}
|
||||||
|
function handle:once(event, cb2)
|
||||||
|
assert(event == "closed")
|
||||||
|
installed[name] = true
|
||||||
|
cb2()
|
||||||
|
end
|
||||||
|
return handle
|
||||||
|
end
|
||||||
|
return pkg
|
||||||
|
end
|
||||||
|
return registry
|
||||||
|
end
|
||||||
|
|
||||||
|
package.preload["mason-core.package"] = function()
|
||||||
|
local Package = {}
|
||||||
|
function Package.Parse(identifier)
|
||||||
|
local name, version = identifier:match("^([^@]+)@?(.*)$")
|
||||||
|
if version == "" then
|
||||||
|
version = nil
|
||||||
|
end
|
||||||
|
return name, version
|
||||||
|
end
|
||||||
|
return Package
|
||||||
|
end
|
||||||
|
|
||||||
|
package.preload["mason.version"] = function()
|
||||||
|
return { MAJOR_VERSION = 2, MINOR_VERSION = 3 }
|
||||||
|
end
|
||||||
|
|
||||||
|
local original_notify = vim.notify
|
||||||
|
vim.notify = function(msg, level)
|
||||||
|
notifications[#notifications + 1] = { msg = msg, level = level or vim.log.levels.INFO }
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---- tests -------------------------------------------------------------
|
||||||
|
|
||||||
|
-- setup() with defaults
|
||||||
|
local mc = require("mason-conform")
|
||||||
|
mc.setup()
|
||||||
|
vim.wait(200)
|
||||||
|
check(vim.deep_equal(mc.config, { ignore_install = {} }), "setup() without opts keeps defaults")
|
||||||
|
|
||||||
|
local function installed_names()
|
||||||
|
local names = {}
|
||||||
|
for _, call in ipairs(install_calls) do
|
||||||
|
names[#names + 1] = call.name
|
||||||
|
end
|
||||||
|
table.sort(names)
|
||||||
|
return names
|
||||||
|
end
|
||||||
|
|
||||||
|
check(
|
||||||
|
vim.deep_equal(installed_names(), { "autopep8", "cbfmt", "gofumpt", "prettier", "prettierd", "stylua" }),
|
||||||
|
"installs mapped formatters from every formatters_by_ft shape; skips broken function: "
|
||||||
|
.. table.concat(installed_names(), ",")
|
||||||
|
)
|
||||||
|
|
||||||
|
-- setup() again with ignore_install
|
||||||
|
install_calls = {}
|
||||||
|
notifications = {}
|
||||||
|
installed = {}
|
||||||
|
mc.setup({ ignore_install = { "prettierd" } })
|
||||||
|
vim.wait(200)
|
||||||
|
check(
|
||||||
|
vim.deep_equal(installed_names(), { "autopep8", "cbfmt", "gofumpt", "prettier", "stylua" }),
|
||||||
|
"ignore_install is respected: " .. table.concat(installed_names(), ",")
|
||||||
|
)
|
||||||
|
check(vim.deep_equal(mc.config.ignore_install, { "prettierd" }), "ignore_install stored")
|
||||||
|
|
||||||
|
-- installed / installing packages are skipped
|
||||||
|
install_calls = {}
|
||||||
|
installed = {}
|
||||||
|
installing = {}
|
||||||
|
installed["stylua"] = true
|
||||||
|
installing["autopep8"] = true
|
||||||
|
mc.setup({ ignore_install = {} })
|
||||||
|
vim.wait(200)
|
||||||
|
check(
|
||||||
|
vim.deep_equal(installed_names(), { "cbfmt", "gofumpt", "prettier", "prettierd" }),
|
||||||
|
"already installed/installing packages are skipped: " .. table.concat(installed_names(), ",")
|
||||||
|
)
|
||||||
|
|
||||||
|
-- unknown mason package -> warning, no error
|
||||||
|
local install = require("mason-conform.install")
|
||||||
|
notifications = {}
|
||||||
|
local ok = pcall(install.try_install, "not-in-registry")
|
||||||
|
check(ok, "try_install on unknown package does not raise")
|
||||||
|
check(#notifications == 1 and notifications[1].level == vim.log.levels.WARN, "unknown package emits a warning")
|
||||||
|
check(
|
||||||
|
notifications[1] and notifications[1].msg:find("not%-in%-registry", 1, false) ~= nil,
|
||||||
|
"warning names the formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
-- version pinning passes through Package.Parse
|
||||||
|
installed = {}
|
||||||
|
install_calls = {}
|
||||||
|
install.try_install("stylua@1.2.0")
|
||||||
|
check(install_calls[1] and install_calls[1].version == "1.2.0", "version suffix forwarded to mason")
|
||||||
|
|
||||||
|
-- setup() validates its argument
|
||||||
|
ok = pcall(mc.setup, "not a table")
|
||||||
|
check(not ok, "setup() rejects non-table opts")
|
||||||
|
|
||||||
|
-- health check runs
|
||||||
|
local health_ok, err = pcall(function()
|
||||||
|
require("mason-conform.health").check()
|
||||||
|
end)
|
||||||
|
check(health_ok, "health check runs without error" .. (health_ok and "" or (": " .. tostring(err))))
|
||||||
|
|
||||||
|
-- formatters module
|
||||||
|
local formatters = require("mason-conform.formatters").configured()
|
||||||
|
check(
|
||||||
|
vim.deep_equal(formatters, { "autopep8", "cbfmt", "gofumpt", "prettier", "prettierd", "stylua" }),
|
||||||
|
"formatters.configured() returns sorted unique names"
|
||||||
|
)
|
||||||
|
|
||||||
|
vim.notify = original_notify
|
||||||
|
|
||||||
|
print(("-"):rep(60))
|
||||||
|
if #failures > 0 then
|
||||||
|
print(("%d FAILURE(S)"):format(#failures))
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
print("all tests passed")
|
||||||
Reference in New Issue
Block a user