1

Update generated neovim config

This commit is contained in:
2024-09-22 20:41:25 +02:00
parent 1743764e48
commit aa1271c42c
1247 changed files with 26512 additions and 15067 deletions

View File

@ -10,7 +10,7 @@ body:
- type: input
attributes:
label: "Neovim version (nvim -v)"
placeholder: "0.8.0 commit db1b0ee3b30f"
placeholder: "NVIM v0.10.1"
validations:
required: true
- type: input
@ -19,6 +19,12 @@ body:
placeholder: "MacOS 11.5"
validations:
required: true
- type: checkboxes
attributes:
label: Read debugging tips
options:
- label: I have read through the [debugging tips](https://github.com/stevearc/conform.nvim/blob/master/doc/debugging.md).
required: true
- type: checkboxes
attributes:
label: Add the debug logs

View File

@ -1,3 +1,3 @@
#!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
#!/nix/store/izpf49b74i15pcr9708s3xdwyqs4jxwl-bash-5.2p32/bin/bash
set -e
make fastlint

View File

@ -1,4 +1,4 @@
#!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
#!/nix/store/izpf49b74i15pcr9708s3xdwyqs4jxwl-bash-5.2p32/bin/bash
set -e
IFS=' '
while read local_ref _local_sha _remote_ref _remote_sha; do

View File

@ -50,7 +50,6 @@ jobs:
strategy:
matrix:
include:
- nvim_tag: v0.9.4
- nvim_tag: v0.10.0
name: Run tests

View File

@ -0,0 +1,9 @@
{
"runtime": {
"version": "LuaJIT",
"pathStrict": true
},
"type": {
"checkTableShape": true
}
}

View File

@ -1,5 +1,46 @@
# Changelog
## [8.1.0](https://github.com/stevearc/conform.nvim/compare/v8.0.0...v8.1.0) (2024-09-10)
### Features
* **deno:** add support for .mjs files ([#528](https://github.com/stevearc/conform.nvim/issues/528)) ([e82b7b1](https://github.com/stevearc/conform.nvim/commit/e82b7b13b0ed348ce4dbf1495f9b1872d33f9d3f))
* **zine:** add superhtml and ziggy support ([#531](https://github.com/stevearc/conform.nvim/issues/531)) ([392fc98](https://github.com/stevearc/conform.nvim/commit/392fc98c475b4f0552078104624e509b4826d197))
### Bug Fixes
* **log:** prepend date to log lines ([#529](https://github.com/stevearc/conform.nvim/issues/529)) ([c6728c5](https://github.com/stevearc/conform.nvim/commit/c6728c55d1e07da3138beea453d4078668719ee0))
## [8.0.0](https://github.com/stevearc/conform.nvim/compare/v7.1.0...v8.0.0) (2024-08-20)
### ⚠ BREAKING CHANGES
* Require Neovim 0.10+
### Code Refactoring
* Require Neovim 0.10+ ([d31323d](https://github.com/stevearc/conform.nvim/commit/d31323db3fa4a33d203dcb05150d98bd0153c42c))
## [7.1.0](https://github.com/stevearc/conform.nvim/compare/v7.0.0...v7.1.0) (2024-08-16)
### Features
* add support for cljfmt ([#500](https://github.com/stevearc/conform.nvim/issues/500)) ([42e10a3](https://github.com/stevearc/conform.nvim/commit/42e10a38cbb427f418ac17f8a472b3c7315517ba))
* add support for markdownfmt ([#511](https://github.com/stevearc/conform.nvim/issues/511)) ([960f51b](https://github.com/stevearc/conform.nvim/commit/960f51becccadc36825b2c2db266c8cffaeadbde))
* add variable for args to insert the file extension ([#510](https://github.com/stevearc/conform.nvim/issues/510)) ([0f4f299](https://github.com/stevearc/conform.nvim/commit/0f4f299dfea09d2adfd7a1da05149a0844ac8eee))
### Bug Fixes
* **djlint:** remove default indentation arguments ([#517](https://github.com/stevearc/conform.nvim/issues/517)) ([38e5f06](https://github.com/stevearc/conform.nvim/commit/38e5f062f241d89ba44f6d67d16b4bf55d3c477e))
* **docformatter:** update exit_codes, 3 is correct in in-place formatting ([#518](https://github.com/stevearc/conform.nvim/issues/518)) ([667102f](https://github.com/stevearc/conform.nvim/commit/667102f26106709cddd2dff1f699610df5b94d7f))
* **nixfmt:** update repo link and description ([#505](https://github.com/stevearc/conform.nvim/issues/505)) ([2122fe2](https://github.com/stevearc/conform.nvim/commit/2122fe2ff01e9a542fc358ee9398ce2cbddf345d))
* **sqlfluff:** don't assume ansi dialect and require config ([#519](https://github.com/stevearc/conform.nvim/issues/519)) ([bb10949](https://github.com/stevearc/conform.nvim/commit/bb10949d80dd0f60d03572f04953322785f39f7a))
## [7.0.0](https://github.com/stevearc/conform.nvim/compare/v6.1.0...v7.0.0) (2024-07-23)

View File

@ -11,6 +11,7 @@ Lightweight yet powerful formatter plugin for Neovim
- [Formatters](#formatters)
- [Customizing formatters](#customizing-formatters)
- [Recipes](#recipes)
- [Debugging](#debugging)
- [Advanced topics](#advanced-topics)
- [Options](#options)
- [Formatter options](#formatter-options)
@ -27,7 +28,7 @@ Lightweight yet powerful formatter plugin for Neovim
## Requirements
- Neovim 0.9+ (for older versions, use a [nvim-0.x branch](https://github.com/stevearc/conform.nvim/branches))
- Neovim 0.10+ (for older versions, use a [nvim-0.x branch](https://github.com/stevearc/conform.nvim/branches))
## Features
@ -205,6 +206,7 @@ You can view this list in vim with `:help conform-formatters`
- [caramel_fmt](https://caramel.run/manual/reference/cli/fmt.html) - Format Caramel code.
- [cbfmt](https://github.com/lukas-reineke/cbfmt) - A tool to format codeblocks inside markdown and org documents.
- [clang-format](https://www.kernel.org/doc/html/latest/process/clang-format.html) - Tool to format C/C++/… code according to a set of rules and heuristics.
- [cljfmt](https://github.com/weavejester/cljfmt) - cljfmt is a tool for detecting and fixing formatting errors in Clojure code.
- [cljstyle](https://github.com/greglook/cljstyle) - Formatter for Clojure code.
- [cmake_format](https://github.com/cheshirekow/cmake_format) - Parse cmake listfiles and format them nicely.
- [codespell](https://github.com/codespell-project/codespell) - Check code for common misspellings.
@ -273,6 +275,7 @@ You can view this list in vim with `:help conform-formatters`
- [llf](https://repo.or.cz/llf.git) - A LaTeX reformatter / beautifier.
- [lua-format](https://github.com/Koihik/LuaFormatter) - Code formatter for Lua.
- [markdown-toc](https://github.com/jonschlinkert/markdown-toc) - API and CLI for generating a markdown TOC (table of contents) for a README or any markdown files.
- [markdownfmt](https://github.com/shurcooL/markdownfmt) - Like gofmt, but for Markdown.
- [markdownlint](https://github.com/DavidAnson/markdownlint) - A Node.js style checker and lint tool for Markdown/CommonMark files.
- [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) - A fast, flexible, configuration-based command-line interface for linting Markdown/CommonMark files with the markdownlint library.
- [mdformat](https://github.com/executablebooks/mdformat) - An opinionated Markdown formatter.
@ -281,7 +284,7 @@ You can view this list in vim with `:help conform-formatters`
- [mix](https://hexdocs.pm/mix/main/Mix.Tasks.Format.html) - Format Elixir files using the mix format command.
- [nickel](https://nickel-lang.org/) - Code formatter for the Nickel programming language.
- [nimpretty](https://github.com/nim-lang/nim) - nimpretty is a Nim source code beautifier that follows the official style guide.
- [nixfmt](https://github.com/serokell/nixfmt) - nixfmt is a formatter for Nix code, intended to apply a uniform style.
- [nixfmt](https://github.com/NixOS/nixfmt) - The official (but not yet stable) formatter for Nix code.
- [nixpkgs_fmt](https://github.com/nix-community/nixpkgs-fmt) - nixpkgs-fmt is a Nix code formatter for nixpkgs.
- [npm-groovy-lint](https://github.com/nvuillam/npm-groovy-lint) - Lint, format and auto-fix your Groovy / Jenkinsfile / Gradle files using command line.
- [ocamlformat](https://github.com/ocaml-ppx/ocamlformat) - Auto-formatter for OCaml code.
@ -332,6 +335,7 @@ You can view this list in vim with `:help conform-formatters`
- [styler](https://github.com/devOpifex/r.nvim) - R formatter and linter.
- [stylish-haskell](https://github.com/haskell/stylish-haskell) - Haskell code prettifier.
- [stylua](https://github.com/JohnnyMorganz/StyLua) - An opinionated code formatter for Lua.
- [superhtml](https://github.com/kristoff-it/superhtml) - HTML Language Server and Templating Language Library.
- [swift_format](https://github.com/apple/swift-format) - Swift formatter from apple. Requires building from source with `swift build`.
- [swiftformat](https://github.com/nicklockwood/SwiftFormat) - SwiftFormat is a code library and command-line tool for reformatting `swift` code on macOS or Linux.
- [swiftlint](https://github.com/realm/SwiftLint) - A tool to enforce Swift style and conventions.
@ -358,6 +362,8 @@ You can view this list in vim with `:help conform-formatters`
- [yew-fmt](https://github.com/schvv31n/yew-fmt) - Code formatter for the Yew framework.
- [yq](https://github.com/mikefarah/yq) - YAML/JSON processor
- [zigfmt](https://github.com/ziglang/zig) - Reformat Zig source into canonical form.
- [ziggy](https://github.com/kristoff-it/ziggy) - A data serialization language for expressing clear API messages, config files, etc.
- [ziggy_schema](https://github.com/kristoff-it/ziggy) - A data serialization language for expressing clear API messages, config files, etc.
- [zprint](https://github.com/kkinnear/zprint) - Formatter for Clojure and EDN.
<!-- /FORMATTERS -->
@ -432,13 +438,22 @@ require("conform").formatters.shfmt = {
- [Format command](doc/recipes.md#format-command)
- [Autoformat with extra features](doc/recipes.md#autoformat-with-extra-features)
- [Command to toggle format-on-save](doc/recipes.md#command-to-toggle-format-on-save)
- [Automatically run slow formatters async](doc/recipes.md#automatically-run-slow-formatters-async)
- [Lazy loading with lazy.nvim](doc/recipes.md#lazy-loading-with-lazynvim)
- [Leave visual mode after range format](doc/recipes.md#leave-visual-mode-after-range-format)
- [Run the first available formatter followed by more formatters](doc/recipes.md#run-the-first-available-formatter-followed-by-more-formatters)
<!-- /RECIPES -->
## Debugging
<!-- DEBUGGING -->
- [Background](doc/debugging.md#background)
- [Tools](doc/debugging.md#tools)
- [Testing the formatter](doc/debugging.md#testing-the-formatter)
<!-- /DEBUGGING -->
## Advanced topics
<!-- ADVANCED -->

View File

@ -22,8 +22,6 @@ The way this "aftermarket" range formatting works is conform will format the ent
## Injected language formatting (code blocks)
Requires: Neovim 0.9+
Sometimes you may have a file that contains small chunks of code in another language. This is most common for markup formats like markdown and neorg, but can theoretically be present in any filetype (for example, embedded SQL queries in a host language). For files like this, it would be nice to be able to format these code chunks using their language-specific formatters.
The way that conform supports this is via the `injected` formatter. If you run this formatter on a file, it will use treesitter to parse out the blocks in the file that have different languages and runs the formatters for that filetype (configured with `formatters_by_ft`). The formatters are run in parallel, one job for each language block.

View File

@ -288,6 +288,8 @@ FORMATTERS *conform-formatter
`cbfmt` - A tool to format codeblocks inside markdown and org documents.
`clang-format` - Tool to format C/C++/… code according to a set of rules and
heuristics.
`cljfmt` - cljfmt is a tool for detecting and fixing formatting errors in
Clojure code.
`cljstyle` - Formatter for Clojure code.
`cmake_format` - Parse cmake listfiles and format them nicely.
`codespell` - Check code for common misspellings.
@ -378,6 +380,7 @@ FORMATTERS *conform-formatter
`lua-format` - Code formatter for Lua.
`markdown-toc` - API and CLI for generating a markdown TOC (table of contents)
for a README or any markdown files.
`markdownfmt` - Like gofmt, but for Markdown.
`markdownlint` - A Node.js style checker and lint tool for Markdown/CommonMark
files.
`markdownlint-cli2` - A fast, flexible, configuration-based command-line
@ -391,8 +394,7 @@ FORMATTERS *conform-formatter
`nickel` - Code formatter for the Nickel programming language.
`nimpretty` - nimpretty is a Nim source code beautifier that follows the
official style guide.
`nixfmt` - nixfmt is a formatter for Nix code, intended to apply a uniform
style.
`nixfmt` - The official (but not yet stable) formatter for Nix code.
`nixpkgs_fmt` - nixpkgs-fmt is a Nix code formatter for nixpkgs.
`npm-groovy-lint` - Lint, format and auto-fix your Groovy / Jenkinsfile / Gradle
files using command line.
@ -459,6 +461,7 @@ FORMATTERS *conform-formatter
`styler` - R formatter and linter.
`stylish-haskell` - Haskell code prettifier.
`stylua` - An opinionated code formatter for Lua.
`superhtml` - HTML Language Server and Templating Language Library.
`swift_format` - Swift formatter from apple. Requires building from source with
`swift build`.
`swiftformat` - SwiftFormat is a code library and command-line tool for
@ -494,6 +497,10 @@ FORMATTERS *conform-formatter
`yew-fmt` - Code formatter for the Yew framework.
`yq` - YAML/JSON processor
`zigfmt` - Reformat Zig source into canonical form.
`ziggy` - A data serialization language for expressing clear API messages,
config files, etc.
`ziggy_schema` - A data serialization language for expressing clear API
messages, config files, etc.
`zprint` - Formatter for Clojure and EDN.
================================================================================

View File

@ -0,0 +1,94 @@
# Debugging
When you are experiencing problems with a formatter, this doc is intended to give you the background
information and tools you need to figure out what is going wrong. It should help you answer
questions like "why isn't my formatter working?" and "why is my formatter using the wrong format?"
<!-- TOC -->
- [Background](#background)
- [Tools](#tools)
- [Testing the formatter](#testing-the-formatter)
<!-- /TOC -->
## Background
How does conform work?
Under the hood, conform is just running a shell command, capturing the output, and replacing the
buffer contents with that output. There are a few fancy things happening with [minimal format
diffs](advanced_topics.md#minimal-format-diffs), but in practice there are almost never problems
with that system so you can mostly ignore it.
Conform runs the formatters using `:help vim.system()`, and does one of two things. Some formatters
support formatting _from_ stdin and _to_ stdout. For these, we pipe the buffer text to the process
via stdin, and read the stdout back as the new buffer contents. For formatters that don't support
stdin/out, we create a temporary file in the same directory, write the buffer to it, run the
formatter, and read back the modified tempfile as the new buffer contents.
## Tools
Conform has two very useful tools for debugging misbehaving formatters: logging and `:ConformInfo`.
Try running `:ConformInfo` now; you should see something like the window below:
<img width="1243" alt="Screenshot 2024-08-07 at 10 03 17PM" src="https://github.com/user-attachments/assets/2dbbc2b7-05c1-4c9f-bb8c-345d039b624c">
This contains a snippet of the log file, the location of the log file in case you need to see more
logs (you can use `gf` to jump to it), available formatters for the current buffer, and a list of
all the configured formatters. Each formatter has a status, an error message if there is something
wrong, a list of filetypes it applies to, and the resolved path to the executable.
This should be enough to fix many issues. Double check to make sure your formatter is `ready` and
that it is configured to run on the filetype(s) you expect. Also double check the path to the
executable. If all of those look good, then it's time to make more use of the logs.
The first thing you will want to do is increase the verbosity of the logs. Do this by setting the
`log_level` option:
```lua
require("conform").setup({
log_level = vim.log.levels.DEBUG,
})
```
It is recommended to start with `DEBUG` level. You can also use `TRACE`, which will log the entire
file input and output to the formatter. This can be helpful in some situations, but takes up a lot
of visual space and so is not recommended until you need that information specifically.
## Testing the formatter
Once you set the log level, try the format operations again, then open the log file (remember, you
can find it from `:ConformInfo`). You're looking for the lines that tell you what command is being
run. It should look like this:
```
21:50:31[DEBUG] Run command: { "black", "--stdin-filename", "/Users/stevearc/dotfiles/vimplugins/conform.nvim/scripts/generate.py", "--quiet", "-" }
21:50:31[DEBUG] Run default CWD: /Users/stevearc/dotfiles/vimplugins/conform.nvim
```
This is logging the lua table that is passed to `vim.system()`. The first thing to do is to take this
command and run it directly in your shell and see what happens. For formatters using stdin/out, it
will look like this:
```
cat path/to/file.py | black --stdin-filename path/to/file.py --quiet -
```
Note that this will print the entire formatted file to stdout. It will be much easier for you if you
can come up with a small test file just a couple lines long that reproduces this issue. MAKE SURE
that you `cd` into the CWD directory from the log lines, as that is the directory that conform will
run the command from. If your formatter doesn't use stdin/out, do the same thing but omit the `cat`.
The command in the log line will contain a path to a temporary file. Just replace that with the path
to the real file:
```
black --quiet path/to/file.py
```
**Q:** What is the point of all of this? \
**A:** We're trying to isolate where the problem is coming from: the formatter, the environment
configuring the formatter, Neovim, or conform. By confirming that the format command works in the
shell, we can eliminate some of those possibilities. If the format command _doesn't_ work in the
shell, you will need to iterate on that until you can find one that works. Please DO NOT file an
issue on this repo until you have a functioning format command in your shell.

View File

@ -5,7 +5,6 @@
- [Format command](#format-command)
- [Autoformat with extra features](#autoformat-with-extra-features)
- [Command to toggle format-on-save](#command-to-toggle-format-on-save)
- [Automatically run slow formatters async](#automatically-run-slow-formatters-async)
- [Lazy loading with lazy.nvim](#lazy-loading-with-lazynvim)
- [Leave visual mode after range format](#leave-visual-mode-after-range-format)
- [Run the first available formatter followed by more formatters](#run-the-first-available-formatter-followed-by-more-formatters)
@ -108,35 +107,6 @@ end, {
})
```
## Automatically run slow formatters async
This snippet will automatically detect which formatters take too long to run synchronously and will run them async on save instead.
```lua
local slow_format_filetypes = {}
require("conform").setup({
format_on_save = function(bufnr)
if slow_format_filetypes[vim.bo[bufnr].filetype] then
return
end
local function on_format(err)
if err and err:match("timeout$") then
slow_format_filetypes[vim.bo[bufnr].filetype] = true
end
end
return { timeout_ms = 200, lsp_format = "fallback" }, on_format
end,
format_after_save = function(bufnr)
if not slow_format_filetypes[vim.bo[bufnr].filetype] then
return
end
return { lsp_format = "fallback" }
end,
})
```
## Lazy loading with lazy.nvim
Here is the recommended config for lazy-loading using lazy.nvim

View File

@ -7,12 +7,8 @@ local M = {}
---@enum conform.ERROR_CODE
M.ERROR_CODE = {
-- Command was passed invalid arguments
INVALID_ARGS = 1,
-- Command was not executable
NOT_EXECUTABLE = 2,
-- Error occurred during when calling jobstart
JOBSTART = 3,
-- Error occurred during when calling vim.system
VIM_SYSTEM = 3,
-- Command timed out during execution
TIMEOUT = 4,
-- Command was pre-empted by another call to format
@ -39,10 +35,7 @@ end
---@param code conform.ERROR_CODE
---@return boolean
M.is_execution_error = function(code)
return code == M.ERROR_CODE.RUNTIME
or code == M.ERROR_CODE.NOT_EXECUTABLE
or code == M.ERROR_CODE.INVALID_ARGS
or code == M.ERROR_CODE.JOBSTART
return code == M.ERROR_CODE.RUNTIME or code == M.ERROR_CODE.VIM_SYSTEM
end
---@param err1? conform.Error

View File

@ -0,0 +1,10 @@
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/weavejester/cljfmt",
description = "cljfmt is a tool for detecting and fixing formatting errors in Clojure code.",
},
command = "cljfmt",
args = { "fix", "-" },
stdin = true,
}

View File

@ -4,6 +4,7 @@ local extensions = {
json = "json",
jsonc = "jsonc",
markdown = "md",
esmodule = "mjs",
typescript = "ts",
typescriptreact = "tsx",
}

View File

@ -6,9 +6,10 @@ return {
description = "✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks - Handlebars - GoLang.",
},
command = "djlint",
args = function(_, ctx)
return { "--reformat", "--indent", ctx.shiftwidth, "-" }
end,
args = {
"--reformat",
"-",
},
cwd = util.root_file({
".djlintrc",
}),

View File

@ -7,4 +7,5 @@ return {
command = "docformatter",
args = { "--in-place", "$FILENAME" },
stdin = false,
exit_codes = { 0, 3 },
}

View File

@ -112,6 +112,7 @@ return {
url = "doc/advanced_topics.md#injected-language-formatting-code-blocks",
description = "Format treesitter injected languages.",
},
---@type conform.InjectedFormatterOptions
options = {
-- Set to true to ignore errors
ignore_errors = false,
@ -151,8 +152,8 @@ return {
callback("No treesitter parser for buffer")
return
end
---@type conform.InjectedFormatterOptions
local options = self.options
---@cast options conform.InjectedFormatterOptions
---@param lang string
---@return nil|conform.FiletypeFormatter

View File

@ -0,0 +1,8 @@
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/shurcooL/markdownfmt",
description = "Like gofmt, but for Markdown.",
},
command = "markdownfmt",
}

View File

@ -1,8 +1,8 @@
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/serokell/nixfmt",
description = "nixfmt is a formatter for Nix code, intended to apply a uniform style.",
url = "https://github.com/NixOS/nixfmt",
description = "The official (but not yet stable) formatter for Nix code.",
},
command = "nixfmt",
}

View File

@ -7,7 +7,7 @@ return {
description = "A modular SQL linter and auto-formatter with support for multiple dialects and templated code.",
},
command = "sqlfluff",
args = { "fix", "--dialect=ansi", "-" },
args = { "fix", "-" },
stdin = true,
cwd = util.root_file({
".sqlfluff",
@ -16,5 +16,5 @@ return {
"setup.cfg",
"tox.ini",
}),
require_cwd = false,
require_cwd = true,
}

View File

@ -0,0 +1,9 @@
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/kristoff-it/superhtml",
description = "HTML Language Server and Templating Language Library.",
},
command = "superhtml",
args = { "fmt", "--stdin" },
}

View File

@ -0,0 +1,9 @@
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/kristoff-it/ziggy",
description = "A data serialization language for expressing clear API messages, config files, etc.",
},
command = "ziggy",
args = { "fmt", "--stdin" },
}

View File

@ -0,0 +1,9 @@
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/kristoff-it/ziggy",
description = "A data serialization language for expressing clear API messages, config files, etc.",
},
command = "ziggy",
args = { "fmt", "--stdin-schema" },
}

View File

@ -1,12 +1,5 @@
local M = {}
---@diagnostic disable: deprecated
-- The "report_" functions have been deprecated, so use the new ones if defined.
local health_start = vim.health.start or vim.health.report_start
local health_warn = vim.health.warn or vim.health.report_warn
local health_info = vim.health.info or vim.health.report_info
local health_ok = vim.health.ok or vim.health.report_ok
---@param name string
---@return string[]
local function get_formatter_filetypes(name)
@ -36,18 +29,21 @@ end
M.check = function()
local conform = require("conform")
health_start("conform.nvim report")
vim.health.start("conform.nvim report")
local log = require("conform.log")
health_info(string.format("Log file: %s", log.get_logfile()))
if vim.fn.has("nvim-0.10") == 0 then
vim.health.error("Neovim 0.10 or later is required")
end
vim.health.info(string.format("Log file: %s", log.get_logfile()))
local all_formatters = conform.list_all_formatters()
for _, formatter in ipairs(all_formatters) do
if not formatter.available then
health_warn(string.format("%s unavailable: %s", formatter.name, formatter.available_msg))
vim.health.warn(string.format("%s unavailable: %s", formatter.name, formatter.available_msg))
else
local filetypes = get_formatter_filetypes(formatter.name)
health_ok(string.format("%s ready (%s)", formatter.name, table.concat(filetypes, ", ")))
vim.health.ok(string.format("%s ready (%s)", formatter.name, table.concat(filetypes, ", ")))
end
end
end
@ -75,6 +71,12 @@ M.show_window = function()
local lines = {}
local highlights = {}
local logfile = log.get_logfile()
if vim.fn.has("nvim-0.10") == 0 then
table.insert(lines, "Neovim 0.10 or later is required")
table.insert(highlights, { "DiagnosticError", #lines, 0, -1 })
end
table.insert(lines, string.format("Log file: %s", logfile))
table.insert(highlights, { "Title", #lines, 0, 10 })
if vim.fn.filereadable(logfile) == 1 then
@ -113,7 +115,7 @@ M.show_window = function()
table.insert(lines, line)
table.insert(
highlights,
{ "DiagnosticInfo", #lines, formatter.name:len(), formatter.name:len() + 6 }
{ "DiagnosticOk", #lines, formatter.name:len(), formatter.name:len() + 6 }
)
table.insert(highlights, {
"DiagnosticInfo",

View File

@ -52,8 +52,8 @@ end
---@param opts? conform.setupOpts
M.setup = function(opts)
if vim.fn.has("nvim-0.9") == 0 then
notify("conform.nvim requires Neovim 0.9+", vim.log.levels.ERROR)
if vim.fn.has("nvim-0.10") == 0 then
notify("conform.nvim requires Neovim 0.10+", vim.log.levels.ERROR)
return
end
opts = opts or {}
@ -311,7 +311,7 @@ end
---@param bufnr integer
---@param mode "v"|"V"
---@return table {start={row,col}, end={row,col}} using (1, 0) indexing
---@return conform.Range {start={row,col}, end={row,col}} using (1, 0) indexing
local function range_from_selection(bufnr, mode)
-- [bufnum, lnum, col, off]; both row and column 1-indexed
local start = vim.fn.getpos("v")
@ -407,6 +407,13 @@ local has_notified_ft_no_formatters = {}
---@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)
if vim.fn.has("nvim-0.10") == 0 then
notify_once("conform.nvim requires Neovim 0.10+", vim.log.levels.ERROR)
if callback then
callback("conform.nvim requires Neovim 0.10+")
end
return false
end
opts = opts or {}
local has_explicit_formatters = opts.formatters ~= nil
-- If formatters were not passed in directly, fetch any options from formatters_by_ft

View File

@ -36,7 +36,7 @@ local function format(level, msg, ...)
end
end
local ok, text = pcall(string.format, msg, vim.F.unpack_len(args))
local timestr = vim.fn.strftime("%H:%M:%S")
local timestr = vim.fn.strftime("%Y-%m-%d %H:%M:%S")
if ok then
local str_level = levels_reverse[level]
return string.format("%s[%s] %s", timestr, str_level, text)

View File

@ -14,12 +14,16 @@ local M = {}
---@param formatter_name string
---@param ctx conform.Context
---@param config conform.JobFormatterConfig
---@return string|string[]
---@return string[]
M.build_cmd = function(formatter_name, ctx, config)
local command = config.command
if type(command) == "function" then
command = command(config, ctx)
end
local exepath = vim.fn.exepath(command)
if exepath ~= "" then
command = exepath
end
---@type string|string[]
local args = {}
if ctx.range and config.range_args then
@ -29,8 +33,7 @@ M.build_cmd = function(formatter_name, ctx, config)
local computed_args = config.args
if type(computed_args) == "function" then
args = computed_args(config, ctx)
else
---@diagnostic disable-next-line: cast-local-type
elseif computed_args then
args = computed_args
end
end
@ -48,10 +51,10 @@ M.build_cmd = function(formatter_name, ctx, config)
:gsub("$FILENAME", ctx.filename)
:gsub("$DIRNAME", ctx.dirname)
:gsub("$RELATIVE_FILEPATH", compute_relative_filepath)
return command .. " " .. interpolated
:gsub("$EXTENSION", ctx.filename:match(".*(%..*)$") or "")
return util.shell_build_argv(command .. " " .. interpolated)
else
local cmd = { command }
---@diagnostic disable-next-line: param-type-mismatch
for _, v in ipairs(args) do
if v == "$FILENAME" then
v = ctx.filename
@ -59,6 +62,8 @@ M.build_cmd = function(formatter_name, ctx, config)
v = ctx.dirname
elseif v == "$RELATIVE_FILEPATH" then
v = compute_relative_filepath()
elseif v == "$EXTENSION" then
v = ctx.filename:match(".*(%..*)$") or ""
end
table.insert(cmd, v)
end
@ -356,40 +361,29 @@ local function run_formatter(bufnr, formatter, config, ctx, input_lines, opts, c
if env then
log.debug("Run ENV: %s", env)
end
local stdout
local stderr
local exit_codes = config.exit_codes or { 0 }
local jid
local ok, jid_or_err = pcall(vim.fn.jobstart, cmd, {
cwd = cwd,
env = env,
stdout_buffered = true,
stderr_buffered = true,
stdin = config.stdin and "pipe" or "null",
on_stdout = function(_, data)
if config.stdin then
stdout = data
end
end,
on_stderr = function(_, data)
stderr = data
end,
on_exit = function(_, code)
local pid
local ok, job_or_err = pcall(
vim.system,
cmd,
{
cwd = cwd,
env = env,
stdin = config.stdin and buffer_text,
text = true,
},
vim.schedule_wrap(function(result)
local code = result.code
local stdout = result.stdout and vim.split(result.stdout, "\n") or {}
local stderr = result.stderr and vim.split(result.stderr, "\n") or {}
if vim.tbl_contains(exit_codes, code) then
local output
local output = stdout
if not config.stdin then
local fd = assert(uv.fs_open(ctx.filename, "r", 448)) -- 0700
local stat = assert(uv.fs_fstat(fd))
local content = assert(uv.fs_read(fd, stat.size))
uv.fs_close(fd)
output = vim.split(content, "\r?\n", {})
else
output = stdout
-- trim trailing \r in every line
-- so that both branches of this if block behaves the same
for i, line in ipairs(output) do
output[i] = string.gsub(line, "\r$", "")
end
output = vim.split(content, "\r?\n")
end
-- Remove the trailing newline from the output to convert back to vim lines representation
if add_extra_newline and output[#output] == "" then
@ -417,7 +411,7 @@ local function run_formatter(bufnr, formatter, config, ctx, input_lines, opts, c
end
if
vim.api.nvim_buf_is_valid(bufnr)
and jid ~= vim.b[bufnr].conform_jid
and pid ~= vim.b[bufnr].conform_pid
and opts.exclusive
then
callback({
@ -431,35 +425,21 @@ local function run_formatter(bufnr, formatter, config, ctx, input_lines, opts, c
})
end
end
end,
})
end)
)
if not ok then
callback({
code = errors.ERROR_CODE.JOBSTART,
message = string.format("Formatter '%s' error in jobstart: %s", formatter.name, jid_or_err),
code = errors.ERROR_CODE.VIM_SYSTEM,
message = string.format("Formatter '%s' error in vim.system: %s", formatter.name, job_or_err),
})
return
end
jid = jid_or_err
if jid == 0 then
callback({
code = errors.ERROR_CODE.INVALID_ARGS,
message = string.format("Formatter '%s' invalid arguments", formatter.name),
})
elseif jid == -1 then
callback({
code = errors.ERROR_CODE.NOT_EXECUTABLE,
message = string.format("Formatter '%s' command is not executable", formatter.name),
})
elseif config.stdin then
vim.api.nvim_chan_send(jid, buffer_text)
vim.fn.chanclose(jid, "stdin")
end
pid = job_or_err.pid
if opts.exclusive then
vim.b[bufnr].conform_jid = jid
vim.b[bufnr].conform_pid = pid
end
return jid
return pid
end
---@param bufnr integer
@ -524,9 +504,9 @@ M.format_async = function(bufnr, formatters, range, opts, callback)
end
-- kill previous jobs for buffer
local prev_jid = vim.b[bufnr].conform_jid
if prev_jid and opts.exclusive then
if vim.fn.jobstop(prev_jid) == 1 then
local prev_pid = vim.b[bufnr].conform_pid
if prev_pid and opts.exclusive then
if uv.kill(prev_pid) == 0 then
log.info("Canceled previous format job for %s", vim.api.nvim_buf_get_name(bufnr))
end
end
@ -616,9 +596,9 @@ M.format_sync = function(bufnr, formatters, timeout_ms, range, opts)
local original_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
-- kill previous jobs for buffer
local prev_jid = vim.b[bufnr].conform_jid
if prev_jid and opts.exclusive then
if vim.fn.jobstop(prev_jid) == 1 then
local prev_pid = vim.b[bufnr].conform_pid
if prev_pid and opts.exclusive then
if uv.kill(prev_pid) == 0 then
log.info("Canceled previous format job for %s", vim.api.nvim_buf_get_name(bufnr))
end
end
@ -669,7 +649,7 @@ M.format_lines_sync = function(bufnr, formatters, timeout_ms, range, input_lines
---@type conform.FormatterConfig
local config = assert(require("conform").get_formatter_config(formatter.name, bufnr))
local ctx = M.build_context(bufnr, config, range)
local jid = run_formatter(
local pid = run_formatter(
bufnr,
formatter,
config,
@ -689,8 +669,8 @@ M.format_lines_sync = function(bufnr, formatters, timeout_ms, range, input_lines
end, 5)
if not wait_result then
if jid then
vim.fn.jobstop(jid)
if pid then
uv.kill(pid)
end
if wait_reason == -1 then
return errors.coalesce(final_err, {

View File

@ -49,13 +49,7 @@ end
---@return fun(self: conform.FormatterConfig, ctx: conform.Context): nil|string
M.root_file = function(files)
return function(self, ctx)
if vim.fn.has("nvim-0.10") == 1 then
return vim.fs.root(ctx.dirname, files)
end
local found = vim.fs.find(files, { upward = true, path = ctx.dirname })[1]
if found then
return vim.fs.dirname(found)
end
return vim.fs.root(ctx.dirname, files)
end
end
@ -209,4 +203,47 @@ M.parse_rust_edition = function(dir)
end
end
---@param cmd string
---@return string[]
M.shell_build_argv = function(cmd)
local argv = {}
-- If the shell starts with a quote, it contains spaces (from :help 'shell').
-- The shell may also have additional arguments in it, separated by spaces.
if vim.startswith(vim.o.shell, '"') then
local quoted = vim.o.shell:match('^"([^"]+)"')
table.insert(argv, quoted)
vim.list_extend(argv, vim.split(vim.o.shell:sub(quoted:len() + 3), "%s+", { trimempty = true }))
else
vim.list_extend(argv, vim.split(vim.o.shell, "%s+"))
end
vim.list_extend(argv, vim.split(vim.o.shellcmdflag, "%s+", { trimempty = true }))
if vim.o.shellxquote ~= "" then
-- When shellxquote is "(", we should escape the shellxescape characters with '^'
-- See :help 'shellxescape'
if vim.o.shellxquote == "(" and vim.o.shellxescape ~= "" then
cmd = cmd:gsub(".", function(char)
if string.find(vim.o.shellxescape, char, 1, true) then
return "^" .. char
else
return char
end
end)
end
if vim.o.shellxquote == "(" then
cmd = "(" .. cmd .. ")"
elseif vim.o.shellxquote == '"(' then
cmd = '"(' .. cmd .. ')"'
else
cmd = vim.o.shellxquote .. cmd .. vim.o.shellxquote
end
end
table.insert(argv, cmd)
return argv
end
return M

View File

@ -1,4 +1,4 @@
#!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
#!/nix/store/izpf49b74i15pcr9708s3xdwyqs4jxwl-bash-5.2p32/bin/bash
set -e
mkdir -p ".testenv/config/nvim"

View File

@ -26,6 +26,7 @@ README = os.path.join(ROOT, "README.md")
DOC = os.path.join(ROOT, "doc")
RECIPES = os.path.join(DOC, "recipes.md")
ADVANCED = os.path.join(DOC, "advanced_topics.md")
DEBUGGING = os.path.join(DOC, "debugging.md")
FORMATTER_OPTIONS = os.path.join(DOC, "formatter_options.md")
VIMDOC = os.path.join(DOC, "conform.txt")
OPTIONS = os.path.join(ROOT, "scripts", "options_doc.lua")
@ -143,21 +144,22 @@ def update_readme_toc():
)
def update_recipes_toc():
def update_tocs():
toc = ["\n"] + generate_md_toc(RECIPES) + ["\n"]
replace_section(RECIPES, r"^<!-- TOC -->$", r"^<!-- /TOC -->$", toc)
subtoc = add_md_link_path("doc/recipes.md", toc)
replace_section(README, r"^<!-- RECIPES -->$", r"^<!-- /RECIPES -->$", subtoc)
def update_advanced_toc():
toc = ["\n"] + generate_md_toc(ADVANCED) + ["\n"]
replace_section(ADVANCED, r"^<!-- TOC -->$", r"^<!-- /TOC -->$", toc)
subtoc = add_md_link_path("doc/advanced_topics.md", toc)
replace_section(README, r"^<!-- ADVANCED -->$", r"^<!-- /ADVANCED -->$", subtoc)
toc = ["\n"] + generate_md_toc(DEBUGGING) + ["\n"]
replace_section(DEBUGGING, r"^<!-- TOC -->$", r"^<!-- /TOC -->$", toc)
subtoc = add_md_link_path("doc/debugging.md", toc)
replace_section(README, r"^<!-- DEBUGGING -->$", r"^<!-- /DEBUGGING -->$", subtoc)
def update_formatter_options_toc():
toc = ["\n"] + generate_md_toc(FORMATTER_OPTIONS) + ["\n"]
replace_section(FORMATTER_OPTIONS, r"^<!-- TOC -->$", r"^<!-- /TOC -->$", toc)
subtoc = add_md_link_path("doc/formatter_options.md", toc)
@ -210,8 +212,6 @@ def main() -> None:
update_autocmd_md()
update_formatter_options_md()
update_md_api()
update_recipes_toc()
update_advanced_toc()
update_formatter_options_toc()
update_tocs()
update_readme_toc()
generate_vimdoc()

View File

@ -1,4 +1,4 @@
#!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
#!/nix/store/izpf49b74i15pcr9708s3xdwyqs4jxwl-bash-5.2p32/bin/bash
set -e

View File

@ -1,5 +1,6 @@
require("plenary.async").tests.add_to_env()
local conform = require("conform")
local fs = require("conform.fs")
local runner = require("conform.runner")
local test_util = require("tests.test_util")
local util = require("conform.util")
@ -121,7 +122,7 @@ describe("runner", function()
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
local cmd = runner.build_cmd("", ctx, config)
assert.are.same({ "echo", vim.api.nvim_buf_get_name(bufnr) }, cmd)
assert.are.same({ vim.fn.exepath("echo"), vim.api.nvim_buf_get_name(bufnr) }, cmd)
end)
it("replaces $DIRNAME in args", function()
@ -135,7 +136,10 @@ describe("runner", function()
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
local cmd = runner.build_cmd("", ctx, config)
assert.are.same({ "echo", vim.fs.dirname(vim.api.nvim_buf_get_name(bufnr)) }, cmd)
assert.are.same(
{ vim.fn.exepath("echo"), vim.fs.dirname(vim.api.nvim_buf_get_name(bufnr)) },
cmd
)
end)
it("resolves arg function", function()
@ -150,35 +154,7 @@ describe("runner", function()
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
local cmd = runner.build_cmd("", ctx, config)
assert.are.same({ "echo", "--stdin" }, cmd)
end)
it("replaces $FILENAME in string args", function()
vim.cmd.edit({ args = { "README.md" } })
local bufnr = vim.api.nvim_get_current_buf()
conform.formatters.test = {
meta = { url = "", description = "" },
command = "echo",
args = "$FILENAME | patch",
}
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
local cmd = runner.build_cmd("", ctx, config)
assert.equal("echo " .. vim.api.nvim_buf_get_name(bufnr) .. " | patch", cmd)
end)
it("replaces $DIRNAME in string args", function()
vim.cmd.edit({ args = { "README.md" } })
local bufnr = vim.api.nvim_get_current_buf()
conform.formatters.test = {
meta = { url = "", description = "" },
command = "echo",
args = "$DIRNAME | patch",
}
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
local cmd = runner.build_cmd("", ctx, config)
assert.equal("echo " .. vim.fs.dirname(vim.api.nvim_buf_get_name(bufnr)) .. " | patch", cmd)
assert.are.same({ vim.fn.exepath("echo"), "--stdin" }, cmd)
end)
it("resolves arg function with string results", function()
@ -193,7 +169,7 @@ describe("runner", function()
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
local cmd = runner.build_cmd("", ctx, config)
assert.equal("echo | patch", cmd)
assert.are.same(util.shell_build_argv(vim.fn.exepath("echo") .. " | patch"), cmd)
end)
end)
@ -410,5 +386,22 @@ print("a")
assert.are.same({ "a", "d", "c" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end)
end)
it("can run the format command in the shell", function()
-- Mac echo doesn't seem to support -e, but the linux ci runner apparently doesn't have seq
if fs.is_mac then
conform.formatters.test = {
command = "seq",
args = "3 1 | sort",
}
run_formatter_test("", "1\n2\n3")
else
conform.formatters.test = {
command = "echo",
args = '-e "World\nHello" | sort',
}
run_formatter_test("", "Hello\nWorld")
end
end)
end)
end)

View File

@ -0,0 +1,72 @@
local test_util = require("tests.test_util")
local util = require("conform.util")
describe("util", function()
local shell = vim.o.shell
local shellcmdflag = vim.o.shellcmdflag
local shellxescape = vim.o.shellxescape
local shellxquote = vim.o.shellxquote
after_each(function()
test_util.reset_editor()
vim.o.shell = shell
vim.o.shellcmdflag = shellcmdflag
vim.o.shellxescape = shellxescape
vim.o.shellxquote = shellxquote
end)
describe("shell_build_argv", function()
it("builds simple command", function()
vim.o.shell = "/bin/bash"
vim.o.shellcmdflag = "-c"
vim.o.shellxescape = ""
vim.o.shellxquote = ""
local argv = util.shell_build_argv("echo hello")
assert.are_same({ "/bin/bash", "-c", "echo hello" }, argv)
end)
it("handles shell arguments", function()
vim.o.shell = "/bin/bash -f"
vim.o.shellcmdflag = "-c"
vim.o.shellxescape = ""
vim.o.shellxquote = ""
local argv = util.shell_build_argv("echo hello")
assert.are_same({ "/bin/bash", "-f", "-c", "echo hello" }, argv)
end)
it("handles shell with spaces", function()
vim.o.shell = '"c:\\program files\\unix\\sh.exe"'
vim.o.shellcmdflag = "-c"
vim.o.shellxescape = ""
vim.o.shellxquote = ""
local argv = util.shell_build_argv("echo hello")
assert.are_same({ "c:\\program files\\unix\\sh.exe", "-c", "echo hello" }, argv)
end)
it("handles shell with spaces and args", function()
vim.o.shell = '"c:\\program files\\unix\\sh.exe" -f'
vim.o.shellcmdflag = "-c"
vim.o.shellxescape = ""
vim.o.shellxquote = ""
local argv = util.shell_build_argv("echo hello")
assert.are_same({ "c:\\program files\\unix\\sh.exe", "-f", "-c", "echo hello" }, argv)
end)
it("applies shellxquote", function()
vim.o.shell = "/bin/bash"
vim.o.shellcmdflag = "-c"
vim.o.shellxescape = ""
vim.o.shellxquote = "'"
local argv = util.shell_build_argv("echo hello")
assert.are_same({ "/bin/bash", "-c", "'echo hello'" }, argv)
end)
it("uses shellxescape", function()
vim.o.shell = "/bin/bash"
vim.o.shellcmdflag = "-c"
vim.o.shellxescape = "el"
vim.o.shellxquote = "("
local argv = util.shell_build_argv("echo hello")
assert.are_same({ "/bin/bash", "-c", "(^echo h^e^l^lo)" }, argv)
end)
end)
end)