` | Custom formatters and overrides for built-in formatters. |
### format(opts, callback)
`format(opts, callback): boolean` \
Format a buffer
| Param | Type | Desc |
| ------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| opts | `nil\|conform.FormatOpts` | |
| >timeout_ms | `nil\|integer` | Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true. |
| >bufnr | `nil\|integer` | Format this buffer (default 0) |
| >async | `nil\|boolean` | If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded. |
| >dry_run | `nil\|boolean` | If true don't apply formatting changes to the buffer |
| >undojoin | `nil\|boolean` | Use undojoin to merge formatting changes with previous edit (default false) |
| >formatters | `nil\|string[]` | List of formatters to run. Defaults to all formatters for the buffer filetype. |
| >lsp_format | `nil\|conform.LspFormatOpts` | Configure if and when LSP should be used for formatting. Defaults to "never". |
| | `"never"` | never use the LSP for formatting (default) |
| | `"fallback"` | LSP formatting is used when no other formatters are available |
| | `"prefer"` | use only LSP formatting when available |
| | `"first"` | LSP formatting is used when available and then other formatters |
| | `"last"` | other formatters are used then LSP formatting when available |
| >stop_after_first | `nil\|boolean` | Only run the first available formatter in the list. Defaults to false. |
| >quiet | `nil\|boolean` | Don't show any notifications for warnings or failures. Defaults to false. |
| >range | `nil\|conform.Range` | Range to format. Table must contain `start` and `end` keys with {row, col} tuples using (1,0) indexing. Defaults to current selection in visual mode |
| >>start | `integer[]` | |
| >>end | `integer[]` | |
| >id | `nil\|integer` | Passed to vim.lsp.buf.format when using LSP formatting |
| >name | `nil\|string` | Passed to vim.lsp.buf.format when using LSP formatting |
| >filter | `nil\|fun(client: table): boolean` | Passed to vim.lsp.buf.format when using LSP formatting |
| >formatting_options | `nil\|table` | Passed to vim.lsp.buf.format when using LSP formatting |
| callback | `nil\|fun(err: nil\|string, did_edit: nil\|boolean)` | Called once formatting has completed |
Returns:
| Type | Desc |
| ------- | ------------------------------------- |
| boolean | True if any formatters were attempted |
**Examples:**
```lua
-- Synchronously format the current buffer
conform.format({ lsp_format = "fallback" })
-- Asynchronously format the current buffer; will not block the UI
conform.format({ async = true }, function(err, did_edit)
-- called after formatting
end
-- Format the current buffer with a specific formatter
conform.format({ formatters = { "ruff_fix" } })
```
### list_formatters(bufnr)
`list_formatters(bufnr): conform.FormatterInfo[]` \
Retrieve the available formatters for a buffer
| Param | Type | Desc |
| ----- | -------------- | ---- |
| bufnr | `nil\|integer` | |
### list_formatters_to_run(bufnr)
`list_formatters_to_run(bufnr): conform.FormatterInfo[], boolean` \
Get the exact formatters that will be run for a buffer.
| Param | Type | Desc |
| ----- | -------------- | ---- |
| bufnr | `nil\|integer` | |
Returns:
| Type | Desc |
| ----------------------- | -------------------------- |
| conform.FormatterInfo[] | |
| boolean | lsp Will use LSP formatter |
**Note:**
This accounts for stop_after_first, lsp fallback logic, etc.
### list_all_formatters()
`list_all_formatters(): conform.FormatterInfo[]` \
List information about all filetype-configured formatters
### get_formatter_info(formatter, bufnr)
`get_formatter_info(formatter, bufnr): conform.FormatterInfo` \
Get information about a formatter (including availability)
| Param | Type | Desc |
| --------- | -------------- | ------------------------- |
| formatter | `string` | The name of the formatter |
| bufnr | `nil\|integer` | |
## FAQ
**Q:** Instead of passing `lsp_format = "..."`, could you just define a `lsp` formatter? \
**A:** No. [#61](https://github.com/stevearc/conform.nvim/issues/61)
**Q:** Is it possible to define a custom formatter that runs a lua function? \
**A:** Yes, but with some very strict constraints. [#653](https://github.com/stevearc/conform.nvim/issues/653)
**Q:** Can I run a command like `:EslintFixAll` or a LSP code action as a formatter? \
**A:** No. [#502](https://github.com/stevearc/conform.nvim/issues/502), [#466](https://github.com/stevearc/conform.nvim/issues/466), [#222](https://github.com/stevearc/conform.nvim/issues/222)
## Acknowledgements
Thanks to
- [nvim-lint](https://github.com/mfussenegger/nvim-lint) for providing inspiration for the config and API. It's an excellent plugin that balances power and simplicity.
- [null-ls](https://github.com/jose-elias-alvarez/null-ls.nvim) for formatter configurations and being my formatter/linter of choice for a long time.
conform.nvim-9.1.0/doc/ 0000775 0000000 0000000 00000000000 15051732407 0014705 5 ustar 00root root 0000000 0000000 conform.nvim-9.1.0/doc/advanced_topics.md 0000664 0000000 0000000 00000006070 15051732407 0020360 0 ustar 00root root 0000000 0000000 # Advanced topics
- [Minimal format diffs](#minimal-format-diffs)
- [Range formatting](#range-formatting)
- [Injected language formatting (code blocks)](#injected-language-formatting-code-blocks)
## Minimal format diffs
To understand why this is important and why conform.nvim is different we need a bit of historical context. Formatting tools work by taking in the current state of the file and outputting the same contents, with formatting applied. The way most formatting plugins work is they take the new content and replace the entire buffer. The benefit of this approach is that it's very simple. It's easy to code, it's easy to reason about, and it's easy to debug.
What conform does differently is it leverages `:help vim.diff`, Neovim's lua bindings for xdiff. We use this to compare the formatted lines to the original content and calculate minimal chunks where changes need to be applied. From there, we convert these chunks into LSP TextEdit objects and use `vim.lsp.util.apply_text_edits()` to actually apply the changes. Since we're using the built-in LSP utility, we get the benefits of all the work that was put into improving the LSP formatting experience, such as the preservation of extmarks. The piecewise update also does a better job of preserving cursor position, folds, viewport position, etc.
## Range formatting
When a formatting tool doesn't have built-in support for range formatting, conform will attempt to "fake it" when requested. This is necessarily a **best effort** operation and is **not** guaranteed to be correct or error-free, however in _most_ cases it should produce acceptable results.
The way this "aftermarket" range formatting works is conform will format the entire buffer as per usual, but during the diff process it will discard diffs that fall outside of the selected range. This usually approximates a correct result, but as you can guess it's possible for the formatting to exceed the range (if the diff covering the range is large) or for the results to be incorrect (if the formatting changes require two diffs in different locations to be semantically correct).
## Injected language formatting (code blocks)
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.
This formatter is experimental; the behavior and configuration options are still subject to change. The current list of configuration options can be found at [formatter options](formatter_options.md#injected)
conform.nvim-9.1.0/doc/conform.txt 0000664 0000000 0000000 00000075267 15051732407 0017132 0 ustar 00root root 0000000 0000000 *conform.txt*
*Conform* *conform* *conform.nvim*
--------------------------------------------------------------------------------
CONTENTS *conform-contents*
1. Options |conform-options|
2. Api |conform-api|
3. Formatters |conform-formatters|
--------------------------------------------------------------------------------
OPTIONS *conform-options*
>lua
require("conform").setup({
-- Map of filetype to formatters
formatters_by_ft = {
lua = { "stylua" },
-- Conform will run multiple formatters sequentially
go = { "goimports", "gofmt" },
-- You can also customize some of the format options for the filetype
rust = { "rustfmt", lsp_format = "fallback" },
-- You can use a function here to determine the formatters dynamically
python = function(bufnr)
if require("conform").get_formatter_info("ruff_format", bufnr).available then
return { "ruff_format" }
else
return { "isort", "black" }
end
end,
-- Use the "*" filetype to run formatters on all filetypes.
["*"] = { "codespell" },
-- Use the "_" filetype to run formatters on filetypes that don't
-- have other formatters configured.
["_"] = { "trim_whitespace" },
},
-- Set this to change the default values when calling conform.format()
-- This will also affect the default values for format_on_save/format_after_save
default_format_opts = {
lsp_format = "fallback",
},
-- If this is set, Conform will run the formatter on save.
-- It will pass the table to conform.format().
-- This can also be a function that returns the table.
format_on_save = {
-- I recommend these options. See :help conform.format for details.
lsp_format = "fallback",
timeout_ms = 500,
},
-- If this is set, Conform will run the formatter asynchronously after save.
-- It will pass the table to conform.format().
-- This can also be a function that returns the table.
format_after_save = {
lsp_format = "fallback",
},
-- Set the log level. Use `:ConformInfo` to see the location of the log file.
log_level = vim.log.levels.ERROR,
-- Conform will notify you when a formatter errors
notify_on_error = true,
-- Conform will notify you when no formatters are available for the buffer
notify_no_formatters = true,
-- Custom formatters and overrides for built-in formatters
formatters = {
my_formatter = {
-- This can be a string or a function that returns a string.
-- When defining a new formatter, this is the only field that is required
command = "my_cmd",
-- A list of strings, or a function that returns a list of strings
-- Return a single string instead of a list to run the command in a shell
args = { "--stdin-from-filename", "$FILENAME" },
-- If the formatter supports range formatting, create the range arguments here
range_args = function(self, ctx)
return { "--line-start", ctx.range.start[1], "--line-end", ctx.range["end"][1] }
end,
-- Send file contents to stdin, read new contents from stdout (default true)
-- When false, will create a temp file (will appear in "$FILENAME" args). The temp
-- file is assumed to be modified in-place by the format command.
stdin = true,
-- A function that calculates the directory to run the command in
cwd = require("conform.util").root_file({ ".editorconfig", "package.json" }),
-- When cwd is not found, don't run the formatter (default false)
require_cwd = true,
-- When stdin=false, use this template to generate the temporary file that gets formatted
tmpfile_format = ".conform.$RANDOM.$FILENAME",
-- When returns false, the formatter will not be used
condition = function(self, ctx)
return vim.fs.basename(ctx.filename) ~= "README.md"
end,
-- Exit codes that indicate success (default { 0 })
exit_codes = { 0, 1 },
-- Environment variables. This can also be a function that returns a table.
env = {
VAR = "value",
},
-- Set to false to disable merging the config with the base definition
inherit = true,
-- When inherit = true, add these additional arguments to the beginning of the command.
-- This can also be a function, like args
prepend_args = { "--use-tabs" },
-- When inherit = true, add these additional arguments to the end of the command.
-- This can also be a function, like args
append_args = { "--trailing-comma" },
},
-- These can also be a function that returns the formatter
other_formatter = function(bufnr)
return {
command = "my_cmd",
}
end,
},
})
-- You can set formatters_by_ft and formatters directly
require("conform").formatters_by_ft.lua = { "stylua" }
require("conform").formatters.my_formatter = {
command = "my_cmd",
}
<
--------------------------------------------------------------------------------
API *conform-api*
setup({opts}) *conform.setup*
Parameters:
{opts} `nil|conform.setupOpts`
{formatters_by_ft} `nil|table` Map
of filetype to formatters
{format_on_save} `nil|conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts`
If this is set, Conform will run the formatter on
save. It will pass the table to conform.format().
This can also be a function that returns the table.
{default_format_opts} `nil|conform.DefaultFormatOpts` The default
options to use when calling conform.format()
{timeout_ms} `nil|integer` Time in milliseconds to block for
formatting. Defaults to 1000. No effect if
async = true.
{lsp_format} `nil|conform.LspFormatOpts` Configure if and
when LSP should be used for formatting.
Defaults to "never".
`"never"` never use the LSP for formatting (default)
`"fallback"` LSP formatting is used when no other formatters
are available
`"prefer"` use only LSP formatting when available
`"first"` LSP formatting is used when available and then
other formatters
`"last"` other formatters are used then LSP formatting
when available
{quiet} `nil|boolean` Don't show any notifications for
warnings or failures. Defaults to false.
{stop_after_first} `nil|boolean` Only run the first available
formatter in the list. Defaults to false.
{format_after_save} `nil|conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts`
, nil|fun(err: nil|string, did_edit: nil|boolean)
If this is set, Conform will run the formatter
asynchronously after save. It will pass the table
to conform.format(). This can also be a function
that returns the table (and an optional callback
that is run after formatting).
{log_level} `nil|integer` Set the log level (e.g.
`vim.log.levels.DEBUG`). Use `:ConformInfo` to see
the location of the log file.
{notify_on_error} `nil|boolean` Conform will notify you when a
formatter errors (default true).
{notify_no_formatters} `nil|boolean` Conform will notify you when no
formatters are available for the buffer (default
true).
{formatters} `nil|table`
Custom formatters and overrides for built-in
formatters.
format({opts}, {callback}): boolean *conform.format*
Format a buffer
Parameters:
{opts} `nil|conform.FormatOpts`
{timeout_ms} `nil|integer` Time in milliseconds to block for
formatting. Defaults to 1000. No effect if async =
true.
{bufnr} `nil|integer` Format this buffer (default 0)
{async} `nil|boolean` If true the method won't block.
Defaults to false. If the buffer is modified before
the formatter completes, the formatting will be
discarded.
{dry_run} `nil|boolean` If true don't apply formatting
changes to the buffer
{undojoin} `nil|boolean` Use undojoin to merge formatting
changes with previous edit (default false)
{formatters} `nil|string[]` List of formatters to run. Defaults
to all formatters for the buffer filetype.
{lsp_format} `nil|conform.LspFormatOpts` Configure if and when
LSP should be used for formatting. Defaults to
"never".
`"never"` never use the LSP for formatting (default)
`"fallback"` LSP formatting is used when no other formatters are
available
`"prefer"` use only LSP formatting when available
`"first"` LSP formatting is used when available and then other
formatters
`"last"` other formatters are used then LSP formatting when
available
{stop_after_first} `nil|boolean` Only run the first available
formatter in the list. Defaults to false.
{quiet} `nil|boolean` Don't show any notifications for
warnings or failures. Defaults to false.
{range} `nil|conform.Range` Range to format. Table must
contain `start` and `end` keys with {row, col}
tuples using (1,0) indexing. Defaults to current
selection in visual mode
{start} `integer[]`
{end} `integer[]`
{id} `nil|integer` Passed to |vim.lsp.buf.format| when
using LSP formatting
{name} `nil|string` Passed to |vim.lsp.buf.format| when
using LSP formatting
{filter} `nil|fun(client: table): boolean` Passed to |vim.ls
p.buf.format| when using LSP formatting
{formatting_options} `nil|table` Passed to |vim.lsp.buf.format| when
using LSP formatting
{callback} `nil|fun(err: nil|string, did_edit: nil|boolean)` Called once
formatting has completed
Returns:
`boolean` True if any formatters were attempted
Examples: >lua
-- Synchronously format the current buffer
conform.format({ lsp_format = "fallback" })
-- Asynchronously format the current buffer; will not block the UI
conform.format({ async = true }, function(err, did_edit)
-- called after formatting
end
-- Format the current buffer with a specific formatter
conform.format({ formatters = { "ruff_fix" } })
<
list_formatters({bufnr}): conform.FormatterInfo[] *conform.list_formatters*
Retrieve the available formatters for a buffer
Parameters:
{bufnr} `nil|integer`
list_formatters_to_run({bufnr}): conform.FormatterInfo[], boolean *conform.list_formatters_to_run*
Get the exact formatters that will be run for a buffer.
Parameters:
{bufnr} `nil|integer`
Returns:
`conform.FormatterInfo[]`
`boolean` lsp Will use LSP formatter
Note:
This accounts for stop_after_first, lsp fallback logic, etc.
list_all_formatters(): conform.FormatterInfo[] *conform.list_all_formatters*
List information about all filetype-configured formatters
get_formatter_info({formatter}, {bufnr}): conform.FormatterInfo *conform.get_formatter_info*
Get information about a formatter (including availability)
Parameters:
{formatter} `string` The name of the formatter
{bufnr} `nil|integer`
--------------------------------------------------------------------------------
FORMATTERS *conform-formatters*
`air` - R formatter and language server.
`alejandra` - The Uncompromising Nix Code Formatter.
`ansible-lint` - ansible-lint with --fix.
`asmfmt` - Go Assembler Formatter
`ast-grep` - A CLI tool for code structural search, lint and rewriting. Written
in Rust.
`astyle` - A Free, Fast, and Small Automatic Formatter for C, C++, C++/CLI,
Objective-C, C#, and Java Source Code.
`auto_optional` - Adds the Optional type-hint to arguments where the default
value is None.
`autocorrect` - A linter and formatter to help you to improve copywriting,
correct spaces, words, and punctuations between CJK.
`autoflake` - Removes unused imports and unused variables as reported by
pyflakes.
`autopep8` - A tool that automatically formats Python code to conform to the PEP
8 style guide.
`bake` - A Makefile formatter and linter.
`bean-format` - Reformat Beancount files to right-align all the numbers at the
same, minimal column.
`beautysh` - A Bash beautifier for the masses.
`bibtex-tidy` - Cleaner and Formatter for BibTeX files.
`bicep` - Bicep is a Domain Specific Language (DSL) for deploying Azure
resources declaratively.
`biome` - A toolchain for web projects, aimed to provide functionalities to
maintain them.
`biome-check` - A toolchain for web projects, aimed to provide functionalities
to maintain them.
`biome-organize-imports` - A toolchain for web projects, aimed to provide
functionalities to maintain them.
`black` - The uncompromising Python code formatter.
`blade-formatter` - An opinionated blade template formatter for Laravel that
respects readability.
`blue` - The slightly less uncompromising Python code formatter.
`bpfmt` - Android Blueprint file formatter.
`bsfmt` - A code formatter for BrighterScript (and BrightScript).
`buf` - A new way of working with Protocol Buffers.
`buildifier` - buildifier is a tool for formatting bazel BUILD and .bzl files
with a standard convention.
`cabal_fmt` - Format cabal files with cabal-fmt.
`caramel_fmt` - Format Caramel code.
`cbfmt` - A tool to format codeblocks inside markdown and org documents.
`cedar` - Formats cedar policies.
`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.
`codeql` - Format queries and libraries with CodeQL.
`codespell` - Check code for common misspellings.
`commitmsgfmt` - Formats commit messages better than fmt(1) and Vim.
`crlfmt` - Formatter for CockroachDB's additions to the Go style guide.
`crystal` - Format Crystal code.
`csharpier` - The opinionated C# code formatter.
`css_beautify` - Beautifier for css.
`cue_fmt` - Format CUE files using `cue fmt` command.
`d2` - D2 is a modern diagram scripting language that turns text to diagrams.
`darker` - Run black only on changed lines.
`dart_format` - Replace the whitespace in your program with formatting that
follows Dart guidelines.
`dcm_fix` - Fixes issues produced by dcm analyze, dcm check-unused-code or dcm
check-dependencies commands.
`dcm_format` - Formats .dart files.
`deno_fmt` - Use [Deno](https://deno.land/) to format TypeScript,
JavaScript/JSON and markdown.
`dfmt` - Formatter for D source code.
`dioxus` - Format `rsx!` snippets in Rust files.
`djlint` - ✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks -
Handlebars - GoLang.
`docformatter` - docformatter automatically formats docstrings to follow a
subset of the PEP 257 conventions.
`dockerfmt` - Dockerfile formatter. a modern dockfmt.
`docstrfmt` - reStructuredText formatter.
`doctoc` - Generates table of contents for markdown files inside local git
repository.
`dprint` - Pluggable and configurable code formatting platform written in Rust.
`easy-coding-standard` - ecs - Use Coding Standard with 0-knowledge of PHP-CS-
Fixer and PHP_CodeSniffer.
`efmt` - Erlang code formatter.
`elm_format` - elm-format formats Elm source code according to a standard set of
rules based on the official [Elm Style Guide](https://elm-
lang.org/docs/style-guide).
`erb_format` - Format ERB files with speed and precision.
`erlfmt` - An automated code formatter for Erlang.
`eslint_d` - Like ESLint, but faster.
`fantomas` - F# source code formatter.
`findent` - Indent, relabel and convert Fortran sources.
`fish_indent` - Indent or otherwise prettify a piece of fish code.
`fixjson` - JSON Fixer for Humans using (relaxed) JSON5.
`fnlfmt` - A formatter for Fennel code.
`forge_fmt` - Forge is a command-line tool that ships with Foundry. Forge tests,
builds, and deploys your smart contracts.
`format-dune-file` - Auto-formatter for Dune files.
`format-queries` - Tree-sitter query formatter.
`fourmolu` - A fork of ormolu that uses four space indentation and allows
arbitrary configuration.
`fprettify` - Auto-formatter for modern fortran source code.
`gawk` - Format awk programs with gawk.
`gci` - GCI, a tool that controls Go package import order and makes it always
deterministic.
`gdformat` - A formatter for Godot's gdscript.
`gersemi` - A formatter to make your CMake code the real treasure.
`ghdl` - Open-source analyzer, compiler, simulator and synthesizer for VHDL.
`ghokin` - Parallelized formatter with no external dependencies for gherkin.
`gleam` - ⭐️ A friendly language for building type-safe, scalable systems!
`gluon_fmt` - Code formatting for the gluon programming language.
`gn` - gn build system.
`gofmt` - Formats go programs.
`gofumpt` - Enforce a stricter format than gofmt, while being backwards
compatible. That is, gofumpt is happy with a subset of the formats
that gofmt is happy with.
`goimports` - Updates your Go import lines, adding missing ones and removing
unreferenced ones.
`goimports-reviser` - Right imports sorting & code formatting tool (goimports
alternative).
`gojq` - Pure Go implementation of jq.
`golangci-lint` - Fast linters runner for Go (with formatter).
`golines` - A golang formatter that fixes long lines.
`google-java-format` - Reformats Java source code according to Google Java
Style.
`grain_format` - Code formatter for the grain programming language.
`hcl` - A formatter for HCL files.
`hindent` - Haskell pretty printer.
`hledger-fmt` - An opinionated hledger's journal files formatter.
`html_beautify` - Beautifier for html.
`htmlbeautifier` - A normaliser/beautifier for HTML that also understands
embedded Ruby. Ideal for tidying up Rails templates.
`hurlfmt` - Formats hurl files.
`imba_fmt` - Code formatter for the Imba programming language.
`indent` - GNU Indent.
`injected` - Format treesitter injected languages.
`inko` - A language for building concurrent software with confidence
`isort` - Python utility / library to sort imports alphabetically and
automatically separate them into sections and by type.
`janet-format` - A formatter for Janet code.
`joker` - Small Clojure interpreter, linter and formatter.
`jq` - Command-line JSON processor.
`js_beautify` - Beautifier for javascript.
`jsonnetfmt` - jsonnetfmt is a command line tool to format jsonnet files.
`just` - Format Justfile.
`kcl` - The KCL Format tool modifies the files according to the KCL code style.
`kdlfmt` - A formatter for kdl documents.
`keep-sorted` - keep-sorted is a language-agnostic formatter that sorts lines
between two markers in a larger file.
`ktfmt` - Reformats Kotlin source code to comply with the common community
standard conventions.
`ktlint` - An anti-bikeshedding Kotlin linter with built-in formatter.
`kulala-fmt` - An opinionated .http and .rest files linter and formatter.
`latexindent` - A perl script for formatting LaTeX files that is generally
included in major TeX distributions.
`leptosfmt` - A formatter for the Leptos view! macro.
`liquidsoap-prettier` - A binary to format Liquidsoap scripts
`llf` - A LaTeX reformatter / beautifier.
`lua-format` - Code formatter for Lua.
`mago_format` - Mago is a toolchain for PHP that aims to provide a set of tools
to help developers write better code.
`mago_lint` - Mago is a toolchain for PHP that aims to provide a set of tools to
help developers write better code.
`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
interface for linting Markdown/CommonMark files with the
markdownlint library.
`mdformat` - An opinionated Markdown formatter.
`mdsf` - Format markdown code blocks using your favorite code formatters.
`mdslw` - Prepare your markdown for easy diff'ing by adding line breaks after
every sentence.
`mix` - Format Elixir files using the mix format command.
`mojo_format` - Official Formatter for The Mojo Programming Language
`nginxfmt` - nginx config file formatter/beautifier written in Python with no
additional dependencies.
`nickel` - Code formatter for the Nickel programming language.
`nimpretty` - nimpretty is a Nim source code beautifier that follows the
official style guide.
`nixfmt` - The official (but not yet stable) formatter for Nix code.
`nixpkgs_fmt` - nixpkgs-fmt is a Nix code formatter for nixpkgs.
`nomad_fmt` - The fmt commands check the syntax and rewrites Nomad configuration
and jobspec files to canonical format.
`nph` - An opinionated code formatter for Nim.
`npm-groovy-lint` - Lint, format and auto-fix your Groovy / Jenkinsfile / Gradle
files using command line.
`nufmt` - The nushell formatter.
`ocamlformat` - Auto-formatter for OCaml code.
`ocp-indent` - Automatic indentation of OCaml source files.
`odinfmt` - Auto-formatter for the Odin programming language.
`opa_fmt` - Format Rego files using `opa fmt` command.
`ormolu` - A formatter for Haskell source code.
`packer_fmt` - The packer fmt Packer command is used to format HCL2
configuration files to a canonical format and style.
`pangu` - Insert whitespace between CJK and half-width characters.
`perlimports` - Make implicit Perl imports explicit.
`perltidy` - Perl::Tidy, a source code formatter for Perl.
`pg_format` - PostgreSQL SQL syntax beautifier.
`php_cs_fixer` - The PHP Coding Standards Fixer.
`phpcbf` - PHP Code Beautifier and Fixer fixes violations of a defined coding
standard.
`phpinsights` - The perfect starting point to analyze the code quality of your
PHP projects.
`pint` - Laravel Pint is an opinionated PHP code style fixer for minimalists.
`prettier` - Prettier is an opinionated code formatter. It enforces a consistent
style by parsing your code and re-printing it with its own rules that
take the maximum line length into account, wrapping code when
necessary.
`prettierd` - prettier, as a daemon, for ludicrous formatting speed.
`pretty-php` - The opinionated PHP code formatter.
`prettypst` - Formatter for Typst.
`prolog` - Language Server Protocol server and formatter for SWI-Prolog.
`puppet-lint` - Check that your Puppet manifests conform to the style guide.
`purs-tidy` - A syntax tidy-upper for PureScript.
`pycln` - A Python formatter for finding and removing unused import statements.
`pyink` - A Python formatter, forked from Black with a few different formatting
behaviors.
`pymarkdownlnt` - A markdown linter and formatter.
`pyproject-fmt` - Apply a consistent format to your pyproject.toml file with
comment support.
`python-ly` - A Python package and commandline tool to manipulate LilyPond
files.
`pyupgrade` - A tool to automatically upgrade syntax for newer versions of
Python.
`qmlformat` - A tool that automatically formats QML files.
`reformat-gherkin` - Formatter for Gherkin language.
`reorder-python-imports` - Rewrites source to reorder python imports
`rescript-format` - The built-in ReScript formatter.
`roc` - A fast, friendly, functional language.
`rstfmt` - A formatter for reStructuredText.
`rubocop` - Ruby static code analyzer and formatter, based on the community Ruby
style guide.
`rubyfmt` - Ruby Autoformatter! (Written in Rust)
`ruff_fix` - An extremely fast Python linter, written in Rust. Fix lint errors.
`ruff_format` - An extremely fast Python linter, written in Rust. Formatter
subcommand.
`ruff_organize_imports` - An extremely fast Python linter, written in Rust.
Organize imports.
`rufo` - Rufo is an opinionated ruby formatter.
`runic` - Julia code formatter.
`rustfmt` - A tool for formatting rust code according to style guidelines.
`rustywind` - A tool for formatting Tailwind CSS classes.
`scalafmt` - Code formatter for Scala.
`shellcheck` - A static analysis tool for shell scripts.
`shellharden` - The corrective bash syntax highlighter.
`shfmt` - A shell parser, formatter, and interpreter with `bash` support.
`sleek` - Sleek is a CLI tool for formatting SQL.
`smlfmt` - A custom parser and code formatter for Standard ML.
`snakefmt` - a formatting tool for Snakemake files following the design of
Black.
`spotless_gradle` - Spotless plugin for Gradle.
`spotless_maven` - Spotless plugin for Maven.
`sql_formatter` - A whitespace formatter for different query languages.
`sqlfluff` - A modular SQL linter and auto-formatter with support for multiple
dialects and templated code.
`sqlfmt` - sqlfmt formats your dbt SQL files so you don't have to. It is similar
in nature to Black, gofmt, and rustfmt (but for SQL)
`sqruff` - sqruff is a SQL linter and formatter written in Rust.
`squeeze_blanks` - Squeeze repeated blank lines into a single blank line via
`cat -s`.
`standard-clj` - A JavaScript library to format Clojure code according to
Standard Clojure Style.
`standardjs` - JavaScript Standard style guide, linter, and formatter.
`standardrb` - Ruby's bikeshed-proof linter and formatter.
`stylelint` - A mighty CSS linter that helps you avoid errors and enforce
conventions.
`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` - Official Swift formatter. Requires Swift 6.0 or later.
`swift_format` - Official Swift formatter. For Swift 6.0 or later prefer setting
the `swift` formatter instead.
`swiftformat` - SwiftFormat is a code library and command-line tool for
reformatting `swift` code on macOS or Linux.
`swiftlint` - A tool to enforce Swift style and conventions.
`syntax_tree` - Syntax Tree is a suite of tools built on top of the internal
CRuby parser.
`taplo` - A TOML toolkit written in Rust.
`templ` - Formats templ template files.
`terraform_fmt` - The terraform-fmt command rewrites `terraform` configuration
files to a canonical format and style.
`terragrunt_hclfmt` - Format hcl files into a canonical format.
`tex-fmt` - An extremely fast LaTeX formatter written in Rust.
`tlint` - Tighten linter for Laravel conventions with support for auto-
formatting.
`tofu_fmt` - The tofu-fmt command rewrites OpenTofu configuration files to a
canonical format and style.
`tombi` - TOML Formatter / Linter.
`treefmt` - one CLI to format your repo.
`trim_newlines` - Trim empty lines at the end of the file.
`trim_whitespace` - Trim trailing whitespace.
`twig-cs-fixer` - Automatically fix Twig Coding Standards issues
`typespec` - TypeSpec compiler and CLI.
`typos` - Source code spell checker
`typstyle` - Beautiful and reliable typst code formatter.
`ufmt` - Safe, atomic formatting with black and µsort.
`uncrustify` - A source code beautifier for C, C++, C#, ObjectiveC, D, Java,
Pawn and Vala.
`usort` - Safe, minimal import sorting for Python projects.
`v` - V language formatter.
`verible` - The SystemVerilog formatter.
`vsg` - Style guide enforcement for VHDL.
`xmlformatter` - xmlformatter is an Open Source Python package, which provides
formatting of XML documents.
`xmllint` - Despite the name, xmllint can be used to format XML files as well as
lint them.
`xmlstarlet` - XMLStarlet is a command-line XML toolkit that can be used to
format XML files.
`yamlfix` - A configurable YAML formatter that keeps comments.
`yamlfmt` - yamlfmt is an extensible command line tool or library to format yaml
files.
`yapf` - Yet Another Python 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.
================================================================================
vim:tw=80:ts=2:ft=help:norl:syntax=help:
conform.nvim-9.1.0/doc/debugging.md 0000664 0000000 0000000 00000013764 15051732407 0017175 0 ustar 00root root 0000000 0000000 # 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?"
- [Background](#background)
- [Tools](#tools)
- [Testing the formatter](#testing-the-formatter)
- [Testing vim.system](#testing-vimsystem)
## 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:
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.
## Testing vim.system
What to do if the formatting command works on the command line? Well, now we need to determine if the issue is with conform or if it's with the underlying Neovim utilities. To isolate this, we're going to attempt to run the command using raw Neovim APIs the same way that conform would. If this succeeds, we can be confident that something is wrong with conform. If this fails, then it is likely that there is an upstream issue with `vim.system`, or possibly that conform needs to call `vim.system` in a different way.
Copy this script into a lua file, edit the bottom to match your use case, and run it with `:source`.
```lua
-- Copy these helper functions directly
local function run_formatter(cmd, cwd, buffer_text)
local proc = vim.system(cmd, {
cwd = cwd,
stdin = buffer_text,
text = true,
})
local ret = proc:wait()
if ret.code == 0 then
print("Success\n--------")
else
print("Failure\n--------")
end
print(ret.stdout)
print(ret.stderr)
end
local function read_file(path)
local file = assert(io.open(path, "r"))
local content = file:read("*a")
file:close()
return content
end
-- Edit these lines to match the values you see in your conform log file
-- To test a stdin formatter
run_formatter({ "formatter_command", "arg1", "arg2" }, "/path/to/cwd", read_file("/path/to/file.txt"))
-- To test a non-stdin formatter
run_formatter({ "formatter_command", "arg1", "arg2" }, "/path/to/cwd")
```
conform.nvim-9.1.0/doc/formatter_options.md 0000664 0000000 0000000 00000005014 15051732407 0021005 0 ustar 00root root 0000000 0000000 # Formatter Options
- [injected](#injected)
- [prettier](#prettier)
- [rustfmt](#rustfmt)
- [yew-fmt](#yew-fmt)
All formatters can be customized by directly changing the command, args, or other values (see [customizing formatters](../README.md#customizing-formatters)). Some formatters have a bit more advanced logic built in to those functions and expose additional configuration options. You can pass these values in like so:
```lua
-- Customize the "injected" formatter
require("conform").formatters.injected = {
-- Set the options field
options = {
-- Set individual option values
ignore_errors = true,
lang_to_formatters = {
json = { "jq" },
},
},
}
```
## injected
```lua
options = {
-- Set to true to ignore errors
ignore_errors = false,
-- Map of treesitter language to filetype
lang_to_ft = {
bash = "sh",
},
-- Map of treesitter language to file extension
-- A temporary file name with this extension will be generated during formatting
-- because some formatters care about the filename.
lang_to_ext = {
bash = "sh",
c_sharp = "cs",
elixir = "exs",
javascript = "js",
julia = "jl",
latex = "tex",
markdown = "md",
python = "py",
ruby = "rb",
rust = "rs",
teal = "tl",
typescript = "ts",
},
-- Map of treesitter language to formatters to use
-- (defaults to the value from formatters_by_ft)
lang_to_formatters = {},
}
```
## prettier
```lua
options = {
-- Use a specific prettier parser for a filetype
-- Otherwise, prettier will try to infer the parser from the file name
ft_parsers = {
-- javascript = "babel",
-- javascriptreact = "babel",
-- typescript = "typescript",
-- typescriptreact = "typescript",
-- vue = "vue",
-- css = "css",
-- scss = "scss",
-- less = "less",
-- html = "html",
-- json = "json",
-- jsonc = "json",
-- yaml = "yaml",
-- markdown = "markdown",
-- ["markdown.mdx"] = "mdx",
-- graphql = "graphql",
-- handlebars = "glimmer",
},
-- Use a specific prettier parser for a file extension
ext_parsers = {
-- qmd = "markdown",
},
}
```
## rustfmt
```lua
options = {
-- The default edition of Rust to use when no Cargo.toml file is found
default_edition = "2021",
}
```
## yew-fmt
```lua
options = {
-- The default edition of Rust to use when no Cargo.toml file is found
default_edition = "2021",
}
```
conform.nvim-9.1.0/doc/recipes.md 0000664 0000000 0000000 00000013461 15051732407 0016666 0 ustar 00root root 0000000 0000000 # Recipes
- [Format command](#format-command)
- [Autoformat with extra features](#autoformat-with-extra-features)
- [Command to toggle format-on-save](#command-to-toggle-format-on-save)
- [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)
## Format command
Define a command to run async formatting
```lua
vim.api.nvim_create_user_command("Format", function(args)
local range = nil
if args.count ~= -1 then
local end_line = vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1]
range = {
start = { args.line1, 0 },
["end"] = { args.line2, end_line:len() },
}
end
require("conform").format({ async = true, lsp_format = "fallback", range = range })
end, { range = true })
```
## Autoformat with extra features
If you want more complex logic than the basic `format_on_save` option allows, you can use a function instead.
```lua
-- if format_on_save is a function, it will be called during BufWritePre
require("conform").setup({
format_on_save = function(bufnr)
-- Disable autoformat on certain filetypes
local ignore_filetypes = { "sql", "java" }
if vim.tbl_contains(ignore_filetypes, vim.bo[bufnr].filetype) then
return
end
-- Disable with a global or buffer-local variable
if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
return
end
-- Disable autoformat for files in a certain path
local bufname = vim.api.nvim_buf_get_name(bufnr)
if bufname:match("/node_modules/") then
return
end
-- ...additional logic...
return { timeout_ms = 500, lsp_format = "fallback" }
end,
})
-- There is a similar affordance for format_after_save, which uses BufWritePost.
-- This is good for formatters that are too slow to run synchronously.
require("conform").setup({
format_after_save = function(bufnr)
if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
return
end
-- ...additional logic...
return { lsp_format = "fallback" }
end,
})
```
## Command to toggle format-on-save
Create user commands to quickly enable/disable autoformatting
```lua
require("conform").setup({
format_on_save = function(bufnr)
-- Disable with a global or buffer-local variable
if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
return
end
return { timeout_ms = 500, lsp_format = "fallback" }
end,
})
vim.api.nvim_create_user_command("FormatDisable", function(args)
if args.bang then
-- FormatDisable! will disable formatting just for this buffer
vim.b.disable_autoformat = true
else
vim.g.disable_autoformat = true
end
end, {
desc = "Disable autoformat-on-save",
bang = true,
})
vim.api.nvim_create_user_command("FormatEnable", function()
vim.b.disable_autoformat = false
vim.g.disable_autoformat = false
end, {
desc = "Re-enable autoformat-on-save",
})
```
## Lazy loading with lazy.nvim
Here is the recommended config for lazy-loading using lazy.nvim
```lua
return {
"stevearc/conform.nvim",
event = { "BufWritePre" },
cmd = { "ConformInfo" },
keys = {
{
-- Customize or remove this keymap to your liking
"f",
function()
require("conform").format({ async = true })
end,
mode = "",
desc = "Format buffer",
},
},
-- This will provide type hinting with LuaLS
---@module "conform"
---@type conform.setupOpts
opts = {
-- Define your formatters
formatters_by_ft = {
lua = { "stylua" },
python = { "isort", "black" },
javascript = { "prettierd", "prettier", stop_after_first = true },
},
-- Set default options
default_format_opts = {
lsp_format = "fallback",
},
-- Set up format-on-save
format_on_save = { timeout_ms = 500 },
-- Customize formatters
formatters = {
shfmt = {
append_args = { "-i", "2" },
},
},
},
init = function()
-- If you want the formatexpr, here is the place to set it
vim.o.formatexpr = "v:lua.require'conform'.formatexpr()"
end,
}
```
## Leave visual mode after range format
If you call `conform.format` when in visual mode, conform will perform a range format on the selected region. If you want it to leave visual mode afterwards (similar to the default `gw` or `gq` behavior), use this mapping:
```lua
vim.keymap.set("", "f", function()
require("conform").format({ async = true }, function(err)
if not err then
local mode = vim.api.nvim_get_mode().mode
if vim.startswith(string.lower(mode), "v") then
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("", true, false, true), "n", true)
end
end
end)
end, { desc = "Format code" })
```
## Run the first available formatter followed by more formatters
With the refactor in [#491](https://github.com/stevearc/conform.nvim/pull/491) it is now easy to
just run the first available formatter in a list, but more difficult to do that _and then_ run
another formatter. For example, "format first with either `prettierd` or `prettier`, _then_ use the
`injected` formatter". Here is how you can easily do that:
```lua
---@param bufnr integer
---@param ... string
---@return string
local function first(bufnr, ...)
local conform = require("conform")
for i = 1, select("#", ...) do
local formatter = select(i, ...)
if conform.get_formatter_info(formatter, bufnr).available then
return formatter
end
end
return select(1, ...)
end
require("conform").setup({
formatters_by_ft = {
markdown = function(bufnr)
return { first(bufnr, "prettierd", "prettier"), "injected" }
end,
},
})
```
conform.nvim-9.1.0/lua/ 0000775 0000000 0000000 00000000000 15051732407 0014721 5 ustar 00root root 0000000 0000000 conform.nvim-9.1.0/lua/conform/ 0000775 0000000 0000000 00000000000 15051732407 0016364 5 ustar 00root root 0000000 0000000 conform.nvim-9.1.0/lua/conform/errors.lua 0000664 0000000 0000000 00000002751 15051732407 0020410 0 ustar 00root root 0000000 0000000 local M = {}
---@class conform.Error
---@field code conform.ERROR_CODE
---@field message string
---@field debounce_message? boolean
---@enum conform.ERROR_CODE
M.ERROR_CODE = {
-- 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
INTERRUPTED = 5,
-- Command produced an error during execution
RUNTIME = 6,
-- Asynchronous formatter results were discarded due to a concurrent modification
CONCURRENT_MODIFICATION = 7,
}
---@param code conform.ERROR_CODE
---@return integer
M.level_for_code = function(code)
if code == M.ERROR_CODE.CONCURRENT_MODIFICATION then
return vim.log.levels.INFO
elseif code == M.ERROR_CODE.TIMEOUT or code == M.ERROR_CODE.INTERRUPTED then
return vim.log.levels.WARN
else
return vim.log.levels.ERROR
end
end
---Returns true if the error occurred while attempting to run the formatter
---@param code conform.ERROR_CODE
---@return boolean
M.is_execution_error = function(code)
return code == M.ERROR_CODE.RUNTIME or code == M.ERROR_CODE.VIM_SYSTEM
end
---@param err1? conform.Error
---@param err2? conform.Error
---@return nil|conform.Error
M.coalesce = function(err1, err2)
if not err1 then
return err2
elseif not err2 then
return err1
end
local level1 = M.level_for_code(err1.code)
local level2 = M.level_for_code(err2.code)
if level2 > level1 then
return err2
else
return err1
end
end
return M
conform.nvim-9.1.0/lua/conform/formatters/ 0000775 0000000 0000000 00000000000 15051732407 0020552 5 ustar 00root root 0000000 0000000 conform.nvim-9.1.0/lua/conform/formatters/air.lua 0000664 0000000 0000000 00000000521 15051732407 0022026 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/posit-dev/air",
description = "R formatter and language server.",
},
command = "air",
args = { "format", "$FILENAME" },
stdin = false,
cwd = util.root_file({
"air.toml",
".air.toml",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/alejandra.lua 0000664 0000000 0000000 00000000305 15051732407 0023174 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://kamadorueda.com/alejandra/",
description = "The Uncompromising Nix Code Formatter.",
},
command = "alejandra",
}
conform.nvim-9.1.0/lua/conform/formatters/ansible-lint.lua 0000664 0000000 0000000 00000000453 15051732407 0023640 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/ansible/ansible-lint",
description = "ansible-lint with --fix.",
},
command = "ansible-lint",
args = { "-f", "codeclimate", "-q", "--fix=all", "$FILENAME" },
stdin = false,
exit_codes = { 0, 2 },
}
conform.nvim-9.1.0/lua/conform/formatters/asmfmt.lua 0000664 0000000 0000000 00000000303 15051732407 0022540 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/klauspost/asmfmt",
description = "Go Assembler Formatter",
},
command = "asmfmt",
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/ast-grep.lua 0000664 0000000 0000000 00000000533 15051732407 0023000 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://ast-grep.github.io/",
description = "A CLI tool for code structural search, lint and rewriting. Written in Rust.",
},
command = "ast-grep",
args = { "scan", "--update-all", "$FILENAME" },
stdin = false,
exit_codes = { 0, 5 }, -- 5 = no config file exists
}
conform.nvim-9.1.0/lua/conform/formatters/astyle.lua 0000664 0000000 0000000 00000000611 15051732407 0022554 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://astyle.sourceforge.net/astyle.html",
description = "A Free, Fast, and Small Automatic Formatter for C, C++, C++/CLI, Objective-C, C#, and Java Source Code.",
},
command = "astyle",
args = { "--quiet" },
cwd = util.root_file({
".astylerc",
"_astylerc",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/auto_optional.lua 0000664 0000000 0000000 00000000440 15051732407 0024130 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://auto-optional.daanluttik.nl/",
description = "Adds the Optional type-hint to arguments where the default value is None.",
},
command = "auto-optional",
args = {
"$FILENAME",
},
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/autocorrect.lua 0000664 0000000 0000000 00000000475 15051732407 0023615 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/huacnlee/autocorrect",
description = "A linter and formatter to help you to improve copywriting, correct spaces, words, and punctuations between CJK.",
},
command = "autocorrect",
args = { "--stdin" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/autoflake.lua 0000664 0000000 0000000 00000000432 15051732407 0023227 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/PyCQA/autoflake",
description = "Removes unused imports and unused variables as reported by pyflakes.",
},
command = "autoflake",
args = { "--stdin-display-name", "$FILENAME", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/autopep8.lua 0000664 0000000 0000000 00000000614 15051732407 0023023 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/hhatto/autopep8",
description = "A tool that automatically formats Python code to conform to the PEP 8 style guide.",
},
command = "autopep8",
args = { "-" },
range_args = function(self, ctx)
return { "-", "--line-range", tostring(ctx.range.start[1]), tostring(ctx.range["end"][1]) }
end,
}
conform.nvim-9.1.0/lua/conform/formatters/awk.lua 0000664 0000000 0000000 00000000375 15051732407 0022044 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://www.gnu.org/software/gawk/manual/gawk.html",
description = "Format awk programs with gawk.",
deprecated = true,
},
command = "awk",
args = { "-f", "-", "-o-" },
}
conform.nvim-9.1.0/lua/conform/formatters/bake.lua 0000664 0000000 0000000 00000000360 15051732407 0022156 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/EbodShojaei/bake",
description = "A Makefile formatter and linter.",
},
command = "bake",
args = { "format", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/bean-format.lua 0000664 0000000 0000000 00000000506 15051732407 0023451 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://beancount.github.io/docs/running_beancount_and_generating_reports.html#bean-format",
description = "Reformat Beancount files to right-align all the numbers at the same, minimal column.",
},
command = "bean-format",
args = {
"-",
},
}
conform.nvim-9.1.0/lua/conform/formatters/beautysh.lua 0000664 0000000 0000000 00000000327 15051732407 0023103 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/lovesegfault/beautysh",
description = "A Bash beautifier for the masses.",
},
command = "beautysh",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/bibtex-tidy.lua 0000664 0000000 0000000 00000000373 15051732407 0023504 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/FlamingTempura/bibtex-tidy",
description = "Cleaner and Formatter for BibTeX files.",
},
command = "bibtex-tidy",
stdin = true,
args = { "--quiet" },
}
conform.nvim-9.1.0/lua/conform/formatters/bicep.lua 0000664 0000000 0000000 00000000435 15051732407 0022341 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/Azure/bicep",
description = "Bicep is a Domain Specific Language (DSL) for deploying Azure resources declaratively.",
},
command = "bicep",
args = { "format", "--stdout", "$FILENAME" },
}
conform.nvim-9.1.0/lua/conform/formatters/biome-check.lua 0000664 0000000 0000000 00000000675 15051732407 0023433 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/biomejs/biome",
description = "A toolchain for web projects, aimed to provide functionalities to maintain them.",
},
command = util.from_node_modules("biome"),
stdin = true,
args = { "check", "--write", "--stdin-file-path", "$FILENAME" },
cwd = util.root_file({
"biome.json",
"biome.jsonc",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/biome-organize-imports.lua 0000664 0000000 0000000 00000001054 15051732407 0025657 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/biomejs/biome",
description = "A toolchain for web projects, aimed to provide functionalities to maintain them.",
},
command = util.from_node_modules("biome"),
stdin = true,
args = {
"check",
"--write",
"--formatter-enabled=false",
"--linter-enabled=false",
"--assist-enabled=true",
"--stdin-file-path",
"$FILENAME",
},
cwd = util.root_file({
"biome.json",
"biome.jsonc",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/biome.lua 0000664 0000000 0000000 00000000663 15051732407 0022355 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/biomejs/biome",
description = "A toolchain for web projects, aimed to provide functionalities to maintain them.",
},
command = util.from_node_modules("biome"),
stdin = true,
args = { "format", "--stdin-file-path", "$FILENAME" },
cwd = util.root_file({
"biome.json",
"biome.jsonc",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/black.lua 0000664 0000000 0000000 00000000730 15051732407 0022331 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/psf/black",
description = "The uncompromising Python code formatter.",
},
command = "black",
args = {
"--stdin-filename",
"$FILENAME",
"--quiet",
"-",
},
cwd = util.root_file({
-- https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#configuration-via-a-file
"pyproject.toml",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/blade-formatter.lua 0000664 0000000 0000000 00000000604 15051732407 0024325 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/shufo/blade-formatter",
description = "An opinionated blade template formatter for Laravel that respects readability.",
},
command = "blade-formatter",
args = { "--stdin" },
stdin = true,
cwd = util.root_file({ "composer.json", "composer.lock" }),
}
conform.nvim-9.1.0/lua/conform/formatters/blue.lua 0000664 0000000 0000000 00000000651 15051732407 0022206 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/grantjenks/blue",
description = "The slightly less uncompromising Python code formatter.",
},
command = "blue",
args = {
"--stdin-filename",
"$FILENAME",
"--quiet",
"-",
},
cwd = util.root_file({
"setup.cfg",
"pyproject.toml",
"tox.ini",
".blue",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/bpfmt.lua 0000664 0000000 0000000 00000000404 15051732407 0022363 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://source.android.com/docs/setup/reference/androidbp",
description = "Android Blueprint file formatter.",
},
command = "bpfmt",
args = { "-w", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/bsfmt.lua 0000664 0000000 0000000 00000000437 15051732407 0022374 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/rokucommunity/brighterscript-formatter",
description = "A code formatter for BrighterScript (and BrightScript).",
},
command = "bsfmt",
args = { "$FILENAME", "--write" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/buf.lua 0000664 0000000 0000000 00000000507 15051732407 0022033 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://buf.build/docs/reference/cli/buf/format",
description = "A new way of working with Protocol Buffers.",
},
command = "buf",
args = { "format", "-w", "$FILENAME" },
stdin = false,
cwd = require("conform.util").root_file({ "buf.yaml" }),
}
conform.nvim-9.1.0/lua/conform/formatters/buildifier.lua 0000664 0000000 0000000 00000000477 15051732407 0023403 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/bazelbuild/buildtools/tree/master/buildifier",
description = "buildifier is a tool for formatting bazel BUILD and .bzl files with a standard convention.",
},
command = "buildifier",
args = { "-path", "$FILENAME", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/cabal_fmt.lua 0000664 0000000 0000000 00000000337 15051732407 0023170 0 ustar 00root root 0000000 0000000 return {
meta = {
url = "https://hackage.haskell.org/package/cabal-fmt",
description = "Format cabal files with cabal-fmt.",
},
command = "cabal-fmt",
args = { "--inplace", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/caramel_fmt.lua 0000664 0000000 0000000 00000000362 15051732407 0023530 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://caramel.run/manual/reference/cli/fmt.html",
description = "Format Caramel code.",
},
command = "caramel",
args = { "fmt", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/cbfmt.lua 0000664 0000000 0000000 00000000660 15051732407 0022352 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/lukas-reineke/cbfmt",
description = "A tool to format codeblocks inside markdown and org documents.",
},
command = "cbfmt",
args = { "--write", "--best-effort", "$FILENAME" },
cwd = util.root_file({
-- https://github.com/lukas-reineke/cbfmt#config
".cbfmt.toml",
}),
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/cedar.lua 0000664 0000000 0000000 00000000310 15051732407 0022325 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/cedar-policy/cedar",
description = "Formats cedar policies.",
},
command = "cedar",
args = "format",
}
conform.nvim-9.1.0/lua/conform/formatters/clang-format.lua 0000664 0000000 0000000 00000001216 15051732407 0023627 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://clang.llvm.org/docs/ClangFormat.html",
description = "Tool to format C/C++/… code according to a set of rules and heuristics.",
},
command = "clang-format",
args = { "-assume-filename", "$FILENAME" },
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 {
"-assume-filename",
"$FILENAME",
"--offset",
tostring(start_offset),
"--length",
tostring(length),
}
end,
}
conform.nvim-9.1.0/lua/conform/formatters/clang_format.lua 0000664 0000000 0000000 00000000222 15051732407 0023705 0 ustar 00root root 0000000 0000000 -- This was renamed to clang-format
local conf = vim.deepcopy(require("conform.formatters.clang-format"))
conf.meta.deprecated = true
return conf
conform.nvim-9.1.0/lua/conform/formatters/cljfmt.lua 0000664 0000000 0000000 00000000424 15051732407 0022534 0 ustar 00root root 0000000 0000000 ---@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,
}
conform.nvim-9.1.0/lua/conform/formatters/cljstyle.lua 0000664 0000000 0000000 00000000414 15051732407 0023105 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/greglook/cljstyle",
description = "Formatter for Clojure code.",
},
command = "cljstyle",
args = { "pipe" },
cwd = require("conform.util").root_file({ ".cljstyle" }),
}
conform.nvim-9.1.0/lua/conform/formatters/cmake_format.lua 0000664 0000000 0000000 00000000352 15051732407 0023705 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/cheshirekow/cmake_format",
description = "Parse cmake listfiles and format them nicely.",
},
command = "cmake-format",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/codeql.lua 0000664 0000000 0000000 00000000432 15051732407 0022523 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://docs.github.com/en/code-security/codeql-cli/codeql-cli-manual/query-format",
description = "Format queries and libraries with CodeQL.",
},
command = "codeql",
args = { "query", "format", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/codespell.lua 0000664 0000000 0000000 00000000653 15051732407 0023233 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/codespell-project/codespell",
description = "Check code for common misspellings.",
},
command = "codespell",
stdin = false,
args = {
"$FILENAME",
"--write-changes",
"--check-hidden", -- conform's temp file is hidden
},
exit_codes = { 0, 65 }, -- code 65 is given when trying to format an ambiguous misspelling
}
conform.nvim-9.1.0/lua/conform/formatters/commitmsgfmt.lua 0000664 0000000 0000000 00000000354 15051732407 0023765 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://gitlab.com/mkjeldsen/commitmsgfmt",
description = "Formats commit messages better than fmt(1) and Vim.",
},
command = "commitmsgfmt",
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/crlfmt.lua 0000664 0000000 0000000 00000000414 15051732407 0022543 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/cockroachdb/crlfmt",
description = "Formatter for CockroachDB's additions to the Go style guide.",
},
command = "crlfmt",
args = { "-w", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/crystal.lua 0000664 0000000 0000000 00000000334 15051732407 0022736 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://crystal-lang.org/",
description = "Format Crystal code.",
},
command = "crystal",
args = { "tool", "format", "-" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/csharpier.lua 0000664 0000000 0000000 00000001647 15051732407 0023245 0 ustar 00root root 0000000 0000000 local COMMAND = "dotnet"
local TOOL = "csharpier"
local cache = nil -- For performance
--- Verify if csharpier is installed locally.
---@return boolean
local function is_local()
if cache == nil then
local obj = vim.system({ COMMAND, TOOL, "--version" }):wait()
cache = obj.code == 0
end
return cache
end
--- Get command favoring locally installed csharpier.
---@return string
local function get_command()
if is_local() then
return COMMAND
end
return TOOL
end
--- Get args favoring locally installed csharpier.
---@return string[]
local function get_args()
local args = {}
if is_local() then
table.insert(args, TOOL)
end
table.insert(args, "format")
return args
end
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/belav/csharpier",
description = "The opinionated C# code formatter.",
},
command = get_command,
args = get_args,
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/css_beautify.lua 0000664 0000000 0000000 00000001030 15051732407 0023727 0 ustar 00root root 0000000 0000000 local fs = require("conform.fs")
local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/beautifier/js-beautify",
description = "Beautifier for css.",
},
command = util.from_node_modules(fs.is_windows and "css-beautify.cmd" or "css-beautify"),
args = { "--editorconfig", "--file", "-" },
cwd = util.root_file({
-- https://github.com/beautifier/js-beautify#loading-settings-from-environment-or-jsbeautifyrc-javascript-only
".jsbeautifyrc",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/cue_fmt.lua 0000664 0000000 0000000 00000000334 15051732407 0022677 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://cuelang.org",
description = "Format CUE files using `cue fmt` command.",
},
command = "cue",
args = { "fmt", "-" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/d2.lua 0000664 0000000 0000000 00000000366 15051732407 0021567 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/terrastruct/d2",
description = "D2 is a modern diagram scripting language that turns text to diagrams.",
},
command = "d2",
args = { "fmt", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/darker.lua 0000664 0000000 0000000 00000001566 15051732407 0022535 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/akaihola/darker",
description = "Run black only on changed lines.",
},
command = "darker",
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
return {
"--quiet",
"--no-color",
"--stdout",
"--revision",
"HEAD..:STDIN:",
"--stdin-filename",
"$FILENAME",
}
else
return {
"--quiet",
"--no-color",
"--stdout",
"$FILENAME",
}
end
end,
cwd = util.root_file({
-- https://github.com/akaihola/darker#customizing-darker-black-isort-flynt-and-linter-behavior
"pyproject.toml",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/dart_format.lua 0000664 0000000 0000000 00000000634 15051732407 0023562 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://dart.dev/tools/dart-format",
description = "Replace the whitespace in your program with formatting that follows Dart guidelines.",
},
command = "dart",
args = { "format", "$FILENAME" },
-- Using stdin does not currently work properly, because the formatter will not pick up the analysis_options.yaml file
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/dcm_fix.lua 0000664 0000000 0000000 00000000460 15051732407 0022666 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://dcm.dev/docs/cli/formatting/fix/",
description = "Fixes issues produced by dcm analyze, dcm check-unused-code or dcm check-dependencies commands.",
},
command = "dcm",
args = { "fix", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/dcm_format.lua 0000664 0000000 0000000 00000000404 15051732407 0023366 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://dcm.dev/docs/cli/formatting/format/",
description = "Formats .dart files.",
},
command = "dcm",
args = { "format", "$FILENAME" },
exit_codes = { 0, 2 },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/deno_fmt.lua 0000664 0000000 0000000 00000003043 15051732407 0023050 0 ustar 00root root 0000000 0000000 local log = require("conform.log")
-- Requires `--unstable-component` flag or
-- `"unstable": ["fmt-component]` config option.
-- https://docs.deno.com/runtime/reference/cli/formatter/#formatting-options-unstable-component
local unstable_extensions = {
astro = "astro",
svelte = "svelte",
vue = "vue",
}
local extensions = vim.tbl_extend("keep", {
css = "css",
html = "html",
javascript = "js",
javascriptreact = "jsx",
json = "json",
jsonc = "jsonc",
less = "less",
markdown = "md",
sass = "sass",
scss = "scss",
typescript = "ts",
typescriptreact = "tsx",
yaml = "yml",
}, unstable_extensions)
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://deno.land/manual/tools/formatter",
description = "Use [Deno](https://deno.land/) to format TypeScript, JavaScript/JSON and markdown.",
},
command = "deno",
cond = function(self, ctx)
return extensions[vim.bo[ctx.buf].filetype] ~= nil
end,
args = function(self, ctx)
local extension = extensions[vim.bo[ctx.buf].filetype]
local formatter_args = {
"fmt",
"-",
"--ext",
extension,
}
if unstable_extensions[extension] then
log.info(
"Adding `--unstable-component` to enable formatting of .%s files. See the Deno documentation for more information: https://docs.deno.com/runtime/reference/cli/formatter/#formatting-options-unstable-component",
extension
)
formatter_args = vim.list_extend(formatter_args, { "--unstable-component" })
end
return formatter_args
end,
}
conform.nvim-9.1.0/lua/conform/formatters/dfmt.lua 0000664 0000000 0000000 00000000273 15051732407 0022211 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/dlang-community/dfmt",
description = "Formatter for D source code.",
},
command = "dfmt",
}
conform.nvim-9.1.0/lua/conform/formatters/dioxus.lua 0000664 0000000 0000000 00000000514 15051732407 0022570 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/dioxuslabs/dioxus",
description = "Format `rsx!` snippets in Rust files.",
},
stdin = false,
command = "dx",
args = { "fmt", "--file", "$FILENAME" },
cwd = util.root_file({ "Dioxus.toml" }),
}
conform.nvim-9.1.0/lua/conform/formatters/djlint.lua 0000664 0000000 0000000 00000000600 15051732407 0022535 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/Riverside-Healthcare/djLint",
description = "✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks - Handlebars - GoLang.",
},
command = "djlint",
args = {
"--reformat",
"-",
},
cwd = util.root_file({
".djlintrc",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/docformatter.lua 0000664 0000000 0000000 00000000524 15051732407 0023747 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://pypi.org/project/docformatter/",
description = "docformatter automatically formats docstrings to follow a subset of the PEP 257 conventions.",
},
command = "docformatter",
args = { "--in-place", "$FILENAME" },
stdin = false,
exit_codes = { 0, 3 },
}
conform.nvim-9.1.0/lua/conform/formatters/dockerfmt.lua 0000664 0000000 0000000 00000000307 15051732407 0023233 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/reteps/dockerfmt",
description = "Dockerfile formatter. a modern dockfmt.",
},
command = "dockerfmt",
}
conform.nvim-9.1.0/lua/conform/formatters/docstrfmt.lua 0000664 0000000 0000000 00000000321 15051732407 0023256 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/LilSpazJoekp/docstrfmt",
description = "reStructuredText formatter.",
},
command = "docstrfmt",
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/doctoc.lua 0000664 0000000 0000000 00000000431 15051732407 0022526 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/thlorenz/doctoc",
description = "Generates table of contents for markdown files inside local git repository.",
},
command = "doctoc",
stdin = false,
args = {
"$FILENAME",
},
}
conform.nvim-9.1.0/lua/conform/formatters/dprint.lua 0000664 0000000 0000000 00000000666 15051732407 0022565 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/dprint/dprint",
description = "Pluggable and configurable code formatting platform written in Rust.",
},
command = util.from_node_modules("dprint"),
args = { "fmt", "--stdin", "$FILENAME" },
cwd = util.root_file({
"dprint.json",
".dprint.json",
"dprint.jsonc",
".dprint.jsonc",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/easy-coding-standard.lua 0000664 0000000 0000000 00000000760 15051732407 0025260 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/easy-coding-standard/easy-coding-standard",
description = "ecs - Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer.",
},
command = util.find_executable({
"vendor/bin/ecs",
}, "ecs"),
args = { "check", "$FILENAME", "--fix", "--no-interaction" },
cwd = util.root_file({
"ecs.php",
}),
require_cwd = true,
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/efmt.lua 0000664 0000000 0000000 00000000314 15051732407 0022206 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/sile/efmt",
description = "Erlang code formatter.",
},
command = "efmt",
args = { "-" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/elm_format.lua 0000664 0000000 0000000 00000000517 15051732407 0023405 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/avh4/elm-format",
description = "elm-format formats Elm source code according to a standard set of rules based on the official [Elm Style Guide](https://elm-lang.org/docs/style-guide).",
},
command = "elm-format",
args = { "--stdin" },
}
conform.nvim-9.1.0/lua/conform/formatters/erb_format.lua 0000664 0000000 0000000 00000000350 15051732407 0023373 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/nebulab/erb-formatter",
description = "Format ERB files with speed and precision.",
},
command = "erb-format",
args = { "--stdin" },
}
conform.nvim-9.1.0/lua/conform/formatters/erlfmt.lua 0000664 0000000 0000000 00000000364 15051732407 0022551 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/WhatsApp/erlfmt",
description = "An automated code formatter for Erlang.",
},
command = "erlfmt",
args = { "-w", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/eslint_d.lua 0000664 0000000 0000000 00000000567 15051732407 0023066 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/mantoni/eslint_d.js/",
description = "Like ESLint, but faster.",
},
command = util.from_node_modules("eslint_d"),
args = { "--fix-to-stdout", "--stdin", "--stdin-filename", "$FILENAME" },
cwd = util.root_file({
"package.json",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/fantomas.lua 0000664 0000000 0000000 00000000346 15051732407 0023070 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/fsprojects/fantomas",
description = "F# source code formatter.",
},
command = "fantomas",
args = { "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/findent.lua 0000664 0000000 0000000 00000000331 15051732407 0022701 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/wvermin/findent",
description = "Indent, relabel and convert Fortran sources.",
},
command = "findent",
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/fish_indent.lua 0000664 0000000 0000000 00000000351 15051732407 0023546 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://fishshell.com/docs/current/cmds/fish_indent.html",
description = "Indent or otherwise prettify a piece of fish code.",
},
command = "fish_indent",
}
conform.nvim-9.1.0/lua/conform/formatters/fixjson.lua 0000664 0000000 0000000 00000000307 15051732407 0022735 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/rhysd/fixjson",
description = "JSON Fixer for Humans using (relaxed) JSON5.",
},
command = "fixjson",
}
conform.nvim-9.1.0/lua/conform/formatters/fnlfmt.lua 0000664 0000000 0000000 00000000314 15051732407 0022541 0 ustar 00root root 0000000 0000000 --@type conform.FileFormatterConfig
return {
meta = {
url = "https://git.sr.ht/~technomancy/fnlfmt",
description = "A formatter for Fennel code.",
},
command = "fnlfmt",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/forge_fmt.lua 0000664 0000000 0000000 00000000474 15051732407 0023232 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/foundry-rs/foundry",
description = "Forge is a command-line tool that ships with Foundry. Forge tests, builds, and deploys your smart contracts.",
},
command = "forge",
args = { "fmt", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/format-dune-file.lua 0000664 0000000 0000000 00000000344 15051732407 0024414 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/ocaml/dune",
description = "Auto-formatter for Dune files.",
},
command = "dune",
args = { "format-dune-file" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/format-queries.lua 0000664 0000000 0000000 00000001674 15051732407 0024230 0 ustar 00root root 0000000 0000000 ---@return nil|string
local function get_format_script()
return vim.api.nvim_get_runtime_file("scripts/format-queries.lua", false)[1]
end
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/nvim-treesitter/nvim-treesitter/blob/main/CONTRIBUTING.md#formatting",
description = "Tree-sitter query formatter.",
},
condition = function()
local ok = pcall(vim.treesitter.language.inspect, "query")
return ok and pcall(require, "nvim-treesitter") and get_format_script() ~= nil
end,
command = "nvim",
args = function()
local script = get_format_script()
assert(script)
-- Manually set the runtimepath to put nvim-treesitter first. The format-queries script relies
-- on the nvim-treesitter parser; the one bundled with Neovim may be outdated.
local rtp = vim.fn.fnamemodify(script, ":h:h")
return { "-c", "set rtp^=" .. rtp, "-l", script, "$FILENAME" }
end,
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/fourmolu.lua 0000664 0000000 0000000 00000000475 15051732407 0023133 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://hackage.haskell.org/package/fourmolu",
description = "A fork of ormolu that uses four space indentation and allows arbitrary configuration.",
},
command = "fourmolu",
args = { "--stdin-input-file", "$FILENAME" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/fprettify.lua 0000664 0000000 0000000 00000000624 15051732407 0023273 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/fortran-lang/fprettify",
description = "Auto-formatter for modern fortran source code.",
},
command = "fprettify",
args = {
-- --silent is recommended for editor integrations https://github.com/fortran-lang/fprettify?tab=readme-ov-file#editor-integration
"--silent",
"-",
},
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/gawk.lua 0000664 0000000 0000000 00000000347 15051732407 0022212 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://www.gnu.org/software/gawk/manual/gawk.html",
description = "Format awk programs with gawk.",
},
command = "gawk",
args = { "-f", "-", "-o-" },
}
conform.nvim-9.1.0/lua/conform/formatters/gci.lua 0000664 0000000 0000000 00000000504 15051732407 0022016 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/daixiang0/gci",
description = "GCI, a tool that controls Go package import order and makes it always deterministic.",
},
command = "gci",
args = { "write", "--skip-generated", "--skip-vendor", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/gdformat.lua 0000664 0000000 0000000 00000000336 15051732407 0023062 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/Scony/godot-gdscript-toolkit",
description = "A formatter for Godot's gdscript.",
},
command = "gdformat",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/gersemi.lua 0000664 0000000 0000000 00000000503 15051732407 0022706 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/BlankSpruce/gersemi",
description = "A formatter to make your CMake code the real treasure.",
},
command = "gersemi",
args = { "--quiet", "-" },
cwd = util.root_file({ ".gersemirc" }),
}
conform.nvim-9.1.0/lua/conform/formatters/ghdl.lua 0000664 0000000 0000000 00000000404 15051732407 0022171 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://ghdl.github.io/ghdl/",
description = "Open-source analyzer, compiler, simulator and synthesizer for VHDL.",
},
command = "ghdl",
args = { "fmt", "--std=08", "$FILENAME" },
}
conform.nvim-9.1.0/lua/conform/formatters/ghokin.lua 0000664 0000000 0000000 00000000372 15051732407 0022536 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/antham/ghokin",
description = "Parallelized formatter with no external dependencies for gherkin.",
},
command = "ghokin",
args = { "fmt", "stdout" },
}
conform.nvim-9.1.0/lua/conform/formatters/gleam.lua 0000664 0000000 0000000 00000000402 15051732407 0022336 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/gleam-lang/gleam",
description = "⭐️ A friendly language for building type-safe, scalable systems!",
},
command = "gleam",
args = { "format", "--stdin" },
}
conform.nvim-9.1.0/lua/conform/formatters/gluon_fmt.lua 0000664 0000000 0000000 00000000401 15051732407 0023242 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/gluon-lang/gluon",
description = "Code formatting for the gluon programming language.",
},
command = "gluon",
args = { "fmt", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/gn.lua 0000664 0000000 0000000 00000000307 15051732407 0021661 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://gn.googlesource.com/gn/",
description = "gn build system.",
},
command = "gn",
args = { "format", "--stdin" },
}
conform.nvim-9.1.0/lua/conform/formatters/gofmt.lua 0000664 0000000 0000000 00000000251 15051732407 0022367 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://pkg.go.dev/cmd/gofmt",
description = "Formats go programs.",
},
command = "gofmt",
}
conform.nvim-9.1.0/lua/conform/formatters/gofumpt.lua 0000664 0000000 0000000 00000000463 15051732407 0022741 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/mvdan/gofumpt",
description = "Enforce a stricter format than gofmt, while being backwards compatible. That is, gofumpt is happy with a subset of the formats that gofmt is happy with.",
},
command = "gofumpt",
}
conform.nvim-9.1.0/lua/conform/formatters/goimports-reviser.lua 0000664 0000000 0000000 00000000454 15051732407 0024760 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/incu6us/goimports-reviser",
description = "Right imports sorting & code formatting tool (goimports alternative).",
},
command = "goimports-reviser",
args = { "-format", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/goimports.lua 0000664 0000000 0000000 00000000445 15051732407 0023303 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://pkg.go.dev/golang.org/x/tools/cmd/goimports",
description = "Updates your Go import lines, adding missing ones and removing unreferenced ones.",
},
command = "goimports",
args = { "-srcdir", "$DIRNAME" },
}
conform.nvim-9.1.0/lua/conform/formatters/gojq.lua 0000664 0000000 0000000 00000000264 15051732407 0022217 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/itchyny/gojq",
description = "Pure Go implementation of jq.",
},
command = "gojq",
}
conform.nvim-9.1.0/lua/conform/formatters/golangci-lint.lua 0000664 0000000 0000000 00000000376 15051732407 0024012 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://golangci-lint.run/usage/configuration/#fmt",
description = "Fast linters runner for Go (with formatter).",
},
command = "golangci-lint",
args = { "fmt", "--stdin" },
}
conform.nvim-9.1.0/lua/conform/formatters/golines.lua 0000664 0000000 0000000 00000000310 15051732407 0022707 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/segmentio/golines",
description = "A golang formatter that fixes long lines.",
},
command = "golines",
}
conform.nvim-9.1.0/lua/conform/formatters/google-java-format.lua 0000664 0000000 0000000 00000000376 15051732407 0024744 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/google/google-java-format",
description = "Reformats Java source code according to Google Java Style.",
},
command = "google-java-format",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/grain_format.lua 0000664 0000000 0000000 00000000431 15051732407 0023723 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://grain-lang.org/docs/tooling/grain_cli#grain-format",
description = "Code formatter for the grain programming language.",
},
command = "grain",
args = { "format", "$FILENAME" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/hcl.lua 0000664 0000000 0000000 00000000264 15051732407 0022025 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/hashicorp/hcl",
description = "A formatter for HCL files.",
},
command = "hclfmt",
}
conform.nvim-9.1.0/lua/conform/formatters/hindent.lua 0000664 0000000 0000000 00000000345 15051732407 0022710 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/mihaimaruseac/hindent",
description = "Haskell pretty printer.",
},
command = "hindent",
args = { "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/hledger-fmt.lua 0000664 0000000 0000000 00000000404 15051732407 0023451 0 ustar 00root root 0000000 0000000 --@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/mondeja/hledger-fmt",
description = "An opinionated hledger's journal files formatter.",
},
command = "hledger-fmt",
args = { "--no-diff", "-" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/html_beautify.lua 0000664 0000000 0000000 00000001033 15051732407 0024106 0 ustar 00root root 0000000 0000000 local fs = require("conform.fs")
local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/beautifier/js-beautify",
description = "Beautifier for html.",
},
command = util.from_node_modules(fs.is_windows and "html-beautify.cmd" or "html-beautify"),
args = { "--editorconfig", "--file", "-" },
cwd = util.root_file({
-- https://github.com/beautifier/js-beautify#loading-settings-from-environment-or-jsbeautifyrc-javascript-only
".jsbeautifyrc",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/htmlbeautifier.lua 0000664 0000000 0000000 00000000433 15051732407 0024261 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/threedaymonk/htmlbeautifier",
description = "A normaliser/beautifier for HTML that also understands embedded Ruby. Ideal for tidying up Rails templates.",
},
command = "htmlbeautifier",
}
conform.nvim-9.1.0/lua/conform/formatters/hurlfmt.lua 0000664 0000000 0000000 00000000237 15051732407 0022740 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://hurl.dev/",
description = "Formats hurl files.",
},
command = "hurlfmt",
}
conform.nvim-9.1.0/lua/conform/formatters/imba_fmt.lua 0000664 0000000 0000000 00000000451 15051732407 0023033 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://imba.io/",
description = "Code formatter for the Imba programming language.",
},
command = "imba",
stdin = false,
-- `-f` is used to ignore the git status of the file.
args = { "fmt", "-f", "$FILENAME" },
}
conform.nvim-9.1.0/lua/conform/formatters/indent.lua 0000664 0000000 0000000 00000000271 15051732407 0022536 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://www.gnu.org/software/indent/",
description = "GNU Indent.",
},
command = "indent",
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/init.lua 0000664 0000000 0000000 00000002244 15051732407 0022222 0 ustar 00root root 0000000 0000000 local M = {}
local uv = vim.uv or vim.loop
---@private
---This is used for documentation generation
M.list_all_formatters = function()
local ret = {}
for path in vim.gsplit(vim.o.runtimepath, ",", { plain = true }) do
local formatter_path = path .. "/lua/conform/formatters"
local formatter_dir = uv.fs_opendir(formatter_path)
if formatter_dir then
local entries = uv.fs_readdir(formatter_dir)
while entries do
for _, entry in ipairs(entries) do
if entry.name ~= "init.lua" then
local basename = string.match(entry.name, "^(.*)%.lua$")
local module = require("conform.formatters." .. basename)
local module_data = vim.deepcopy(module.meta)
module_data.has_options = module.options ~= nil
ret[basename] = module_data
end
end
entries = uv.fs_readdir(formatter_dir)
end
uv.fs_closedir(formatter_dir)
end
end
return ret
end
-- A little metatable magic to allow accessing formatters like
-- require("conform.formatters").prettier
return setmetatable(M, {
__index = function(_, k)
return require("conform.formatters." .. k)
end,
})
conform.nvim-9.1.0/lua/conform/formatters/injected.lua 0000664 0000000 0000000 00000033666 15051732407 0023060 0 ustar 00root root 0000000 0000000 ---@param range? conform.Range
---@param start_lnum integer
---@param end_lnum integer
---@return boolean
local function in_range(range, start_lnum, end_lnum)
return not range or (start_lnum <= range["end"][1] and range["start"][1] <= end_lnum)
end
---@param language? string
local function prefix_pattern(language)
-- Handle markdown code blocks that are inside blockquotes
-- > ```lua
-- > local x = 1
-- > ```
return language == "markdown" and "^>?%s*" or "^%s*"
end
---@param lines string[]
---@param language? string The language of the buffer
---@return string?
local function get_indent(lines, language)
local indent = nil
local pattern = prefix_pattern(language)
for _, line in ipairs(lines) do
if line ~= "" then
local whitespace = line:match(pattern)
if whitespace == "" then
return nil
elseif not indent or whitespace:len() < indent:len() then
indent = whitespace
end
end
end
return indent
end
---@param root_lang string
---@param lang string
---@return boolean
local function include_language_tree(root_lang, lang)
-- We should not attempt to format html inside markdown
-- See https://github.com/stevearc/conform.nvim/issues/485
if root_lang == "markdown" and lang == "html" then
return false
end
-- Don't format the root language with the injected formatter
return root_lang ~= lang
end
---@class (exact) conform.Injected.Surrounding
---@field indent string?
---@field postfix string?
---Remove leading indentation from lines and return the indentation string
---@param lines string[]
---@param language? string The language of the buffer
---@return conform.Injected.Surrounding
local function remove_surrounding(lines, language)
local surrounding = {}
if lines[#lines]:match("^%s*$") then
surrounding.postfix = lines[#lines]
table.remove(lines)
end
local indent = get_indent(lines, language)
if not indent then
return surrounding
end
local sub_start = indent:len() + 1
for i, line in ipairs(lines) do
if line ~= "" then
lines[i] = line:sub(sub_start)
end
end
surrounding.indent = indent
return surrounding
end
---@param lines string[]?
---@param surrounding conform.Injected.Surrounding
local function restore_surrounding(lines, surrounding)
if not lines then
return
end
local indent = surrounding.indent
if indent then
for i, line in ipairs(lines) do
if line ~= "" then
lines[i] = indent .. line
end
end
end
local postfix = surrounding.postfix
if postfix then
table.insert(lines, postfix)
end
end
---Merge adjacent ranges that have the same language and share a prefix
---@param regions LangRange[]
---@param bufnr integer
---@param buf_lang? string
---@return LangRange[]
local function merge_ranges_with_prefix(regions, bufnr, buf_lang)
local ret = {}
local last_range = nil
local accum = {}
local function append_accum()
if #accum == 0 then
return
end
local lines = vim.api.nvim_buf_get_lines(bufnr, accum[1][2] - 1, accum[#accum][4], true)
local prefix = get_indent(lines, buf_lang)
if prefix then
local new_range = {
accum[1][1],
accum[1][2],
accum[1][3],
accum[#accum][4],
accum[#accum][5],
}
table.insert(ret, new_range)
else
vim.list_extend(ret, accum)
end
accum = {}
end
for _, range in ipairs(regions) do
if not last_range or range[1] ~= last_range[1] or range[2] ~= last_range[4] then
-- This is a new region entirely; new language, or not contiguous
append_accum()
accum = {}
end
table.insert(accum, range)
last_range = range
end
append_accum()
return ret
end
---@class (exact) LangRange
---@field [1] string language
---@field [2] integer start lnum
---@field [3] integer start col
---@field [4] integer end lnum
---@field [5] integer end col
---@param ranges LangRange[]
---@param range LangRange
local function accum_range(ranges, range)
local last_range = ranges[#ranges]
if last_range then
if last_range[1] == range[1] and last_range[4] == range[2] and last_range[5] == range[3] then
last_range[4] = range[4]
last_range[5] = range[5]
return
end
end
table.insert(ranges, range)
end
---@class (exact) conform.InjectedFormatterOptions
---@field ignore_errors boolean
---@field lang_to_ext table
---@field lang_to_ft table
---@field lang_to_formatters table
---@type conform.FileLuaFormatterConfig
return {
meta = {
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,
-- Map of treesitter language to filetype
lang_to_ft = {
bash = "sh",
},
-- Map of treesitter language to file extension
-- A temporary file name with this extension will be generated during formatting
-- because some formatters care about the filename.
lang_to_ext = {
bash = "sh",
c_sharp = "cs",
elixir = "exs",
javascript = "js",
julia = "jl",
latex = "tex",
markdown = "md",
python = "py",
ruby = "rb",
rust = "rs",
teal = "tl",
typescript = "ts",
},
-- Map of treesitter language to formatters to use
-- (defaults to the value from formatters_by_ft)
lang_to_formatters = {},
},
condition = function(self, ctx)
local buf_lang = vim.treesitter.language.get_lang(vim.bo[ctx.buf].filetype)
local ok = pcall(vim.treesitter.get_string_parser, "", buf_lang)
return ok
end,
format = function(self, ctx, lines, callback)
local conform = require("conform")
local errors = require("conform.errors")
local log = require("conform.log")
local util = require("conform.util")
-- Need to add a trailing newline; some parsers need this.
-- For example, if a markdown code block ends at the end of the file, a trailing newline is
-- required otherwise the ``` will be grabbed as part of the injected block
local text = table.concat(lines, "\n") .. "\n"
local buf_lang = vim.treesitter.language.get_lang(vim.bo[ctx.buf].filetype)
local ok, parser = pcall(vim.treesitter.get_string_parser, text, buf_lang)
if not ok then
callback("No treesitter parser for buffer")
return
end
local options = self.options
---@cast options conform.InjectedFormatterOptions
---@param lang string
---@return nil|conform.FiletypeFormatter
local function get_formatters(lang)
local ft = options.lang_to_ft[lang] or lang
return options.lang_to_formatters[ft] or conform.formatters_by_ft[ft]
end
--- Disable diagnostic to pass the typecheck github action
--- This is available on nightly, but not on stable
--- Stable doesn't have any parameters, so it's safe
---@diagnostic disable-next-line: redundant-parameter
parser:parse(true)
local root_lang = parser:lang()
---@type LangRange[]
local regions = {}
for lang, lang_tree in pairs(parser:children()) do
if include_language_tree(root_lang, lang) then
for _, ranges in ipairs(lang_tree:included_regions()) do
for _, region in ipairs(ranges) do
local formatters = get_formatters(lang)
if formatters == nil then
log.info("No formatters found for injected treesitter language %s", lang)
else
-- The types are wrong. included_regions should be Range[][] not integer[][]
---@diagnostic disable-next-line: param-type-mismatch
local start_row, start_col, _, end_row, end_col, _ = unpack(region)
accum_range(regions, { lang, start_row + 1, start_col, end_row + 1, end_col })
end
end
end
end
end
regions = merge_ranges_with_prefix(regions, ctx.buf, buf_lang)
if ctx.range then
regions = vim.tbl_filter(function(region)
return in_range(ctx.range, region[2], region[4])
end, regions)
end
-- Sort from largest start_lnum to smallest
table.sort(regions, function(a, b)
return a[2] > b[2]
end)
log.trace("Injected formatter regions %s", regions)
local replacements = {}
local format_error = nil
local function apply_format_results()
if format_error then
-- Find all of the conform errors in the replacements table and remove them
local i = 1
while i <= #replacements do
if replacements[i].code then
table.remove(replacements, i)
else
i = i + 1
end
end
if options.ignore_errors then
format_error = nil
end
end
local formatted_lines = vim.deepcopy(lines)
for _, replacement in ipairs(replacements) do
local start_lnum, start_col, end_lnum, end_col, new_lines = unpack(replacement)
local prefix = formatted_lines[start_lnum]:sub(1, start_col)
local suffix = formatted_lines[end_lnum]:sub(end_col + 1)
new_lines[1] = prefix .. new_lines[1]
new_lines[#new_lines] = new_lines[#new_lines] .. suffix
for _ = start_lnum, end_lnum do
table.remove(formatted_lines, start_lnum)
end
for i = #new_lines, 1, -1 do
table.insert(formatted_lines, start_lnum, new_lines[i])
end
end
callback(format_error, formatted_lines)
end
local num_format = 0
local tmp_bufs = {}
local formatter_cb = function(err, idx, region, input_lines, new_lines)
if err then
format_error = errors.coalesce(format_error, err)
replacements[idx] = err
else
-- If the original lines started/ended with a newline, preserve that newline.
-- Many formatters will trim them, but they're important for the document structure.
if input_lines[1] == "" and new_lines[1] ~= "" then
table.insert(new_lines, 1, "")
end
if input_lines[#input_lines] == "" and new_lines[#new_lines] ~= "" then
table.insert(new_lines, "")
end
replacements[idx] = { region[2], region[3], region[4], region[5], new_lines }
end
num_format = num_format - 1
if num_format == 0 then
for buf in pairs(tmp_bufs) do
vim.api.nvim_buf_delete(buf, { force = true })
end
apply_format_results()
end
end
local last_start_lnum = #lines + 1
for i, region in ipairs(regions) do
local lang = region[1]
local start_lnum = region[2]
local start_col = region[3]
local end_lnum = region[4]
local end_col = region[5]
-- Ignore regions that overlap (contain) other regions
if end_lnum < last_start_lnum then
num_format = num_format + 1
last_start_lnum = start_lnum
local input_lines = util.tbl_slice(lines, start_lnum, end_lnum)
input_lines[#input_lines] = input_lines[#input_lines]:sub(1, end_col)
if start_col > 0 then
local prefix = input_lines[1]:sub(0, start_col)
if prefix:match(prefix_pattern(buf_lang)) == prefix then
-- The first line in the range doesn't start at col 0, but the text on that line before
-- it is just indentation nothing semantic.
-- Update the range to include the indentation so that remove_surrounding() below can
-- consider it as part of the indentation for the entire block.
region[3] = 0
else
input_lines[1] = input_lines[1]:sub(start_col + 1)
end
end
local ft_formatters = assert(get_formatters(lang))
---@type string[]
local formatter_names
if type(ft_formatters) == "function" then
ft_formatters = ft_formatters(ctx.buf)
end
local stop_after_first = ft_formatters.stop_after_first
if stop_after_first == nil then
stop_after_first = conform.default_format_opts.stop_after_first
end
if stop_after_first == nil then
stop_after_first = false
end
local formatters =
conform.resolve_formatters(ft_formatters, ctx.buf, false, stop_after_first)
formatter_names = vim.tbl_map(function(f)
return f.name
end, formatters)
local idx = num_format
log.debug("Injected format %s:%d:%d: %s", lang, start_lnum, end_lnum, formatter_names)
log.trace("Injected format lines %s", input_lines)
local surrounding = remove_surrounding(input_lines, buf_lang)
-- Create a temporary buffer. This is only needed because some formatters rely on the file
-- extension to determine a run mode (see https://github.com/stevearc/conform.nvim/issues/194)
-- This is using lang_to_ext to map the language name to the file extension, and falls back
-- to using the language name itself.
local extension = options.lang_to_ext[lang] or lang
local buf =
vim.fn.bufadd(string.format("%s.%d.%s", vim.api.nvim_buf_get_name(ctx.buf), i, extension))
vim.bo[buf].swapfile = false
-- Actually load the buffer to set the buffer context which is required by some formatters such as `filetype`
vim.fn.bufload(buf)
tmp_bufs[buf] = true
local format_opts = { async = true, bufnr = buf, quiet = true }
conform.format_lines(formatter_names, input_lines, format_opts, function(err, new_lines)
log.trace("Injected %s:%d:%d formatted lines %s", lang, start_lnum, end_lnum, new_lines)
-- Preserve indentation in case the code block is indented
restore_surrounding(new_lines, surrounding)
vim.schedule_wrap(formatter_cb)(err, idx, region, input_lines, new_lines)
end)
end
end
if num_format == 0 then
apply_format_results()
end
end,
-- TODO this is kind of a hack. It's here to ensure all_support_range_formatting is set properly.
-- Should figure out a better way to do this.
range_args = true,
}
conform.nvim-9.1.0/lua/conform/formatters/inko.lua 0000664 0000000 0000000 00000000342 15051732407 0022214 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://inko-lang.org/",
description = "A language for building concurrent software with confidence",
},
command = "inko",
args = { "fmt", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/isort.lua 0000664 0000000 0000000 00000001273 15051732407 0022420 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/PyCQA/isort",
description = "Python utility / library to sort imports alphabetically and automatically separate them into sections and by type.",
},
command = "isort",
args = function(self, ctx)
return {
"--stdout",
"--line-ending",
util.buf_line_ending(ctx.buf),
"--filename",
"$FILENAME",
"-",
}
end,
cwd = util.root_file({
-- https://pycqa.github.io/isort/docs/configuration/config_files.html
".isort.cfg",
"pyproject.toml",
"setup.py",
"setup.cfg",
"tox.ini",
".editorconfig",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/janet-format.lua 0000664 0000000 0000000 00000000315 15051732407 0023643 0 ustar 00root root 0000000 0000000 --@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/janet-lang/spork",
description = "A formatter for Janet code.",
},
command = "janet-format",
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/joker.lua 0000664 0000000 0000000 00000000363 15051732407 0022371 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/candid82/joker",
description = "Small Clojure interpreter, linter and formatter.",
},
command = "joker",
args = { "--format", "--write", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/jq.lua 0000664 0000000 0000000 00000000260 15051732407 0021665 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/stedolan/jq",
description = "Command-line JSON processor.",
},
command = "jq",
}
conform.nvim-9.1.0/lua/conform/formatters/js_beautify.lua 0000664 0000000 0000000 00000001035 15051732407 0023560 0 ustar 00root root 0000000 0000000 local fs = require("conform.fs")
local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/beautifier/js-beautify",
description = "Beautifier for javascript.",
},
command = util.from_node_modules(fs.is_windows and "js-beautify.cmd" or "js-beautify"),
args = { "--editorconfig", "--file", "-" },
cwd = util.root_file({
-- https://github.com/beautifier/js-beautify#loading-settings-from-environment-or-jsbeautifyrc-javascript-only
".jsbeautifyrc",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/jsonnetfmt.lua 0000664 0000000 0000000 00000000431 15051732407 0023442 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/google/go-jsonnet/tree/master/cmd/jsonnetfmt",
description = "jsonnetfmt is a command line tool to format jsonnet files.",
},
command = "jsonnetfmt",
args = { "-" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/just.lua 0000664 0000000 0000000 00000000310 15051732407 0022234 0 ustar 00root root 0000000 0000000 return {
meta = {
url = "https://github.com/casey/just",
description = "Format Justfile.",
},
command = "just",
args = { "--fmt", "--unstable", "-f", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/kcl.lua 0000664 0000000 0000000 00000000436 15051732407 0022031 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://www.kcl-lang.io/docs/tools/cli/kcl/fmt",
description = "The KCL Format tool modifies the files according to the KCL code style.",
},
command = "kcl",
args = { "fmt", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/kdlfmt.lua 0000664 0000000 0000000 00000000346 15051732407 0022541 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/hougesen/kdlfmt",
description = "A formatter for kdl documents.",
},
command = "kdlfmt",
args = { "format", "-" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/keep-sorted.lua 0000664 0000000 0000000 00000000432 15051732407 0023476 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/google/keep-sorted",
description = "keep-sorted is a language-agnostic formatter that sorts lines between two markers in a larger file.",
},
command = "keep-sorted",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/ktfmt.lua 0000664 0000000 0000000 00000000402 15051732407 0022376 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/facebook/ktfmt",
description = "Reformats Kotlin source code to comply with the common community standard conventions.",
},
command = "ktfmt",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/ktlint.lua 0000664 0000000 0000000 00000000406 15051732407 0022562 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://ktlint.github.io/",
description = "An anti-bikeshedding Kotlin linter with built-in formatter.",
},
command = "ktlint",
args = { "--format", "--stdin", "--log-level=none" },
}
conform.nvim-9.1.0/lua/conform/formatters/kulala-fmt.lua 0000664 0000000 0000000 00000000427 15051732407 0023315 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/mistweaverco/kulala-fmt",
description = "An opinionated .http and .rest files linter and formatter.",
},
command = "kulala-fmt",
args = { "format", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/latexindent.lua 0000664 0000000 0000000 00000000641 15051732407 0023575 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/cmhughes/latexindent.pl",
description = "A perl script for formatting LaTeX files that is generally included in major TeX distributions.",
},
command = "latexindent",
args = { "-" },
range_args = function(_, ctx)
return { "--lines", ctx.range.start[1] .. "-" .. ctx.range["end"][1], "-" }
end,
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/leptosfmt.lua 0000664 0000000 0000000 00000000340 15051732407 0023267 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/bram209/leptosfmt",
description = "A formatter for the Leptos view! macro.",
},
command = "leptosfmt",
args = { "--stdin" },
}
conform.nvim-9.1.0/lua/conform/formatters/liquidsoap-prettier.lua 0000664 0000000 0000000 00000000510 15051732407 0025257 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/savonet/liquidsoap-prettier",
description = "A binary to format Liquidsoap scripts",
},
command = util.from_node_modules("liquidsoap-prettier"),
args = { "-w", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/llf.lua 0000664 0000000 0000000 00000000302 15051732407 0022025 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://repo.or.cz/llf.git",
description = "A LaTeX reformatter / beautifier.",
},
command = "llf",
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/lua-format.lua 0000664 0000000 0000000 00000000313 15051732407 0023321 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/Koihik/LuaFormatter",
description = "Code formatter for Lua.",
},
command = "lua-format",
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/mago_format.lua 0000664 0000000 0000000 00000000476 15051732407 0023557 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/carthage-software/mago",
description = "Mago is a toolchain for PHP that aims to provide a set of tools to help developers write better code.",
},
command = "mago",
stdin = true,
args = { "format", "--stdin-input" },
}
conform.nvim-9.1.0/lua/conform/formatters/mago_lint.lua 0000664 0000000 0000000 00000000516 15051732407 0023230 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/carthage-software/mago",
description = "Mago is a toolchain for PHP that aims to provide a set of tools to help developers write better code.",
},
command = "mago",
stdin = false,
args = { "lint", "--fix", "--format", "$FILENAME" },
}
conform.nvim-9.1.0/lua/conform/formatters/markdown-toc.lua 0000664 0000000 0000000 00000001101 15051732407 0023653 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/jonschlinkert/markdown-toc",
description = "API and CLI for generating a markdown TOC (table of contents) for a README or any markdown files.",
},
command = "markdown-toc",
stdin = false,
args = function(_, 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(ctx.shiftwidth) or "\t"
return { "--indent=" .. indent, "-i", "$FILENAME" }
end,
}
conform.nvim-9.1.0/lua/conform/formatters/markdownfmt.lua 0000664 0000000 0000000 00000000303 15051732407 0023602 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/shurcooL/markdownfmt",
description = "Like gofmt, but for Markdown.",
},
command = "markdownfmt",
}
conform.nvim-9.1.0/lua/conform/formatters/markdownlint-cli2.lua 0000664 0000000 0000000 00000000724 15051732407 0024620 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/DavidAnson/markdownlint-cli2",
description = "A fast, flexible, configuration-based command-line interface for linting Markdown/CommonMark files with the markdownlint library.",
},
command = "markdownlint-cli2",
args = { "--fix", "$FILENAME" },
exit_codes = { 0, 1 }, -- code 1 is returned when linting/formatter was successful and there were errors
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/markdownlint.lua 0000664 0000000 0000000 00000000606 15051732407 0023770 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/DavidAnson/markdownlint",
description = "A Node.js style checker and lint tool for Markdown/CommonMark files.",
},
command = "markdownlint",
args = { "--fix", "$FILENAME" },
exit_codes = { 0, 1 }, -- code 1 is given when trying a file that includes non-autofixable errors
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/mdformat.lua 0000664 0000000 0000000 00000000333 15051732407 0023065 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/executablebooks/mdformat",
description = "An opinionated Markdown formatter.",
},
command = "mdformat",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/mdsf.lua 0000664 0000000 0000000 00000000415 15051732407 0022206 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/hougesen/mdsf",
description = "Format markdown code blocks using your favorite code formatters.",
},
command = "mdsf",
args = { "format", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/mdslw.lua 0000664 0000000 0000000 00000000356 15051732407 0022407 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/razziel89/mdslw",
description = "Prepare your markdown for easy diff'ing by adding line breaks after every sentence.",
},
command = "mdslw",
}
conform.nvim-9.1.0/lua/conform/formatters/mix.lua 0000664 0000000 0000000 00000000527 15051732407 0022056 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://hexdocs.pm/mix/main/Mix.Tasks.Format.html",
description = "Format Elixir files using the mix format command.",
},
command = "mix",
args = { "format", "--stdin-filename", "$FILENAME", "-" },
cwd = require("conform.util").root_file({
"mix.exs",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/mojo_format.lua 0000664 0000000 0000000 00000000417 15051732407 0023573 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://docs.modular.com/mojo/cli/format",
description = "Official Formatter for The Mojo Programming Language",
},
command = "mojo",
args = { "format", "-q", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/nginxfmt.lua 0000664 0000000 0000000 00000000433 15051732407 0023107 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/slomkowski/nginx-config-formatter",
description = "nginx config file formatter/beautifier written in Python with no additional dependencies.",
},
command = "nginxfmt",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/nickel.lua 0000664 0000000 0000000 00000000372 15051732407 0022524 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://nickel-lang.org/",
description = "Code formatter for the Nickel programming language.",
},
command = "nickel",
stdin = false,
args = { "format", "$FILENAME" },
}
conform.nvim-9.1.0/lua/conform/formatters/nimpretty.lua 0000664 0000000 0000000 00000000427 15051732407 0023313 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/nim-lang/nim",
description = "nimpretty is a Nim source code beautifier that follows the official style guide.",
},
command = "nimpretty",
args = { "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/nixfmt.lua 0000664 0000000 0000000 00000000322 15051732407 0022557 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/NixOS/nixfmt",
description = "The official (but not yet stable) formatter for Nix code.",
},
command = "nixfmt",
}
conform.nvim-9.1.0/lua/conform/formatters/nixpkgs_fmt.lua 0000664 0000000 0000000 00000000333 15051732407 0023605 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/nix-community/nixpkgs-fmt",
description = "nixpkgs-fmt is a Nix code formatter for nixpkgs.",
},
command = "nixpkgs-fmt",
}
conform.nvim-9.1.0/lua/conform/formatters/nomad_fmt.lua 0000664 0000000 0000000 00000000462 15051732407 0023223 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://developer.hashicorp.com/nomad/docs/commands/fmt",
description = "The fmt commands check the syntax and rewrites Nomad configuration and jobspec files to canonical format.",
},
command = "nomad",
args = { "fmt", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/nph.lua 0000664 0000000 0000000 00000000341 15051732407 0022040 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/arnetheduck/nph",
description = "An opinionated code formatter for Nim.",
},
command = "nph",
stdin = true,
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/npm-groovy-lint.lua 0000664 0000000 0000000 00000000735 15051732407 0024343 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/nvuillam/npm-groovy-lint",
description = "Lint, format and auto-fix your Groovy / Jenkinsfile / Gradle files using command line.",
},
command = "npm-groovy-lint",
args = { "--fix", "$FILENAME" },
-- https://github.com/nvuillam/npm-groovy-lint/blob/14e2649ff7ca642dba3e901c17252b178bea8b1b/lib/groovy-lint.js#L48
exit_codes = { 0, 1 }, -- 1 = expected error
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/nufmt.lua 0000664 0000000 0000000 00000000332 15051732407 0022404 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/nushell/nufmt",
description = "The nushell formatter.",
},
command = "nufmt",
args = { "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/ocamlformat.lua 0000664 0000000 0000000 00000000423 15051732407 0023560 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/ocaml-ppx/ocamlformat",
description = "Auto-formatter for OCaml code.",
},
command = "ocamlformat",
args = { "--enable-outside-detected-project", "--name", "$FILENAME", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/ocp-indent.lua 0000664 0000000 0000000 00000000320 15051732407 0023310 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/OCamlPro/ocp-indent",
description = "Automatic indentation of OCaml source files.",
},
command = "ocp-indent",
}
conform.nvim-9.1.0/lua/conform/formatters/odinfmt.lua 0000664 0000000 0000000 00000001021 15051732407 0022707 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/DanielGavin/ols",
description = "Auto-formatter for the Odin programming language.",
},
command = "odinfmt",
args = {
-- Odinfmt hunts for the first "odinfmt.json" file it finds from the
-- current directory and back up the file system. All formatting directives
-- are in that file.
--
-- Odinfmt writes to stdout by default, but must be directed to read from
-- stdin.
"-stdin",
},
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/opa_fmt.lua 0000664 0000000 0000000 00000000355 15051732407 0022705 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://www.openpolicyagent.org/docs/latest/cli/#opa-fmt",
description = "Format Rego files using `opa fmt` command.",
},
command = "opa",
args = { "fmt" },
}
conform.nvim-9.1.0/lua/conform/formatters/ormolu.lua 0000664 0000000 0000000 00000000410 15051732407 0022565 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://hackage.haskell.org/package/ormolu",
description = "A formatter for Haskell source code.",
},
command = "ormolu",
args = { "--stdin-input-file", "$FILENAME" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/packer_fmt.lua 0000664 0000000 0000000 00000000464 15051732407 0023374 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://developer.hashicorp.com/packer/docs/commands/fmt",
description = "The packer fmt Packer command is used to format HCL2 configuration files to a canonical format and style.",
},
command = "packer",
args = { "fmt", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/pangu.lua 0000664 0000000 0000000 00000000342 15051732407 0022366 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/vinta/pangu.py",
description = "Insert whitespace between CJK and half-width characters.",
},
command = "pangu",
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/perlimports.lua 0000664 0000000 0000000 00000000425 15051732407 0023636 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/perl-ide/App-perlimports",
description = "Make implicit Perl imports explicit.",
},
command = "perlimports",
args = {
"--read-stdin",
"--filename",
"$FILENAME",
},
}
conform.nvim-9.1.0/lua/conform/formatters/perltidy.lua 0000664 0000000 0000000 00000000345 15051732407 0023113 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/perltidy/perltidy",
description = "Perl::Tidy, a source code formatter for Perl.",
},
command = "perltidy",
args = { "--quiet" },
}
conform.nvim-9.1.0/lua/conform/formatters/pg_format.lua 0000664 0000000 0000000 00000000303 15051732407 0023227 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/darold/pgFormatter",
description = "PostgreSQL SQL syntax beautifier.",
},
command = "pg_format",
}
conform.nvim-9.1.0/lua/conform/formatters/php_cs_fixer.lua 0000664 0000000 0000000 00000000676 15051732407 0023737 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer",
description = "The PHP Coding Standards Fixer.",
},
command = util.find_executable({
"tools/php-cs-fixer/vendor/bin/php-cs-fixer",
"vendor/bin/php-cs-fixer",
}, "php-cs-fixer"),
args = { "fix", "$FILENAME" },
stdin = false,
cwd = util.root_file({ "composer.json" }),
}
conform.nvim-9.1.0/lua/conform/formatters/phpcbf.lua 0000664 0000000 0000000 00000001153 15051732407 0022517 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://phpqa.io/projects/phpcbf.html",
description = "PHP Code Beautifier and Fixer fixes violations of a defined coding standard.",
},
command = util.find_executable({
"vendor/bin/phpcbf",
}, "phpcbf"),
args = { "$FILENAME" },
stdin = false,
-- phpcbf ignores hidden files, so we have to override the default here
tmpfile_format = "conform.$RANDOM.$FILENAME",
-- 0: no errors found
-- 1: errors found
-- 2: fixable errors found
-- 3: processing error
exit_codes = { 0, 1, 2 },
}
conform.nvim-9.1.0/lua/conform/formatters/phpinsights.lua 0000664 0000000 0000000 00000000734 15051732407 0023621 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/nunomaduro/phpinsights",
description = "The perfect starting point to analyze the code quality of your PHP projects.",
},
command = util.find_executable({
"vendor/bin/phpinsights",
}, "phpinsights"),
args = { "fix", "$FILENAME", "--no-interaction", "--quiet" },
cwd = util.root_file({
"phpinsights.php",
}),
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/pint.lua 0000664 0000000 0000000 00000000540 15051732407 0022226 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/laravel/pint",
description = "Laravel Pint is an opinionated PHP code style fixer for minimalists.",
},
command = util.find_executable({
"vendor/bin/pint",
}, "pint"),
args = { "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/prettier.lua 0000664 0000000 0000000 00000004631 15051732407 0023117 0 ustar 00root root 0000000 0000000 local fs = require("conform.fs")
local util = require("conform.util")
local cwd = require("conform.formatters.prettierd").cwd
--- Helper function to parse options to into a parser if available
---@param self conform.JobFormatterConfig
---@param ctx conform.Context|conform.RangeContext
---@return string[]|nil args the arguments for setting a `prettier` parser if they exist in the options, nil otherwise
local function eval_parser(self, ctx)
local ft = vim.bo[ctx.buf].filetype
local ext = vim.fn.fnamemodify(ctx.filename, ":e")
local options = self.options
local parser = options
and (
(options.ft_parsers and options.ft_parsers[ft])
or (options.ext_parsers and options.ext_parsers[ext])
)
if parser then
return { "--parser", parser }
end
end
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/prettier/prettier",
description = [[Prettier is an opinionated code formatter. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary.]],
},
options = {
-- Use a specific prettier parser for a filetype
-- Otherwise, prettier will try to infer the parser from the file name
ft_parsers = {
-- javascript = "babel",
-- javascriptreact = "babel",
-- typescript = "typescript",
-- typescriptreact = "typescript",
-- vue = "vue",
-- css = "css",
-- scss = "scss",
-- less = "less",
-- html = "html",
-- json = "json",
-- jsonc = "json",
-- yaml = "yaml",
-- markdown = "markdown",
-- ["markdown.mdx"] = "mdx",
-- graphql = "graphql",
-- handlebars = "glimmer",
},
-- Use a specific prettier parser for a file extension
ext_parsers = {
-- qmd = "markdown",
},
},
command = util.from_node_modules(fs.is_windows and "prettier.cmd" or "prettier"),
args = function(self, ctx)
return eval_parser(self, ctx) or { "--stdin-filepath", "$FILENAME" }
end,
range_args = function(self, ctx)
local start_offset, end_offset = util.get_offsets_from_range(ctx.buf, ctx.range)
local args = eval_parser(self, ctx) or { "--stdin-filepath", "$FILENAME" }
return vim.list_extend(args, { "--range-start=" .. start_offset, "--range-end=" .. end_offset })
end,
cwd = cwd,
}
conform.nvim-9.1.0/lua/conform/formatters/prettierd.lua 0000664 0000000 0000000 00000003765 15051732407 0023272 0 ustar 00root root 0000000 0000000 local fs = require("conform.fs")
local log = require("conform.log")
local util = require("conform.util")
local config_file_names = {
-- https://prettier.io/docs/en/configuration.html
".prettierrc",
".prettierrc.json",
".prettierrc.yml",
".prettierrc.yaml",
".prettierrc.json5",
".prettierrc.js",
".prettierrc.cjs",
".prettierrc.mjs",
".prettierrc.toml",
"prettier.config.js",
"prettier.config.cjs",
"prettier.config.mjs",
}
---@param file string
---@return nil|table
local function read_json(file)
local f = io.open(file, "r")
if not f then
log.error("Unable to open file %s", file)
return nil
end
local file_content = f:read("*all") -- Read entire file contents
f:close()
local ok, json = pcall(vim.json.decode, file_content)
if not ok then
log.error("Unable to parse json file %s", file)
return nil
end
return json
end
-- @param self conform.FormatterConfig
-- @param ctx conform.Context|conform.RangeContext
-- @return string|nil args the arguments for setting a `prettier` parser if they exist in the options, nil otherwise
local cwd = function(self, ctx)
return vim.fs.root(ctx.dirname, function(name, path)
if vim.tbl_contains(config_file_names, name) then
return true
end
if name == "package.json" then
local full_path = vim.fs.joinpath(path, name)
local package_data = read_json(full_path)
return package_data and package_data.prettier and true or false
end
return false
end)
end
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/fsouza/prettierd",
description = "prettier, as a daemon, for ludicrous formatting speed.",
},
command = util.from_node_modules(fs.is_windows and "prettierd.cmd" or "prettierd"),
args = { "$FILENAME" },
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,
cwd = cwd,
}
conform.nvim-9.1.0/lua/conform/formatters/pretty-php.lua 0000664 0000000 0000000 00000000517 15051732407 0023374 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/lkrms/pretty-php",
description = "The opinionated PHP code formatter.",
},
command = util.find_executable({
"vendor/bin/pretty-php",
}, "pretty-php"),
args = { "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/prettypst.lua 0000664 0000000 0000000 00000000367 15051732407 0023341 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/antonWetzel/prettypst",
description = "Formatter for Typst.",
},
command = "prettypst",
args = { "--use-std-in", "--use-std-out" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/prolog.lua 0000664 0000000 0000000 00000000424 15051732407 0022557 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/jamesnvc/lsp_server",
description = "Language Server Protocol server and formatter for SWI-Prolog.",
},
command = "swipl",
args = { "formatter", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/puppet-lint.lua 0000664 0000000 0000000 00000000461 15051732407 0023537 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/puppetlabs/puppet-lint",
description = "Check that your Puppet manifests conform to the style guide.",
},
command = "puppet-lint",
args = { "--fix", "$FILENAME" },
stdin = false,
exit_codes = { 0, 1 },
}
conform.nvim-9.1.0/lua/conform/formatters/purs-tidy.lua 0000664 0000000 0000000 00000000365 15051732407 0023221 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/natefaubion/purescript-tidy",
description = "A syntax tidy-upper for PureScript.",
},
command = "purs-tidy",
args = { "format" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/pycln.lua 0000664 0000000 0000000 00000000570 15051732407 0022404 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/hadialqattan/pycln",
description = "A Python formatter for finding and removing unused import statements.",
},
command = "pycln",
args = {
"--silence",
"-",
},
cwd = util.root_file({
"pyproject.toml",
"setup.cfg",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/pyink.lua 0000664 0000000 0000000 00000000511 15051732407 0022404 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/google/pyink",
description = "A Python formatter, forked from Black with a few different formatting behaviors.",
},
command = "pyink",
args = {
"--stdin-filename",
"$FILENAME",
"--quiet",
"-",
},
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/pymarkdownlnt.lua 0000664 0000000 0000000 00000000440 15051732407 0024164 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/jackdewinter/pymarkdown",
description = "A markdown linter and formatter.",
},
command = "pymarkdownlnt",
args = { "--return-code-scheme", "minimal", "fix", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/pyproject-fmt.lua 0000664 0000000 0000000 00000000736 15051732407 0024066 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/tox-dev/toml-fmt/tree/main/pyproject-fmt",
description = "Apply a consistent format to your pyproject.toml file with comment support.",
},
command = "pyproject-fmt",
args = {
"-",
},
cwd = util.root_file({
"pyproject.toml",
}),
exit_codes = { 0, 1 }, -- 1 error code used when formatting is successful and if there are errors
}
conform.nvim-9.1.0/lua/conform/formatters/python-ly.lua 0000664 0000000 0000000 00000000453 15051732407 0023222 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/frescobaldi/python-ly",
description = "A Python package and commandline tool to manipulate LilyPond files.",
},
command = "ly",
args = { "reformat", "$FILENAME", "-o", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/pyupgrade.lua 0000664 0000000 0000000 00000000713 15051732407 0023256 0 ustar 00root root 0000000 0000000 --- NOTE: When adding pyupgrade to your config, you might want to add specific version flag
--- For instance use:
--- prepend_args = { "--py313-plus" }
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/asottile/pyupgrade",
description = "A tool to automatically upgrade syntax for newer versions of Python.",
},
command = "pyupgrade",
args = { "--exit-zero-even-if-changed", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/qmlformat.lua 0000664 0000000 0000000 00000000416 15051732407 0023260 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://doc.qt.io/qt-6//qtqml-tooling-qmlformat.html",
description = "A tool that automatically formats QML files.",
},
command = "qmlformat",
args = { "-i", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/reformat-gherkin.lua 0000664 0000000 0000000 00000000365 15051732407 0024525 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/ducminh-phan/reformat-gherkin",
description = "Formatter for Gherkin language.",
},
command = "reformat-gherkin",
args = { "-" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/reorder-python-imports.lua 0000664 0000000 0000000 00000000446 15051732407 0025735 0 ustar 00root root 0000000 0000000 --@type conform.FileFormatterConfig-
return {
meta = {
url = "https://github.com/asottile/reorder-python-imports",
description = "Rewrites source to reorder python imports",
},
command = "reorder-python-imports",
args = { "--exit-zero-even-if-changed", "-" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/rescript-format.lua 0000664 0000000 0000000 00000001534 15051732407 0024401 0 ustar 00root root 0000000 0000000 -- The formatter expects one of [.res | .resi | .ml | .mli] passed as
-- the value to the '-stdin' argument.
local valid_extensions = {
res = true,
resi = true,
ml = true,
mli = true,
}
local default_extension = "res"
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://rescript-lang.org/",
description = "The built-in ReScript formatter.",
},
command = "rescript",
args = function(self, ctx)
local extension = vim.fn.fnamemodify(ctx.filename, ":e")
local is_invalid_extension = valid_extensions[extension] == nil
if is_invalid_extension then
extension = default_extension
end
return {
"format",
"-stdin",
"." .. extension,
}
end,
stdin = true,
require_cwd = true,
cwd = require("conform.util").root_file({
"rescript.json",
"bsconfig.json",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/roc.lua 0000664 0000000 0000000 00000000372 15051732407 0022042 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/roc-lang/roc",
description = "A fast, friendly, functional language.",
},
command = "roc",
args = { "format", "--stdin", "--stdout" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/rstfmt.lua 0000664 0000000 0000000 00000000344 15051732407 0022575 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/dzhu/rstfmt",
description = "A formatter for reStructuredText.",
},
command = "rstfmt",
args = { "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/rubocop.lua 0000664 0000000 0000000 00000000570 15051732407 0022730 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/rubocop/rubocop",
description = "Ruby static code analyzer and formatter, based on the community Ruby style guide.",
},
command = "rubocop",
args = {
"--server",
"-a",
"-f",
"quiet",
"--stderr",
"--stdin",
"$FILENAME",
},
exit_codes = { 0, 1 },
}
conform.nvim-9.1.0/lua/conform/formatters/rubyfmt.lua 0000664 0000000 0000000 00000000242 15051732407 0022743 0 ustar 00root root 0000000 0000000 return {
meta = {
url = "https://github.com/fables-tales/rubyfmt",
description = "Ruby Autoformatter! (Written in Rust)",
},
command = "rubyfmt",
}
conform.nvim-9.1.0/lua/conform/formatters/ruff.lua 0000664 0000000 0000000 00000000212 15051732407 0022212 0 ustar 00root root 0000000 0000000 -- This was renamed to ruff_fix
local conf = vim.deepcopy(require("conform.formatters.ruff_fix"))
conf.meta.deprecated = true
return conf
conform.nvim-9.1.0/lua/conform/formatters/ruff_fix.lua 0000664 0000000 0000000 00000000751 15051732407 0023070 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://docs.astral.sh/ruff/",
description = "An extremely fast Python linter, written in Rust. Fix lint errors.",
},
command = "ruff",
args = {
"check",
"--fix",
"--force-exclude",
"--exit-zero",
"--no-cache",
"--stdin-filename",
"$FILENAME",
"-",
},
stdin = true,
cwd = require("conform.util").root_file({
"pyproject.toml",
"ruff.toml",
".ruff.toml",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/ruff_format.lua 0000664 0000000 0000000 00000001432 15051732407 0023567 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://docs.astral.sh/ruff/",
description = "An extremely fast Python linter, written in Rust. Formatter subcommand.",
},
command = "ruff",
args = {
"format",
"--force-exclude",
"--stdin-filename",
"$FILENAME",
"-",
},
range_args = function(self, ctx)
return {
"format",
"--force-exclude",
"--range",
string.format(
"%d:%d-%d:%d",
ctx.range.start[1],
ctx.range.start[2] + 1,
ctx.range["end"][1],
ctx.range["end"][2] + 1
),
"--stdin-filename",
"$FILENAME",
"-",
}
end,
stdin = true,
cwd = require("conform.util").root_file({
"pyproject.toml",
"ruff.toml",
".ruff.toml",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/ruff_organize_imports.lua 0000664 0000000 0000000 00000000777 15051732407 0025705 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://docs.astral.sh/ruff/",
description = "An extremely fast Python linter, written in Rust. Organize imports.",
},
command = "ruff",
args = {
"check",
"--fix",
"--force-exclude",
"--select=I001",
"--exit-zero",
"--no-cache",
"--stdin-filename",
"$FILENAME",
"-",
},
stdin = true,
cwd = require("conform.util").root_file({
"pyproject.toml",
"ruff.toml",
".ruff.toml",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/rufo.lua 0000664 0000000 0000000 00000000270 15051732407 0022227 0 ustar 00root root 0000000 0000000 return {
meta = {
url = "https://github.com/ruby-formatter/rufo",
description = "Rufo is an opinionated ruby formatter.",
},
command = "rufo",
exit_codes = { 0, 3 },
}
conform.nvim-9.1.0/lua/conform/formatters/runic.lua 0000664 0000000 0000000 00000000452 15051732407 0022376 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/fredrikekre/Runic.jl",
description = "Julia code formatter.",
},
command = "runic",
range_args = function(_, ctx)
return { "--lines=" .. ctx.range.start[1] .. ":" .. ctx.range["end"][1] }
end,
}
conform.nvim-9.1.0/lua/conform/formatters/rustfmt.lua 0000664 0000000 0000000 00000001252 15051732407 0022761 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/rust-lang/rustfmt",
description = "A tool for formatting rust code according to style guidelines.",
},
command = "rustfmt",
options = {
-- The default edition of Rust to use when no Cargo.toml file is found
default_edition = "2021",
},
args = function(self, ctx)
local args = { "--emit=stdout" }
local edition = util.parse_rust_edition(ctx.dirname) or self.options.default_edition
table.insert(args, "--edition=" .. edition)
return args
end,
cwd = util.root_file({
"rustfmt.toml",
".rustfmt.toml",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/rustywind.lua 0000664 0000000 0000000 00000000345 15051732407 0023327 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/avencera/rustywind",
description = "A tool for formatting Tailwind CSS classes.",
},
command = "rustywind",
args = { "--stdin" },
}
conform.nvim-9.1.0/lua/conform/formatters/scalafmt.lua 0000664 0000000 0000000 00000000322 15051732407 0023044 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/scalameta/scalafmt",
description = "Code formatter for Scala.",
},
command = "scalafmt",
args = { "--stdin" },
}
conform.nvim-9.1.0/lua/conform/formatters/shellcheck.lua 0000664 0000000 0000000 00000000434 15051732407 0023363 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/koalaman/shellcheck",
description = "A static analysis tool for shell scripts.",
},
command = "shellcheck",
args = "'$FILENAME' --format=diff | patch -p1 '$FILENAME'",
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/shellharden.lua 0000664 0000000 0000000 00000000354 15051732407 0023550 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/anordal/shellharden",
description = "The corrective bash syntax highlighter.",
},
command = "shellharden",
args = { "--transform", "" },
}
conform.nvim-9.1.0/lua/conform/formatters/shfmt.lua 0000664 0000000 0000000 00000001262 15051732407 0022377 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/mvdan/sh",
description = "A shell parser, formatter, and interpreter with `bash` support.",
},
command = "shfmt",
args = function(_, ctx)
local args = { "-filename", "$FILENAME" }
local has_editorconfig = vim.fs.find(".editorconfig", { path = ctx.dirname, upward = true })[1]
~= nil
-- If there is an editorconfig, don't pass any args because shfmt will apply settings from there
-- when no command line args are passed.
if not has_editorconfig and vim.bo[ctx.buf].expandtab then
vim.list_extend(args, { "-i", ctx.shiftwidth })
end
return args
end,
}
conform.nvim-9.1.0/lua/conform/formatters/sleek.lua 0000664 0000000 0000000 00000000320 15051732407 0022353 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/nrempel/sleek",
description = "Sleek is a CLI tool for formatting SQL.",
},
command = "sleek",
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/smlfmt.lua 0000664 0000000 0000000 00000000321 15051732407 0022553 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/shwestrick/smlfmt",
description = "A custom parser and code formatter for Standard ML.",
},
command = "smlfmt",
}
conform.nvim-9.1.0/lua/conform/formatters/snakefmt.lua 0000664 0000000 0000000 00000000414 15051732407 0023064 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/snakemake/snakefmt",
description = "a formatting tool for Snakemake files following the design of Black.",
},
command = "snakefmt",
args = "$FILENAME",
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/spotless_gradle.lua 0000664 0000000 0000000 00000001015 15051732407 0024444 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/diffplug/spotless",
description = "Spotless plugin for Gradle.",
},
stdin = true,
require_cwd = true,
cwd = require("conform.util").root_file({ "gradlew" }),
command = "./gradlew",
args = function(_, ctx)
return {
"spotlessApply",
"-PspotlessIdeHook=" .. ctx.filename,
"-PspotlessIdeHookUseStdIn",
"-PspotlessIdeHookUseStdOut",
"--no-configuration-cache",
"--quiet",
}
end,
}
conform.nvim-9.1.0/lua/conform/formatters/spotless_maven.lua 0000664 0000000 0000000 00000000745 15051732407 0024325 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/diffplug/spotless",
description = "Spotless plugin for Maven.",
},
stdin = true,
require_cwd = true,
cwd = require("conform.util").root_file({ "mvnw" }),
command = "./mvnw",
args = function(_, ctx)
return {
"spotless:apply",
"-DspotlessIdeHook=" .. ctx.filename,
"-DspotlessIdeHookUseStdIn",
"-DspotlessIdeHookUseStdOut",
"--quiet",
}
end,
}
conform.nvim-9.1.0/lua/conform/formatters/sql_formatter.lua 0000664 0000000 0000000 00000000350 15051732407 0024135 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/sql-formatter-org/sql-formatter",
description = "A whitespace formatter for different query languages.",
},
command = "sql-formatter",
}
conform.nvim-9.1.0/lua/conform/formatters/sqlfluff.lua 0000664 0000000 0000000 00000000731 15051732407 0023100 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/sqlfluff/sqlfluff",
description = "A modular SQL linter and auto-formatter with support for multiple dialects and templated code.",
},
command = "sqlfluff",
args = { "fix", "-" },
stdin = true,
cwd = util.root_file({
".sqlfluff",
"pep8.ini",
"pyproject.toml",
"setup.cfg",
"tox.ini",
}),
require_cwd = true,
}
conform.nvim-9.1.0/lua/conform/formatters/sqlfmt.lua 0000664 0000000 0000000 00000000435 15051732407 0022565 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://docs.sqlfmt.com",
description = "sqlfmt formats your dbt SQL files so you don't have to. It is similar in nature to Black, gofmt, and rustfmt (but for SQL)",
},
command = "sqlfmt",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/sqruff.lua 0000664 0000000 0000000 00000000662 15051732407 0022567 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/quarylabs/sqruff",
description = "sqruff is a SQL linter and formatter written in Rust.",
},
command = "sqruff",
stdin = false,
args = { "fix", "$FILENAME" },
cwd = util.root_file({
-- https://github.com/quarylabs/sqruff/tree/main#configuration
".sqruff",
}),
require_cwd = false,
}
conform.nvim-9.1.0/lua/conform/formatters/squeeze_blanks.lua 0000664 0000000 0000000 00000000467 15051732407 0024277 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html#cat-invocation",
description = "Squeeze repeated blank lines into a single blank line via `cat -s`.",
},
command = "cat",
args = { "-s" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/standard-clj.lua 0000664 0000000 0000000 00000000532 15051732407 0023623 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/oakmac/standard-clojure-style-js",
description = "A JavaScript library to format Clojure code according to Standard Clojure Style.",
},
command = util.from_node_modules("standard-clj"),
args = { "fix", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/standardjs.lua 0000664 0000000 0000000 00000000450 15051732407 0023411 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://standardjs.com",
description = "JavaScript Standard style guide, linter, and formatter.",
},
command = util.from_node_modules("standard"),
args = { "--fix", "--stdin" },
}
conform.nvim-9.1.0/lua/conform/formatters/standardrb.lua 0000664 0000000 0000000 00000000514 15051732407 0023401 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/standardrb/standard",
description = "Ruby's bikeshed-proof linter and formatter.",
},
command = "standardrb",
args = {
"--fix",
"-f",
"quiet",
"--stderr",
"--stdin",
"$FILENAME",
},
exit_codes = { 0, 1 },
}
conform.nvim-9.1.0/lua/conform/formatters/stylelint.lua 0000664 0000000 0000000 00000001020 15051732407 0023275 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/stylelint/stylelint",
description = "A mighty CSS linter that helps you avoid errors and enforce conventions.",
},
command = util.from_node_modules("stylelint"),
args = { "--stdin", "--stdin-filename", "$FILENAME", "--fix" },
exit_codes = { 0, 2 }, -- code 2 is given when trying file includees some non-autofixable errors
stdin = true,
cwd = util.root_file({
"package.json",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/styler.lua 0000664 0000000 0000000 00000001030 15051732407 0022571 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/devOpifex/r.nvim",
description = "R formatter and linter.",
},
command = util.find_executable({ "usr/bin/" }, "R"),
-- Any args to style_file must be passed after `commandArgs(TRUE)`
-- Include "--no-init-file" before "e" to ignore .Rprofile, for example
-- to avoid long renv startup time
args = { "-s", "-e", "styler::style_file(commandArgs(TRUE))", "--args", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/stylish-haskell.lua 0000664 0000000 0000000 00000000342 15051732407 0024374 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/haskell/stylish-haskell",
description = "Haskell code prettifier.",
},
command = "stylish-haskell",
args = {},
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/stylua.lua 0000664 0000000 0000000 00000001405 15051732407 0022576 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/JohnnyMorganz/StyLua",
description = "An opinionated code formatter for Lua.",
},
command = "stylua",
args = {
"--search-parent-directories",
"--respect-ignores",
"--stdin-filepath",
"$FILENAME",
"-",
},
range_args = function(self, ctx)
local start_offset, end_offset = util.get_offsets_from_range(ctx.buf, ctx.range)
return {
"--search-parent-directories",
"--stdin-filepath",
"$FILENAME",
"--range-start",
tostring(start_offset),
"--range-end",
tostring(end_offset),
"-",
}
end,
cwd = util.root_file({
".stylua.toml",
"stylua.toml",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/superhtml.lua 0000664 0000000 0000000 00000000371 15051732407 0023301 0 ustar 00root root 0000000 0000000 ---@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" },
}
conform.nvim-9.1.0/lua/conform/formatters/swift.lua 0000664 0000000 0000000 00000000433 15051732407 0022411 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/swiftlang/swift-format",
description = "Official Swift formatter. Requires Swift 6.0 or later.",
},
command = "swift",
args = { "format", "$FILENAME", "--in-place" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/swift_format.lua 0000664 0000000 0000000 00000000500 15051732407 0023754 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/swiftlang/swift-format",
description = "Official Swift formatter. For Swift 6.0 or later prefer setting the `swift` formatter instead.",
},
command = "swift-format",
args = { "$FILENAME", "--in-place" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/swiftformat.lua 0000664 0000000 0000000 00000001226 15051732407 0023623 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/nicklockwood/SwiftFormat",
description = "SwiftFormat is a code library and command-line tool for reformatting `swift` code on macOS or Linux.",
},
command = "swiftformat",
stdin = true,
args = { "--stdinpath", "$FILENAME" },
range_args = function(self, ctx)
local startOffset = tonumber(ctx.range.start[1]) - 1
local endOffset = tonumber(ctx.range["end"][1]) - 1
return {
"--linerange",
startOffset .. "," .. endOffset,
}
end,
cwd = require("conform.util").root_file({ ".swiftformat", "Package.swift", "buildServer.json" }),
}
conform.nvim-9.1.0/lua/conform/formatters/swiftlint.lua 0000664 0000000 0000000 00000000550 15051732407 0023300 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/realm/SwiftLint",
description = "A tool to enforce Swift style and conventions.",
},
command = "swiftlint",
stdin = true,
args = { "lint", "--use-stdin", "--fix", "--format" },
cwd = require("conform.util").root_file({ ".swiftlint.yml", "Package.swift" }),
}
conform.nvim-9.1.0/lua/conform/formatters/syntax_tree.lua 0000664 0000000 0000000 00000000541 15051732407 0023622 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/ruby-syntax-tree/syntax_tree",
description = "Syntax Tree is a suite of tools built on top of the internal CRuby parser.",
},
command = "stree",
stdin = false,
args = { "write", "$FILENAME" },
cwd = require("conform.util").root_file({ ".streerc" }),
}
conform.nvim-9.1.0/lua/conform/formatters/taplo.lua 0000664 0000000 0000000 00000000324 15051732407 0022373 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/tamasfe/taplo",
description = "A TOML toolkit written in Rust.",
},
command = "taplo",
args = { "format", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/templ.lua 0000664 0000000 0000000 00000000351 15051732407 0022375 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://templ.guide/developer-tools/cli/#formatting-templ-files",
description = "Formats templ template files.",
},
command = "templ",
args = { "fmt" },
}
conform.nvim-9.1.0/lua/conform/formatters/terraform_fmt.lua 0000664 0000000 0000000 00000000471 15051732407 0024126 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://www.terraform.io/docs/cli/commands/fmt.html",
description = "The terraform-fmt command rewrites `terraform` configuration files to a canonical format and style.",
},
command = "terraform",
args = { "fmt", "-no-color", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/terragrunt_hclfmt.lua 0000664 0000000 0000000 00000000640 15051732407 0025007 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://terragrunt.gruntwork.io/docs/reference/cli-options/#hclfmt",
description = "Format hcl files into a canonical format.",
},
command = "terragrunt",
args = { "hclfmt", "--terragrunt-hclfmt-file", "$FILENAME" },
stdin = false,
condition = function(self, ctx)
return vim.fs.basename(ctx.filename) ~= "terragrunt.hcl"
end,
}
conform.nvim-9.1.0/lua/conform/formatters/tex-fmt.lua 0000664 0000000 0000000 00000000346 15051732407 0022644 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/WGUNDERWOOD/tex-fmt",
description = "An extremely fast LaTeX formatter written in Rust.",
},
command = "tex-fmt",
args = { "-s" },
}
conform.nvim-9.1.0/lua/conform/formatters/tlint.lua 0000664 0000000 0000000 00000000561 15051732407 0022411 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/tighten/tlint",
description = "Tighten linter for Laravel conventions with support for auto-formatting.",
},
command = util.find_executable({
"vendor/bin/tlint",
}, "tlint"),
args = { "format", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/tofu_fmt.lua 0000664 0000000 0000000 00000000427 15051732407 0023103 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://opentofu.org/docs/cli/commands/fmt/",
description = "The tofu-fmt command rewrites OpenTofu configuration files to a canonical format and style.",
},
command = "tofu",
args = { "fmt", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/tombi.lua 0000664 0000000 0000000 00000000341 15051732407 0022365 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/tombi-toml/tombi",
description = "TOML Formatter / Linter.",
},
command = "tombi",
args = { "format", "-" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/treefmt.lua 0000664 0000000 0000000 00000000336 15051732407 0022725 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/numtide/treefmt",
description = "one CLI to format your repo.",
},
command = "treefmt",
args = { "--stdin", "$FILENAME" },
}
conform.nvim-9.1.0/lua/conform/formatters/trim_newlines.lua 0000664 0000000 0000000 00000000714 15051732407 0024136 0 ustar 00root root 0000000 0000000 ---@type conform.FileLuaFormatterConfig
return {
meta = {
url = "https://github.com/stevearc/conform.nvim/blob/master/lua/conform/formatters/trim_newlines.lua",
description = "Trim empty lines at the end of the file.",
},
format = function(self, ctx, lines, callback)
local out_lines = vim.deepcopy(lines)
while #out_lines > 0 and out_lines[#out_lines] == "" do
table.remove(out_lines)
end
callback(nil, out_lines)
end,
}
conform.nvim-9.1.0/lua/conform/formatters/trim_whitespace.lua 0000664 0000000 0000000 00000000713 15051732407 0024445 0 ustar 00root root 0000000 0000000 ---@type conform.FileLuaFormatterConfig
return {
meta = {
url = "https://github.com/stevearc/conform.nvim/blob/master/lua/conform/formatters/trim_whitespace.lua",
description = "Trim trailing whitespace.",
},
format = function(self, ctx, lines, callback)
local out_lines = {}
for _, line in ipairs(lines) do
local trimmed = line:gsub("%s+$", "")
table.insert(out_lines, trimmed)
end
callback(nil, out_lines)
end,
}
conform.nvim-9.1.0/lua/conform/formatters/twig-cs-fixer.lua 0000664 0000000 0000000 00000001040 15051732407 0023740 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/VincentLanglet/Twig-CS-Fixer",
description = "Automatically fix Twig Coding Standards issues",
},
command = util.find_executable({
"vendor/bin/twig-cs-fixer",
}, "twig-cs-fixer"),
args = { "lint", "$FILENAME", "--fix", "--no-interaction", "--quiet" },
cwd = util.root_file({
".twig-cs-fixer.php",
".twig-cs-fixer.dist.php",
"composer.json",
}),
require_cwd = false,
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/typespec.lua 0000664 0000000 0000000 00000000527 15051732407 0023115 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/microsoft/typespec",
description = "TypeSpec compiler and CLI.",
},
command = util.from_node_modules("tsp"),
stdin = false,
args = { "format", "$FILENAME" },
cwd = util.root_file({ "tspconfig.yaml" }),
}
conform.nvim-9.1.0/lua/conform/formatters/typos.lua 0000664 0000000 0000000 00000000731 15051732407 0022434 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/crate-ci/typos",
description = "Source code spell checker",
},
command = "typos",
-- cannot use stdin, as otherwise `typos` has no information on the filename,
-- making excluded-file-configs ineffective
stdin = false,
args = {
"--write-changes",
"--force-exclude", -- so excluded files in the config take effect
"$FILENAME",
},
exit_codes = { 0, 2 },
}
conform.nvim-9.1.0/lua/conform/formatters/typstfmt.lua 0000664 0000000 0000000 00000000401 15051732407 0023142 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/astrale-sharp/typstfmt",
description = "Basic formatter for the Typst language with a future!",
deprecated = true,
},
command = "typstfmt",
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/typstyle.lua 0000664 0000000 0000000 00000000340 15051732407 0023147 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/Enter-tainer/typstyle",
description = "Beautiful and reliable typst code formatter.",
},
command = "typstyle",
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/ufmt.lua 0000664 0000000 0000000 00000000372 15051732407 0022232 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/omnilib/ufmt",
description = "Safe, atomic formatting with black and µsort.",
},
command = "ufmt",
args = { "format", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/uncrustify.lua 0000664 0000000 0000000 00000001131 15051732407 0023464 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/uncrustify/uncrustify",
description = "A source code beautifier for C, C++, C#, ObjectiveC, D, Java, Pawn and Vala.",
},
command = "uncrustify",
args = function(_, ctx)
local args = { "-q", "-l", vim.bo[ctx.buf].filetype:upper() }
-- Find uncrustify.cfg in the project if it exists
local cfg_path = vim.fs.find("uncrustify.cfg", { upward = true, path = ctx.dirname })[1]
if cfg_path then
table.insert(args, "-c")
table.insert(args, cfg_path)
end
return args
end,
}
conform.nvim-9.1.0/lua/conform/formatters/usort.lua 0000664 0000000 0000000 00000000522 15051732407 0022430 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/facebook/usort",
description = "Safe, minimal import sorting for Python projects.",
},
command = "usort",
args = { "format", "-" },
stdin = true,
cwd = util.root_file({
"pyproject.toml",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/v.lua 0000664 0000000 0000000 00000000322 15051732407 0021517 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://vlang.io",
description = "V language formatter.",
},
command = "v",
args = { "fmt", "-w", "$FILENAME" },
stdin = false,
}
conform.nvim-9.1.0/lua/conform/formatters/verible.lua 0000664 0000000 0000000 00000000453 15051732407 0022707 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/chipsalliance/verible/blob/master/verilog/tools/formatter/README.md",
description = "The SystemVerilog formatter.",
},
command = "verible-verilog-format",
args = { "--stdin_name", "$FILENAME", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/vsg.lua 0000664 0000000 0000000 00000002071 15051732407 0022054 0 ustar 00root root 0000000 0000000 local config_files = {
"vsg_config.yaml",
"vsg_config.yml",
"vsg_config.json",
"vsg.yaml",
"vsg.yml",
"vsg.json",
".vsg_config.yaml",
".vsg_config.yml",
".vsg_config.json",
".vsg.yaml",
".vsg.yml",
".vsg.json",
}
local function find_config(dirname)
local paths = {
dirname,
(os.getenv("XDG_CONFIG_HOME") or os.getenv("HOME") .. "/.config") .. "/vsg",
}
for _, path in ipairs(paths) do
local config = vim.fs.find(config_files, {
path = path,
upward = path == dirname,
})[1]
if config then
return config
end
end
end
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/jeremiah-c-leary/vhdl-style-guide",
description = "Style guide enforcement for VHDL.",
},
command = "vsg",
stdin = false,
args = function(_, ctx)
local args = { "-of", "syntastic", "--fix", "-f", "$FILENAME" }
local config_file = find_config(ctx.dirname)
if config_file then
table.insert(args, "-c")
table.insert(args, config_file)
end
return args
end,
}
conform.nvim-9.1.0/lua/conform/formatters/xmlformat.lua 0000664 0000000 0000000 00000000222 15051732407 0023262 0 ustar 00root root 0000000 0000000 -- This was renamed to xmlformatter
local conf = vim.deepcopy(require("conform.formatters.xmlformatter"))
conf.meta.deprecated = true
return conf
conform.nvim-9.1.0/lua/conform/formatters/xmlformatter.lua 0000664 0000000 0000000 00000000421 15051732407 0023776 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/pamoller/xmlformatter",
description = "xmlformatter is an Open Source Python package, which provides formatting of XML documents.",
},
command = "xmlformat",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/xmllint.lua 0000664 0000000 0000000 00000000407 15051732407 0022745 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "http://xmlsoft.org/xmllint.html",
description = "Despite the name, xmllint can be used to format XML files as well as lint them.",
},
command = "xmllint",
args = { "--format", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/xmlstarlet.lua 0000664 0000000 0000000 00000000437 15051732407 0023460 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "http://xmlstar.sourceforge.net/",
description = "XMLStarlet is a command-line XML toolkit that can be used to format XML files.",
},
command = "xmlstarlet",
args = { "format", "--indent-spaces", "2", "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/yamlfix.lua 0000664 0000000 0000000 00000000342 15051732407 0022725 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/lyz-code/yamlfix",
description = "A configurable YAML formatter that keeps comments.",
},
command = "yamlfix",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/yamlfmt.lua 0000664 0000000 0000000 00000000371 15051732407 0022727 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/google/yamlfmt",
description = "yamlfmt is an extensible command line tool or library to format yaml files.",
},
command = "yamlfmt",
args = { "-" },
}
conform.nvim-9.1.0/lua/conform/formatters/yapf.lua 0000664 0000000 0000000 00000000532 15051732407 0022214 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/google/yapf",
description = "Yet Another Python Formatter.",
},
command = "yapf",
args = { "--quiet" },
range_args = function(self, ctx)
return { "--quiet", "--lines", string.format("%d-%d", ctx.range.start[1], ctx.range["end"][1]) }
end,
}
conform.nvim-9.1.0/lua/conform/formatters/yew-fmt.lua 0000664 0000000 0000000 00000001220 15051732407 0022640 0 ustar 00root root 0000000 0000000 local util = require("conform.util")
---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/schvv31n/yew-fmt",
description = "Code formatter for the Yew framework.",
},
command = "yew-fmt",
options = {
-- The default edition of Rust to use when no Cargo.toml file is found
default_edition = "2021",
},
args = function(self, ctx)
local args = { "--emit=stdout" }
local edition = util.parse_rust_edition(ctx.dirname) or self.options.default_edition
table.insert(args, "--edition=" .. edition)
return args
end,
cwd = util.root_file({
"rustfmt.toml",
".rustfmt.toml",
}),
}
conform.nvim-9.1.0/lua/conform/formatters/yq.lua 0000664 0000000 0000000 00000000320 15051732407 0021701 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/mikefarah/yq",
description = "YAML/JSON processor",
},
command = "yq",
args = { "-P", "-" },
stdin = true,
}
conform.nvim-9.1.0/lua/conform/formatters/zigfmt.lua 0000664 0000000 0000000 00000000334 15051732407 0022555 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/ziglang/zig",
description = "Reformat Zig source into canonical form.",
},
command = "zig",
args = { "fmt", "--stdin" },
}
conform.nvim-9.1.0/lua/conform/formatters/ziggy.lua 0000664 0000000 0000000 00000000417 15051732407 0022410 0 ustar 00root root 0000000 0000000 ---@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" },
}
conform.nvim-9.1.0/lua/conform/formatters/ziggy_schema.lua 0000664 0000000 0000000 00000000426 15051732407 0023730 0 ustar 00root root 0000000 0000000 ---@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" },
}
conform.nvim-9.1.0/lua/conform/formatters/zprint.lua 0000664 0000000 0000000 00000000706 15051732407 0022606 0 ustar 00root root 0000000 0000000 ---@type conform.FileFormatterConfig
return {
meta = {
url = "https://github.com/kkinnear/zprint",
description = "Formatter for Clojure and EDN.",
},
command = "zprint",
range_args = function(self, ctx)
return {
string.format(
"{:input {:range {:start %d :end %d :use-previous-!zprint? true :continue-after-!zprint-error? true}}}",
ctx.range.start[1] - 1,
ctx.range["end"][1] - 1
),
}
end,
}
conform.nvim-9.1.0/lua/conform/fs.lua 0000664 0000000 0000000 00000004603 15051732407 0017502 0 ustar 00root root 0000000 0000000 local M = {}
local uv = vim.uv or vim.loop
---@type boolean
M.is_windows = uv.os_uname().version:match("Windows")
M.is_mac = uv.os_uname().sysname == "Darwin"
---@type string
M.sep = M.is_windows and "\\" or "/"
---@param ... string
M.join = function(...)
return table.concat({ ... }, M.sep)
end
M.is_absolute = function(path)
if M.is_windows then
return path:lower():match("^%a:")
else
return vim.startswith(path, "/")
end
end
M.abspath = function(path)
if not M.is_absolute(path) then
path = vim.fn.fnamemodify(path, ":p")
end
return path
end
---Returns true if candidate is a subpath of root, or if they are the same path.
---@param root string
---@param candidate string
---@return boolean
M.is_subpath = function(root, candidate)
if candidate == "" then
return false
end
root = vim.fs.normalize(M.abspath(root))
-- Trim trailing "/" from the root
if root:find("/", -1) then
root = root:sub(1, -2)
end
candidate = vim.fs.normalize(M.abspath(candidate))
if M.is_windows then
root = root:lower()
candidate = candidate:lower()
end
if root == candidate then
return true
end
local prefix = candidate:sub(1, root:len())
if prefix ~= root then
return false
end
local candidate_starts_with_sep = candidate:find("/", root:len() + 1, true) == root:len() + 1
local root_ends_with_sep = root:find("/", root:len(), true) == root:len()
return candidate_starts_with_sep or root_ends_with_sep
end
---Create a relative path from the source to the target
---@param source string
---@param target string
---@return string
M.relative_path = function(source, target)
source = M.abspath(source)
target = M.abspath(target)
local path = {}
while not M.is_subpath(source, target) do
table.insert(path, "..")
local new_source = vim.fs.dirname(source)
-- If source is a root directory, we can't go up further so there is no relative path to the
-- target. This should only happen on Windows, which prohibits relative paths between drives.
if source == new_source then
local log = require("conform.log")
log.warn("Could not find relative path from %s to %s", source, target)
return target
end
source = new_source
end
local offset = vim.endswith(source, M.sep) and 1 or 2
local rel_target = target:sub(source:len() + offset)
table.insert(path, rel_target)
return M.join(unpack(path))
end
return M
conform.nvim-9.1.0/lua/conform/ft_to_ext.lua 0000664 0000000 0000000 00000000340 15051732407 0021057 0 ustar 00root root 0000000 0000000 return {
elixir = "ex",
graphql = "gql",
javascript = "js",
javascriptreact = "jsx",
markdown = "md",
perl = "pl",
python = "py",
ruby = "rb",
rust = "rs",
typescript = "ts",
typescriptreact = "tsx",
}
conform.nvim-9.1.0/lua/conform/health.lua 0000664 0000000 0000000 00000014634 15051732407 0020344 0 ustar 00root root 0000000 0000000 local M = {}
---@param name string
---@return string[]
local function get_formatter_filetypes(name)
local conform = require("conform")
local filetypes = {}
for filetype, formatters in pairs(conform.formatters_by_ft) do
if type(formatters) == "function" then
formatters = formatters(0)
end
for _, ft_name in ipairs(formatters) do
if type(ft_name) == "string" then
if ft_name == name then
table.insert(filetypes, filetype)
break
end
else
if vim.tbl_contains(ft_name, name) then
table.insert(filetypes, filetype)
break
end
end
end
end
return filetypes
end
M.check = function()
local conform = require("conform")
vim.health.start("conform.nvim report")
local log = require("conform.log")
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
vim.health.warn(string.format("%s unavailable: %s", formatter.name, formatter.available_msg))
else
local filetypes = get_formatter_filetypes(formatter.name)
vim.health.ok(string.format("%s ready (%s)", formatter.name, table.concat(filetypes, ", ")))
end
end
end
---@param formatters conform.FiletypeFormatterInternal
---@return string[]
local function flatten_formatters(formatters)
local flat = {}
for _, name in ipairs(formatters) do
if type(name) == "string" then
table.insert(flat, name)
else
for _, f in ipairs(flatten_formatters(name)) do
table.insert(flat, f)
end
end
end
return flat
end
M.show_window = function()
local conform = require("conform")
local log = require("conform.log")
local lsp_format = require("conform.lsp_format")
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, #lines[#lines] })
end
table.insert(lines, string.format("Log file: %s", logfile))
table.insert(highlights, { "Title", #lines, 0, 10 })
if vim.fn.filereadable(logfile) == 1 then
local f = io.open(logfile, "r")
if f then
local context = -1024
-- Show more logs if the log level is set to trace.
if log.level == vim.log.levels.TRACE then
context = 3 * context
end
f:seek("end", context)
local text = f:read("*a")
f:close()
local log_lines = vim.split(text, "\r?\n", { trimempty = true })
for i = 2, #log_lines do
table.insert(lines, string.rep(" ", 10) .. log_lines[i])
end
end
end
table.insert(lines, "")
---@param formatter conform.FormatterInfo
local function append_formatter_info(formatter)
if not formatter.available then
local type_label = formatter.error and "error" or "unavailable"
local line = string.format("%s %s: %s", formatter.name, type_label, formatter.available_msg)
table.insert(lines, line)
local hl = formatter.error and "DiagnosticError" or "DiagnosticWarn"
local hl_start = formatter.name:len() + 1
table.insert(highlights, { hl, #lines, hl_start, hl_start + type_label:len() })
else
local filetypes = get_formatter_filetypes(formatter.name)
local filetypes_list = table.concat(filetypes, ", ")
local path = vim.fn.exepath(formatter.command)
local line = string.format("%s ready (%s) %s", formatter.name, filetypes_list, path)
table.insert(lines, line)
table.insert(
highlights,
{ "DiagnosticOk", #lines, formatter.name:len(), formatter.name:len() + 6 }
)
table.insert(highlights, {
"DiagnosticInfo",
#lines,
formatter.name:len() + 7 + filetypes_list:len() + 3,
line:len(),
})
end
end
local seen = {}
---@param formatters string[]
local function append_formatters(formatters)
for _, name in ipairs(formatters) do
if type(name) == "table" then
append_formatters(name)
else
seen[name] = true
local formatter = conform.get_formatter_info(name)
append_formatter_info(formatter)
end
end
end
table.insert(lines, "Formatters for this buffer:")
table.insert(highlights, { "Title", #lines, 0, #lines[#lines] })
local lsp_clients = lsp_format.get_format_clients({ bufnr = vim.api.nvim_get_current_buf() })
local has_lsp_formatter = not vim.tbl_isempty(lsp_clients)
if has_lsp_formatter then
table.insert(lines, "LSP: " .. table.concat(
vim.tbl_map(function(c)
return c.name
end, lsp_clients),
", "
))
end
local buf_formatters = flatten_formatters(conform.list_formatters_for_buffer())
append_formatters(buf_formatters)
if vim.tbl_isempty(buf_formatters) and not has_lsp_formatter then
table.insert(lines, "")
end
table.insert(lines, "")
table.insert(lines, "Other formatters:")
table.insert(highlights, { "Title", #lines, 0, #lines[#lines] })
for _, formatter in ipairs(conform.list_all_formatters()) do
if not seen[formatter.name] then
append_formatter_info(formatter)
end
end
local bufnr = vim.api.nvim_create_buf(false, true)
local winid = vim.api.nvim_open_win(bufnr, true, {
relative = "editor",
border = "rounded",
width = vim.o.columns - 6,
height = vim.o.lines - 6,
col = 2,
row = 2,
style = "minimal",
})
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, lines)
vim.bo[bufnr].modifiable = false
vim.bo[bufnr].modified = false
vim.bo[bufnr].bufhidden = "wipe"
vim.keymap.set("n", "q", "close", { buffer = bufnr, nowait = true })
vim.keymap.set("n", "", "close", { buffer = bufnr })
vim.api.nvim_create_autocmd("BufLeave", {
desc = "Close info window when leaving buffer",
buffer = bufnr,
once = true,
nested = true,
callback = function()
if vim.api.nvim_win_is_valid(winid) then
vim.api.nvim_win_close(winid, true)
end
end,
})
local ns = vim.api.nvim_create_namespace("conform")
for _, hl in ipairs(highlights) do
local group, lnum, col_start, col_end = unpack(hl)
vim.api.nvim_buf_set_extmark(bufnr, ns, lnum - 1, col_start, {
end_col = col_end,
hl_group = group,
})
end
end
return M
conform.nvim-9.1.0/lua/conform/init.lua 0000664 0000000 0000000 00000065356 15051732407 0020051 0 ustar 00root root 0000000 0000000 local M = {}
---@type table
M.formatters_by_ft = {}
---@type table
M.formatters = {}
M.notify_on_error = true
M.notify_no_formatters = true
---@type conform.DefaultFormatOpts
M.default_format_opts = {}
-- Defer notifications because nvim-notify can throw errors if called immediately
-- in some contexts (e.g. inside statusline function)
local notify = vim.schedule_wrap(function(...)
vim.notify(...)
end)
local notify_once = vim.schedule_wrap(function(...)
vim.notify_once(...)
end)
local allowed_default_opts = { "timeout_ms", "lsp_format", "quiet", "stop_after_first" }
local allowed_default_filetype_opts = { "name", "id", "filter" }
---@param a table
---@param b table
---@param opts? { allow_filetype_opts?: boolean }
---@return table
local function merge_default_opts(a, b, opts)
for _, key in ipairs(allowed_default_opts) do
if a[key] == nil then
a[key] = b[key]
end
end
if opts and opts.allow_filetype_opts then
for _, key in ipairs(allowed_default_filetype_opts) do
if a[key] == nil then
a[key] = b[key]
end
end
end
return a
end
---@param conf? conform.FiletypeFormatter
local function check_for_default_opts(conf)
if not conf or type(conf) ~= "table" then
return
end
for k in pairs(conf) do
if type(k) == "string" then
notify(
string.format(
'conform.setup: the "*" key in formatters_by_ft does not support configuring format options, such as "%s"',
k
),
vim.log.levels.WARN
)
break
end
end
end
---@param opts? conform.setupOpts
M.setup = function(opts)
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 {}
M.formatters = vim.tbl_extend("force", M.formatters, opts.formatters or {})
M.formatters_by_ft = vim.tbl_extend("force", M.formatters_by_ft, opts.formatters_by_ft or {})
check_for_default_opts(M.formatters_by_ft["*"])
M.default_format_opts =
vim.tbl_extend("force", M.default_format_opts, opts.default_format_opts or {})
if opts.log_level then
require("conform.log").level = opts.log_level
end
if opts.notify_on_error ~= nil then
M.notify_on_error = opts.notify_on_error
end
if opts.notify_no_formatters ~= nil then
M.notify_no_formatters = opts.notify_no_formatters
end
local aug = vim.api.nvim_create_augroup("Conform", { clear = true })
if opts.format_on_save then
if type(opts.format_on_save) == "boolean" then
opts.format_on_save = {}
end
vim.api.nvim_create_autocmd("BufWritePre", {
desc = "Format on save",
pattern = "*",
group = aug,
callback = function(args)
if not vim.api.nvim_buf_is_valid(args.buf) or vim.bo[args.buf].buftype ~= "" then
return
end
local format_args, callback = opts.format_on_save, nil
if type(format_args) == "function" then
format_args, callback = format_args(args.buf)
end
if format_args then
if format_args.async then
notify_once(
"Conform format_on_save cannot use async=true. Use format_after_save instead.",
vim.log.levels.ERROR
)
end
M.format(
vim.tbl_deep_extend("force", format_args, {
buf = args.buf,
async = false,
}),
callback
)
end
end,
})
vim.api.nvim_create_autocmd("VimLeavePre", {
desc = "conform.nvim hack to work around Neovim bug",
pattern = "*",
group = aug,
callback = function()
-- HACK: Work around https://github.com/neovim/neovim/issues/21856
-- causing exit code 134 on :wq
vim.cmd.sleep({ args = { "1m" } })
end,
})
end
if opts.format_after_save then
if type(opts.format_after_save) == "boolean" then
opts.format_after_save = {}
end
local exit_timeout = 1000
local num_running_format_jobs = 0
vim.api.nvim_create_autocmd("BufWritePost", {
desc = "Format after save",
pattern = "*",
group = aug,
callback = function(args)
if
not vim.api.nvim_buf_is_valid(args.buf)
or vim.b[args.buf].conform_applying_formatting
or vim.bo[args.buf].buftype ~= ""
then
return
end
local format_args, callback = opts.format_after_save, nil
if type(format_args) == "function" then
format_args, callback = format_args(args.buf)
end
if format_args then
exit_timeout = format_args.timeout_ms or exit_timeout
num_running_format_jobs = num_running_format_jobs + 1
if format_args.async == false then
notify_once(
"Conform format_after_save cannot use async=false. Use format_on_save instead.",
vim.log.levels.ERROR
)
end
M.format(
vim.tbl_deep_extend("force", format_args, {
buf = args.buf,
async = true,
}),
function(err)
num_running_format_jobs = num_running_format_jobs - 1
if not err and vim.api.nvim_buf_is_valid(args.buf) then
vim.api.nvim_buf_call(args.buf, function()
vim.b[args.buf].conform_applying_formatting = true
vim.cmd.update()
vim.b[args.buf].conform_applying_formatting = false
end)
end
if callback then
callback(err)
end
end
)
end
end,
})
vim.api.nvim_create_autocmd("BufWinLeave", {
desc = "conform.nvim store changedtick for use during Neovim exit",
pattern = "*",
group = aug,
callback = function(args)
-- We store this because when vim is exiting it will set changedtick = -1 for visible
-- buffers right after firing BufWinLeave
vim.b[args.buf].last_changedtick = vim.api.nvim_buf_get_changedtick(args.buf)
end,
})
vim.api.nvim_create_autocmd("VimLeavePre", {
desc = "conform.nvim wait for running formatters before exit",
pattern = "*",
group = aug,
callback = function()
if num_running_format_jobs == 0 then
return
end
local uv = vim.uv or vim.loop
local start = uv.hrtime() / 1e6
vim.wait(exit_timeout, function()
return num_running_format_jobs == 0
end, 10)
local elapsed = uv.hrtime() / 1e6 - start
if elapsed > 200 then
local log = require("conform.log")
log.warn("Delayed Neovim exit by %dms to wait for formatting to complete", elapsed)
end
-- HACK: Work around https://github.com/neovim/neovim/issues/21856
-- causing exit code 134 on :wq
vim.cmd.sleep({ args = { "1m" } })
end,
})
end
end
---@param obj any
---@return boolean
local function is_empty_table(obj)
return type(obj) == "table" and vim.tbl_isempty(obj)
end
---Get the configured formatter filetype for a buffer
---@param bufnr? integer
---@return nil|string filetype or nil if no formatter is configured. Can be "_".
local function get_matching_filetype(bufnr)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
local filetypes = vim.split(vim.bo[bufnr].filetype, ".", { plain = true })
-- Reverse the list so we can check the most specific filetypes first.
-- Start with the whole filetype, so users can specify an entire compound filetype if they want.
-- (e.g. "markdown.vimwiki")
local rev_filetypes = { vim.bo[bufnr].filetype }
for i = #filetypes, 1, -1 do
table.insert(rev_filetypes, filetypes[i])
end
table.insert(rev_filetypes, "_")
for _, filetype in ipairs(rev_filetypes) do
local ft_formatters = M.formatters_by_ft[filetype]
-- Sometimes people put an empty table here, and that should not count as configuring formatters
-- for a filetype.
if ft_formatters and not is_empty_table(ft_formatters) then
return filetype
end
end
end
---@private
---@param bufnr? integer
---@return string[]
M.list_formatters_for_buffer = function(bufnr)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
local formatters = {}
local seen = {}
local function dedupe_formatters(names, collect)
for _, name in ipairs(names) do
assert(
type(name) == "string",
"The nested {} syntax to run the first formatter has been replaced by the stop_after_first option (see :help conform.format)."
)
if not seen[name] then
table.insert(collect, name)
seen[name] = true
end
end
end
local filetypes = {}
local matching_filetype = get_matching_filetype(bufnr)
if matching_filetype then
table.insert(filetypes, matching_filetype)
end
table.insert(filetypes, "*")
for _, ft in ipairs(filetypes) do
local ft_formatters = M.formatters_by_ft[ft]
if ft_formatters then
if type(ft_formatters) == "function" then
dedupe_formatters(ft_formatters(bufnr), formatters)
else
dedupe_formatters(ft_formatters, formatters)
end
end
end
return formatters
end
---@param bufnr? integer
---@return nil|conform.DefaultFiletypeFormatOpts
local function get_opts_from_filetype(bufnr)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
local matching_filetype = get_matching_filetype(bufnr)
if not matching_filetype then
return nil
end
local ft_formatters = M.formatters_by_ft[matching_filetype]
assert(ft_formatters ~= nil, "get_matching_filetype ensures formatters_by_ft has key")
if type(ft_formatters) == "function" then
ft_formatters = ft_formatters(bufnr)
end
return merge_default_opts({}, ft_formatters, { allow_filetype_opts = true })
end
---@param bufnr integer
---@param mode "v"|"V"
---@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")
local end_ = vim.fn.getpos(".")
local start_row = start[2]
local start_col = start[3]
local end_row = end_[2]
local end_col = end_[3]
-- A user can start visual selection at the end and move backwards
-- Normalize the range to start < end
if start_row == end_row and end_col < start_col then
end_col, start_col = start_col, end_col
elseif end_row < start_row then
start_row, end_row = end_row, start_row
start_col, end_col = end_col, start_col
end
if mode == "V" then
start_col = 1
local lines = vim.api.nvim_buf_get_lines(bufnr, end_row - 1, end_row, true)
end_col = #lines[1]
end
return {
["start"] = { start_row, start_col - 1 },
["end"] = { end_row, end_col - 1 },
}
end
---@private
---@param names conform.FiletypeFormatterInternal
---@param bufnr integer
---@param warn_on_missing boolean
---@param stop_after_first boolean
---@return conform.FormatterInfo[]
M.resolve_formatters = function(names, bufnr, warn_on_missing, stop_after_first)
local all_info = {}
local function add_info(info, warn)
if info.available then
table.insert(all_info, info)
elseif warn then
notify(
string.format("Formatter '%s' unavailable: %s", info.name, info.available_msg),
vim.log.levels.WARN
)
end
return info.available
end
for _, name in ipairs(names) do
assert(
type(name) == "string",
"The nested {} syntax to run the first formatter has been replaced by the stop_after_first option (see :help conform.format)."
)
local info = M.get_formatter_info(name, bufnr)
add_info(info, warn_on_missing)
if stop_after_first and #all_info > 0 then
break
end
end
return all_info
end
---@param opts table
---@return boolean
local function has_lsp_formatter(opts)
local lsp_format = require("conform.lsp_format")
return not vim.tbl_isempty(lsp_format.get_format_clients(opts))
end
local has_notified_ft_no_formatters = {}
---Format a buffer
---@param opts? conform.FormatOpts
---@param callback? fun(err: nil|string, did_edit: nil|boolean) Called once formatting has completed
---@return boolean True if any formatters were attempted
---@example
--- -- Synchronously format the current buffer
--- conform.format({ lsp_format = "fallback" })
--- -- Asynchronously format the current buffer; will not block the UI
--- conform.format({ async = true }, function(err, did_edit)
--- -- called after formatting
--- end
--- -- Format the current buffer with a specific formatter
--- conform.format({ formatters = { "ruff_fix" } })
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
if not has_explicit_formatters then
merge_default_opts(
opts,
get_opts_from_filetype(opts.bufnr) or {},
{ allow_filetype_opts = true }
)
end
merge_default_opts(opts, M.default_format_opts)
---@type {timeout_ms: integer, bufnr: integer, async: boolean, dry_run: boolean, lsp_format: "never"|"first"|"last"|"prefer"|"fallback", quiet: boolean, stop_after_first: boolean, formatters?: string[], range?: conform.Range, undojoin: boolean}
opts = vim.tbl_extend("keep", opts, {
timeout_ms = 1000,
bufnr = 0,
async = false,
dry_run = false,
lsp_format = "never",
quiet = false,
undojoin = false,
stop_after_first = false,
})
if opts.bufnr == 0 then
opts.bufnr = vim.api.nvim_get_current_buf()
end
-- For backwards compatibility
---@diagnostic disable-next-line: undefined-field
if opts.lsp_fallback == true then
opts.lsp_format = "fallback"
---@diagnostic disable-next-line: undefined-field
elseif opts.lsp_fallback == "always" then
opts.lsp_format = "last"
end
local mode = vim.api.nvim_get_mode().mode
if not opts.range and (mode == "v" or mode == "V") then
opts.range = range_from_selection(opts.bufnr, mode)
end
callback = callback or function(_err, _did_edit) end
local errors = require("conform.errors")
local log = require("conform.log")
local lsp_format = require("conform.lsp_format")
local runner = require("conform.runner")
local formatter_names = opts.formatters or M.list_formatters_for_buffer(opts.bufnr)
local formatters = M.resolve_formatters(
formatter_names,
opts.bufnr,
not opts.quiet and has_explicit_formatters,
opts.stop_after_first
)
local has_lsp = has_lsp_formatter(opts)
---Handle errors and maybe run LSP formatting after cli formatters complete
---@param err? conform.Error
---@param did_edit? boolean
local function handle_result(err, did_edit)
if err then
local level = errors.level_for_code(err.code)
log.log(level, err.message)
---@type boolean?
local should_notify = not opts.quiet and level >= vim.log.levels.WARN
-- Execution errors have special handling. Maybe should reconsider this.
local notify_msg = err.message
if errors.is_execution_error(err.code) then
should_notify = should_notify and M.notify_on_error and not err.debounce_message
notify_msg = "Formatter failed. See :ConformInfo for details"
end
if should_notify then
notify(notify_msg, level)
end
end
local err_message = err and err.message
if not err_message and not vim.api.nvim_buf_is_valid(opts.bufnr) then
err_message = "buffer was deleted"
end
if err_message then
return callback(err_message)
end
if opts.dry_run and did_edit then
callback(nil, true)
elseif opts.lsp_format == "last" and has_lsp then
log.debug("Running LSP formatter on %s", vim.api.nvim_buf_get_name(opts.bufnr))
lsp_format.format(opts, callback)
else
callback(nil, did_edit)
end
end
---Run the resolved formatters on the buffer
local function run_cli_formatters(cb)
local resolved_names = vim.tbl_map(function(f)
return f.name
end, formatters)
log.debug("Running formatters on %s: %s", vim.api.nvim_buf_get_name(opts.bufnr), resolved_names)
---@type conform.RunOpts
local run_opts = { exclusive = true, dry_run = opts.dry_run, undojoin = opts.undojoin }
if opts.async then
runner.format_async(opts.bufnr, formatters, opts.range, run_opts, cb)
else
local err, did_edit =
runner.format_sync(opts.bufnr, formatters, opts.timeout_ms, opts.range, run_opts)
cb(err, did_edit)
end
end
-- check if at least one of the configured formatters is available
local any_formatters = not vim.tbl_isempty(formatters)
if
has_lsp
and (opts.lsp_format == "prefer" or (opts.lsp_format ~= "never" and not any_formatters))
then
-- LSP formatting only
log.debug("Running LSP formatter on %s", vim.api.nvim_buf_get_name(opts.bufnr))
lsp_format.format(opts, callback)
return true
elseif has_lsp and opts.lsp_format == "first" then
-- LSP formatting, then other formatters
log.debug("Running LSP formatter on %s", vim.api.nvim_buf_get_name(opts.bufnr))
lsp_format.format(opts, function(err, did_edit)
if err or (did_edit and opts.dry_run) then
return callback(err, did_edit)
end
run_cli_formatters(function(err2, did_edit2)
handle_result(err2, did_edit or did_edit2)
end)
end)
return true
elseif not vim.tbl_isempty(formatters) then
run_cli_formatters(handle_result)
return true
else
local level = has_explicit_formatters and "warn" or "debug"
log[level]("Formatters unavailable for %s", vim.api.nvim_buf_get_name(opts.bufnr))
local ft = vim.bo[opts.bufnr].filetype
if
not vim.tbl_isempty(formatter_names)
and not has_notified_ft_no_formatters[ft]
and not opts.quiet
and M.notify_no_formatters
then
notify(string.format("Formatters unavailable for %s file", ft), vim.log.levels.WARN)
has_notified_ft_no_formatters[ft] = true
end
callback("No formatters available for buffer")
return false
end
end
---Process lines with formatters
---@private
---@param formatter_names string[]
---@param lines string[]
---@param opts? conform.FormatLinesOpts
---@param callback? fun(err: nil|conform.Error, lines: nil|string[]) Called once formatting has completed
---@return nil|conform.Error error Only present if async = false
---@return nil|string[] new_lines Only present if async = false
M.format_lines = function(formatter_names, lines, opts, callback)
---@type {timeout_ms: integer, bufnr: integer, async: boolean, quiet: boolean, stop_after_first: boolean}
opts = vim.tbl_extend("keep", opts or {}, {
timeout_ms = 1000,
bufnr = 0,
async = false,
quiet = false,
stop_after_first = false,
})
callback = callback or function(_err, _lines) end
local errors = require("conform.errors")
local log = require("conform.log")
local runner = require("conform.runner")
local formatters =
M.resolve_formatters(formatter_names, opts.bufnr, not opts.quiet, opts.stop_after_first)
if vim.tbl_isempty(formatters) then
callback(nil, lines)
return
end
---@param err? conform.Error
---@param new_lines? string[]
local function handle_err(err, new_lines)
if err then
local level = errors.level_for_code(err.code)
log.log(level, err.message)
end
callback(err, new_lines)
end
---@type conform.RunOpts
local run_opts = { exclusive = false, dry_run = false, undojoin = false }
if opts.async then
runner.format_lines_async(opts.bufnr, formatters, nil, lines, run_opts, handle_err)
else
local err, new_lines =
runner.format_lines_sync(opts.bufnr, formatters, opts.timeout_ms, nil, lines, run_opts)
handle_err(err, new_lines)
return err, new_lines
end
end
---Retrieve the available formatters for a buffer
---@param bufnr? integer
---@return conform.FormatterInfo[]
M.list_formatters = function(bufnr)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
local formatters = M.list_formatters_for_buffer(bufnr)
return M.resolve_formatters(formatters, bufnr, false, false)
end
---Get the exact formatters that will be run for a buffer.
---@param bufnr? integer
---@return conform.FormatterInfo[]
---@return boolean lsp Will use LSP formatter
---@note
--- This accounts for stop_after_first, lsp fallback logic, etc.
M.list_formatters_to_run = function(bufnr)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
---@type {bufnr: integer, lsp_format: conform.LspFormatOpts, stop_after_first: boolean}
local opts = vim.tbl_extend(
"keep",
get_opts_from_filetype(bufnr) or {},
M.default_format_opts,
{ stop_after_first = false, lsp_format = "never", bufnr = bufnr }
)
local formatter_names = M.list_formatters_for_buffer(bufnr)
local formatters = M.resolve_formatters(formatter_names, bufnr, false, opts.stop_after_first)
local has_lsp = has_lsp_formatter(opts)
local any_formatters = not vim.tbl_isempty(formatters)
if
has_lsp
and (opts.lsp_format == "prefer" or (opts.lsp_format ~= "never" and not any_formatters))
then
return {}, true
elseif has_lsp and opts.lsp_format == "first" then
return formatters, true
elseif not vim.tbl_isempty(formatters) then
return formatters, opts.lsp_format == "last" and has_lsp
else
return {}, false
end
end
---List information about all filetype-configured formatters
---@return conform.FormatterInfo[]
M.list_all_formatters = function()
local formatters = {}
for _, ft_formatters in pairs(M.formatters_by_ft) do
if type(ft_formatters) == "function" then
ft_formatters = ft_formatters(0)
end
for _, formatter in ipairs(ft_formatters) do
assert(
type(formatter) == "string",
"The nested {} syntax to run the first formatter has been replaced by the stop_after_first option (see :help conform.format)."
)
formatters[formatter] = true
end
end
---@type conform.FormatterInfo[]
local all_info = {}
for formatter in pairs(formatters) do
local info = M.get_formatter_info(formatter)
table.insert(all_info, info)
end
table.sort(all_info, function(a, b)
return a.name < b.name
end)
return all_info
end
---@private
---@param formatter string
---@param bufnr? integer
---@return nil|conform.FormatterConfig
M.get_formatter_config = function(formatter, bufnr)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
---@type nil|conform.FormatterConfigOverride|fun(bufnr: integer): nil|conform.FormatterConfigOverride
local override = M.formatters[formatter]
if type(override) == "function" then
override = override(bufnr)
end
if override and override.command and override.format then
local msg =
string.format("Formatter '%s' cannot define both 'command' and 'format' function", formatter)
notify_once(msg, vim.log.levels.ERROR)
return nil
end
---@type nil|conform.FormatterConfig
local config = override
if not override or override.inherit ~= false then
local ok, mod_config = pcall(require, "conform.formatters." .. formatter)
if ok then
if override then
config = require("conform.util").merge_formatter_configs(mod_config, override)
else
config = mod_config
end
elseif override then
if override.command or override.format then
config = override
else
local msg = string.format(
"Formatter '%s' missing built-in definition\nSet `command` to get rid of this error.",
formatter
)
notify_once(msg, vim.log.levels.ERROR)
return nil
end
else
return nil
end
end
if config and config.stdin == nil then
config.stdin = true
end
return config
end
---Get information about a formatter (including availability)
---@param formatter string The name of the formatter
---@param bufnr? integer
---@return conform.FormatterInfo
M.get_formatter_info = function(formatter, bufnr)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
local config = M.get_formatter_config(formatter, bufnr)
if not config then
return {
name = formatter,
command = formatter,
available = false,
available_msg = "Unknown formatter. Formatter config missing or incomplete",
error = true,
}
end
local ctx = require("conform.runner").build_context(bufnr, config)
local available = true
local available_msg = nil
if config.format then
---@cast config conform.LuaFormatterConfig
if config.condition and not config:condition(ctx) then
available = false
available_msg = "Condition failed"
end
return {
name = formatter,
command = formatter,
available = available,
available_msg = available_msg,
}
end
local command = config.command
if type(command) == "function" then
---@cast config conform.JobFormatterConfig
command = command(config, ctx)
end
if vim.fn.executable(command) == 0 then
available = false
available_msg = string.format("Command '%s' not found", command)
elseif config.condition and not config.condition(config, ctx) then
available = false
available_msg = "Condition failed"
end
local cwd = nil
if config.cwd then
---@cast config conform.JobFormatterConfig
cwd = config.cwd(config, ctx)
if available and not cwd and config.require_cwd then
available = false
available_msg = "Root directory not found"
end
end
---@type conform.FormatterInfo
return {
name = formatter,
command = command,
cwd = cwd,
available = available,
available_msg = available_msg,
}
end
M.formatexpr = function(opts)
-- Change the defaults slightly from conform.format
opts = vim.tbl_deep_extend("keep", opts or {}, {
timeout_ms = 500,
lsp_format = "fallback",
bufnr = vim.api.nvim_get_current_buf(),
})
-- Force async = false
opts.async = false
if vim.tbl_contains({ "i", "R", "ic", "ix" }, vim.fn.mode()) then
-- `formatexpr` is also called when exceeding `textwidth` in insert mode
-- fall back to internal formatting
return 1
end
local start_lnum = vim.v.lnum
local end_lnum = start_lnum + vim.v.count - 1
if start_lnum <= 0 or end_lnum <= 0 then
return 0
end
local end_line = vim.fn.getline(end_lnum)
local end_col = end_line:len()
if vim.v.count == vim.fn.line("$") then
-- Whole buffer is selected; use buffer formatting
opts.range = nil
else
opts.range = {
start = { start_lnum, 0 },
["end"] = { end_lnum, end_col },
}
end
M.format(opts)
return 0
end
return M
conform.nvim-9.1.0/lua/conform/log.lua 0000664 0000000 0000000 00000005210 15051732407 0017646 0 ustar 00root root 0000000 0000000 local uv = vim.uv or vim.loop
local levels_reverse = {}
for k, v in pairs(vim.log.levels) do
levels_reverse[v] = k
end
local Log = {}
---@type integer
Log.level = vim.log.levels.WARN
---@return string
Log.get_logfile = function()
local fs = require("conform.fs")
local ok, stdpath = pcall(vim.fn.stdpath, "log")
if not ok then
stdpath = vim.fn.stdpath("cache")
end
assert(type(stdpath) == "string")
return fs.join(stdpath, "conform.log")
end
---@param level integer
---@param msg string
---@param ... any[]
---@return string
local function format(level, msg, ...)
local args = vim.F.pack_len(...)
for i = 1, args.n do
local v = args[i]
if type(v) == "table" then
args[i] = vim.inspect(v)
elseif v == nil then
args[i] = "nil"
end
end
local ok, text = pcall(string.format, msg, vim.F.unpack_len(args))
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)
else
return string.format(
"%s[ERROR] error formatting log line: '%s' args %s",
timestr,
vim.inspect(msg),
vim.inspect(args)
)
end
end
---@param line string
local function write(line)
-- This will be replaced during initialization
end
local initialized = false
local function initialize()
if initialized then
return
end
initialized = true
local filepath = Log.get_logfile()
local stat = uv.fs_stat(filepath)
if stat and stat.size > 10 * 1024 * 1024 then
local backup = filepath .. ".1"
uv.fs_unlink(backup)
uv.fs_rename(filepath, backup)
end
local parent = vim.fs.dirname(filepath)
vim.fn.mkdir(parent, "p")
local logfile, openerr = io.open(filepath, "a+")
if not logfile then
local err_msg = string.format("Failed to open conform.nvim log file: %s", openerr)
vim.notify(err_msg, vim.log.levels.ERROR)
else
write = function(line)
logfile:write(line)
logfile:write("\n")
logfile:flush()
end
end
end
---Override the file handler e.g. for tests
---@param handler fun(line: string)
function Log.set_handler(handler)
write = handler
initialized = true
end
function Log.log(level, msg, ...)
if Log.level <= level then
initialize()
local text = format(level, msg, ...)
write(text)
end
end
function Log.trace(...)
Log.log(vim.log.levels.TRACE, ...)
end
function Log.debug(...)
Log.log(vim.log.levels.DEBUG, ...)
end
function Log.info(...)
Log.log(vim.log.levels.INFO, ...)
end
function Log.warn(...)
Log.log(vim.log.levels.WARN, ...)
end
function Log.error(...)
Log.log(vim.log.levels.ERROR, ...)
end
return Log
conform.nvim-9.1.0/lua/conform/lsp_format.lua 0000664 0000000 0000000 00000014314 15051732407 0021240 0 ustar 00root root 0000000 0000000 ---This module replaces the default vim.lsp.buf.format() so that we can inject our own logic
local log = require("conform.log")
local util = require("vim.lsp.util")
local M = {}
local function apply_text_edits(text_edits, bufnr, offset_encoding, dry_run, undojoin)
if
#text_edits == 1
and text_edits[1].range.start.line == 0
and text_edits[1].range.start.character == 0
and text_edits[1].range["end"].line >= vim.api.nvim_buf_line_count(bufnr)
and text_edits[1].range["end"].character == 0
then
local original_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
local new_lines = vim.split(text_edits[1].newText, "\r?\n", {})
-- If it had a trailing newline, remove it to make the lines match the expected vim format
if #new_lines > 1 and new_lines[#new_lines] == "" then
table.remove(new_lines)
end
log.debug("Converting full-file LSP format to piecewise format")
return require("conform.runner").apply_format(
bufnr,
original_lines,
new_lines,
nil,
false,
dry_run,
undojoin
)
elseif dry_run then
return #text_edits > 0
else
if undojoin then
pcall(vim.cmd.undojoin)
end
vim.lsp.util.apply_text_edits(text_edits, bufnr, offset_encoding)
return #text_edits > 0
end
end
---@param options table
---@return table[] clients
function M.get_format_clients(options)
local method = options.range and "textDocument/rangeFormatting" or "textDocument/formatting"
local clients
if vim.lsp.get_clients then
clients = vim.lsp.get_clients({
id = options.id,
bufnr = options.bufnr,
name = options.name,
method = method,
})
else
---@diagnostic disable-next-line: deprecated
clients = vim.lsp.get_active_clients({
id = options.id,
bufnr = options.bufnr,
name = options.name,
})
clients = vim.tbl_filter(function(client)
return client.supports_method(method, { bufnr = options.bufnr })
end, clients)
end
if options.filter then
clients = vim.tbl_filter(options.filter, clients)
end
return clients
end
---@param options conform.FormatOpts
---@param callback fun(err?: string, did_edit?: boolean)
function M.format(options, callback)
options = options or {}
local bufnr = options.bufnr
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
options.bufnr = bufnr
end
local range = options.range
local method = range and "textDocument/rangeFormatting" or "textDocument/formatting"
local clients = M.get_format_clients(options)
if #clients == 0 then
return callback("[LSP] Format request failed, no matching language servers.")
end
local function set_range(client, params)
if range then
local range_params =
util.make_given_range_params(range.start, range["end"], bufnr, client.offset_encoding)
params.range = range_params.range
end
return params
end
if options.async then
local changedtick = vim.b[bufnr].changedtick
local do_format
local did_edit = false
do_format = function(idx, client)
if not client then
return callback(nil, did_edit)
end
--- @diagnostic disable-next-line: param-type-mismatch
local params = set_range(client, util.make_formatting_params(options.formatting_options))
local auto_id = vim.api.nvim_create_autocmd("LspDetach", {
buffer = bufnr,
callback = function(args)
if args.data.client_id == client.id then
log.warn("LSP %s detached during format request", client.name)
callback("LSP detached")
end
end,
})
local request = vim.fn.has("nvim-0.11") == 1
and function(c, ...)
return c:request(...)
end
or function(c, ...)
return c.request(...)
end
request(client, method, params, function(err, result, ctx, _)
vim.api.nvim_del_autocmd(auto_id)
if not result then
return callback(err or "No result returned from LSP formatter")
elseif not vim.api.nvim_buf_is_valid(bufnr) then
return callback("buffer was deleted")
elseif changedtick ~= require("conform.util").buf_get_changedtick(bufnr) then
return callback(
string.format(
"Async LSP formatter discarding changes for %s: concurrent modification",
vim.api.nvim_buf_get_name(bufnr)
)
)
else
local this_did_edit = apply_text_edits(
result,
ctx.bufnr,
client.offset_encoding,
options.dry_run,
options.undojoin
)
changedtick = vim.b[bufnr].changedtick
if options.dry_run and this_did_edit then
callback(nil, true)
else
did_edit = did_edit or this_did_edit
do_format(next(clients, idx))
end
end
end, bufnr)
end
do_format(next(clients))
else
local timeout_ms = options.timeout_ms or 1000
local did_edit = false
local request_sync = vim.fn.has("nvim-0.11") == 1
and function(c, ...)
return c:request_sync(...)
end
or function(c, ...)
return c.request_sync(...)
end
for _, client in pairs(clients) do
--- @diagnostic disable-next-line: param-type-mismatch
local params = set_range(client, util.make_formatting_params(options.formatting_options))
local result, wait_error = request_sync(client, method, params, timeout_ms, bufnr)
local lsp_error = (result and result.err) or wait_error
if result and result.result then
local this_did_edit = apply_text_edits(
result.result,
bufnr,
client.offset_encoding,
options.dry_run,
options.undojoin
)
did_edit = did_edit or this_did_edit
if options.dry_run and did_edit then
callback(nil, true)
return true
end
elseif lsp_error then
if not options.quiet then
vim.notify(string.format("[LSP][%s] %s", client.name, lsp_error), vim.log.levels.WARN)
end
return callback(string.format("[LSP][%s] %s", client.name, lsp_error))
end
end
callback(nil, did_edit)
end
end
return M
conform.nvim-9.1.0/lua/conform/runner.lua 0000664 0000000 0000000 00000053377 15051732407 0020417 0 ustar 00root root 0000000 0000000 local errors = require("conform.errors")
local fs = require("conform.fs")
local ft_to_ext = require("conform.ft_to_ext")
local log = require("conform.log")
local util = require("conform.util")
local uv = vim.uv or vim.loop
local M = {}
---@class (exact) conform.RunOpts
---@field exclusive boolean If true, ensure only a single formatter is running per buffer
---@field dry_run boolean If true, do not apply changes and stop after the first formatter attempts to do so
---@field undojoin boolean Use undojoin to merge formatting changes with previous edit
---@param formatter_name string
---@param ctx conform.Context
---@param config conform.JobFormatterConfig
---@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
---@cast ctx conform.RangeContext
args = config.range_args(config, ctx)
elseif config.args then
local computed_args = config.args
if type(computed_args) == "function" then
args = computed_args(config, ctx)
elseif computed_args then
args = computed_args
end
end
local function compute_relative_filepath()
local cwd
if config.cwd then
cwd = config.cwd(config, ctx)
end
return fs.relative_path(cwd or vim.fn.getcwd(), ctx.filename)
end
if type(args) == "string" then
local interpolated = args
:gsub("$FILENAME", ctx.filename)
:gsub("$DIRNAME", ctx.dirname)
:gsub("$RELATIVE_FILEPATH", compute_relative_filepath)
:gsub("$EXTENSION", ctx.filename:match(".*(%..*)$") or "")
return util.shell_build_argv(command .. " " .. interpolated)
else
local cmd = { command }
for _, v in ipairs(args) do
if v == "$FILENAME" then
v = ctx.filename
elseif v == "$DIRNAME" then
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
return cmd
end
end
---@param value any
---@return boolean
local function truthy(value)
return value ~= nil and value ~= false
end
---@param range conform.Range
---@param start_a integer
---@param end_a integer
---@return boolean
local function indices_in_range(range, start_a, end_a)
return start_a <= range["end"][1] and range["start"][1] <= end_a
end
---@param a? string
---@param b? string
---@return integer
local function common_prefix_len(a, b)
if not a or not b then
return 0
end
local min_len = math.min(#a, #b)
for i = 1, min_len do
if string.byte(a, i) ~= string.byte(b, i) then
return i - 1
end
end
return min_len
end
---@param a string
---@param b string
---@return integer
local function common_suffix_len(a, b)
local a_len = #a
local b_len = #b
local min_len = math.min(a_len, b_len)
for i = 0, min_len - 1 do
if string.byte(a, a_len - i) ~= string.byte(b, b_len - i) then
return i
end
end
return min_len
end
local function create_text_edit(
original_lines,
replacement,
is_insert,
is_replace,
orig_line_start,
orig_line_end,
line_ending
)
local start_line, end_line = orig_line_start - 1, orig_line_end - 1
local start_char, end_char = 0, 0
if is_replace then
-- If we're replacing text, see if we can avoid replacing the entire line
start_char = common_prefix_len(original_lines[orig_line_start], replacement[1])
if start_char > 0 then
replacement[1] = replacement[1]:sub(start_char + 1)
end
if original_lines[orig_line_end] then
local last_line = replacement[#replacement]
local suffix = common_suffix_len(original_lines[orig_line_end], last_line)
-- If we're only replacing one line, make sure the prefix/suffix calculations don't overlap
if orig_line_end == orig_line_start then
suffix = math.min(suffix, original_lines[orig_line_end]:len() - start_char)
end
end_char = original_lines[orig_line_end]:len() - suffix
if suffix > 0 then
replacement[#replacement] = last_line:sub(1, last_line:len() - suffix)
end
end
end
-- If we're inserting text, make sure the text includes a newline at the end.
-- The one exception is if we're inserting at the end of the file, in which case the newline is
-- implicit
if is_insert and start_line < #original_lines then
table.insert(replacement, "")
end
local new_text = table.concat(replacement, line_ending)
return {
newText = new_text,
range = {
start = {
line = start_line,
character = start_char,
},
["end"] = {
line = end_line,
character = end_char,
},
},
}
end
---@param bufnr integer
---@param original_lines string[]
---@param new_lines string[]
---@param range? conform.Range
---@param only_apply_range boolean
---@param dry_run boolean
---@param undojoin boolean
---@return boolean any_changes
M.apply_format = function(
bufnr,
original_lines,
new_lines,
range,
only_apply_range,
dry_run,
undojoin
)
if bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
if not vim.api.nvim_buf_is_valid(bufnr) then
return false
end
local bufname = vim.api.nvim_buf_get_name(bufnr)
log.trace("Applying formatting to %s", bufname)
-- The vim.diff algorithm doesn't handle changes in newline-at-end-of-file well. The unified
-- result_type has some text to indicate that the eol changed, but the indices result_type has no
-- such indication. To work around this, we just add a trailing newline to the end of both the old
-- and the new text.
table.insert(original_lines, "")
table.insert(new_lines, "")
local original_text = table.concat(original_lines, "\n")
local new_text = table.concat(new_lines, "\n")
table.remove(original_lines)
table.remove(new_lines)
-- Abort if output is empty but input is not (i.e. has some non-whitespace characters).
-- This is to hack around oddly behaving formatters (e.g black outputs nothing for excluded files).
if new_text:match("^%s*$") and not original_text:match("^%s*$") then
log.warn("Aborting because a formatter returned empty output for buffer %s", bufname)
return false
end
log.trace("Comparing lines %s and %s", original_lines, new_lines)
---@diagnostic disable-next-line: missing-fields
local indices = vim.diff(original_text, new_text, {
result_type = "indices",
algorithm = "histogram",
})
assert(type(indices) == "table")
log.trace("Diff indices %s", indices)
local text_edits = {}
for _, idx in ipairs(indices) do
local orig_line_start, orig_line_count, new_line_start, new_line_count = unpack(idx)
local is_insert = orig_line_count == 0
local is_delete = new_line_count == 0
local is_replace = not is_insert and not is_delete
local orig_line_end = orig_line_start + orig_line_count
local new_line_end = new_line_start + new_line_count
if is_insert then
-- When the diff is an insert, it actually means to insert after the mentioned line
orig_line_start = orig_line_start + 1
orig_line_end = orig_line_end + 1
end
local replacement = util.tbl_slice(new_lines, new_line_start, new_line_end - 1)
-- For replacement edits, convert the end line to be inclusive
if is_replace then
orig_line_end = orig_line_end - 1
end
local should_apply_diff = not only_apply_range
or not range
or indices_in_range(range, orig_line_start, orig_line_end)
if should_apply_diff then
local text_edit = create_text_edit(
original_lines,
replacement,
is_insert,
is_replace,
orig_line_start,
orig_line_end,
util.buf_line_ending(bufnr)
)
table.insert(text_edits, text_edit)
-- If we're using the aftermarket range formatting, diffs often have paired delete/insert
-- diffs. We should make sure that if one of them overlaps our selected range, extend the
-- range so that we pick up the other diff as well.
if range and only_apply_range then
range = vim.deepcopy(range)
range["end"][1] = math.max(range["end"][1], orig_line_end + 1)
end
end
end
if not dry_run then
log.trace("Applying text edits: %s", text_edits)
if undojoin then
-- may fail if after undo
-- Vim:E790: undojoin is not allowed after undo
pcall(vim.cmd.undojoin)
end
vim.lsp.util.apply_text_edits(text_edits, bufnr, "utf-8")
log.trace("Done formatting %s", bufname)
end
return not vim.tbl_isempty(text_edits)
end
---@param output? string[]
---@return boolean
local function is_empty_output(output)
return not output or vim.tbl_isempty(output) or (#output == 1 and output[1] == "")
end
---Map of formatter name to if the last run of that formatter produced an error
---@type table
local last_run_errored = {}
---@param bufnr integer
---@param formatter conform.FormatterInfo
---@param config conform.FormatterConfig
---@param ctx conform.Context
---@param input_lines string[]
---@param opts conform.RunOpts
---@param callback fun(err?: conform.Error, output?: string[])
---@return integer? job_id
local function run_formatter(bufnr, formatter, config, ctx, input_lines, opts, callback)
local autocmd_data = {
formatter = {
name = formatter.name,
},
}
vim.api.nvim_exec_autocmds("User", {
pattern = "ConformFormatPre",
data = autocmd_data,
})
log.info("Run %s on %s", formatter.name, vim.api.nvim_buf_get_name(bufnr))
log.trace("Input lines: %s", input_lines)
callback = util.wrap_callback(callback, function(err)
if err then
if last_run_errored[formatter.name] then
err.debounce_message = true
end
last_run_errored[formatter.name] = true
else
last_run_errored[formatter.name] = false
end
autocmd_data["err"] = err
vim.api.nvim_exec_autocmds("User", {
pattern = "ConformFormatPost",
data = autocmd_data,
})
end)
if config.format then
local err_string_cb = function(err, ...)
if err then
callback({
code = errors.ERROR_CODE.RUNTIME,
message = err,
}, ...)
else
callback(nil, ...)
end
end
---@cast config conform.LuaFormatterConfig
local ok, err = pcall(config.format, config, ctx, input_lines, err_string_cb)
if not ok then
err_string_cb(string.format("Formatter '%s' error: %s", formatter.name, err))
end
return
end
---@cast config conform.JobFormatterConfig
local cmd = M.build_cmd(formatter.name, ctx, config)
local cwd = nil
if config.cwd then
cwd = config.cwd(config, ctx)
end
local env = config.env
if type(env) == "function" then
env = env(config, ctx)
end
local buffer_text
-- If the buffer has a newline at the end, make sure we include that in the input to the formatter
local add_extra_newline = vim.bo[bufnr].eol
if add_extra_newline then
table.insert(input_lines, "")
end
buffer_text = table.concat(input_lines, "\n")
if add_extra_newline then
table.remove(input_lines)
end
if not config.stdin then
log.debug("Creating temp file %s", ctx.filename)
local fd = assert(uv.fs_open(ctx.filename, "w", 448)) -- 0700
uv.fs_write(fd, buffer_text)
uv.fs_close(fd)
callback = util.wrap_callback(callback, function()
log.debug("Cleaning up temp file %s", ctx.filename)
uv.fs_unlink(ctx.filename)
end)
end
log.debug("Run command: %s", cmd)
if cwd then
log.debug("Run CWD: %s", cwd)
else
log.debug("Run default CWD: %s", vim.fn.getcwd())
end
if env then
log.debug("Run ENV: %s", env)
end
local exit_codes = config.exit_codes or { 0 }
local pid
local ok, job_or_err = pcall(
vim.system,
cmd,
{
cwd = cwd,
env = env,
stdin = config.stdin and buffer_text or nil,
text = true,
},
vim.schedule_wrap(function(result)
local code = result.code
local stdout = result.stdout and vim.split(result.stdout, "\r?\n") or {}
local stderr = result.stderr and vim.split(result.stderr, "\r?\n") or {}
if vim.tbl_contains(exit_codes, code) then
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")
end
-- Remove the trailing newline from the output to convert back to vim lines representation
if add_extra_newline and output[#output] == "" then
table.remove(output)
end
-- Vim will never let the lines array be empty. An empty file will still look like { "" }
if #output == 0 then
table.insert(output, "")
end
log.debug("%s exited with code %d", formatter.name, code)
log.trace("Output lines: %s", output)
log.trace("%s stderr: %s", formatter.name, stderr)
callback(nil, output)
else
log.info("%s exited with code %d", formatter.name, code)
log.debug("%s stdout: %s", formatter.name, stdout)
log.debug("%s stderr: %s", formatter.name, stderr)
local err_str
if not is_empty_output(stderr) then
err_str = table.concat(stderr, "\n")
elseif not is_empty_output(stdout) then
err_str = table.concat(stdout, "\n")
else
err_str = "unknown error"
end
if
vim.api.nvim_buf_is_valid(bufnr)
and pid ~= vim.b[bufnr].conform_pid
and opts.exclusive
then
callback({
code = errors.ERROR_CODE.INTERRUPTED,
message = string.format("Formatter '%s' was interrupted", formatter.name),
})
else
callback({
code = errors.ERROR_CODE.RUNTIME,
message = string.format("Formatter '%s' error: %s", formatter.name, err_str),
})
end
end
end)
)
if not ok then
callback({
code = errors.ERROR_CODE.VIM_SYSTEM,
message = string.format("Formatter '%s' error in vim.system: %s", formatter.name, job_or_err),
})
return
end
pid = job_or_err.pid
if opts.exclusive then
vim.b[bufnr].conform_pid = pid
end
return pid
end
---@param bufnr integer
---@param config conform.FormatterConfig
---@param range? conform.Range
---@return conform.Context
M.build_context = function(bufnr, config, range)
if bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
local filename = vim.api.nvim_buf_get_name(bufnr)
local shiftwidth = vim.bo[bufnr].shiftwidth
if shiftwidth == 0 then
shiftwidth = vim.bo[bufnr].tabstop
end
-- Hack around checkhealth. For buffers that are not files, we need to fabricate a filename
if vim.bo[bufnr].buftype ~= "" then
filename = ""
end
local dirname
if filename == "" then
dirname = vim.fn.getcwd()
filename = fs.join(dirname, "unnamed_temp")
local ft = vim.bo[bufnr].filetype
if ft and ft ~= "" then
filename = filename .. "." .. (ft_to_ext[ft] or ft)
end
else
dirname = vim.fs.dirname(filename)
end
if not config.stdin then
local template = config.tmpfile_format
if not template then
template = ".conform.$RANDOM.$FILENAME"
end
local basename = vim.fs.basename(filename)
local tmpname =
template:gsub("$RANDOM", tostring(math.random(1000000, 9999999))):gsub("$FILENAME", basename)
local parent = vim.fs.dirname(filename)
filename = fs.join(parent, tmpname)
end
return {
buf = bufnr,
filename = filename,
dirname = dirname,
range = range,
shiftwidth = shiftwidth,
}
end
---@param bufnr integer
---@param formatters conform.FormatterInfo[]
---@param range? conform.Range
---@param opts conform.RunOpts
---@param callback fun(err?: conform.Error, did_edit?: boolean)
M.format_async = function(bufnr, formatters, range, opts, callback)
if bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
-- kill previous jobs for buffer
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
local original_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
local changedtick = vim.b[bufnr].changedtick
M.format_lines_async(
bufnr,
formatters,
range,
original_lines,
opts,
function(err, output_lines, all_support_range_formatting)
local did_edit = nil
-- discard formatting if buffer has changed
if not vim.api.nvim_buf_is_valid(bufnr) or changedtick ~= util.buf_get_changedtick(bufnr) then
err = {
code = errors.ERROR_CODE.CONCURRENT_MODIFICATION,
message = string.format(
"Async formatter discarding changes for %d: concurrent modification",
bufnr
),
}
else
did_edit = M.apply_format(
bufnr,
original_lines,
output_lines,
range,
not all_support_range_formatting,
opts.dry_run,
opts.undojoin
)
end
callback(err, did_edit)
end
)
end
---@param bufnr integer
---@param formatters conform.FormatterInfo[]
---@param range? conform.Range
---@param input_lines string[]
---@param opts conform.RunOpts
---@param callback fun(err?: conform.Error, output_lines: string[], all_support_range_formatting: boolean)
M.format_lines_async = function(bufnr, formatters, range, input_lines, opts, callback)
if bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
local idx = 1
local all_support_range_formatting = true
local final_err = nil
local function run_next_formatter()
local formatter = formatters[idx]
if not formatter then
callback(final_err, input_lines, all_support_range_formatting)
return
end
idx = idx + 1
local config = assert(require("conform").get_formatter_config(formatter.name, bufnr))
local ctx = M.build_context(bufnr, config, range)
run_formatter(bufnr, formatter, config, ctx, input_lines, opts, function(err, output)
if err then
final_err = errors.coalesce(final_err, err)
end
input_lines = output or input_lines
all_support_range_formatting = all_support_range_formatting and truthy(config.range_args)
run_next_formatter()
end)
end
run_next_formatter()
end
---@param bufnr integer
---@param formatters conform.FormatterInfo[]
---@param timeout_ms integer
---@param range? conform.Range
---@param opts conform.RunOpts
---@return conform.Error? error
---@return boolean did_edit
M.format_sync = function(bufnr, formatters, timeout_ms, range, opts)
if bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
local original_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
-- kill previous jobs for buffer
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
local err, final_result, all_support_range_formatting =
M.format_lines_sync(bufnr, formatters, timeout_ms, range, original_lines, opts)
local did_edit = M.apply_format(
bufnr,
original_lines,
final_result,
range,
not all_support_range_formatting,
opts.dry_run,
opts.undojoin
)
return err, did_edit
end
---@param bufnr integer
---@param formatters conform.FormatterInfo[]
---@param timeout_ms integer
---@param range? conform.Range
---@param opts conform.RunOpts
---@return conform.Error? error
---@return string[] output_lines
---@return boolean all_support_range_formatting
M.format_lines_sync = function(bufnr, formatters, timeout_ms, range, input_lines, opts)
if bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
local start = uv.hrtime() / 1e6
local all_support_range_formatting = true
local final_err = nil
for _, formatter in ipairs(formatters) do
local remaining = timeout_ms - (uv.hrtime() / 1e6 - start)
if remaining <= 0 then
return errors.coalesce(final_err, {
code = errors.ERROR_CODE.TIMEOUT,
message = string.format("Formatter '%s' timeout", formatter.name),
}),
input_lines,
all_support_range_formatting
end
local done = false
local result = nil
---@type conform.FormatterConfig
local config = assert(require("conform").get_formatter_config(formatter.name, bufnr))
local ctx = M.build_context(bufnr, config, range)
local pid = run_formatter(
bufnr,
formatter,
config,
ctx,
input_lines,
opts,
function(err, output)
final_err = errors.coalesce(final_err, err)
done = true
result = output
end
)
all_support_range_formatting = all_support_range_formatting and truthy(config.range_args)
local wait_result, wait_reason = vim.wait(remaining, function()
return done
end, 5)
if not wait_result then
if pid then
uv.kill(pid)
end
if wait_reason == -1 then
return errors.coalesce(final_err, {
code = errors.ERROR_CODE.TIMEOUT,
message = string.format("Formatter '%s' timeout", formatter.name),
}),
input_lines,
all_support_range_formatting
else
return errors.coalesce(final_err, {
code = errors.ERROR_CODE.INTERRUPTED,
message = string.format("Formatter '%s' was interrupted", formatter.name),
}),
input_lines,
all_support_range_formatting
end
end
input_lines = result or input_lines
end
return final_err, input_lines, all_support_range_formatting
end
return M
conform.nvim-9.1.0/lua/conform/types.lua 0000664 0000000 0000000 00000017705 15051732407 0020245 0 ustar 00root root 0000000 0000000 ---@class (exact) conform.FormatterInfo
---@field name string
---@field command string
---@field cwd? string
---@field available boolean
---@field available_msg? string
---@field error? boolean
---@class (exact) conform.JobFormatterConfig
---@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 tmpfile_format? string When stdin=false, use this format for temporary files (default ".conform.$RANDOM.$FILENAME")
---@field condition? fun(self: conform.JobFormatterConfig, ctx: conform.Context): boolean
---@field exit_codes? integer[] Exit codes that indicate success (default {0})
---@field env? table|fun(self: conform.JobFormatterConfig, ctx: conform.Context): table
---@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[]))
---@field condition? fun(self: conform.LuaFormatterConfig, ctx: conform.Context): boolean
---@field options? table
---@class (exact) conform.FileLuaFormatterConfig : conform.LuaFormatterConfig
---@field meta conform.FormatterMeta
---@class (exact) conform.FileFormatterConfig : conform.JobFormatterConfig
---@field meta conform.FormatterMeta
---@alias conform.FormatterConfig conform.JobFormatterConfig|conform.LuaFormatterConfig
---@class (exact) conform.FormatterConfigOverride : conform.JobFormatterConfig
---@field inherit? boolean
---@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 append_args? string|string[]|fun(self: conform.FormatterConfig, ctx: conform.Context): string|string[]
---@field format? fun(self: conform.LuaFormatterConfig, ctx: conform.Context, lines: string[], callback: fun(err: nil|string, new_lines: nil|string[])) Mutually exclusive with command
---@field options? table
---@class (exact) conform.FormatterMeta
---@field url string
---@field description string
---@field deprecated? boolean
---@class (exact) conform.Context
---@field buf integer
---@field filename string
---@field dirname string
---@field range? conform.Range
---@field shiftwidth integer
---@class (exact) conform.RangeContext : conform.Context
---@field range conform.Range
---@class (exact) conform.Range
---@field start integer[]
---@field end integer[]
---@alias conform.FiletypeFormatter conform.FiletypeFormatterInternal|fun(bufnr: integer): conform.FiletypeFormatterInternal
---This list of formatters to run for a filetype, an any associated format options.
---@class conform.FiletypeFormatterInternal : conform.DefaultFiletypeFormatOpts
---@field [integer] string
---@alias conform.LspFormatOpts
---| '"never"' # never use the LSP for formatting (default)
---| '"fallback"' # LSP formatting is used when no other formatters are available
---| '"prefer"' # use only LSP formatting when available
---| '"first"' # LSP formatting is used when available and then other formatters
---| '"last"' # other formatters are used then LSP formatting when available
---@class (exact) conform.FormatOpts
---@field timeout_ms? integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
---@field bufnr? integer Format this buffer (default 0)
---@field async? boolean If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded.
---@field dry_run? boolean If true don't apply formatting changes to the buffer
---@field undojoin? boolean Use undojoin to merge formatting changes with previous edit (default false)
---@field formatters? string[] List of formatters to run. Defaults to all formatters for the buffer filetype.
---@field lsp_format? conform.LspFormatOpts Configure if and when LSP should be used for formatting. Defaults to "never".
---@field stop_after_first? boolean Only run the first available formatter in the list. Defaults to false.
---@field quiet? boolean Don't show any notifications for warnings or failures. Defaults to false.
---@field range? conform.Range Range to format. Table must contain `start` and `end` keys with {row, col} tuples using (1,0) indexing. Defaults to current selection in visual mode
---@field id? integer Passed to |vim.lsp.buf.format| when using LSP formatting
---@field name? string Passed to |vim.lsp.buf.format| when using LSP formatting
---@field filter? fun(client: table): boolean Passed to |vim.lsp.buf.format| when using LSP formatting
---@field formatting_options? table Passed to |vim.lsp.buf.format| when using LSP formatting
---@class (exact) conform.DefaultFormatOpts
---@field timeout_ms? integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
---@field lsp_format? conform.LspFormatOpts Configure if and when LSP should be used for formatting. Defaults to "never".
---@field quiet? boolean Don't show any notifications for warnings or failures. Defaults to false.
---@field stop_after_first? boolean Only run the first available formatter in the list. Defaults to false.
---@class (exact) conform.DefaultFiletypeFormatOpts : conform.DefaultFormatOpts
---@field id? integer Passed to |vim.lsp.buf.format| when using LSP formatting
---@field name? string Passed to |vim.lsp.buf.format| when using LSP formatting
---@field filter? fun(client: table): boolean Passed to |vim.lsp.buf.format| when using LSP formatting
---@field formatting_options? table Passed to |vim.lsp.buf.format| when using LSP formatting
---@class conform.FormatLinesOpts
---@field timeout_ms? integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
---@field bufnr? integer use this as the working buffer (default 0)
---@field async? boolean If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded.
---@field quiet? boolean Don't show any notifications for warnings or failures. Defaults to false.
---@field stop_after_first? boolean Only run the first available formatter in the list. Defaults to false.
---@class (exact) conform.setupOpts
---@field formatters_by_ft? table Map of filetype to formatters
---@field format_on_save? conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts If this is set, Conform will run the formatter on save. It will pass the table to conform.format(). This can also be a function that returns the table.
---@field default_format_opts? conform.DefaultFormatOpts The default options to use when calling conform.format()
---@field format_after_save? conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts, nil|fun(err: nil|string, did_edit: nil|boolean) If this is set, Conform will run the formatter asynchronously after save. It will pass the table to conform.format(). This can also be a function that returns the table (and an optional callback that is run after formatting).
---@field log_level? integer Set the log level (e.g. `vim.log.levels.DEBUG`). Use `:ConformInfo` to see the location of the log file.
---@field notify_on_error? boolean Conform will notify you when a formatter errors (default true).
---@field notify_no_formatters? boolean Conform will notify you when no formatters are available for the buffer (default true).
---@field formatters? table Custom formatters and overrides for built-in formatters.
conform.nvim-9.1.0/lua/conform/util.lua 0000664 0000000 0000000 00000017266 15051732407 0020060 0 ustar 00root root 0000000 0000000 local M = {}
---Find a command in node_modules
---@param cmd string
---@return fun(ctx: conform.Context): string
M.from_node_modules = function(cmd)
return M.find_executable({ "node_modules/.bin/" .. cmd }, cmd)
end
---Search parent directories for a relative path to a command
---@param paths string[]
---@param default 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(self, ctx)
for _, path in ipairs(paths) do
local normpath = vim.fs.normalize(path)
local is_absolute = vim.startswith(normpath, "/")
if is_absolute and vim.fn.executable(normpath) then
return normpath
end
local idx = normpath:find("/", 1, true)
local dir, subpath
if idx then
dir = normpath:sub(1, idx - 1)
subpath = normpath:sub(idx)
else
-- This is a bare relative-path executable
dir = normpath
subpath = ""
end
local results = vim.fs.find(dir, { upward = true, path = ctx.dirname, limit = math.huge })
for _, result in ipairs(results) do
local fullpath = result .. subpath
if vim.fn.executable(fullpath) == 1 then
return fullpath
end
end
end
return default
end
end
---@param files string|string[]
---@return fun(self: conform.FormatterConfig, ctx: conform.Context): nil|string
M.root_file = function(files)
return function(self, ctx)
return vim.fs.root(ctx.dirname, files)
end
end
---@param bufnr integer
---@param range conform.Range
---@return integer start_offset
---@return integer end_offset
M.get_offsets_from_range = function(bufnr, range)
local row = range.start[1] - 1
local end_row = range["end"][1] - 1
local col = range.start[2]
local end_col = range["end"][2]
local start_offset = vim.api.nvim_buf_get_offset(bufnr, row) + col
local end_offset = vim.api.nvim_buf_get_offset(bufnr, end_row) + end_col
return start_offset, end_offset
end
---@generic T : any
---@param tbl T[]
---@param start_idx? number
---@param end_idx? number
---@return T[]
M.tbl_slice = function(tbl, start_idx, end_idx)
local ret = {}
if not start_idx then
start_idx = 1
end
if not end_idx then
end_idx = #tbl
end
for i = start_idx, end_idx do
table.insert(ret, tbl[i])
end
return ret
end
---@generic T : fun()
---@param cb T
---@param wrapper T
---@return T
M.wrap_callback = function(cb, wrapper)
return function(...)
wrapper(...)
cb(...)
end
end
---Helper function to add to the default args of a formatter.
---@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")
--- local prettier = require("conform.formatters.prettier")
--- require("conform").formatters.prettier = vim.tbl_deep_extend("force", prettier, {
--- args = util.extend_args(prettier.args, { "--tab", "--indent", "2" }),
--- range_args = util.extend_args(prettier.range_args, { "--tab", "--indent", "2" }),
--- })
M.extend_args = function(args, extra_args, opts)
opts = opts or {}
return function(self, ctx)
if type(args) == "function" then
args = args(self, ctx)
end
if type(extra_args) == "function" then
extra_args = extra_args(self, ctx)
end
if type(args) == "string" then
if type(extra_args) ~= "string" then
extra_args = table.concat(extra_args, " ")
end
if opts.append then
return args .. " " .. extra_args
else
return extra_args .. " " .. args
end
else
if type(extra_args) == "string" then
error("extra_args must be a table when args is a table")
end
local ret = {}
if opts.append then
vim.list_extend(ret, args or {})
vim.list_extend(ret, extra_args or {})
else
vim.list_extend(ret, extra_args or {})
vim.list_extend(ret, args or {})
end
return ret
end
end
end
---@param formatter conform.FormatterConfig
---@param extra_args string|string[]|fun(self: conform.FormatterConfig, ctx: conform.Context): string|string[]
---@param opts? { append?: boolean }
---@example
--- local util = require("conform.util")
--- local prettier = require("conform.formatters.prettier")
--- util.add_formatter_args(prettier, { "--tab", "--indent", "2" })
M.add_formatter_args = function(formatter, extra_args, opts)
formatter.args = M.extend_args(formatter.args, extra_args, opts)
if formatter.range_args then
formatter.range_args = M.extend_args(formatter.range_args, extra_args, opts)
end
end
---@param config conform.FormatterConfig
---@param override conform.FormatterConfigOverride
---@return conform.FormatterConfig
M.merge_formatter_configs = function(config, override)
local ret = vim.tbl_deep_extend("force", config, override)
if override.prepend_args then
M.add_formatter_args(ret, override.prepend_args, { append = false })
elseif override.append_args then
M.add_formatter_args(ret, override.append_args, { append = true })
end
return ret
end
---@param bufnr integer
---@return integer
M.buf_get_changedtick = function(bufnr)
if not vim.api.nvim_buf_is_valid(bufnr) then
return -2
end
local changedtick = vim.b[bufnr].changedtick
-- changedtick gets set to -1 when vim is exiting. We have an autocmd that should store it in
-- last_changedtick before it is set to -1.
if changedtick == -1 then
return vim.b[bufnr].last_changedtick or -1
else
return changedtick
end
end
---Parse the rust edition from the Cargo.toml file
---@param dir string
---@return string?
M.parse_rust_edition = function(dir)
local manifest = vim.fs.find("Cargo.toml", { upward = true, path = dir })[1]
if manifest then
for line in io.lines(manifest) do
if line:match("^edition *=") then
local edition = line:match("%d+")
if edition then
return edition
end
end
end
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
---@param bufnr integer
---@return string
M.buf_line_ending = function(bufnr)
local fileformat = vim.bo[bufnr].fileformat
if fileformat == "dos" then
return "\r\n"
elseif fileformat == "mac" then
return "\r"
else
return "\n"
end
end
return M
conform.nvim-9.1.0/plugin/ 0000775 0000000 0000000 00000000000 15051732407 0015436 5 ustar 00root root 0000000 0000000 conform.nvim-9.1.0/plugin/conform.lua 0000664 0000000 0000000 00000000242 15051732407 0017602 0 ustar 00root root 0000000 0000000 vim.api.nvim_create_user_command("ConformInfo", function()
require("conform.health").show_window()
end, { desc = "Show information about Conform formatters" })
conform.nvim-9.1.0/run_tests.sh 0000775 0000000 0000000 00000001561 15051732407 0016530 0 ustar 00root root 0000000 0000000 #!/bin/bash
set -e
mkdir -p ".testenv/config/nvim"
mkdir -p ".testenv/data/nvim"
mkdir -p ".testenv/state/nvim"
mkdir -p ".testenv/run/nvim"
mkdir -p ".testenv/cache/nvim"
PLUGINS=".testenv/data/nvim/site/pack/plugins/start"
if [ ! -e "$PLUGINS/plenary.nvim" ]; then
git clone --depth=1 https://github.com/nvim-lua/plenary.nvim.git "$PLUGINS/plenary.nvim"
else
(cd "$PLUGINS/plenary.nvim" && git pull)
fi
if [ ! -e "$PLUGINS/nvim-treesitter" ]; then
git clone --depth=1 https://github.com/nvim-treesitter/nvim-treesitter.git "$PLUGINS/nvim-treesitter"
else
(cd "$PLUGINS/nvim-treesitter" && git pull)
fi
XDG_CONFIG_HOME=".testenv/config" \
XDG_DATA_HOME=".testenv/data" \
XDG_STATE_HOME=".testenv/state" \
XDG_RUNTIME_DIR=".testenv/run" \
XDG_CACHE_HOME=".testenv/cache" \
nvim --headless -u tests/minimal_init.lua \
-c "RunTests ${1-tests}"
echo "Success"
conform.nvim-9.1.0/scripts/ 0000775 0000000 0000000 00000000000 15051732407 0015627 5 ustar 00root root 0000000 0000000 conform.nvim-9.1.0/scripts/autoformat_doc.lua 0000664 0000000 0000000 00000002147 15051732407 0021344 0 ustar 00root root 0000000 0000000 -- if format_on_save is a function, it will be called during BufWritePre
require("conform").setup({
format_on_save = function(bufnr)
-- Disable autoformat on certain filetypes
local ignore_filetypes = { "sql", "java" }
if vim.tbl_contains(ignore_filetypes, vim.bo[bufnr].filetype) then
return
end
-- Disable with a global or buffer-local variable
if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
return
end
-- Disable autoformat for files in a certain path
local bufname = vim.api.nvim_buf_get_name(bufnr)
if bufname:match("/node_modules/") then
return
end
-- ...additional logic...
return { timeout_ms = 500, lsp_format = "fallback" }
end,
})
-- There is a similar affordance for format_after_save, which uses BufWritePost.
-- This is good for formatters that are too slow to run synchronously.
require("conform").setup({
format_after_save = function(bufnr)
if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then
return
end
-- ...additional logic...
return { lsp_format = "fallback" }
end,
})
conform.nvim-9.1.0/scripts/generate.py 0000775 0000000 0000000 00000014334 15051732407 0020003 0 ustar 00root root 0000000 0000000 import os
import os.path
import re
from dataclasses import dataclass
from functools import lru_cache
from typing import List
from nvim_doc_tools import (
Vimdoc,
VimdocSection,
dedent,
generate_md_toc,
indent,
parse_directory,
read_nvim_json,
read_section,
render_md_api2,
render_vimdoc_api2,
replace_section,
wrap,
)
HERE = os.path.dirname(__file__)
ROOT = os.path.abspath(os.path.join(HERE, os.path.pardir))
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")
AUTOFORMAT = os.path.join(ROOT, "scripts", "autoformat_doc.lua")
@dataclass
class Formatter:
name: str
description: str
url: str
has_options: bool
deprecated: bool = False
@lru_cache
def get_all_formatters() -> List[Formatter]:
formatters = []
formatter_map = read_nvim_json(
'require("conform.formatters").list_all_formatters()'
)
for name, meta in formatter_map.items():
formatter = Formatter(name, **meta)
if not formatter.deprecated:
formatters.append(formatter)
formatters.sort(key=lambda f: f.name)
return formatters
def update_formatter_list():
formatter_lines = ["\n"]
for formatter in get_all_formatters():
formatter_lines.append(
f"- [{formatter.name}]({formatter.url}) - {formatter.description}\n"
)
replace_section(
README,
r"^$",
r"^$",
formatter_lines,
)
def update_options():
option_lines = ["\n", "```lua\n"]
with open(OPTIONS, "r", encoding="utf-8") as f:
option_lines.extend(f.readlines())
option_lines.extend(["```\n", "\n"])
replace_section(
README,
r"^$",
r"^$",
option_lines,
)
def update_autocmd_md():
example_lines = ["\n", "```lua\n"]
with open(AUTOFORMAT, "r", encoding="utf-8") as f:
example_lines.extend(f.readlines())
example_lines.extend(["```\n", "\n"])
replace_section(
RECIPES,
r"^$",
r"^$",
example_lines,
)
def update_formatter_options_md():
lines = ["\n"]
for formatter in get_all_formatters():
if formatter.has_options:
lines.extend([f"## {formatter.name}\n", "\n", "```lua\n", "options = {\n"])
formatter_file = os.path.join(
ROOT, "lua", "conform", "formatters", f"{formatter.name}.lua"
)
code = read_section(formatter_file, r"^ options = {$", r"^ },$")
lines.extend(dedent(code, 2))
lines.extend(["}\n", "```\n", "\n"])
replace_section(
FORMATTER_OPTIONS,
r"^$",
r"^$",
lines,
)
def add_md_link_path(path: str, lines: List[str]) -> List[str]:
ret = []
for line in lines:
ret.append(re.sub(r"(\(#)", "(" + path + "#", line))
return ret
def update_md_api():
types = parse_directory(os.path.join(ROOT, "lua"))
funcs = types.files["conform/init.lua"].functions
lines = ["\n"] + render_md_api2(funcs, types, 3)[:-1] # trim last newline
replace_section(
README,
r"^$",
r"^$",
lines,
)
def update_readme_toc():
toc = ["\n"] + generate_md_toc(README) + ["\n"]
replace_section(
README,
r"^$",
r"^$",
toc,
)
def update_tocs():
toc = ["\n"] + generate_md_toc(RECIPES) + ["\n"]
replace_section(RECIPES, r"^$", r"^$", toc)
subtoc = add_md_link_path("doc/recipes.md", toc)
replace_section(README, r"^$", r"^$", subtoc)
toc = ["\n"] + generate_md_toc(ADVANCED) + ["\n"]
replace_section(ADVANCED, r"^$", r"^$", toc)
subtoc = add_md_link_path("doc/advanced_topics.md", toc)
replace_section(README, r"^$", r"^$", subtoc)
toc = ["\n"] + generate_md_toc(DEBUGGING) + ["\n"]
replace_section(DEBUGGING, r"^$", r"^$", toc)
subtoc = add_md_link_path("doc/debugging.md", toc)
replace_section(README, r"^$", r"^$", subtoc)
toc = ["\n"] + generate_md_toc(FORMATTER_OPTIONS) + ["\n"]
replace_section(FORMATTER_OPTIONS, r"^$", r"^$", toc)
subtoc = add_md_link_path("doc/formatter_options.md", toc)
replace_section(
README,
r"^$",
r"^$",
subtoc,
)
def gen_options_vimdoc() -> VimdocSection:
section = VimdocSection("Options", "conform-options", ["\n", ">lua\n"])
with open(OPTIONS, "r", encoding="utf-8") as f:
section.body.extend(indent(f.readlines(), 4))
section.body.append("<\n")
return section
def gen_formatter_vimdoc() -> VimdocSection:
section = VimdocSection("Formatters", "conform-formatters", ["\n"])
for formatter in get_all_formatters():
line = f"`{formatter.name}` - {formatter.description}\n"
section.body.extend(wrap(line, sub_indent=len(formatter.name) + 3))
return section
def generate_vimdoc():
doc = Vimdoc("conform.txt", "conform")
types = parse_directory(os.path.join(ROOT, "lua"))
funcs = types.files["conform/init.lua"].functions
doc.sections.extend(
[
gen_options_vimdoc(),
VimdocSection(
"API", "conform-api", render_vimdoc_api2("conform", funcs, types)
),
gen_formatter_vimdoc(),
]
)
with open(VIMDOC, "w", encoding="utf-8") as ofile:
ofile.writelines(doc.render())
def main() -> None:
"""Update the README"""
update_formatter_list()
update_options()
update_autocmd_md()
update_formatter_options_md()
update_md_api()
update_tocs()
update_readme_toc()
generate_vimdoc()
conform.nvim-9.1.0/scripts/main.py 0000775 0000000 0000000 00000001456 15051732407 0017136 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
import argparse
import os
import sys
HERE = os.path.dirname(__file__)
ROOT = os.path.abspath(os.path.join(HERE, os.path.pardir))
DOC = os.path.join(ROOT, "doc")
def main() -> None:
"""Generate docs"""
sys.path.append(HERE)
parser = argparse.ArgumentParser(description=main.__doc__)
parser.add_argument("command", choices=["generate", "lint"])
args = parser.parse_args()
if args.command == "generate":
import generate
generate.main()
elif args.command == "lint":
from nvim_doc_tools import lint_md_links
files = [os.path.join(ROOT, "README.md")] + [
os.path.join(DOC, file) for file in os.listdir(DOC) if file.endswith(".md")
]
lint_md_links.main(ROOT, files)
if __name__ == "__main__":
main()
conform.nvim-9.1.0/scripts/options_doc.lua 0000664 0000000 0000000 00000010635 15051732407 0020657 0 ustar 00root root 0000000 0000000 require("conform").setup({
-- Map of filetype to formatters
formatters_by_ft = {
lua = { "stylua" },
-- Conform will run multiple formatters sequentially
go = { "goimports", "gofmt" },
-- You can also customize some of the format options for the filetype
rust = { "rustfmt", lsp_format = "fallback" },
-- You can use a function here to determine the formatters dynamically
python = function(bufnr)
if require("conform").get_formatter_info("ruff_format", bufnr).available then
return { "ruff_format" }
else
return { "isort", "black" }
end
end,
-- Use the "*" filetype to run formatters on all filetypes.
["*"] = { "codespell" },
-- Use the "_" filetype to run formatters on filetypes that don't
-- have other formatters configured.
["_"] = { "trim_whitespace" },
},
-- Set this to change the default values when calling conform.format()
-- This will also affect the default values for format_on_save/format_after_save
default_format_opts = {
lsp_format = "fallback",
},
-- If this is set, Conform will run the formatter on save.
-- It will pass the table to conform.format().
-- This can also be a function that returns the table.
format_on_save = {
-- I recommend these options. See :help conform.format for details.
lsp_format = "fallback",
timeout_ms = 500,
},
-- If this is set, Conform will run the formatter asynchronously after save.
-- It will pass the table to conform.format().
-- This can also be a function that returns the table.
format_after_save = {
lsp_format = "fallback",
},
-- Set the log level. Use `:ConformInfo` to see the location of the log file.
log_level = vim.log.levels.ERROR,
-- Conform will notify you when a formatter errors
notify_on_error = true,
-- Conform will notify you when no formatters are available for the buffer
notify_no_formatters = true,
-- Custom formatters and overrides for built-in formatters
formatters = {
my_formatter = {
-- This can be a string or a function that returns a string.
-- When defining a new formatter, this is the only field that is required
command = "my_cmd",
-- A list of strings, or a function that returns a list of strings
-- Return a single string instead of a list to run the command in a shell
args = { "--stdin-from-filename", "$FILENAME" },
-- If the formatter supports range formatting, create the range arguments here
range_args = function(self, ctx)
return { "--line-start", ctx.range.start[1], "--line-end", ctx.range["end"][1] }
end,
-- Send file contents to stdin, read new contents from stdout (default true)
-- When false, will create a temp file (will appear in "$FILENAME" args). The temp
-- file is assumed to be modified in-place by the format command.
stdin = true,
-- A function that calculates the directory to run the command in
cwd = require("conform.util").root_file({ ".editorconfig", "package.json" }),
-- When cwd is not found, don't run the formatter (default false)
require_cwd = true,
-- When stdin=false, use this template to generate the temporary file that gets formatted
tmpfile_format = ".conform.$RANDOM.$FILENAME",
-- When returns false, the formatter will not be used
condition = function(self, ctx)
return vim.fs.basename(ctx.filename) ~= "README.md"
end,
-- Exit codes that indicate success (default { 0 })
exit_codes = { 0, 1 },
-- Environment variables. This can also be a function that returns a table.
env = {
VAR = "value",
},
-- Set to false to disable merging the config with the base definition
inherit = true,
-- When inherit = true, add these additional arguments to the beginning of the command.
-- This can also be a function, like args
prepend_args = { "--use-tabs" },
-- When inherit = true, add these additional arguments to the end of the command.
-- This can also be a function, like args
append_args = { "--trailing-comma" },
},
-- These can also be a function that returns the formatter
other_formatter = function(bufnr)
return {
command = "my_cmd",
}
end,
},
})
-- You can set formatters_by_ft and formatters directly
require("conform").formatters_by_ft.lua = { "stylua" }
require("conform").formatters.my_formatter = {
command = "my_cmd",
}
conform.nvim-9.1.0/scripts/requirements.txt 0000664 0000000 0000000 00000000042 15051732407 0021107 0 ustar 00root root 0000000 0000000 pyparsing==3.0.9
black
isort
mypy
conform.nvim-9.1.0/tests/ 0000775 0000000 0000000 00000000000 15051732407 0015302 5 ustar 00root root 0000000 0000000 conform.nvim-9.1.0/tests/api_spec.lua 0000664 0000000 0000000 00000005146 15051732407 0017576 0 ustar 00root root 0000000 0000000 require("plenary.async").tests.add_to_env()
local conform = require("conform")
local test_util = require("tests.test_util")
describe("api", function()
after_each(function()
test_util.reset_editor()
end)
it("retrieves info about a formatter", function()
local info = conform.get_formatter_info("stylua")
assert.equal("stylua", info.name)
assert.equal("stylua", info.command)
assert.equal("boolean", type(info.available))
assert.is_nil(info.error)
end)
it("retrieves unavailable info if formatter does not exist", function()
local info = conform.get_formatter_info("asdf")
assert.equal("asdf", info.name)
assert.equal("asdf", info.command)
assert.falsy(info.available)
assert.truthy(info.error)
end)
describe("list_formatters", function()
local get_formatter_info = conform.get_formatter_info
before_each(function()
conform.get_formatter_info = function(...)
local info = get_formatter_info(...)
info.available = true
return info
end
end)
after_each(function()
conform.get_formatter_info = get_formatter_info
end)
it("lists all formatters configured for buffer", function()
conform.formatters_by_ft.lua = { "stylua", "lua-format" }
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_set_current_buf(bufnr)
vim.bo[bufnr].filetype = "lua"
local formatters = conform.list_formatters()
local formatter_names = vim.tbl_map(function(f)
return f.name
end, formatters)
assert.are.same({ "stylua", "lua-format" }, formatter_names)
end)
it("merges formatters from mixed filetypes", function()
conform.formatters_by_ft.lua = { "stylua", "lua-format" }
conform.formatters_by_ft["*"] = { "trim_whitespace" }
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_set_current_buf(bufnr)
vim.bo[bufnr].filetype = "lua"
local formatters = conform.list_formatters()
local formatter_names = vim.tbl_map(function(f)
return f.name
end, formatters)
assert.are.same({ "stylua", "lua-format", "trim_whitespace" }, formatter_names)
end)
end)
it("lists_all_formatters configured for all buffers", function()
conform.formatters_by_ft.lua = { "stylua", "lua-format" }
conform.formatters_by_ft["*"] = { "trim_whitespace" }
local formatters = conform.list_all_formatters()
local formatter_names = vim.tbl_map(function(f)
return f.name
end, formatters)
table.sort(formatter_names)
assert.are.same({ "lua-format", "stylua", "trim_whitespace" }, formatter_names)
end)
end)
conform.nvim-9.1.0/tests/fake_formatter.sh 0000775 0000000 0000000 00000000446 15051732407 0020636 0 ustar 00root root 0000000 0000000 #!/bin/bash
set -e
CODE=0
if [ "$1" = "--fail" ]; then
shift
echo "failure" >&2
CODE=1
fi
if [ "$1" = "--timeout" ]; then
shift
echo "timeout" >&2
sleep 4
fi
output_file="$1"
if [ -n "$output_file" ] && [ -e "$output_file" ]; then
cat "$output_file"
else
cat
fi
exit $CODE
conform.nvim-9.1.0/tests/formatters/ 0000775 0000000 0000000 00000000000 15051732407 0017470 5 ustar 00root root 0000000 0000000 conform.nvim-9.1.0/tests/formatters/prettierd_spec.lua 0000664 0000000 0000000 00000011014 15051732407 0023204 0 ustar 00root root 0000000 0000000 require("plenary.async").tests.add_to_env()
local conform = require("conform")
local test_util = require("tests.test_util")
local TMP_DIR = "./tmp/formatters/prettierd/"
describe("formatters/prettierd", function()
before_each(function()
vim.fn.mkdir(TMP_DIR, "p")
end)
after_each(function()
test_util.reset_editor()
vim.fn.delete(TMP_DIR, "rf")
end)
describe("cwd", function()
it("has no marker", function()
vim.fn.writefile({ "{}" }, vim.fs.joinpath(TMP_DIR, "package.json"))
local jsfile = vim.fs.joinpath(TMP_DIR, "some.js")
vim.fn.writefile({ "" }, jsfile)
vim.cmd("e " .. jsfile)
local info = conform.get_formatter_info("prettierd")
assert.equal(nil, info.cwd)
end)
describe("config file", function()
it("recognizes prettier config file", function()
vim.fn.writefile({ "" }, vim.fs.joinpath(TMP_DIR, ".prettierrc"))
local jsfile = vim.fs.joinpath(TMP_DIR, "some.js")
vim.fn.writefile({ "" }, jsfile)
vim.cmd("e " .. jsfile)
local info = conform.get_formatter_info("prettierd")
assert.equal(vim.fn.fnamemodify(jsfile, ":p:h"), info.cwd)
end)
it("looks up recursively", function()
vim.fn.writefile({ "" }, vim.fs.joinpath(TMP_DIR, ".prettierrc"))
local nested_dir = vim.fs.joinpath(TMP_DIR, "nested")
vim.fn.mkdir(nested_dir, "p")
vim.fn.writefile({ "{}" }, vim.fs.joinpath(nested_dir, "package.json"))
local jsfile = vim.fs.joinpath(nested_dir, "some.js")
vim.fn.writefile({ "" }, jsfile)
vim.cmd("e " .. jsfile)
local info = conform.get_formatter_info("prettierd")
assert.equal(vim.fn.fnamemodify(TMP_DIR, ":p:h"), info.cwd)
end)
end)
describe("package.json", function()
it("handles syntax error", function()
vim.fn.writefile({ "plain text" }, vim.fs.joinpath(TMP_DIR, "package.json"))
local jsfile = vim.fs.joinpath(TMP_DIR, "some.js")
vim.fn.writefile({ "" }, jsfile)
vim.cmd("e " .. jsfile)
local log = {}
require("conform.log").set_handler(function(text)
table.insert(log, text)
end)
local info = conform.get_formatter_info("prettierd")
assert.equal(nil, info.cwd)
assert.is_true(#log == 1)
assert.no_nil(string.find(log[1], "[ERROR] Unable to parse json file", 1, true))
end)
it("recognizes prettier field", function()
vim.fn.writefile({ '{"prettier": {}}' }, vim.fs.joinpath(TMP_DIR, "package.json"))
local jsfile = vim.fs.joinpath(TMP_DIR, "some.js")
vim.fn.writefile({ "" }, jsfile)
vim.cmd("e " .. jsfile)
local info = conform.get_formatter_info("prettierd")
assert.equal(vim.fn.fnamemodify(jsfile, ":p:h"), info.cwd)
end)
-- test it explicitly just for a future traveler's clarity
it("ignores prettier dependency", function()
vim.fn.writefile(
{ '{"dependencies": {"prettier": "1.1.1"}, "devDependencies": {"prettier": "1.1.1"}}' },
vim.fs.joinpath(TMP_DIR, "package.json")
)
local jsfile = vim.fs.joinpath(TMP_DIR, "some.js")
vim.fn.writefile({ "" }, jsfile)
vim.cmd("e " .. jsfile)
local info = conform.get_formatter_info("prettierd")
assert.equal(nil, info.cwd)
end)
it("looks up recursively", function()
vim.fn.writefile({ '{"prettier": {}}' }, vim.fs.joinpath(TMP_DIR, "package.json"))
local nested_dir = vim.fs.joinpath(TMP_DIR, "nested")
vim.fn.mkdir(nested_dir, "p")
vim.fn.writefile({ "{}" }, vim.fs.joinpath(nested_dir, "package.json"))
local jsfile = vim.fs.joinpath(nested_dir, "some.js")
vim.fn.writefile({ "" }, jsfile)
vim.cmd("e " .. jsfile)
local info = conform.get_formatter_info("prettierd")
assert.equal(vim.fn.fnamemodify(TMP_DIR, ":p:h"), info.cwd)
end)
end)
it("stops on the first found marker", function()
vim.fn.writefile({ '{"prettier": {}}' }, vim.fs.joinpath(TMP_DIR, "package.json"))
local nested_dir = vim.fs.joinpath(TMP_DIR, "nested")
vim.fn.mkdir(nested_dir, "p")
vim.fn.writefile({ '{"prettier": {}}' }, vim.fs.joinpath(nested_dir, "package.json"))
local jsfile = vim.fs.joinpath(nested_dir, "some.js")
vim.fn.writefile({ "" }, jsfile)
vim.cmd("e " .. jsfile)
local info = conform.get_formatter_info("prettierd")
assert.equal(vim.fn.fnamemodify(jsfile, ":p:h"), info.cwd)
end)
end)
end)
conform.nvim-9.1.0/tests/fs_spec.lua 0000664 0000000 0000000 00000001361 15051732407 0017430 0 ustar 00root root 0000000 0000000 local fs = require("conform.fs")
describe("fs", function()
local relative_paths = {
{ "/home", "/home/file.txt", "file.txt" },
{ "/home/", "/home/file.txt", "file.txt" },
{ "/home", "/foo/file.txt", "../foo/file.txt" },
{ "/home/foo", "/home/bar/file.txt", "../bar/file.txt" },
{ "/home", "/file.txt", "../file.txt" },
{ "/home", "/home/foo/file.txt", "foo/file.txt" },
{ ".", "foo/file.txt", "foo/file.txt" },
{ "home", "home/file.txt", "file.txt" },
{ "home", "file.txt", "../file.txt" },
}
it("relative_path", function()
for _, paths in ipairs(relative_paths) do
local source, target, expected = unpack(paths)
assert.are.same(fs.relative_path(source, target), expected)
end
end)
end)
conform.nvim-9.1.0/tests/fuzzer_spec.lua 0000664 0000000 0000000 00000007211 15051732407 0020345 0 ustar 00root root 0000000 0000000 require("plenary.async").tests.add_to_env()
local conform = require("conform")
local log = require("conform.log")
local runner = require("conform.runner")
local test_util = require("tests.test_util")
describe("fuzzer", function()
before_each(function()
conform.formatters.test = {
meta = { url = "", description = "" },
command = "tests/fake_formatter.sh",
}
end)
after_each(function()
test_util.reset_editor()
end)
---@param buf_content string[]
---@param expected string[]
---@param opts? table
local function run_formatter(buf_content, expected, opts)
local bufnr = vim.fn.bufadd("testfile")
vim.fn.bufload(bufnr)
vim.api.nvim_set_current_buf(bufnr)
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, buf_content)
vim.bo[bufnr].modified = false
runner.apply_format(0, buf_content, expected, nil, false, false, false)
assert.are.same(expected, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end
local function make_word()
local chars = {}
for _ = 1, math.random(1, 10) do
table.insert(chars, string.char(math.random(97, 122)))
end
return table.concat(chars, "")
end
local function make_line()
local words = {}
for _ = 1, math.random(0, 6) do
table.insert(words, make_word())
end
return table.concat(words, " ")
end
local function make_file(num_lines)
local lines = {}
for _ = 1, math.random(1, num_lines) do
table.insert(lines, make_line())
end
return lines
end
local function do_insert(lines)
local idx = math.random(1, #lines + 1)
for _ = 1, math.random(1, 3) do
table.insert(lines, idx, make_line())
end
end
local function do_replace(lines)
local num_lines = math.random(1, math.min(3, #lines))
local idx = math.random(1, #lines - num_lines + 1)
local replacement = {}
local num_replace = math.random(1, 5)
for _ = 1, num_replace do
table.insert(replacement, make_line())
end
local col = math.random(1, lines[idx]:len())
replacement[1] = lines[idx]:sub(1, col) .. replacement[1]
col = math.random(1, lines[idx + num_lines - 1]:len())
replacement[#replacement] = replacement[#replacement] .. lines[idx + num_lines - 1]:sub(col)
for _ = 1, num_lines - num_replace do
table.remove(lines, idx)
end
for _ = 1, num_replace - num_lines do
table.insert(lines, idx, "")
end
for i = 1, num_replace do
lines[idx + i - 1] = replacement[i]
end
end
local function do_delete(lines)
local num_lines = math.random(1, 3)
local idx = math.random(1, #lines - num_lines)
for _ = 1, num_lines do
table.remove(lines, idx)
end
-- vim will never let the lines be empty. An empty file has a single blank line.
if #lines == 0 then
table.insert(lines, "")
end
end
local function make_edits(lines)
local was_empty = table.concat(lines):match("^%s*$")
lines = vim.deepcopy(lines)
for _ = 1, math.random(0, 3) do
do_insert(lines)
end
for _ = 1, math.random(0, 3) do
do_replace(lines)
end
for _ = 1, math.random(0, 3) do
do_delete(lines)
end
-- avoid blank output (whitepsace only) which is ignored when applying formatting
if not was_empty then
while table.concat(lines):match("^%s*$") do
do_replace(lines)
end
end
return lines
end
it("formats correctly", function()
-- log.level = vim.log.levels.TRACE
for i = 1, 50000 do
math.randomseed(i)
log.info("Fuzz testing with seed %d", i)
local content = make_file(20)
local formatted = make_edits(content)
run_formatter(content, formatted)
end
end)
end)
conform.nvim-9.1.0/tests/injected/ 0000775 0000000 0000000 00000000000 15051732407 0017067 5 ustar 00root root 0000000 0000000 conform.nvim-9.1.0/tests/injected/block_quote.md 0000664 0000000 0000000 00000000071 15051732407 0021716 0 ustar 00root root 0000000 0000000 text
> ```lua
> local foo = 'bar'
> local bar = 2
> ```
conform.nvim-9.1.0/tests/injected/block_quote.md.formatted 0000664 0000000 0000000 00000000073 15051732407 0023704 0 ustar 00root root 0000000 0000000 text
> ```lua
> >local foo = 'bar'
> local bar = 2<
> ```
conform.nvim-9.1.0/tests/injected/combined_injections.md 0000664 0000000 0000000 00000000164 15051732407 0023417 0 ustar 00root root 0000000 0000000 text
```lua
local foo = 'bar'
```
```lua
local foo = 'bar'
local bar = 3
```
conform.nvim-9.1.0/tests/injected/combined_injections.md.formatted 0000664 0000000 0000000 00000000170 15051732407 0025400 0 ustar 00root root 0000000 0000000 text
```lua
>local foo = 'bar'<
```
```lua
>local foo = 'bar'
local bar = 3<
```
conform.nvim-9.1.0/tests/injected/inline.ts 0000664 0000000 0000000 00000000375 15051732407 0020722 0 ustar 00root root 0000000 0000000 foo.innerHTML = ` hello
`;
bar.innerHTML = `
world
`;
baz.innerHTML = `
world
`;
baz.innerHTML = `
world
`;
baz.innerHTML = `
world
`;
baz.innerHTML = `
world
`;
conform.nvim-9.1.0/tests/injected/inline.ts.formatted 0000664 0000000 0000000 00000000411 15051732407 0022675 0 ustar 00root root 0000000 0000000 foo.innerHTML = `> hello
<`;
bar.innerHTML = `
> world
<
`;
baz.innerHTML = `
> world
<
`;
baz.innerHTML = `>
world
<`;
baz.innerHTML = `>
world
<
`;
baz.innerHTML = `>
world
<
`;
conform.nvim-9.1.0/tests/injected/list_item.md 0000664 0000000 0000000 00000000134 15051732407 0021400 0 ustar 00root root 0000000 0000000 1. item
```lua
local function foo()
print("hello world")
end
```
conform.nvim-9.1.0/tests/injected/list_item.md.formatted 0000664 0000000 0000000 00000000136 15051732407 0023366 0 ustar 00root root 0000000 0000000 1. item
```lua
>local function foo()
print("hello world")
end<
```
conform.nvim-9.1.0/tests/injected/simple.md 0000664 0000000 0000000 00000000061 15051732407 0020677 0 ustar 00root root 0000000 0000000 text
```lua
local foo = "bar"
local bar = 2
```
conform.nvim-9.1.0/tests/injected/simple.md.formatted 0000664 0000000 0000000 00000000063 15051732407 0022665 0 ustar 00root root 0000000 0000000 text
```lua
>local foo = "bar"
local bar = 2<
```
conform.nvim-9.1.0/tests/injected_spec.lua 0000664 0000000 0000000 00000005427 15051732407 0020614 0 ustar 00root root 0000000 0000000 require("plenary.async").tests.add_to_env()
local conform = require("conform")
local injected = require("conform.formatters.injected")
local runner = require("conform.runner")
local test_util = require("tests.test_util")
---@param dir string
---@return string[]
local function list_test_files(dir)
---@diagnostic disable-next-line: param-type-mismatch
local fd = vim.loop.fs_opendir(dir, nil, 32)
---@diagnostic disable-next-line: param-type-mismatch
local entries = vim.loop.fs_readdir(fd)
local ret = {}
while entries do
for _, entry in ipairs(entries) do
if entry.type == "file" and not vim.endswith(entry.name, ".formatted") then
table.insert(ret, entry.name)
end
end
---@diagnostic disable-next-line: param-type-mismatch
entries = vim.loop.fs_readdir(fd)
end
---@diagnostic disable-next-line: param-type-mismatch
vim.loop.fs_closedir(fd)
return ret
end
describe("injected formatter", function()
before_each(function()
-- require("conform.log").level = vim.log.levels.TRACE
conform.formatters_by_ft = {
lua = { "test_mark" },
html = { "test_mark" },
}
-- A test formatter that bookends lines with "><" so we can check what was passed in
conform.formatters.test_mark = {
format = function(self, ctx, lines, callback)
lines = vim.deepcopy(lines)
-- Simulate formatters removing starting newline
while #lines > 0 and lines[1] == "" do
table.remove(lines, 1)
end
-- Simulate formatters removing trailing newline
while #lines > 0 and lines[#lines] == "" do
table.remove(lines)
end
lines[1] = ">" .. lines[1]
lines[#lines] = lines[#lines] .. "<"
callback(nil, lines)
end,
}
end)
after_each(function()
test_util.reset_editor()
end)
for _, filename in ipairs(list_test_files("tests/injected")) do
local filepath = "./tests/injected/" .. filename
local formatted_file = filepath .. ".formatted"
it(filename, function()
local bufnr = vim.fn.bufadd(filepath)
vim.fn.bufload(bufnr)
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
local config = assert(conform.get_formatter_config("injected", bufnr))
local ctx = runner.build_context(bufnr, config)
local err, new_lines, done
injected.format(injected, ctx, lines, function(e, formatted)
done = true
err = e
new_lines = formatted
end)
vim.wait(1000, function()
return done
end)
assert(err == nil, err)
local expected_bufnr = vim.fn.bufadd(formatted_file)
vim.fn.bufload(expected_bufnr)
local expected_lines = vim.api.nvim_buf_get_lines(expected_bufnr, 0, -1, true)
assert.are.same(expected_lines, new_lines)
end)
end
end)
conform.nvim-9.1.0/tests/minimal_init.lua 0000664 0000000 0000000 00000001170 15051732407 0020455 0 ustar 00root root 0000000 0000000 vim.cmd([[set runtimepath+=.]])
vim.o.swapfile = false
vim.bo.swapfile = false
require("tests.test_util").reset_editor()
local configs = require("nvim-treesitter.configs")
configs.setup({
ensure_installed = { "markdown", "markdown_inline", "lua", "typescript", "html" },
sync_install = true,
})
-- this needs to be run a second time to make tests behave
require("nvim-treesitter").setup()
vim.api.nvim_create_user_command("RunTests", function(opts)
local path = opts.fargs[1] or "tests"
require("plenary.test_harness").test_directory(
path,
{ minimal_init = "./tests/minimal_init.lua" }
)
end, { nargs = "?" })
conform.nvim-9.1.0/tests/runner_spec.lua 0000664 0000000 0000000 00000032515 15051732407 0020336 0 ustar 00root root 0000000 0000000 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")
describe("runner", function()
local OUTPUT_FILE
local CLEANUP_FILES = {}
---@param lines string[]
local function set_formatter_output(lines)
local fd, output_file = vim.loop.fs_mkstemp(".testenv/outputXXXXXXXXX")
assert(type(fd) == "number" and output_file, fd)
local content = table.concat(lines, "\n")
vim.loop.fs_write(fd, content)
-- Make sure we add the final newline
vim.loop.fs_write(fd, "\n")
vim.loop.fs_fsync(fd)
vim.loop.fs_close(fd)
OUTPUT_FILE = output_file
table.insert(CLEANUP_FILES, output_file)
end
after_each(function()
test_util.reset_editor()
OUTPUT_FILE = nil
for _, file in ipairs(CLEANUP_FILES) do
if vim.loop.fs_stat(file) then
vim.loop.fs_unlink(file)
end
end
CLEANUP_FILES = {}
end)
it("resolves config function", function()
conform.formatters.test = function()
return {
meta = { url = "", description = "" },
command = "echo",
}
end
local config = assert(conform.get_formatter_config("test"))
assert.are.same({
meta = { url = "", description = "" },
command = "echo",
stdin = true,
}, config)
end)
describe("build_context", function()
it("sets the filename and dirname", function()
vim.cmd.edit({ args = { "README.md" } })
local bufnr = vim.api.nvim_get_current_buf()
conform.formatters.test = {
meta = { url = "", description = "" },
command = "echo",
}
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
local filename = vim.api.nvim_buf_get_name(bufnr)
assert.equal(bufnr, ctx.buf)
assert.equal(filename, ctx.filename)
assert.equal(vim.fs.dirname(filename), ctx.dirname)
end)
it("sets the shiftwidth to shiftwidth", function()
vim.cmd.edit({ args = { "README.md" } })
local bufnr = vim.api.nvim_get_current_buf()
vim.bo[bufnr].shiftwidth = 7
conform.formatters.test = {
meta = { url = "", description = "" },
command = "echo",
}
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
assert.equal(7, ctx.shiftwidth)
end)
it("sets the shiftwidth to tabstop as fallback", function()
vim.cmd.edit({ args = { "README.md" } })
local bufnr = vim.api.nvim_get_current_buf()
vim.bo[bufnr].shiftwidth = 0
vim.bo[bufnr].tabstop = 3
conform.formatters.test = {
meta = { url = "", description = "" },
command = "echo",
}
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
assert.equal(3, ctx.shiftwidth)
end)
it("sets temp file when stdin = false", function()
vim.cmd.edit({ args = { "README.md" } })
local bufnr = vim.api.nvim_get_current_buf()
conform.formatters.test = {
meta = { url = "", description = "" },
command = "echo",
stdin = false,
}
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
local bufname = vim.api.nvim_buf_get_name(bufnr)
local dirname = vim.fs.dirname(bufname)
assert.equal(bufnr, ctx.buf)
assert.equal(dirname, ctx.dirname)
assert.truthy(ctx.filename:match(dirname .. "/.conform.%d+.README.md$"))
end)
end)
describe("build_cmd", function()
it("replaces $FILENAME in 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" },
}
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({ vim.fn.exepath("echo"), vim.api.nvim_buf_get_name(bufnr) }, cmd)
end)
it("replaces $DIRNAME in 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" },
}
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(
{ vim.fn.exepath("echo"), vim.fs.dirname(vim.api.nvim_buf_get_name(bufnr)) },
cmd
)
end)
it("resolves arg function", function()
vim.cmd.edit({ args = { "README.md" } })
conform.formatters.test = {
meta = { url = "", description = "" },
command = "echo",
args = function()
return { "--stdin" }
end,
}
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({ vim.fn.exepath("echo"), "--stdin" }, cmd)
end)
it("resolves arg function with string results", function()
vim.cmd.edit({ args = { "README.md" } })
conform.formatters.test = {
meta = { url = "", description = "" },
command = "echo",
args = function()
return "| patch"
end,
}
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(util.shell_build_argv(vim.fn.exepath("echo") .. " | patch"), cmd)
end)
end)
describe("e2e", function()
before_each(function()
conform.formatters.test = {
command = "tests/fake_formatter.sh",
args = function()
if OUTPUT_FILE then
return { OUTPUT_FILE }
end
return {}
end,
}
end)
---@param buf_content string
---@param expected string
---@param opts? table
local function run_formatter(buf_content, expected, opts)
local bufnr = vim.fn.bufadd("testfile")
vim.fn.bufload(bufnr)
vim.api.nvim_set_current_buf(bufnr)
local lines = vim.split(buf_content, "\n", { plain = true })
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, lines)
vim.bo[bufnr].modified = false
local expected_lines = vim.split(expected, "\n", { plain = true })
set_formatter_output(expected_lines)
conform.format(vim.tbl_extend("keep", opts or {}, { formatters = { "test" }, quiet = true }))
return expected_lines
end
---@param buf_content string
---@param new_content string
local function run_formatter_test(buf_content, new_content)
local lines = run_formatter(buf_content, new_content)
assert.are.same(lines, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end
it("sets the correct output", function()
run_formatter_test(
[[
if true {
print("hello")
}]],
[[
if true {
print("hello")
}]]
)
run_formatter_test(
[[
if true {
print("hello")
}]],
[[
if true {
print("goodbye")
}]]
)
run_formatter_test(
[[
if true {
print("hello")
}]],
[[
if true {
print("hello world")
print("hello world")
print("hello world")
}]]
)
run_formatter_test(
[[
print("a")
print("b")
print("c")
]],
[[
print("c")
print("b")
print("a")
]]
)
run_formatter_test("hello\ngoodbye", "hello\n\n\ngoodbye")
run_formatter_test("hello", "hello\ngoodbye")
run_formatter_test("hello\ngoodbye", "hello")
run_formatter_test("", "hello")
run_formatter_test("\nfoo", "\nhello\nfoo")
run_formatter_test("hello", "hello\n")
run_formatter_test("hello", "hello\n\n")
run_formatter_test("hello\n", "hello")
run_formatter_test("hello\n ", "hello")
-- These should generate no changes to the buffer
run_formatter_test("hello\n", "hello\n")
assert.falsy(vim.bo.modified)
run_formatter_test("hello", "hello")
assert.falsy(vim.bo.modified)
end)
it("does not change output if formatter fails", function()
conform.formatters.test.args = util.extend_args(conform.formatters.test.args, { "--fail" })
run_formatter("hello", "goodbye")
assert.are.same({ "hello" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end)
it("allows nonzero exit codes", function()
conform.formatters.test.args = util.extend_args(conform.formatters.test.args, { "--fail" })
conform.formatters.test.exit_codes = { 0, 1 }
run_formatter_test("hello", "goodbye")
end)
it("does not format if it times out", function()
conform.formatters.test.args = util.extend_args(conform.formatters.test.args, { "--timeout" })
run_formatter("hello", "goodbye", { timeout_ms = 10 })
assert.are.same({ "hello" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end)
it("can format async", function()
run_formatter("hello", "goodbye", { async = true })
assert.are.same({ "hello" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
vim.wait(1000, function()
return vim.api.nvim_buf_get_lines(0, 0, -1, false)[1] == "goodbye"
end)
assert.are.same({ "goodbye" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end)
it("discards formatting changes if buffer has been concurrently modified", function()
run_formatter("hello", "goodbye", { async = true })
assert.are.same({ "hello" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
vim.api.nvim_buf_set_lines(0, 0, -1, true, { "newcontent" })
vim.wait(1000, function()
return vim.api.nvim_buf_get_lines(0, 0, -1, false)[1] == "newcontent"
end)
assert.are.same({ "newcontent" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end)
it("discards formatting changes if formatter output is empty /w non-empty input", function()
local bufnr = vim.fn.bufadd("testfile")
vim.fn.bufload(bufnr)
vim.api.nvim_set_current_buf(bufnr)
local original_lines = { "line one", "line two" }
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, original_lines)
vim.bo[bufnr].modified = false
set_formatter_output({ "" })
conform.format({ formatters = { "test" }, quiet = true })
local output_lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
assert.are.same(original_lines, output_lines)
end)
it("formats on save", function()
conform.setup({
formatters_by_ft = { ["*"] = { "test" } },
format_on_save = true,
})
vim.cmd.edit({ args = { "tests/testfile.txt" } })
vim.api.nvim_buf_set_lines(0, 0, -1, true, { "hello" })
set_formatter_output({ "goodbye" })
vim.cmd.write()
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
vim.fn.delete("tests/testfile.txt")
assert.are.same({ "goodbye" }, lines)
end)
it("formats file even if one formatter errors", function()
conform.formatters.test2 = {
command = "tests/fake_formatter.sh",
args = { "--fail" },
}
local lines = run_formatter("hello", "goodbye", { formatters = { "test2", "test" } })
assert.are.same(lines, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end)
it("does not change output if dry_run is true", function()
run_formatter("hello", "foo", { dry_run = true })
assert.are.same({ "hello" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end)
describe("range formatting", function()
it("applies edits that overlap the range start", function()
run_formatter(
"a\nb\nc",
"d\nb\nd",
{ range = {
start = { 1, 0 },
["end"] = { 2, 0 },
} }
)
assert.are.same({ "d", "b", "c" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end)
it("applies edits that overlap the range end", function()
run_formatter(
"a\nb\nc",
"d\nb\nd",
{ range = {
start = { 3, 0 },
["end"] = { 3, 1 },
} }
)
assert.are.same({ "a", "b", "d" }, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end)
it("applies edits that are completely contained by the range", function()
run_formatter(
"a\nb\nc",
"a\nd\nc",
{ range = {
start = { 1, 0 },
["end"] = { 3, 0 },
} }
)
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)
conform.nvim-9.1.0/tests/test_util.lua 0000664 0000000 0000000 00000001303 15051732407 0020016 0 ustar 00root root 0000000 0000000 require("plenary.async").tests.add_to_env()
local conform = require("conform")
local log = require("conform.log")
local M = {}
M.reset_editor = function()
vim.cmd.tabonly({ mods = { silent = true } })
for i, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
if i > 1 then
vim.api.nvim_win_close(winid, true)
end
end
vim.api.nvim_win_set_buf(0, vim.api.nvim_create_buf(false, true))
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
vim.api.nvim_buf_delete(bufnr, { force = true })
end
conform.formatters = {}
conform.formatters_by_ft = {}
pcall(vim.api.nvim_del_augroup_by_name, "Conform")
log.level = vim.log.levels.ERROR
log.set_handler(print)
end
return M
conform.nvim-9.1.0/tests/util_spec.lua 0000664 0000000 0000000 00000004570 15051732407 0020002 0 ustar 00root root 0000000 0000000 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)