pax_global_header00006660000000000000000000000064150517324070014516gustar00rootroot0000000000000052 comment=3543d000dafbc41cc7761d860cfdb24e82154f75 conform.nvim-9.1.0/000077500000000000000000000000001505173240700141405ustar00rootroot00000000000000conform.nvim-9.1.0/.envrc000066400000000000000000000002021505173240700152500ustar00rootroot00000000000000export VIRTUAL_ENV=venv layout python python3 python -c 'import pyparsing' 2>/dev/null || pip install -r scripts/requirements.txt conform.nvim-9.1.0/.github/000077500000000000000000000000001505173240700155005ustar00rootroot00000000000000conform.nvim-9.1.0/.github/ISSUE_TEMPLATE/000077500000000000000000000000001505173240700176635ustar00rootroot00000000000000conform.nvim-9.1.0/.github/ISSUE_TEMPLATE/bug_report.yml000066400000000000000000000077011505173240700225630ustar00rootroot00000000000000name: Bug Report description: File a bug/issue title: "bug: " labels: [bug] body: - type: markdown attributes: value: | Before reporting a bug, make sure to search [existing issues](https://github.com/stevearc/conform.nvim/issues) - type: input attributes: label: "Neovim version (nvim -v)" placeholder: "NVIM v0.10.1" validations: required: true - type: input attributes: label: "Operating system/version" placeholder: "MacOS 11.5" validations: required: true - type: checkboxes attributes: label: Read debugging tips options: - label: I have read through the [debugging tips](https://github.com/stevearc/conform.nvim/blob/master/doc/debugging.md). required: true - type: checkboxes attributes: label: Add the debug logs options: - label: I have set `log_level = vim.log.levels.DEBUG` and pasted the log contents below. required: true - type: textarea attributes: label: "Log file" description: "Recent contents from the log file. You can find it with :ConformInfo" validations: required: true - type: textarea attributes: label: Describe the bug description: A clear and concise description of what the bug is. validations: required: true - type: dropdown attributes: label: What is the severity of this bug? options: - minor (annoyance) - tolerable (can work around it) - breaking (some functionality is broken) - blocking (cannot use plugin) validations: required: true - type: textarea attributes: label: Steps To Reproduce description: Steps to reproduce the behavior. placeholder: | 1. nvim -u repro.lua 2. 3. validations: required: true - type: textarea attributes: label: Expected Behavior description: A concise description of what you expected to happen. validations: required: true - type: textarea attributes: label: Minimal example file description: A small example file you are editing that produces the issue validations: required: false - type: textarea attributes: label: Minimal init.lua description: Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua` This uses lazy.nvim (a plugin manager). value: | -- DO NOT change the paths and don't remove the colorscheme local root = vim.fn.fnamemodify("./.repro", ":p") -- set stdpaths to use .repro for _, name in ipairs({ "config", "data", "state", "cache" }) do vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name end -- bootstrap lazy local lazypath = root .. "/plugins/lazy.nvim" if not vim.loop.fs_stat(lazypath) then vim.fn.system({ "git", "clone", "--filter=blob:none", "--single-branch", "https://github.com/folke/lazy.nvim.git", lazypath, }) end vim.opt.runtimepath:prepend(lazypath) -- install plugins local plugins = { "folke/tokyonight.nvim", { "stevearc/conform.nvim", config = function() require("conform").setup({ log_level = vim.log.levels.DEBUG, -- add your config here }) end, }, -- add any other plugins here } require("lazy").setup(plugins, { root = root .. "/plugins", }) vim.cmd.colorscheme("tokyonight") -- add anything else here render: Lua validations: required: false - type: textarea attributes: label: Additional context description: Any additional information or screenshots you would like to provide validations: required: false conform.nvim-9.1.0/.github/ISSUE_TEMPLATE/feature_request.yml000066400000000000000000000025541505173240700236170ustar00rootroot00000000000000name: Feature Request description: Submit a feature request title: "feature request: " labels: [enhancement] body: - type: markdown attributes: value: | Before submitting a feature request, make sure to search for [existing requests](https://github.com/stevearc/conform.nvim/issues) - type: checkboxes attributes: label: Did you check existing requests? options: - label: I have searched the existing issues required: true - type: textarea attributes: label: Describe the feature description: A short summary of the feature you want validations: required: true - type: textarea attributes: label: Provide background description: Describe the reasoning behind why you want the feature. placeholder: I am trying to do X. My current workflow is Y. validations: required: false - type: dropdown attributes: label: What is the significance of this feature? options: - nice to have - strongly desired - cannot use this plugin without it validations: required: true - type: textarea attributes: label: Additional details description: Any additional information you would like to provide. Things you've tried, alternatives considered, examples from other plugins, etc. validations: required: false conform.nvim-9.1.0/.github/pre-commit000077500000000000000000000000411505173240700174750ustar00rootroot00000000000000#!/bin/bash set -e make fastlint conform.nvim-9.1.0/.github/pre-push000077500000000000000000000005651505173240700171770ustar00rootroot00000000000000#!/bin/bash set -e IFS=' ' while read local_ref _local_sha _remote_ref _remote_sha; do remote_main=$( (git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null || echo "///master") | cut -f 4 -d / | tr -d "[:space:]") local_ref_short=$(echo "$local_ref" | cut -f 3 -d / | tr -d "[:space:]") if [ "$local_ref_short" = "$remote_main" ]; then make lint make test fi done conform.nvim-9.1.0/.github/workflows/000077500000000000000000000000001505173240700175355ustar00rootroot00000000000000conform.nvim-9.1.0/.github/workflows/automation_remove_question_label_on_comment.yml000066400000000000000000000007771505173240700313340ustar00rootroot00000000000000name: Remove Question Label on Issue Comment on: [issue_comment] jobs: # Remove the "question" label when a new comment is added. # This lets me ask a question, tag the issue with "question", and filter out all "question"-tagged # issues in my "needs triage" filter. remove_question: runs-on: ubuntu-latest if: github.event.sender.login != 'stevearc' steps: - uses: actions/checkout@v4 - uses: actions-ecosystem/action-remove-labels@v1 with: labels: question conform.nvim-9.1.0/.github/workflows/automation_request_review.yml000066400000000000000000000014101505173240700255650ustar00rootroot00000000000000name: Request Review permissions: pull-requests: write on: pull_request_target: types: [opened, reopened, ready_for_review, synchronize] branches-ignore: - "release-please--**" jobs: # Request review automatically when PRs are opened request_review: runs-on: ubuntu-latest steps: - name: Request Review uses: actions/github-script@v7 if: github.actor != 'stevearc' with: github-token: ${{secrets.GITHUB_TOKEN}} script: | const pr = context.payload.pull_request; github.rest.pulls.requestReviewers({ owner: context.repo.owner, repo: context.repo.repo, pull_number: pr.number, reviewers: ['stevearc'] }); conform.nvim-9.1.0/.github/workflows/install_nvim.sh000066400000000000000000000012261505173240700225710ustar00rootroot00000000000000#!/bin/bash set -e version="${NVIM_TAG-stable}" dl_name="nvim-linux-x86_64.appimage" # The appimage name changed in v0.10.4 if python -c 'from packaging.version import Version; import sys; sys.exit(not (Version(sys.argv[1]) < Version("v0.10.4")))' "$version" 2>/dev/null; then dl_name="nvim.appimage" fi curl -sL "https://github.com/neovim/neovim/releases/download/${version}/${dl_name}" -o nvim.appimage chmod +x nvim.appimage ./nvim.appimage --appimage-extract >/dev/null rm -f nvim.appimage mkdir -p ~/.local/share/nvim mv squashfs-root ~/.local/share/nvim/appimage sudo ln -s "$HOME/.local/share/nvim/appimage/AppRun" /usr/bin/nvim /usr/bin/nvim --version conform.nvim-9.1.0/.github/workflows/tests.yml000066400000000000000000000057601505173240700214320ustar00rootroot00000000000000name: Run tests on: push: branches: - master pull_request: branches: - master jobs: luacheck: name: Luacheck runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: Prepare run: | sudo apt-get update sudo add-apt-repository universe sudo apt install luarocks -y sudo luarocks install luacheck - name: Run Luacheck run: luacheck lua tests typecheck: name: typecheck runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - uses: stevearc/nvim-typecheck-action@v2 with: path: lua stylua: name: StyLua runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: Stylua uses: JohnnyMorganz/stylua-action@v4 with: token: ${{ secrets.GITHUB_TOKEN }} version: v2.0.2 args: --check lua tests run_tests: strategy: matrix: include: - nvim_tag: v0.10.0 - nvim_tag: v0.10.4 - nvim_tag: v0.11.0 name: Run tests runs-on: ubuntu-22.04 env: NVIM_TAG: ${{ matrix.nvim_tag }} steps: - uses: actions/checkout@v4 - name: Install Neovim and dependencies run: | bash ./.github/workflows/install_nvim.sh - name: Run tests run: | bash ./run_tests.sh update_docs: name: Update docs runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: Install Neovim and dependencies run: | bash ./.github/workflows/install_nvim.sh - name: Update docs run: | python -m pip install pyparsing==3.0.9 make doc - name: Commit changes if: ${{ github.ref == 'refs/heads/master' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} COMMIT_MSG: | [docgen] Update docs skip-checks: true run: | git config user.email "actions@github" git config user.name "Github Actions" git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git git add README.md doc # Only commit and push if we have changes git diff --quiet && git diff --staged --quiet || (git commit -m "${COMMIT_MSG}"; git push origin HEAD:${GITHUB_REF}) release: name: release if: ${{ github.ref == 'refs/heads/master' }} needs: - luacheck - stylua - typecheck - run_tests - update_docs runs-on: ubuntu-22.04 steps: - uses: googleapis/release-please-action@v4 id: release with: release-type: simple - uses: actions/checkout@v4 - uses: rickstaa/action-create-tag@v1 if: ${{ steps.release.outputs.release_created }} with: tag: stable message: "Current stable release: ${{ steps.release.outputs.tag_name }}" tag_exists_error: false force_push_tag: true conform.nvim-9.1.0/.gitignore000066400000000000000000000007171505173240700161350ustar00rootroot00000000000000# Compiled Lua sources luac.out # luarocks build files *.src.rock *.zip *.tar.gz # Object files *.o *.os *.ko *.obj *.elf # Precompiled Headers *.gch *.pch # Libraries *.lib *.a *.la *.lo *.def *.exp # Shared objects (inc. Windows DLLs) *.dll *.so *.so.* *.dylib # Executables *.exe *.out *.app *.i*86 *.x86_64 *.hex .direnv/ .testenv/ venv/ doc/tags tests/testfile.txt tests/fake_formatter_output scripts/nvim_doc_tools scripts/nvim-typecheck-action tmp/ conform.nvim-9.1.0/.gitmodules000066400000000000000000000000001505173240700163030ustar00rootroot00000000000000conform.nvim-9.1.0/.luacheckrc000066400000000000000000000004211505173240700162420ustar00rootroot00000000000000max_comment_line_length = false codes = true exclude_files = { "tests/treesitter", } ignore = { "212", -- Unused argument "631", -- Line is too long "122", -- Setting a readonly global "542", -- Empty if branch } read_globals = { "vim", "a", "assert", } conform.nvim-9.1.0/.luarc.json000066400000000000000000000001641505173240700162200ustar00rootroot00000000000000{ "runtime": { "version": "LuaJIT", "pathStrict": true }, "type": { "checkTableShape": true } } conform.nvim-9.1.0/.stylua.toml000066400000000000000000000001321505173240700164300ustar00rootroot00000000000000column_width = 100 indent_type = "Spaces" indent_width = 2 [sort_requires] enabled = true conform.nvim-9.1.0/CHANGELOG.md000066400000000000000000002436171505173240700157660ustar00rootroot00000000000000# Changelog ## [9.1.0](https://github.com/stevearc/conform.nvim/compare/v9.0.0...v9.1.0) (2025-08-22) ### Features * add ansible-lint ([#639](https://github.com/stevearc/conform.nvim/issues/639)) ([4e34573](https://github.com/stevearc/conform.nvim/commit/4e3457308f220dea5dc548e83a59f43c979bd82d)) * add bake for Makefile ([#745](https://github.com/stevearc/conform.nvim/issues/745)) ([8acd010](https://github.com/stevearc/conform.nvim/commit/8acd010d55442502f58eb9625f44823942420059)) * add cedar formatter ([#724](https://github.com/stevearc/conform.nvim/issues/724)) ([3343567](https://github.com/stevearc/conform.nvim/commit/3343567c007f3b344f532c759c5b203d0d645584)) * add dioxus formatter ([#707](https://github.com/stevearc/conform.nvim/issues/707)) ([b36bb17](https://github.com/stevearc/conform.nvim/commit/b36bb1718cd6a19a2dd245fb892c70f808ffeb0f)) * add dockerfmt formatter ([#739](https://github.com/stevearc/conform.nvim/issues/739)) ([77fa71b](https://github.com/stevearc/conform.nvim/commit/77fa71b61539116a7da11ead097ace4bdc43a200)) * add formatter definition for odinfmt ([#686](https://github.com/stevearc/conform.nvim/issues/686)) ([2b1d8a4](https://github.com/stevearc/conform.nvim/commit/2b1d8a442ca1b75b9c2d5de0f0f7c1ea15a5864d)) * add ghokin formatter for cucumber files ([#731](https://github.com/stevearc/conform.nvim/issues/731)) ([3a57887](https://github.com/stevearc/conform.nvim/commit/3a57887ad48226a4093bc270a5a09a0d68743234)) * add golangci-lint fmt ([#678](https://github.com/stevearc/conform.nvim/issues/678)) ([db37c57](https://github.com/stevearc/conform.nvim/commit/db37c57658cd31cefd3aff5208d4b928ec4e52e1)) * add hledger-fmt for ledger ([#709](https://github.com/stevearc/conform.nvim/issues/709)) ([6ed26d2](https://github.com/stevearc/conform.nvim/commit/6ed26d2dc9c7c32443c39f472ffac2f5be890e54)) * add janet-format for Janet lang ([#706](https://github.com/stevearc/conform.nvim/issues/706)) ([d8497af](https://github.com/stevearc/conform.nvim/commit/d8497af9a7967f6f25c19dd7dc218ced15ba13ab)) * add keep-sorted ([#732](https://github.com/stevearc/conform.nvim/issues/732)) ([cfb6ad1](https://github.com/stevearc/conform.nvim/commit/cfb6ad184584b2b622125e78dd692eea7dc32fb5)) * add official swift formatter ([#718](https://github.com/stevearc/conform.nvim/issues/718)) ([5bb3cc7](https://github.com/stevearc/conform.nvim/commit/5bb3cc759bb3d5167051725d01e82b03402849f9)) * add pycln ([c556b01](https://github.com/stevearc/conform.nvim/commit/c556b01fcf0d4ee1b1f5738fa95c2eb19822d863)) * add pycln ([#611](https://github.com/stevearc/conform.nvim/issues/611)) ([c556b01](https://github.com/stevearc/conform.nvim/commit/c556b01fcf0d4ee1b1f5738fa95c2eb19822d863)) * add pymarkdownlnt ([#753](https://github.com/stevearc/conform.nvim/issues/753)) ([de51845](https://github.com/stevearc/conform.nvim/commit/de5184539d45d5b6e99fe62e1cffd0567a6499d6)) * add pyupgrade ([#737](https://github.com/stevearc/conform.nvim/issues/737)) ([493b13a](https://github.com/stevearc/conform.nvim/commit/493b13a016e1d29ac7ed6df1577e30bb38d6ef1b)) * add qmlformat for QML files ([#757](https://github.com/stevearc/conform.nvim/issues/757)) ([62ba147](https://github.com/stevearc/conform.nvim/commit/62ba147fe700bf2b2e496f77b6d53a37a45b00e9)) * add runic formatter ([#657](https://github.com/stevearc/conform.nvim/issues/657)) ([b443a93](https://github.com/stevearc/conform.nvim/commit/b443a93e6400d1b14f737161b3ad408d3049b57a)) * add spotless formatter ([#754](https://github.com/stevearc/conform.nvim/issues/754)) ([9157834](https://github.com/stevearc/conform.nvim/commit/9157834fd3cc9877ef6618f8c9b091fd7c174eef)) * add support for ghdl ([#744](https://github.com/stevearc/conform.nvim/issues/744)) ([33cf03b](https://github.com/stevearc/conform.nvim/commit/33cf03b619c864e11524990f9aa33407e4172301)) * add support for mago ([#684](https://github.com/stevearc/conform.nvim/issues/684)) ([74b8332](https://github.com/stevearc/conform.nvim/commit/74b8332feff2cc18299b6cdf54f256b492637f4e)) * add support for tombi ([#741](https://github.com/stevearc/conform.nvim/issues/741)) ([f7b66a9](https://github.com/stevearc/conform.nvim/commit/f7b66a9e61d0e8dc1a0ee082da120a0027a7070e)) * add support for typespec ([#687](https://github.com/stevearc/conform.nvim/issues/687)) ([372fc52](https://github.com/stevearc/conform.nvim/commit/372fc521f8421b7830ea6db4d6ea3bae1c77548c)) * add swipl prolog formatter ([#759](https://github.com/stevearc/conform.nvim/issues/759)) ([d85de8d](https://github.com/stevearc/conform.nvim/commit/d85de8d0bee886c7d0a5db7be54672aaa47de0ce)) * add V lang support ([#728](https://github.com/stevearc/conform.nvim/issues/728)) ([e0340f7](https://github.com/stevearc/conform.nvim/commit/e0340f76306020263a19ad6fe0bae1242722f000)) * support treefmt formatter ([#702](https://github.com/stevearc/conform.nvim/issues/702)) ([f9e5cd5](https://github.com/stevearc/conform.nvim/commit/f9e5cd5fca255212b303600ca5d22d2b9642e243)) ### Bug Fixes * add .cljstyle as the root file for cljstyle formatter ([#711](https://github.com/stevearc/conform.nvim/issues/711)) ([6feb2f2](https://github.com/stevearc/conform.nvim/commit/6feb2f28f9a9385e401857b21eeac3c1b66dd628)) * allow '_' to specify keyword options ([f9ef25a](https://github.com/stevearc/conform.nvim/commit/f9ef25a7ef00267b7d13bfc00b0dea22d78702d5)) * biome v2 organize imports ([#734](https://github.com/stevearc/conform.nvim/issues/734)) ([4014969](https://github.com/stevearc/conform.nvim/commit/4014969be52fb1f0f4026b68c62502bc5c98b286)) * **cabal-fmt:** pass filename to expand pragmas ([#662](https://github.com/stevearc/conform.nvim/issues/662)) ([74e541e](https://github.com/stevearc/conform.nvim/commit/74e541eba7219f31517fbc505f935b068ed8a791)) * change LSP fallback logic for wildcard filetypes ([d513820](https://github.com/stevearc/conform.nvim/commit/d5138205d085a02602e6922e22e636ba8cee1fbd)) * **csharpier:** use csharpier 1.0.0 format command ([#695](https://github.com/stevearc/conform.nvim/issues/695)) ([2dae543](https://github.com/stevearc/conform.nvim/commit/2dae54343f3c3fe31b3058188684dcd903e9d00f)) * dart format not picking up config file ([#715](https://github.com/stevearc/conform.nvim/issues/715)) ([f643d1b](https://github.com/stevearc/conform.nvim/commit/f643d1b51d1d3d14c8641a46ce44f6bce73c2697)) * deprecated LSP warnings ([#681](https://github.com/stevearc/conform.nvim/issues/681)) ([819c283](https://github.com/stevearc/conform.nvim/commit/819c283db24211fd8ed2732b89a92ff9daa879b6)) * don't overwrite given range with current selection ([#758](https://github.com/stevearc/conform.nvim/issues/758)) ([c2b9a3e](https://github.com/stevearc/conform.nvim/commit/c2b9a3ec310e49487f9b2302042fd91513a7c24b)) * formatters_by_ft can map entire compound filetype ([#679](https://github.com/stevearc/conform.nvim/issues/679)) ([b1a7532](https://github.com/stevearc/conform.nvim/commit/b1a75324ddf96b7bb84963a297b1ed334db087c0)) * js_beautify, css_beautify & html_beautify respect EditorConfig ([#730](https://github.com/stevearc/conform.nvim/issues/730)) ([973f3cb](https://github.com/stevearc/conform.nvim/commit/973f3cb73887d510321653044791d7937c7ec0fa)) * **kulala-fmt:** update args for new version ([#660](https://github.com/stevearc/conform.nvim/issues/660)) ([b5bcbf6](https://github.com/stevearc/conform.nvim/commit/b5bcbf690981f4a4290be55bba2b9b76c8f2f8ba)) * **latexindent:** regression in `f2063898e9` ([#661](https://github.com/stevearc/conform.nvim/issues/661)) ([db8a4a9](https://github.com/stevearc/conform.nvim/commit/db8a4a9edb217067b1d7a2e0362c74bfe9cc944d)) * **prettypst:** stdin and stdout args ([#663](https://github.com/stevearc/conform.nvim/issues/663)) ([8512bba](https://github.com/stevearc/conform.nvim/commit/8512bbaefbfac24fb58d6b4f828bf1e986f61d04)) * respect dos line endings ([#691](https://github.com/stevearc/conform.nvim/issues/691)) ([f542595](https://github.com/stevearc/conform.nvim/commit/f54259518695178168fbad442468e25f121230d4)) * show errors from LSP server response ([#751](https://github.com/stevearc/conform.nvim/issues/751)) ([388759b](https://github.com/stevearc/conform.nvim/commit/388759bb7c150055f84c846b65ae8050d53f4264)) * spurious errors from LSP formatting ([04bfa5f](https://github.com/stevearc/conform.nvim/commit/04bfa5f35706410376bf7618a01fcf44e3f35b59)) * **sqruff:** remove `--force` flag ([#736](https://github.com/stevearc/conform.nvim/issues/736)) ([42e5a34](https://github.com/stevearc/conform.nvim/commit/42e5a346b97cf3b250e4c88cffb6d3860e491a3c)) * **sqruff:** update args, stdin and require_cwd ([#683](https://github.com/stevearc/conform.nvim/issues/683)) ([54eac08](https://github.com/stevearc/conform.nvim/commit/54eac08b5d00e637e150cfe4b1fac50afcc32eb7)) * uncaught undojoin after undo error ([#658](https://github.com/stevearc/conform.nvim/issues/658)) ([03958a3](https://github.com/stevearc/conform.nvim/commit/03958a37a2e0ae6a3ca2b1cbcf0c91cd6ecbdb46)) * **uncrustify:** use project cfg if it exists ([#761](https://github.com/stevearc/conform.nvim/issues/761)) ([26ebdcf](https://github.com/stevearc/conform.nvim/commit/26ebdcfb4f3c9d33d6f81c9534037bd5172b6d65)) * Updated expected exit codes from dcm_format ([#720](https://github.com/stevearc/conform.nvim/issues/720)) ([0e93e0d](https://github.com/stevearc/conform.nvim/commit/0e93e0d12d2f7ebdea9e3e444dfaff0050cefbe6)) ## [9.0.0](https://github.com/stevearc/conform.nvim/compare/v8.4.0...v9.0.0) (2025-02-15) ### ⚠ BREAKING CHANGES * remove deprecated syntax and functions ### cleanup * remove deprecated syntax and functions ([f8d743c](https://github.com/stevearc/conform.nvim/commit/f8d743ce333bedc47821de2cd4d23c43856ecbe5)) ### Features * add air format ([#647](https://github.com/stevearc/conform.nvim/issues/647)) ([754150b](https://github.com/stevearc/conform.nvim/commit/754150b63cf8689f46f19d483cca69b508e0fe22)) * add codeql formatter ([#642](https://github.com/stevearc/conform.nvim/issues/642)) ([65922d8](https://github.com/stevearc/conform.nvim/commit/65922d8b714abcfc2d95ea1738d6fe4ba536c8d8)) * add hurlfmt (hurl files) ([#632](https://github.com/stevearc/conform.nvim/issues/632)) ([ee323a0](https://github.com/stevearc/conform.nvim/commit/ee323a06ed22de68b45caafae4406e20c1be3dc0)) * add support for pyproject-fmt ([#629](https://github.com/stevearc/conform.nvim/issues/629)) ([a7c7e8f](https://github.com/stevearc/conform.nvim/commit/a7c7e8fc0fb3bebabd8e597f6906a83f1515af34)) * **latexindent:** support range formatting ([#654](https://github.com/stevearc/conform.nvim/issues/654)) ([f206389](https://github.com/stevearc/conform.nvim/commit/f2063898e943893b20aeb30a324d5364ebaddff6)) * support nph ([#643](https://github.com/stevearc/conform.nvim/issues/643)) ([e564be1](https://github.com/stevearc/conform.nvim/commit/e564be103a59b32e211977b0833c12869182be7d)) * support reformat-gherkin ([#652](https://github.com/stevearc/conform.nvim/issues/652)) ([8ce4bbd](https://github.com/stevearc/conform.nvim/commit/8ce4bbd3526e3fd8d190ea3744f8c397044c0dc8)) ### Bug Fixes * **csharpier:** update the command to run `dotnet csharpier` ([#649](https://github.com/stevearc/conform.nvim/issues/649)) ([c309423](https://github.com/stevearc/conform.nvim/commit/c309423479f83f561d68d93d74c899f1683834f7)) * give priority to most specific piece of compound filetype ([#630](https://github.com/stevearc/conform.nvim/issues/630)) ([7831107](https://github.com/stevearc/conform.nvim/commit/783110741669a52b85cfac41f499c8162c4423fa)) * incorrect filetype calculation ([b788593](https://github.com/stevearc/conform.nvim/commit/b788593a9fa658b47bc30a04d8f0f7dc98144b14)) * **ruff_format:** add explicit range format args [#638](https://github.com/stevearc/conform.nvim/issues/638) ([59088eb](https://github.com/stevearc/conform.nvim/commit/59088eb6fea54e5a27e719df160329a0ead86b5c)) ## [8.4.0](https://github.com/stevearc/conform.nvim/compare/v8.3.0...v8.4.0) (2025-01-22) ### Features * add nomad_fmt ([#613](https://github.com/stevearc/conform.nvim/issues/613)) ([990d370](https://github.com/stevearc/conform.nvim/commit/990d37017e193fe40bdabf058e598e76f5e7d929)) * add pre and post formatter autocmds ([#623](https://github.com/stevearc/conform.nvim/issues/623)) ([bf94626](https://github.com/stevearc/conform.nvim/commit/bf94626f32fbc3c9987ce2f4aab60d96866587df)) * added js-beautify, css-beautify, and html-beautify) ([#624](https://github.com/stevearc/conform.nvim/issues/624)) ([2569141](https://github.com/stevearc/conform.nvim/commit/25691417836abd0df072b402ff9c103d5c0bab18)) * added sqruff ([#625](https://github.com/stevearc/conform.nvim/issues/625)) ([ab2cf06](https://github.com/stevearc/conform.nvim/commit/ab2cf06b94cf992e202e38729ca68dc394c5b817)) * biome organize imports ([#599](https://github.com/stevearc/conform.nvim/issues/599)) ([06804af](https://github.com/stevearc/conform.nvim/commit/06804af4f2a8ebbc991bb4c7d369c5208e27b0b6)) ### Bug Fixes * create ConformInfo regardless of setup ([#605](https://github.com/stevearc/conform.nvim/issues/605)) ([9180320](https://github.com/stevearc/conform.nvim/commit/9180320205d250429f0f80e073326c674e2a7149)) * disable swapfile for injected formatter temp files ([#619](https://github.com/stevearc/conform.nvim/issues/619)) ([6dc21d4](https://github.com/stevearc/conform.nvim/commit/6dc21d4ce050c2e592d9635b7983d67baf216e3d)) * **format-queries:** require nvim-treesitter before scanning rtp ([#614](https://github.com/stevearc/conform.nvim/issues/614)) ([9941f10](https://github.com/stevearc/conform.nvim/commit/9941f10f8b615ccbaaaaf24cd714e338a9ab9130)) * **injected:** better handling of formatting indented code blocks ([#606](https://github.com/stevearc/conform.nvim/issues/606)) ([28f7fc7](https://github.com/stevearc/conform.nvim/commit/28f7fc7b679438a7090e8f83aa9ba5f67df18146)) * **injected:** bug with inline language injections ([53f6ae4](https://github.com/stevearc/conform.nvim/commit/53f6ae4232179fe43eff3bee63d88d981c491695)) * **injected:** don't format html embedded in markdown ([#485](https://github.com/stevearc/conform.nvim/issues/485)) ([0fbb850](https://github.com/stevearc/conform.nvim/commit/0fbb850657695a1f5df6c803079fc1421002d196)) * **stylua:** Add `--respect-ignores` to the default args ([#616](https://github.com/stevearc/conform.nvim/issues/616)) ([7001912](https://github.com/stevearc/conform.nvim/commit/70019124aa4f2e6838be9fbd2007f6d13b27a96d)) ## [8.3.0](https://github.com/stevearc/conform.nvim/compare/v8.2.0...v8.3.0) (2024-12-21) ### Features * add `prettypst` formatter ([#595](https://github.com/stevearc/conform.nvim/issues/595)) ([676704d](https://github.com/stevearc/conform.nvim/commit/676704d6e6b58cc8cd7321491e99b07a3fd47a1d)) * add commitmsgfmt ([#579](https://github.com/stevearc/conform.nvim/issues/579)) ([b6b03cb](https://github.com/stevearc/conform.nvim/commit/b6b03cb5c826a9ef310b14edeb8f33b18093f8af)) * add format-dune-file ([#602](https://github.com/stevearc/conform.nvim/issues/602)) ([880aa37](https://github.com/stevearc/conform.nvim/commit/880aa379f91ed36c328806846f7c1eca9b49241e)) * add gojq ([#598](https://github.com/stevearc/conform.nvim/issues/598)) ([c5cdc47](https://github.com/stevearc/conform.nvim/commit/c5cdc475c9100933b9e2f6a4876e8baf5ef2735a)) * add support for syntax_tree ([#578](https://github.com/stevearc/conform.nvim/issues/578)) ([8a8b158](https://github.com/stevearc/conform.nvim/commit/8a8b158ead6dee99c6b3af91ad6a41e7a4c54ef3)) * add tex-fmt ([#593](https://github.com/stevearc/conform.nvim/issues/593)) ([d2fdcc3](https://github.com/stevearc/conform.nvim/commit/d2fdcc3fa48cf2f2696f13730a5c74f97a7e9677)) ### Bug Fixes * **buildifier:** formatting of BUILD file ([#594](https://github.com/stevearc/conform.nvim/issues/594)) ([e76afe8](https://github.com/stevearc/conform.nvim/commit/e76afe8f7976071fae308e31bf426f557a8ef339)) * catch failure with undojoin after undo ([#584](https://github.com/stevearc/conform.nvim/issues/584)) ([a203480](https://github.com/stevearc/conform.nvim/commit/a203480a350b03092e473bf3001733d547160a73)) * **elixir mix:** run formatter from project root ([#576](https://github.com/stevearc/conform.nvim/issues/576)) ([f1125f8](https://github.com/stevearc/conform.nvim/commit/f1125f8eace158255cf55772ce039aaf178a6b42)) * improve error message for unknown formatters ([#583](https://github.com/stevearc/conform.nvim/issues/583)) ([19c7ba1](https://github.com/stevearc/conform.nvim/commit/19c7ba1b4be2ebb768b021c6359700918245fe2d)) * injected formatter works for bash ([62055b4](https://github.com/stevearc/conform.nvim/commit/62055b40c4d0b001c87559c7adf96a4a464bcdd5)) * **prettier:** respect "prettier" config field in "package.json" ([#573](https://github.com/stevearc/conform.nvim/issues/573)) ([1a7ff54](https://github.com/stevearc/conform.nvim/commit/1a7ff54dcfbe1af139b11829c6d58f5ffab87707)) * rename awk formatter to gawk ([#589](https://github.com/stevearc/conform.nvim/issues/589)) ([917bc56](https://github.com/stevearc/conform.nvim/commit/917bc566832d91dff00b6e6a6dc658366fd51bac)) * **runner:** replace `$FILENAME` last to avoid magic char conflicts ([#591](https://github.com/stevearc/conform.nvim/issues/591)) ([7a3d99e](https://github.com/stevearc/conform.nvim/commit/7a3d99eb151e636670ce4842ab073d7485f7bc61)) * **stylelint:** support ignored files, node_modules, and cwd ([#577](https://github.com/stevearc/conform.nvim/issues/577)) ([2e281bc](https://github.com/stevearc/conform.nvim/commit/2e281bc8f3833ebc606660081be50c88ccadcbea)) * **xmlformat:** rename to xmlformatter ([#572](https://github.com/stevearc/conform.nvim/issues/572)) ([d23765f](https://github.com/stevearc/conform.nvim/commit/d23765f50637529078aca879351a219d6b1d8010)) ## [8.2.0](https://github.com/stevearc/conform.nvim/compare/v8.1.0...v8.2.0) (2024-11-09) ### Features * add kulala-fmt ([#534](https://github.com/stevearc/conform.nvim/issues/534)) ([555a5c4](https://github.com/stevearc/conform.nvim/commit/555a5c4638957400fe59bf8125e09576bbc6ea86)) * add mojo format ([#540](https://github.com/stevearc/conform.nvim/issues/540)) ([9bde4fb](https://github.com/stevearc/conform.nvim/commit/9bde4fbbbbc80351e96ff91adc92ad566294ad4c)) * add support for kdlfmt ([#543](https://github.com/stevearc/conform.nvim/issues/543)) ([7b9a88c](https://github.com/stevearc/conform.nvim/commit/7b9a88c9d1cd29cb573029b497a96397b87f3c64)), closes [#509](https://github.com/stevearc/conform.nvim/issues/509) * add support for nginx-config-formatter ([#562](https://github.com/stevearc/conform.nvim/issues/562)) ([4fe4f6a](https://github.com/stevearc/conform.nvim/commit/4fe4f6ac44f80163d17f2fa251c0f006d58efc11)) * add support for nufmt ([#551](https://github.com/stevearc/conform.nvim/issues/551)) ([ee640e1](https://github.com/stevearc/conform.nvim/commit/ee640e173bb1b7ee1f4e23dc803c841a70d49221)) * add support for standard-clj ([#568](https://github.com/stevearc/conform.nvim/issues/568)) ([7739b8e](https://github.com/stevearc/conform.nvim/commit/7739b8ee03608f3e7da1760d1b27704b2cd94d06)) * add support for xmlstarlet ([#558](https://github.com/stevearc/conform.nvim/issues/558)) ([bb9c64f](https://github.com/stevearc/conform.nvim/commit/bb9c64fa408cfbbb9f71521f6e158f026da28435)) * allow formatters_by_ft to specify name, id, filter ([#565](https://github.com/stevearc/conform.nvim/issues/565)) ([d28ccf9](https://github.com/stevearc/conform.nvim/commit/d28ccf945374edd9f1c34a82f6c22261dbd8ab98)) * support python-ly ([#549](https://github.com/stevearc/conform.nvim/issues/549)) ([3686f97](https://github.com/stevearc/conform.nvim/commit/3686f974db117e038208c21dbaca6396d112f0f4)) * support ufmt ([#544](https://github.com/stevearc/conform.nvim/issues/544)) ([8a76eef](https://github.com/stevearc/conform.nvim/commit/8a76eef724ba3c0c17380fd6e1d7f1410f1a87a4)) ### Bug Fixes * crash in error handling for function formatters ([#554](https://github.com/stevearc/conform.nvim/issues/554)) ([51e99ef](https://github.com/stevearc/conform.nvim/commit/51e99efa1675bd003a549fb02244b0a54e8de800)) * **deno_fmt:** add support for more file extensions ([#552](https://github.com/stevearc/conform.nvim/issues/552)) ([6a28c90](https://github.com/stevearc/conform.nvim/commit/6a28c90082a67f62a323ab90d988e000a718a8c7)) * health checks error for old Neovim versions ([936f241](https://github.com/stevearc/conform.nvim/commit/936f2413e6c57185cd873623a29a0685bce4b423)) * more notifications when Neovim is below supported version ([130e0d6](https://github.com/stevearc/conform.nvim/commit/130e0d68fdc7f4b8ff7114648f3fa0899bb5fa0f)) * **prettierd:** respect `prettier` config field in the "package.json" ([#564](https://github.com/stevearc/conform.nvim/issues/564)) ([ed919d3](https://github.com/stevearc/conform.nvim/commit/ed919d3f1d824a7713d182560bc7e2e27c0f349b)) ## [8.1.0](https://github.com/stevearc/conform.nvim/compare/v8.0.0...v8.1.0) (2024-09-10) ### Features * **deno:** add support for .mjs files ([#528](https://github.com/stevearc/conform.nvim/issues/528)) ([e82b7b1](https://github.com/stevearc/conform.nvim/commit/e82b7b13b0ed348ce4dbf1495f9b1872d33f9d3f)) * **zine:** add superhtml and ziggy support ([#531](https://github.com/stevearc/conform.nvim/issues/531)) ([392fc98](https://github.com/stevearc/conform.nvim/commit/392fc98c475b4f0552078104624e509b4826d197)) ### Bug Fixes * **log:** prepend date to log lines ([#529](https://github.com/stevearc/conform.nvim/issues/529)) ([c6728c5](https://github.com/stevearc/conform.nvim/commit/c6728c55d1e07da3138beea453d4078668719ee0)) ## [8.0.0](https://github.com/stevearc/conform.nvim/compare/v7.1.0...v8.0.0) (2024-08-20) ### ⚠ BREAKING CHANGES * Require Neovim 0.10+ ### Code Refactoring * Require Neovim 0.10+ ([d31323d](https://github.com/stevearc/conform.nvim/commit/d31323db3fa4a33d203dcb05150d98bd0153c42c)) ## [7.1.0](https://github.com/stevearc/conform.nvim/compare/v7.0.0...v7.1.0) (2024-08-16) ### Features * add support for cljfmt ([#500](https://github.com/stevearc/conform.nvim/issues/500)) ([42e10a3](https://github.com/stevearc/conform.nvim/commit/42e10a38cbb427f418ac17f8a472b3c7315517ba)) * add support for markdownfmt ([#511](https://github.com/stevearc/conform.nvim/issues/511)) ([960f51b](https://github.com/stevearc/conform.nvim/commit/960f51becccadc36825b2c2db266c8cffaeadbde)) * add variable for args to insert the file extension ([#510](https://github.com/stevearc/conform.nvim/issues/510)) ([0f4f299](https://github.com/stevearc/conform.nvim/commit/0f4f299dfea09d2adfd7a1da05149a0844ac8eee)) ### Bug Fixes * **djlint:** remove default indentation arguments ([#517](https://github.com/stevearc/conform.nvim/issues/517)) ([38e5f06](https://github.com/stevearc/conform.nvim/commit/38e5f062f241d89ba44f6d67d16b4bf55d3c477e)) * **docformatter:** update exit_codes, 3 is correct in in-place formatting ([#518](https://github.com/stevearc/conform.nvim/issues/518)) ([667102f](https://github.com/stevearc/conform.nvim/commit/667102f26106709cddd2dff1f699610df5b94d7f)) * **nixfmt:** update repo link and description ([#505](https://github.com/stevearc/conform.nvim/issues/505)) ([2122fe2](https://github.com/stevearc/conform.nvim/commit/2122fe2ff01e9a542fc358ee9398ce2cbddf345d)) * **sqlfluff:** don't assume ansi dialect and require config ([#519](https://github.com/stevearc/conform.nvim/issues/519)) ([bb10949](https://github.com/stevearc/conform.nvim/commit/bb10949d80dd0f60d03572f04953322785f39f7a)) ## [7.0.0](https://github.com/stevearc/conform.nvim/compare/v6.1.0...v7.0.0) (2024-07-23) ### ⚠ BREAKING CHANGES * drop support for nvim 0.8 ### cleanup * drop support for nvim 0.8 ([54ea60d](https://github.com/stevearc/conform.nvim/commit/54ea60d1591486e7e56183addf1f45b03244386d)) ### Features * add sleek, a SQL formatter ([#496](https://github.com/stevearc/conform.nvim/issues/496)) ([8925292](https://github.com/stevearc/conform.nvim/commit/8925292a1e18430a0176671552394d819642b9d9)) * allow configuring conform.format() args on a per-filetype basis ([3a0e9b4](https://github.com/stevearc/conform.nvim/commit/3a0e9b44076514ffba6c81ca28685107928b55f7)) * allow customizing format() defaults ([d7de350](https://github.com/stevearc/conform.nvim/commit/d7de350233e8f686b9affac9c1e106a6602f5fe8)) * deprecate will_fallback_lsp in favor of list_formatters_to_run ([1b590cd](https://github.com/stevearc/conform.nvim/commit/1b590cda290bbabdb116397cb241d20530281b87)) * format parameter to only run the first available formatter ([0b3d259](https://github.com/stevearc/conform.nvim/commit/0b3d25969e2da2f5de90cc02ccd6446aa68dd895)) * notify when no formatters available for a buffer ([8c226d9](https://github.com/stevearc/conform.nvim/commit/8c226d917918ffe92e0f30f4e13acfc088a5faa7)) ### Bug Fixes * crash in nvim-notify ([c16c749](https://github.com/stevearc/conform.nvim/commit/c16c749612fb34a9c1dcc6e4a0f40e24e37d5cfb)) * ensure only expected options get passed through ([834d42c](https://github.com/stevearc/conform.nvim/commit/834d42c17687541750447046b94193d47386665d)) * warn user when they are attempting unsupported behavior ([8b0e62b](https://github.com/stevearc/conform.nvim/commit/8b0e62b731429ecd89cdb6c6b8f004f8468bcf71)) ## [6.1.0](https://github.com/stevearc/conform.nvim/compare/v6.0.0...v6.1.0) (2024-07-19) ### Features * add Swiftlint formatter ([#484](https://github.com/stevearc/conform.nvim/issues/484)) ([bf94a7c](https://github.com/stevearc/conform.nvim/commit/bf94a7cee31df9525239bc7d5ca4910009dfa4ee)) * add undojoin as a format option ([#488](https://github.com/stevearc/conform.nvim/issues/488)) ([1d1362b](https://github.com/stevearc/conform.nvim/commit/1d1362b0261d06a0b91872e916c172320bbb988a)) * **shfmt:** add automatic indentation detection ([#481](https://github.com/stevearc/conform.nvim/issues/481)) ([cd75be8](https://github.com/stevearc/conform.nvim/commit/cd75be867f2331b22905f47d28c0c270a69466aa)) * support doctoc ([#489](https://github.com/stevearc/conform.nvim/issues/489)) ([4f476ba](https://github.com/stevearc/conform.nvim/commit/4f476ba2247bfa5fe46ad52d934536d271d75431)) ### Bug Fixes * **biome-check:** use --write instead of deprecated --apply ([#482](https://github.com/stevearc/conform.nvim/issues/482)) ([0cdd6a7](https://github.com/stevearc/conform.nvim/commit/0cdd6a7c66a57560c91c816a567bd1d247be53c3)) * display stdout as error message if stderr is empty ([#486](https://github.com/stevearc/conform.nvim/issues/486)) ([310e2e9](https://github.com/stevearc/conform.nvim/commit/310e2e95a4f832163f3f7a9fedebb1a4afc0db69)) * **npm-groovy-lint:** ignore exit code 1 ([#477](https://github.com/stevearc/conform.nvim/issues/477)) ([c26dadf](https://github.com/stevearc/conform.nvim/commit/c26dadf8a47a547768d1048a0d698ecec33494ce)) * **shfmt:** don't pass indentation if .editorconfig is present ([#492](https://github.com/stevearc/conform.nvim/issues/492)) ([acc7d93](https://github.com/stevearc/conform.nvim/commit/acc7d93f4a080fec587a99fcb36cffa29adc4bad)) ## [6.0.0](https://github.com/stevearc/conform.nvim/compare/v5.9.0...v6.0.0) (2024-06-25) ### ⚠ BREAKING CHANGES * expand options for LSP formatting ([#456](https://github.com/stevearc/conform.nvim/issues/456)) ### Features * add support for caramel fmt ([#469](https://github.com/stevearc/conform.nvim/issues/469)) ([c35f52b](https://github.com/stevearc/conform.nvim/commit/c35f52b04e4436d5525102b2d61150679c967100)) * **djlint:** use tabstop to set indentation ([#467](https://github.com/stevearc/conform.nvim/issues/467)) ([ac6e142](https://github.com/stevearc/conform.nvim/commit/ac6e142a10c8817762f55a35ed6cb9632671ec79)), closes [#457](https://github.com/stevearc/conform.nvim/issues/457) * expand options for LSP formatting ([#456](https://github.com/stevearc/conform.nvim/issues/456)) ([9228b2f](https://github.com/stevearc/conform.nvim/commit/9228b2ff4efd58b6e081defec643bf887ebadff6)) * support brighterscript-formatter ([#468](https://github.com/stevearc/conform.nvim/issues/468)) ([89af7f0](https://github.com/stevearc/conform.nvim/commit/89af7f00b6e52647c7b0e04eb8cc9bc9cab91e3e)) * support crlfmt ([#470](https://github.com/stevearc/conform.nvim/issues/470)) ([7394d49](https://github.com/stevearc/conform.nvim/commit/7394d4989cd08ddb72e526c43afae7dd3111d553)) * support dcm fix and dcm format ([#471](https://github.com/stevearc/conform.nvim/issues/471)) ([b67f273](https://github.com/stevearc/conform.nvim/commit/b67f2732a2d0276454c7623204741d908de5358a)) * support docformatter ([#472](https://github.com/stevearc/conform.nvim/issues/472)) ([b5ae342](https://github.com/stevearc/conform.nvim/commit/b5ae342ab28919a8083b589a587b030ad859592e)) * support gluon fmt ([#473](https://github.com/stevearc/conform.nvim/issues/473)) ([d1f9bd4](https://github.com/stevearc/conform.nvim/commit/d1f9bd4823628d26a10b98acc9b3b6dbc7b1c053)) * support grain format ([#474](https://github.com/stevearc/conform.nvim/issues/474)) ([d2afc5d](https://github.com/stevearc/conform.nvim/commit/d2afc5de7a24dcde7af13209b91d8e3b87a89661)) * support imba fmt ([#475](https://github.com/stevearc/conform.nvim/issues/475)) ([6856aed](https://github.com/stevearc/conform.nvim/commit/6856aed6d7abf94735739d44a459aef977c2ab44)) * support nickel format ([#476](https://github.com/stevearc/conform.nvim/issues/476)) ([241c892](https://github.com/stevearc/conform.nvim/commit/241c892b265f7a5906584b34c5be36b48c09a4b8)) ### Bug Fixes * deprecate typstfmt formatter ([#458](https://github.com/stevearc/conform.nvim/issues/458)) ([6e5d476](https://github.com/stevearc/conform.nvim/commit/6e5d476e97dbd251cc2233d42fd238c810404701)) * LSP fallback behavior when formatters not availble ([bde3bee](https://github.com/stevearc/conform.nvim/commit/bde3bee1773c96212b6c49f009e05174f932c23a)) ## [5.9.0](https://github.com/stevearc/conform.nvim/compare/v5.8.0...v5.9.0) (2024-06-10) ### Features * add support for d2 ([#445](https://github.com/stevearc/conform.nvim/issues/445)) ([5e7a000](https://github.com/stevearc/conform.nvim/commit/5e7a000e4f239b56077e5a38680c5e9a0bf60e6a)) * add support for efmt ([#428](https://github.com/stevearc/conform.nvim/issues/428)) ([a1d3c0a](https://github.com/stevearc/conform.nvim/commit/a1d3c0aff306b974bc07b4cdf52f1766dd89fc90)) * add support for for vsg ([#451](https://github.com/stevearc/conform.nvim/issues/451)) ([cf562dd](https://github.com/stevearc/conform.nvim/commit/cf562dd160c27a7fc5342dfce7e1227746dd3aaa)) * add support for fprettify ([#429](https://github.com/stevearc/conform.nvim/issues/429)) ([7999faf](https://github.com/stevearc/conform.nvim/commit/7999faf7bbec7461f62dabd57cccb784c8d804b5)) * add support for hindent ([#430](https://github.com/stevearc/conform.nvim/issues/430)) ([9f46982](https://github.com/stevearc/conform.nvim/commit/9f46982b8dc2bf1e267d386ccd096f896369e323)) * add support for kcl fmt ([#431](https://github.com/stevearc/conform.nvim/issues/431)) ([03a07d5](https://github.com/stevearc/conform.nvim/commit/03a07d58be09a681ab162f3a069dc9e86589bacb)) * add support for npm-groovy-lint ([#433](https://github.com/stevearc/conform.nvim/issues/433)) ([8fd894c](https://github.com/stevearc/conform.nvim/commit/8fd894cdc248cad64dbfeac6b89e03db9f737a35)) * add treesitter query formatter ([#425](https://github.com/stevearc/conform.nvim/issues/425)) ([63e0a32](https://github.com/stevearc/conform.nvim/commit/63e0a32c85a39484813957dc480f171907aa90b9)) * **erlang:** support erlfmt ([#436](https://github.com/stevearc/conform.nvim/issues/436)) ([948c83b](https://github.com/stevearc/conform.nvim/commit/948c83b00eb81bf16b54c6a092ddd88be46793cd)) * formatter override can use ([#453](https://github.com/stevearc/conform.nvim/issues/453)) ([a28a425](https://github.com/stevearc/conform.nvim/commit/a28a4255e5c5631ee9c58537592fca05447f0503)) * **fortran:** support findent ([#426](https://github.com/stevearc/conform.nvim/issues/426)) ([969cdf5](https://github.com/stevearc/conform.nvim/commit/969cdf50b011bec08b4fb8bd3ea3031df183501b)) * **haskell:** support stylish-haskell ([#435](https://github.com/stevearc/conform.nvim/issues/435)) ([dc612fb](https://github.com/stevearc/conform.nvim/commit/dc612fbf6194fcb3ef401871db1cae74134e9423)) * **latex:** support llf ([#446](https://github.com/stevearc/conform.nvim/issues/446)) ([1743ee6](https://github.com/stevearc/conform.nvim/commit/1743ee6f9fc52825bdee9493e246876bed591bc1)) * **lua:** support lua-format ([#432](https://github.com/stevearc/conform.nvim/issues/432)) ([b421e95](https://github.com/stevearc/conform.nvim/commit/b421e95a31e6c3b064a964292255e3b9c762fddd)) * **python:** support pyink ([#427](https://github.com/stevearc/conform.nvim/issues/427)) ([8b147ca](https://github.com/stevearc/conform.nvim/commit/8b147ca7abccbb19dd952dbb7aeebcdd56b02aee)) * **rst:** support rstfmt ([#434](https://github.com/stevearc/conform.nvim/issues/434)) ([294bd1d](https://github.com/stevearc/conform.nvim/commit/294bd1d4d32d4c4b797bfc997ea0e4c1a7019ce5)) * support docstrfmt ([#441](https://github.com/stevearc/conform.nvim/issues/441)) ([c841697](https://github.com/stevearc/conform.nvim/commit/c84169717ee74698f9df20c6437fa06df03bf1fe)) ### Bug Fixes * always add cwd to debug logs ([44879ff](https://github.com/stevearc/conform.nvim/commit/44879ffd0268ba931532537b1ee44ed77cd90a5d)) * **dprint:** add support for binary in node_modules ([#422](https://github.com/stevearc/conform.nvim/issues/422)) ([b1285c7](https://github.com/stevearc/conform.nvim/commit/b1285c7c24559688a9e02d3828d9b72f553b3549)) * **format-queries:** update query formatter for breaking changes in nvim-treesitter ([7159a23](https://github.com/stevearc/conform.nvim/commit/7159a23d19fb982269dae2e8147ebbe34965095b)) * improve error message when formatter config is missing ([3f61023](https://github.com/stevearc/conform.nvim/commit/3f610236caf3db6576a0dd7760e5b0731659db68)) * **rustfmt:** add a default cwd when config file is detected ([#419](https://github.com/stevearc/conform.nvim/issues/419)) ([355049b](https://github.com/stevearc/conform.nvim/commit/355049bc318c3c968b2b434cea9a5bcdf6bf8ea7)) * set correct file extension for unsaved buffer temp files ([#440](https://github.com/stevearc/conform.nvim/issues/440)) ([88b699b](https://github.com/stevearc/conform.nvim/commit/88b699b595703f1ae9d9061c050e52b1fe7c33f1)) * use vim.fs.root in neovim 0.10 ([584adfe](https://github.com/stevearc/conform.nvim/commit/584adfe7c665827601f4245c0c40273e8bc9e7cb)) ## [5.8.0](https://github.com/stevearc/conform.nvim/compare/v5.7.0...v5.8.0) (2024-05-22) ### Features * add `ruff_organize_imports` formatter ([#418](https://github.com/stevearc/conform.nvim/issues/418)) ([184756b](https://github.com/stevearc/conform.nvim/commit/184756b7522f82ccdac0013adff1caa313cb897a)) * add forge_fmt formatter support for solidity filetype ([#417](https://github.com/stevearc/conform.nvim/issues/417)) ([18a3fa4](https://github.com/stevearc/conform.nvim/commit/18a3fa45d841c941399b4559ef60b39f2e3ded7c)) * add support for leptosfmt ([#415](https://github.com/stevearc/conform.nvim/issues/415)) ([b999fad](https://github.com/stevearc/conform.nvim/commit/b999fad66fd797a57d745c1a999d000b889bd587)) * add support for typstyle ([#412](https://github.com/stevearc/conform.nvim/issues/412)) ([e47dcde](https://github.com/stevearc/conform.nvim/commit/e47dcde340c80645ab32b09da2c492174e6660c4)) ## [5.7.0](https://github.com/stevearc/conform.nvim/compare/v5.6.0...v5.7.0) (2024-05-16) ### Features * add hcl formatter (hclfmt) ([#402](https://github.com/stevearc/conform.nvim/issues/402)) ([37cbcea](https://github.com/stevearc/conform.nvim/commit/37cbceab0a3b4979c4f0f1ae7aede0d0fa84c1d1)) * add ktfmt formatter for Kotlin ([#392](https://github.com/stevearc/conform.nvim/issues/392)) ([b72f650](https://github.com/stevearc/conform.nvim/commit/b72f650206ddfeadd6c7df0f775a928e82ece353)) * add ormolu formatter for Haskell ([#377](https://github.com/stevearc/conform.nvim/issues/377)) ([#397](https://github.com/stevearc/conform.nvim/issues/397)) ([6207f41](https://github.com/stevearc/conform.nvim/commit/6207f41e8f3813d72ef4499a8132c11d8baabe9f)) * add snakefmt formatter for snakemake files ([#399](https://github.com/stevearc/conform.nvim/issues/399)) ([dc950e5](https://github.com/stevearc/conform.nvim/commit/dc950e5717f1da65b1fcd986b1bbff0d6bd0e2ee)) * add support for bicep ([#368](https://github.com/stevearc/conform.nvim/issues/368)) ([588f357](https://github.com/stevearc/conform.nvim/commit/588f357d305943371de5c945aea65959fd4d80b9)) * add support for bpfmt ([#405](https://github.com/stevearc/conform.nvim/issues/405)) ([3c278a7](https://github.com/stevearc/conform.nvim/commit/3c278a7e09e135e524545adcd725f89bfcc7ffbd)) * add support for mdsf ([#380](https://github.com/stevearc/conform.nvim/issues/380)) ([34d3c5f](https://github.com/stevearc/conform.nvim/commit/34d3c5f58017b1a7e1cd23739b263d7af0f66d7c)) * add support for yew-fmt ([#398](https://github.com/stevearc/conform.nvim/issues/398)) ([b52d462](https://github.com/stevearc/conform.nvim/commit/b52d462cb7bea5e81174ece43eb349357add2f11)) * add verible formatter for SystemVerilog ([#391](https://github.com/stevearc/conform.nvim/issues/391)) ([fb2d35f](https://github.com/stevearc/conform.nvim/commit/fb2d35f2875967b92af9e1e7d31724ce0456fa83)) * formatters can use $RELATIVE_FILEPATH in args ([#349](https://github.com/stevearc/conform.nvim/issues/349)) ([6dc1603](https://github.com/stevearc/conform.nvim/commit/6dc1603ea408f476a57937bbeaf7f86520a21a98)) ### Bug Fixes * **biome-check:** use safe fixes ([#373](https://github.com/stevearc/conform.nvim/issues/373)) ([500a6ae](https://github.com/stevearc/conform.nvim/commit/500a6ae6c10b2a96e85e64045ad9f3b16e2af7f8)) * **biome:** support biome.jsonc file ([#394](https://github.com/stevearc/conform.nvim/issues/394)) ([3cd1135](https://github.com/stevearc/conform.nvim/commit/3cd1135cb2978c9d45b8dc6afc80045fb8a93157)) * handle windows line ending when config.stdin is true ([#361](https://github.com/stevearc/conform.nvim/issues/361)) ([820eec9](https://github.com/stevearc/conform.nvim/commit/820eec990d5f332d30cf939954c8672a43a0459e)) * **isort:** explicitly pass line endings ([#395](https://github.com/stevearc/conform.nvim/issues/395)) ([a3e3e0e](https://github.com/stevearc/conform.nvim/commit/a3e3e0e2966a9fa477bbc86487e920ee0c34f133)) * lazily compute relative filepath ([40faaa8](https://github.com/stevearc/conform.nvim/commit/40faaa8fdd0b7f98f58070943306fd93abb5caad)) * **mix:** allow mix formatter to format different filetypes ([#389](https://github.com/stevearc/conform.nvim/issues/389)) ([12b3995](https://github.com/stevearc/conform.nvim/commit/12b3995537f52ba2810a9857e8ca256881febbda)) * **prettierd:** correctly find prettierd executable on windows ([#378](https://github.com/stevearc/conform.nvim/issues/378)) ([a6965ac](https://github.com/stevearc/conform.nvim/commit/a6965ac128eba75537ec2bc5ddd5d5e357062bdc)) * refactor deprecated methods in neovim 0.10 ([7a205c9](https://github.com/stevearc/conform.nvim/commit/7a205c944d228ca0a5ec67656f59d20ba11ccca2)) * **util:** new function throwing an error when the given extended value is nil ([#385](https://github.com/stevearc/conform.nvim/issues/385)) ([4660e53](https://github.com/stevearc/conform.nvim/commit/4660e534bf7678ee0f85879aa75fdcb6855612c2)) * warning messages for improper async in format_on_save ([#401](https://github.com/stevearc/conform.nvim/issues/401)) ([59d0dd2](https://github.com/stevearc/conform.nvim/commit/59d0dd233a2cafacfa1235ab22054c4d80a72319)) * **windows:** assertion failure when computing relative path ([#400](https://github.com/stevearc/conform.nvim/issues/400)) ([4f0cdf0](https://github.com/stevearc/conform.nvim/commit/4f0cdf07b5498935c34d6cfefde059a3a91584c4)) ## [5.6.0](https://github.com/stevearc/conform.nvim/compare/v5.5.0...v5.6.0) (2024-03-28) ### Features * a formatter for SML (Standard ML) ([#353](https://github.com/stevearc/conform.nvim/issues/353)) ([ae6a069](https://github.com/stevearc/conform.nvim/commit/ae6a069e33027fc522151bf656ab06cf93abca46)) * add formatter for Inko ([#351](https://github.com/stevearc/conform.nvim/issues/351)) ([6874087](https://github.com/stevearc/conform.nvim/commit/68740871bd1b7aecc3759136d576ecb704c4a636)) * add ocp-indent for OCaml formatting ([#335](https://github.com/stevearc/conform.nvim/issues/335)) ([551d02f](https://github.com/stevearc/conform.nvim/commit/551d02f472b646cb82657700e3459f16d9933005)) * add support for nimpretty ([#343](https://github.com/stevearc/conform.nvim/issues/343)) ([67f7fb2](https://github.com/stevearc/conform.nvim/commit/67f7fb2fe82d170c681e6c0da67aa848e6f5a742)) * add support for purs-tidy ([#345](https://github.com/stevearc/conform.nvim/issues/345)) ([bf109f0](https://github.com/stevearc/conform.nvim/commit/bf109f061fc3cd75394b7823923187ae045cbf22)) * add support for roc format ([#342](https://github.com/stevearc/conform.nvim/issues/342)) ([293236a](https://github.com/stevearc/conform.nvim/commit/293236aa7445fb24aba56d8e9a03be54d0c1c2e8)) * **prettier, prettierd:** add mjs files to supported config files ([#350](https://github.com/stevearc/conform.nvim/issues/350)) ([ac4a022](https://github.com/stevearc/conform.nvim/commit/ac4a022c9e10e9697235f657f166372326139e8b)) * support crystal tool format ([#344](https://github.com/stevearc/conform.nvim/issues/344)) ([f8c64b8](https://github.com/stevearc/conform.nvim/commit/f8c64b835f60a80639375500a80e8cd303d8eda6)) ### Bug Fixes * **injected:** ignore indentation of final whitespace line ([#340](https://github.com/stevearc/conform.nvim/issues/340)) ([0a530b3](https://github.com/stevearc/conform.nvim/commit/0a530b31acacf10eca9f9a74b2434ece4d232ca3)) * **terraform_fmt:** do not output color escape codes ([#354](https://github.com/stevearc/conform.nvim/issues/354)) ([f3363ad](https://github.com/stevearc/conform.nvim/commit/f3363ad4b1453b0c9a591d2571c540ed145323d7)) * use `--force-exclude` with Ruff ([#348](https://github.com/stevearc/conform.nvim/issues/348)) ([93f3d4c](https://github.com/stevearc/conform.nvim/commit/93f3d4cabe41473477a314c731e635175458f591)) ## [5.5.0](https://github.com/stevearc/conform.nvim/compare/v5.4.0...v5.5.0) (2024-03-17) ### Features * add formatter config option to change name of temporary file ([#332](https://github.com/stevearc/conform.nvim/issues/332)) ([b059626](https://github.com/stevearc/conform.nvim/commit/b05962622d3eebeefe6b1a90deb9eb86947e0349)) ### Bug Fixes * **phpcbf:** use non-stdin formatting and customize tempfile name ([#333](https://github.com/stevearc/conform.nvim/issues/333)) ([67ee225](https://github.com/stevearc/conform.nvim/commit/67ee2258e08ccb91345d52f62484b657feccef25)) * **rustfmt:** parse edition from Cargo.toml ([#330](https://github.com/stevearc/conform.nvim/issues/330)) ([a605ce4](https://github.com/stevearc/conform.nvim/commit/a605ce4b2db397c84ae6fa8bcfc85f00b985bc73)) * **sqlfluff:** remove --force flag since it's default now ([#338](https://github.com/stevearc/conform.nvim/issues/338)) ([42f3d8e](https://github.com/stevearc/conform.nvim/commit/42f3d8e1c1a90e1114d12a49be838409cbbd1239)) ## [5.4.0](https://github.com/stevearc/conform.nvim/compare/v5.3.0...v5.4.0) (2024-03-13) ### Features * add `gersemi` formatter ([#305](https://github.com/stevearc/conform.nvim/issues/305)) ([79d7fd9](https://github.com/stevearc/conform.nvim/commit/79d7fd9ee84e603bdb66038b1d1ed2703ec08d14)) * add formatter sqlfmt ([#307](https://github.com/stevearc/conform.nvim/issues/307)) ([015f9e9](https://github.com/stevearc/conform.nvim/commit/015f9e90d945545b665dfda52e6c96590c3d1292)) * add gleam formatter ([#327](https://github.com/stevearc/conform.nvim/issues/327)) ([2ebfcaa](https://github.com/stevearc/conform.nvim/commit/2ebfcaa4f2e85550d985eae8ed417401319ebccd)) * add OpenTofu formatter ([#313](https://github.com/stevearc/conform.nvim/issues/313)) ([68dad93](https://github.com/stevearc/conform.nvim/commit/68dad93cde8d8b71e53d07ac43029d0fca06bf26)) * add the cabal-fmt formatter ([#318](https://github.com/stevearc/conform.nvim/issues/318)) ([ea73026](https://github.com/stevearc/conform.nvim/commit/ea73026a163e124edb47fe48075091d924d139af)) * **formatter:** add liquidsoap-prettier ([#312](https://github.com/stevearc/conform.nvim/issues/312)) ([dc873e9](https://github.com/stevearc/conform.nvim/commit/dc873e94f300cdadf0c1949c14b6e9137e7a9981)) ### Bug Fixes * add cwd to honor project php-cs-fixer ([#325](https://github.com/stevearc/conform.nvim/issues/325)) ([f5f8498](https://github.com/stevearc/conform.nvim/commit/f5f8498cf27931e06645c9fe020b9c28dce49d98)) * **prettier:** Fix range formatting of buffer ([#322](https://github.com/stevearc/conform.nvim/issues/322)) ([bc93756](https://github.com/stevearc/conform.nvim/commit/bc937565f251866c0ff344fd13fe27f00a4c0d25)) * remove call to deprecated tbl_add_reverse_lookup ([5a15cc4](https://github.com/stevearc/conform.nvim/commit/5a15cc46e75cad804fd51ec5af9227aeb1d1bdaa)) * **rustfmt:** use Cargo.toml settings and default to recent edition ([#328](https://github.com/stevearc/conform.nvim/issues/328)) ([0ff1b7d](https://github.com/stevearc/conform.nvim/commit/0ff1b7d32fd3e8df194ca5ebec1dab9c61fb9911)) * **swiftformat:** range formatting support and add cwd ([#326](https://github.com/stevearc/conform.nvim/issues/326)) ([db2c697](https://github.com/stevearc/conform.nvim/commit/db2c697fe8302f0328b50b480204be1b577a1e2f)) ## [5.3.0](https://github.com/stevearc/conform.nvim/compare/v5.2.1...v5.3.0) (2024-02-20) ### Features * add awk formatter ([#286](https://github.com/stevearc/conform.nvim/issues/286)) ([338c307](https://github.com/stevearc/conform.nvim/commit/338c3070ae7f7028185ae6123541c2ca71cfe7ff)) * add biome-check formatter ([#287](https://github.com/stevearc/conform.nvim/issues/287)) ([5a71b60](https://github.com/stevearc/conform.nvim/commit/5a71b6064ec6ecf0fff91af67e95200aae9e9562)) * add fantomas formatter ([#302](https://github.com/stevearc/conform.nvim/issues/302)) ([0d99714](https://github.com/stevearc/conform.nvim/commit/0d997149a0472ab811bcfdca5dc45d9db483f949)) * Add reorder-python-imports formatter ([#284](https://github.com/stevearc/conform.nvim/issues/284)) ([9a07f60](https://github.com/stevearc/conform.nvim/commit/9a07f60f7499cdc76ed40af62bb9a50ac928d7d2)) * add ReScript formatter ([#293](https://github.com/stevearc/conform.nvim/issues/293)) ([a34b66f](https://github.com/stevearc/conform.nvim/commit/a34b66f9a4a8f4fb8e270ebfa9c8836fdb8381c1)) * add terragrunt_hclfmt formatter ([#278](https://github.com/stevearc/conform.nvim/issues/278)) ([375258f](https://github.com/stevearc/conform.nvim/commit/375258f1fe1500f175d7135aef1dc6a87dbd83b2)) * add twig-cs-fixer ([#304](https://github.com/stevearc/conform.nvim/issues/304)) ([766812b](https://github.com/stevearc/conform.nvim/commit/766812b0e830c2e40613f99f89102d8840431c6a)) * add yq formatter ([#288](https://github.com/stevearc/conform.nvim/issues/288)) ([15c4a02](https://github.com/stevearc/conform.nvim/commit/15c4a0273bb5468004bb46f632dc5326bc5634d7)) ### Bug Fixes * `swift_format` doesn't respect `.swift-format` file ([#283](https://github.com/stevearc/conform.nvim/issues/283)) ([4588008](https://github.com/stevearc/conform.nvim/commit/4588008a7c5b57fbff97fdfb529c059235cdc7ee)) * set a cwd for biome ([#282](https://github.com/stevearc/conform.nvim/issues/282)) ([03feeb5](https://github.com/stevearc/conform.nvim/commit/03feeb5024a4b44754d63dec55b79b8133a8ea9f)) ## [5.2.1](https://github.com/stevearc/conform.nvim/compare/v5.2.0...v5.2.1) (2024-01-21) ### Bug Fixes * handle windows line endings ([#274](https://github.com/stevearc/conform.nvim/issues/274)) ([9a785eb](https://github.com/stevearc/conform.nvim/commit/9a785eb8f0199ac47ce8bb9e9b6103de5ad8e3a7)) ## [5.2.0](https://github.com/stevearc/conform.nvim/compare/v5.1.0...v5.2.0) (2024-01-16) ### Features * add cue_fmt formatter ([#265](https://github.com/stevearc/conform.nvim/issues/265)) ([03de11a](https://github.com/stevearc/conform.nvim/commit/03de11a0dcf686fda58d64a895483e284dd0c5b6)) * Add dry_run option and report if buffer was/would be changed by formatters ([#273](https://github.com/stevearc/conform.nvim/issues/273)) ([e0276bb](https://github.com/stevearc/conform.nvim/commit/e0276bb32e9b33ece11fef2a5cfc8fb2108df0df)) * add opa_fmt formatter ([#267](https://github.com/stevearc/conform.nvim/issues/267)) ([a4e84d5](https://github.com/stevearc/conform.nvim/commit/a4e84d56d5959dae685c5e22db202cd86b5b322b)) * add xmllint formatter ([#259](https://github.com/stevearc/conform.nvim/issues/259)) ([c50ba4b](https://github.com/stevearc/conform.nvim/commit/c50ba4baad90f02840cc31ee745b09078b7a1777)) * **formatexpr:** don't require LSP range formatting if operating on whole file ([#272](https://github.com/stevearc/conform.nvim/issues/272)) ([47ceff6](https://github.com/stevearc/conform.nvim/commit/47ceff644e9d00872f410be374cc973eefa20ba9)) ### Bug Fixes * **black:** formatting excluded files results in blank buffer ([#254](https://github.com/stevearc/conform.nvim/issues/254)) ([c4b2efb](https://github.com/stevearc/conform.nvim/commit/c4b2efb8aee4af0ef179a9b49ba401de3c4ef5d2)) * copy input parameters for will_fallback_lsp ([ad347d7](https://github.com/stevearc/conform.nvim/commit/ad347d70e66737a8b9d62c19df1c0e2c5b2cd008)) * injected formatter works on nightly ([#270](https://github.com/stevearc/conform.nvim/issues/270)) ([229e9ab](https://github.com/stevearc/conform.nvim/commit/229e9ab5d6e90bc5e6d24141dce3cc28ba95293a)) * LSP deprecated method warning on nvim nightly ([75e7c5c](https://github.com/stevearc/conform.nvim/commit/75e7c5c7eb5fbd53f8b12dc420b31ec70770b231)) * pass explicit bufnr to avoid race conditions ([#260](https://github.com/stevearc/conform.nvim/issues/260)) ([a8e3935](https://github.com/stevearc/conform.nvim/commit/a8e39359814b7b5df5fac7423b4dc93826d64464)) * set a cwd for djlint ([#264](https://github.com/stevearc/conform.nvim/issues/264)) ([0802406](https://github.com/stevearc/conform.nvim/commit/08024063232a7bd38ecdfaf89f06162a5ba2df91)) * set a cwd for dprint ([#263](https://github.com/stevearc/conform.nvim/issues/263)) ([e6c1353](https://github.com/stevearc/conform.nvim/commit/e6c135338257f69c018e8351a6e5f63683f86318)) ## [5.1.0](https://github.com/stevearc/conform.nvim/compare/v5.0.0...v5.1.0) (2023-12-26) ### Features * add fnlfmt formatter ([#247](https://github.com/stevearc/conform.nvim/issues/247)) ([af6643a](https://github.com/stevearc/conform.nvim/commit/af6643afa10e17c0228da97c84d4c32f144a6ad3)) * ConformInfo shows path to executable ([#244](https://github.com/stevearc/conform.nvim/issues/244)) ([fb9b050](https://github.com/stevearc/conform.nvim/commit/fb9b0500270ba05b89cc27cd8b7762443bcfae22)) * **prettier:** add `options` for configuring prettier parser based on filetype and extension ([#241](https://github.com/stevearc/conform.nvim/issues/241)) ([8df1bed](https://github.com/stevearc/conform.nvim/commit/8df1bed7b8de9cf40476996fb5ab73ed667aed35)) ### Bug Fixes * crash in error handling ([4185249](https://github.com/stevearc/conform.nvim/commit/41852493b5abd7b5a0fd61ff007994c777a08ec9)) * **formatexpr:** does not fallback to the built-in formatexpr ([#238](https://github.com/stevearc/conform.nvim/issues/238)) ([48bc999](https://github.com/stevearc/conform.nvim/commit/48bc9996ebfe90e7766f46338360f75fd6ecb174)) * **injected:** code block at end of markdown file ([9245b61](https://github.com/stevearc/conform.nvim/commit/9245b616d1edb159775a0832c03324bf92884494)) * **injected:** handle inline injections ([#251](https://github.com/stevearc/conform.nvim/issues/251)) ([f245cca](https://github.com/stevearc/conform.nvim/commit/f245cca8ad42c9d344b53a18c3fc1a3c6724c2d4)) * **prettier:** use correct prettier executable on windows ([#236](https://github.com/stevearc/conform.nvim/issues/236)) ([7396fc0](https://github.com/stevearc/conform.nvim/commit/7396fc0208539e2bd70e3e446f27529e28dba12b)) * **rubocop:** pass --server for faster execution ([#246](https://github.com/stevearc/conform.nvim/issues/246)) ([0ec6edd](https://github.com/stevearc/conform.nvim/commit/0ec6edd67689e8df6726b83333106bcec13c36d4)) ## [5.0.0](https://github.com/stevearc/conform.nvim/compare/v4.3.0...v5.0.0) (2023-12-07) ### ⚠ BREAKING CHANGES * formatter config functions take self as first argument ([#233](https://github.com/stevearc/conform.nvim/issues/233)) ### Features * add asmfmt ([#239](https://github.com/stevearc/conform.nvim/issues/239)) ([a5ef494](https://github.com/stevearc/conform.nvim/commit/a5ef4943f6382f36a5a8d6e16eb0a0c60af5e7a5)) * add joker for clojure formatting ([#240](https://github.com/stevearc/conform.nvim/issues/240)) ([6b13100](https://github.com/stevearc/conform.nvim/commit/6b1310014ceec5752fd5859f9cc62ef7c93d72b2)) ### Code Refactoring * formatter config functions take self as first argument ([#233](https://github.com/stevearc/conform.nvim/issues/233)) ([659838f](https://github.com/stevearc/conform.nvim/commit/659838ff4244ef6af095395ce68aaaf99fa8e696)) ## [4.3.0](https://github.com/stevearc/conform.nvim/compare/v4.2.0...v4.3.0) (2023-12-07) ### Features * add `auto-optional` ([#196](https://github.com/stevearc/conform.nvim/issues/196)) ([9156364](https://github.com/stevearc/conform.nvim/commit/9156364c23cff19734a0055377321c22b1484c0f)) * add `typos` ([#214](https://github.com/stevearc/conform.nvim/issues/214)) ([d86c186](https://github.com/stevearc/conform.nvim/commit/d86c186ba910d28a6266c4d6210578dca984f3e3)) * add autocorrect ([#223](https://github.com/stevearc/conform.nvim/issues/223)) ([cd81d21](https://github.com/stevearc/conform.nvim/commit/cd81d215d39b16186186a1539c71b48705bb081d)) * add beancount formatter ([#212](https://github.com/stevearc/conform.nvim/issues/212)) ([c0924a6](https://github.com/stevearc/conform.nvim/commit/c0924a61e079d94f0be40da2d4188210c6e4ffea)) * add cbfmt ([#198](https://github.com/stevearc/conform.nvim/issues/198)) ([aa36bc0](https://github.com/stevearc/conform.nvim/commit/aa36bc05563d5390a2ef67956d72560048acdc2e)) * add fourmolu support ([#209](https://github.com/stevearc/conform.nvim/issues/209)) ([e688864](https://github.com/stevearc/conform.nvim/commit/e688864883aa4f468cc73a4c1db661c7c94addc4)) * add jsonnetfmt ([#230](https://github.com/stevearc/conform.nvim/issues/230)) ([769dde8](https://github.com/stevearc/conform.nvim/commit/769dde8ddccf8338c68da706e46fd2fb004e6455)) * add packer formatter ([#202](https://github.com/stevearc/conform.nvim/issues/202)) ([a0cabaa](https://github.com/stevearc/conform.nvim/commit/a0cabaaf5c94137c8dc34043244a34b552860af6)) * add pangu ([#188](https://github.com/stevearc/conform.nvim/issues/188)) ([f0780e2](https://github.com/stevearc/conform.nvim/commit/f0780e2231df2e4751e31db32c1545872412ba75)) * add phpinsights ([#170](https://github.com/stevearc/conform.nvim/issues/170)) ([5235405](https://github.com/stevearc/conform.nvim/commit/5235405cc6d4ac98dc9008ffa850038e3325bbce)) * add styler formatter for R ([#184](https://github.com/stevearc/conform.nvim/issues/184)) ([6afc64e](https://github.com/stevearc/conform.nvim/commit/6afc64e9f36cbae35c2a8b6852d0b91c9807a72a)) * add support for buildifier ([#216](https://github.com/stevearc/conform.nvim/issues/216)) ([e478834](https://github.com/stevearc/conform.nvim/commit/e478834227e0958e21a54f31c9cd896a3a8bdde0)) * add support for sqlfluff ([#213](https://github.com/stevearc/conform.nvim/issues/213)) ([e8c8683](https://github.com/stevearc/conform.nvim/commit/e8c8683a00fb932dfe669e1c96832da12b8054bd)) ### Bug Fixes * **biome:** perform formatting over stdin ([#220](https://github.com/stevearc/conform.nvim/issues/220)) ([eddd643](https://github.com/stevearc/conform.nvim/commit/eddd6431370814caacec1d1e3c7d6d95d41b133d)) * **biome:** use binary from node_modules ([#226](https://github.com/stevearc/conform.nvim/issues/226)) ([5bf1405](https://github.com/stevearc/conform.nvim/commit/5bf1405fd234d469243ea6f394e0aeec9ea53bd8)) * injected formatter adds language to file extension ([#199](https://github.com/stevearc/conform.nvim/issues/199)) ([e2b889e](https://github.com/stevearc/conform.nvim/commit/e2b889e26586acf30dda7b4a5c3f1a063bc18f18)) * injected parser shouldn't format combined injections ([#205](https://github.com/stevearc/conform.nvim/issues/205)) ([eeef888](https://github.com/stevearc/conform.nvim/commit/eeef88849fb644d84a5856524adf10d0ad2d7cbe)) * invalid prettier configuration in last commit ([e8ac7f1](https://github.com/stevearc/conform.nvim/commit/e8ac7f1a9a3973ecce6942b2f26d16e65902aa70)) * range format method for async formatters and injected ([a36c68d](https://github.com/stevearc/conform.nvim/commit/a36c68d2cd551e49883ddb2492c178d915567f58)) * respect excluded-files-config from `typos.toml` ([#219](https://github.com/stevearc/conform.nvim/issues/219)) ([db9da1a](https://github.com/stevearc/conform.nvim/commit/db9da1aa57e8be683ada1b1e5f8129c28d2576eb)) * show more logs in ConformInfo when log level is TRACE ([0963118](https://github.com/stevearc/conform.nvim/commit/0963118e60e0895e2e4842aeffc67cdf9e2bcd10)) * various fixes for the `injected` formatter ([#235](https://github.com/stevearc/conform.nvim/issues/235)) ([07fcbfc](https://github.com/stevearc/conform.nvim/commit/07fcbfc13490786f5983bce3f404643fcfd83775)) ## [4.2.0](https://github.com/stevearc/conform.nvim/compare/v4.1.0...v4.2.0) (2023-11-09) ### Features * add typstfmt ([#180](https://github.com/stevearc/conform.nvim/issues/180)) ([b1f1194](https://github.com/stevearc/conform.nvim/commit/b1f1194338c96d385ec6370ac734ab63c0289776)) ### Bug Fixes * catch jobstart errors ([#183](https://github.com/stevearc/conform.nvim/issues/183)) ([dcbe650](https://github.com/stevearc/conform.nvim/commit/dcbe650bd4811cefe5a885fafb6309c7d592bda6)) * injected formatter not working ([#187](https://github.com/stevearc/conform.nvim/issues/187)) ([68abada](https://github.com/stevearc/conform.nvim/commit/68abada5a348f448eabdbd7d71884c195969484f)) * nonzero exit code on :wq ([#176](https://github.com/stevearc/conform.nvim/issues/176)) ([161d95b](https://github.com/stevearc/conform.nvim/commit/161d95bfbb1ad1a2b89ba2ea75ca1b5e012a111e)) * rename `astgrep` to `ast-grep` ([#178](https://github.com/stevearc/conform.nvim/issues/178)) ([bfa69a9](https://github.com/stevearc/conform.nvim/commit/bfa69a942e19159d3a3e958a5be85cb7cdae19a7)) ## [4.1.0](https://github.com/stevearc/conform.nvim/compare/v4.0.0...v4.1.0) (2023-11-05) ### Features * add `ast-grep` ([#177](https://github.com/stevearc/conform.nvim/issues/177)) ([fa3cf1c](https://github.com/stevearc/conform.nvim/commit/fa3cf1c40716492fd0df0c3dedd54c8018f9ea70)) * add CSharpier ([#165](https://github.com/stevearc/conform.nvim/issues/165)) ([b2368ff](https://github.com/stevearc/conform.nvim/commit/b2368ff18a9dd9452170d3a6f41b1f872ae5d0b2)) * add markdownlint-cli2 ([#171](https://github.com/stevearc/conform.nvim/issues/171)) ([9bb3a94](https://github.com/stevearc/conform.nvim/commit/9bb3a940389dda796192a477a016069472692526)) * add mdslw markdown formatter ([#175](https://github.com/stevearc/conform.nvim/issues/175)) ([369c7fe](https://github.com/stevearc/conform.nvim/commit/369c7fe690b3fec0ecdd7c17faeebf3f8113a0f5)) * add pretty-php ([#161](https://github.com/stevearc/conform.nvim/issues/161)) ([4653408](https://github.com/stevearc/conform.nvim/commit/4653408d5c270168e31ffd0585d1cf2de27fc827)) * add puppet-lint formatter ([#153](https://github.com/stevearc/conform.nvim/issues/153)) ([0219648](https://github.com/stevearc/conform.nvim/commit/0219648cd9a2bafc13fda64903e49fda5db0016b)) * add tlint ([#162](https://github.com/stevearc/conform.nvim/issues/162)) ([2538784](https://github.com/stevearc/conform.nvim/commit/253878436e2b6d73dfd91ccf0ac12d04cc683d34)) * add usort ([#167](https://github.com/stevearc/conform.nvim/issues/167)) ([f7766d2](https://github.com/stevearc/conform.nvim/commit/f7766d2fbe23f0f22a3db1513beba7d03a8dc261)) * allow formatters_by_ft to be a function ([#174](https://github.com/stevearc/conform.nvim/issues/174)) ([0bbe838](https://github.com/stevearc/conform.nvim/commit/0bbe83830be5a07a1161bb1a23d7280310656177)) * gn build file format cmd ([#155](https://github.com/stevearc/conform.nvim/issues/155)) ([3716927](https://github.com/stevearc/conform.nvim/commit/37169273a0776752a3c01cbe01227e275b642b89)) * zprint formatter for clojure ([#146](https://github.com/stevearc/conform.nvim/issues/146)) ([2800552](https://github.com/stevearc/conform.nvim/commit/280055248661a4fc7b692db2d5ee80a465ebb577)) ### Bug Fixes * **formatexpr:** use default formatexpr if no formatters or LSP clients ([#55](https://github.com/stevearc/conform.nvim/issues/55)) ([278bcd8](https://github.com/stevearc/conform.nvim/commit/278bcd8bf2017e187e963b515017341fdd87fe2f)) * **rubyfmt:** exit code 1 should not be a success ([#157](https://github.com/stevearc/conform.nvim/issues/157)) ([e4ecb6e](https://github.com/stevearc/conform.nvim/commit/e4ecb6e8ed3163c86d7e647f1dc3d94de77ca687)) ## [4.0.0](https://github.com/stevearc/conform.nvim/compare/v3.10.0...v4.0.0) (2023-10-16) ### ⚠ BREAKING CHANGES * merge configs in conform.formatters with defaults ([#140](https://github.com/stevearc/conform.nvim/issues/140)) ### Features * add blade-formatter ([#136](https://github.com/stevearc/conform.nvim/issues/136)) ([f90b222](https://github.com/stevearc/conform.nvim/commit/f90b2229c481252c43a71a004972b473952c1c3c)) * add blue formatter ([#142](https://github.com/stevearc/conform.nvim/issues/142)) ([a97ddff](https://github.com/stevearc/conform.nvim/commit/a97ddfff2d701245ad49daf24ef436a50ee72a50)) * Add config for laravel/pint ([#144](https://github.com/stevearc/conform.nvim/issues/144)) ([43414c8](https://github.com/stevearc/conform.nvim/commit/43414c8ebd22921f44806fb9612a2f4f376419af)) * add goimports-reviser ([#143](https://github.com/stevearc/conform.nvim/issues/143)) ([3fcebb0](https://github.com/stevearc/conform.nvim/commit/3fcebb0001e6d5b943dbb36fe5c035e3ef8c3509)) * add ktlint ([#137](https://github.com/stevearc/conform.nvim/issues/137)) ([8b02f47](https://github.com/stevearc/conform.nvim/commit/8b02f478fefe93f76a7f57c983418744287f4c69)) * add rufo support ([#132](https://github.com/stevearc/conform.nvim/issues/132)) ([aca5d30](https://github.com/stevearc/conform.nvim/commit/aca5d307232a22600bd0ab57571a8b6e2dc9a12c)) * merge configs in conform.formatters with defaults ([#140](https://github.com/stevearc/conform.nvim/issues/140)) ([7027ebb](https://github.com/stevearc/conform.nvim/commit/7027ebbd772e2d3593f7dd566dea06d2d20622ee)) * support for rubyfmt ([#139](https://github.com/stevearc/conform.nvim/issues/139)) ([ae33777](https://github.com/stevearc/conform.nvim/commit/ae337775e46804a8347ea7c3da92be5587e5850e)) ### Bug Fixes * prevent format-after-save autocmd from running on invalid buffers ([80f2f70](https://github.com/stevearc/conform.nvim/commit/80f2f70740431b07d725cc66f63abbfd66aaae6d)) * prevent format-on-save autocmd from running on invalid buffers ([#128](https://github.com/stevearc/conform.nvim/issues/128)) ([69ee0bf](https://github.com/stevearc/conform.nvim/commit/69ee0bfde439e30344ae57de6227cb3a035dd0bb)) * **shellcheck:** support filenames with spaces ([#135](https://github.com/stevearc/conform.nvim/issues/135)) ([64a8956](https://github.com/stevearc/conform.nvim/commit/64a89568925c3f62b7ecdcf60b612001d2749eb1)) ## [3.10.0](https://github.com/stevearc/conform.nvim/compare/v3.9.0...v3.10.0) (2023-10-09) ### Features * add easy-coding-standard ([#121](https://github.com/stevearc/conform.nvim/issues/121)) ([e758196](https://github.com/stevearc/conform.nvim/commit/e75819642c36810a55a7235b6b5e16a5ce896ed3)) * add fixjson ([#126](https://github.com/stevearc/conform.nvim/issues/126)) ([280360e](https://github.com/stevearc/conform.nvim/commit/280360eb019fe52433a68b7918790c9187076865)) * add justfile formatter ([#114](https://github.com/stevearc/conform.nvim/issues/114)) ([4c91b52](https://github.com/stevearc/conform.nvim/commit/4c91b5270a6f741850de2eef3a804ff1dc6ec3ee)) * errors do not stop formatting early ([a94f686](https://github.com/stevearc/conform.nvim/commit/a94f686986631d5b97bd75b3877813c39de55c47)) * expose configuration options for injected formatter ([#118](https://github.com/stevearc/conform.nvim/issues/118)) ([ba1ca20](https://github.com/stevearc/conform.nvim/commit/ba1ca20bb5f89a8bdd94b268411263275550843a)) ### Bug Fixes * **biome:** do not use stdin due to biome bug ([#120](https://github.com/stevearc/conform.nvim/issues/120)) ([e5ed063](https://github.com/stevearc/conform.nvim/commit/e5ed0635d9aa66c6c2f7eac3235e6a8eb2de0653)) * catch and fix more cases of bad-behaving LSP formatters ([#119](https://github.com/stevearc/conform.nvim/issues/119)) ([9bd1690](https://github.com/stevearc/conform.nvim/commit/9bd169029ac7fac5d0b3899a47556549d113a4c2)) * handle one failure mode with range formatting ([#123](https://github.com/stevearc/conform.nvim/issues/123)) ([b5a2da9](https://github.com/stevearc/conform.nvim/commit/b5a2da9410d56bd7bc229d0185ad427a966cac50)) * injected formatter handles markdown code blocks in blockquotes ([#117](https://github.com/stevearc/conform.nvim/issues/117)) ([0bffab5](https://github.com/stevearc/conform.nvim/commit/0bffab53672d62cbfe8fc450e78757982e656318)) * move justfile formatter to correct directory ([8217144](https://github.com/stevearc/conform.nvim/commit/8217144491e8aba3a24828a71ee768b007a2ec43)) ## [3.9.0](https://github.com/stevearc/conform.nvim/compare/v3.8.0...v3.9.0) (2023-10-04) ### Features * add phpcbf ([#103](https://github.com/stevearc/conform.nvim/issues/103)) ([db5af4b](https://github.com/stevearc/conform.nvim/commit/db5af4b04e5d61236a142ab78ec3f9416aab848c)) * gci formatter for Go ([#109](https://github.com/stevearc/conform.nvim/issues/109)) ([362e4ec](https://github.com/stevearc/conform.nvim/commit/362e4ec709d241e47d6093dd4b030125ce214cfa)) ### Bug Fixes * format on save autocmds ignore nonstandard buffers ([cb87cab](https://github.com/stevearc/conform.nvim/commit/cb87cab7a6baa6192bf13123c2a5af6fd059d62c)) * injected formatter silent failure on nvim nightly ([#100](https://github.com/stevearc/conform.nvim/issues/100)) ([0156beb](https://github.com/stevearc/conform.nvim/commit/0156beb8397169d7ec18d4f4ea8dd002ee9bcc96)) * phpcbf invalid stdin-path arguments ([#108](https://github.com/stevearc/conform.nvim/issues/108)) ([ce427b0](https://github.com/stevearc/conform.nvim/commit/ce427b03b9cc428ee7a64cb77487ed19efec202d)) * support for mix format ([#107](https://github.com/stevearc/conform.nvim/issues/107)) ([6836930](https://github.com/stevearc/conform.nvim/commit/6836930ed5a0ec6e8bb531116c62cc10f475c298)) ## [3.8.0](https://github.com/stevearc/conform.nvim/compare/v3.7.2...v3.8.0) (2023-10-02) ### Features * add 'google-java-format' formatter ([#99](https://github.com/stevearc/conform.nvim/issues/99)) ([e887736](https://github.com/stevearc/conform.nvim/commit/e8877369df244515af20e18bf1307632fc638d2a)) * add standardrb ([#91](https://github.com/stevearc/conform.nvim/issues/91)) ([37d0367](https://github.com/stevearc/conform.nvim/commit/37d036704a100ef6e6457be45b4dfc2f8e429572)) * metatable to make accessing formatters a bit easier ([#89](https://github.com/stevearc/conform.nvim/issues/89)) ([d8170c1](https://github.com/stevearc/conform.nvim/commit/d8170c14db0f3c90fa799db3bca29d3fb3c089c3)) ### Bug Fixes * alternations follow notification rules ([3f89275](https://github.com/stevearc/conform.nvim/commit/3f8927532bc8ce4fc4b5b75eab1bf8f1fc83f6b9)) * error handling for injected formatter ([f7b82fb](https://github.com/stevearc/conform.nvim/commit/f7b82fb395a4cd636a26ee879b5fd7690612e5a9)) * injected formatter doesn't have interruption errors ([af3d59d](https://github.com/stevearc/conform.nvim/commit/af3d59da20d2bc37933df409f8fc9e24ec15e066)) * injected formatter operates on input lines ([501319e](https://github.com/stevearc/conform.nvim/commit/501319eed2ff26f856ea91b5456bef1d00f77df7)) ## [3.7.2](https://github.com/stevearc/conform.nvim/compare/v3.7.1...v3.7.2) (2023-09-29) ### Bug Fixes * injected formatter hangs on empty file ([671186e](https://github.com/stevearc/conform.nvim/commit/671186e4b29e26ee9fc0f1df4e529134bc334666)) * injected formatter preserves indentation of code blocks ([470d419](https://github.com/stevearc/conform.nvim/commit/470d41988e83913df428c9e832c15b8bb84301ad)) * lsp format calls method from wrong util file ([df69e3e](https://github.com/stevearc/conform.nvim/commit/df69e3ee61e1a0cbb960c8466ace74c696cc7830)) ## [3.7.1](https://github.com/stevearc/conform.nvim/compare/v3.7.0...v3.7.1) (2023-09-29) ### Bug Fixes * format_after_save blocks on exit for lsp formatting ([0c52ee2](https://github.com/stevearc/conform.nvim/commit/0c52ee248245f40610a4957b6bc9515ce1fd9ab6)) ## [3.7.0](https://github.com/stevearc/conform.nvim/compare/v3.6.0...v3.7.0) (2023-09-29) ### Features * add 'JavaScript Standard Style' formatter ([#82](https://github.com/stevearc/conform.nvim/issues/82)) ([971fa7f](https://github.com/stevearc/conform.nvim/commit/971fa7f2e4005454ce141ca8ee0462a3c34d2922)) * add darker ([#80](https://github.com/stevearc/conform.nvim/issues/80)) ([e359687](https://github.com/stevearc/conform.nvim/commit/e359687e3684452ff45d7a5f1a59cd40b0bfa320)) * format injected languages ([#83](https://github.com/stevearc/conform.nvim/issues/83)) ([a5526fb](https://github.com/stevearc/conform.nvim/commit/a5526fb2ee963cf426ab6d6ba1f3eb82887b1c22)) ### Bug Fixes * format_after_save autocmd blocks nvim exit until complete ([388d6e2](https://github.com/stevearc/conform.nvim/commit/388d6e2440bccded26d5e67ce6a7039c1953ae70)) * only show "no formatters" warning if formatters passed in explicitly ([#85](https://github.com/stevearc/conform.nvim/issues/85)) ([45edf94](https://github.com/stevearc/conform.nvim/commit/45edf9462d06db0809d4a4a7afc6b7896b63fa35)) ## [3.6.0](https://github.com/stevearc/conform.nvim/compare/v3.5.0...v3.6.0) (2023-09-27) ### Features * add `markdown-toc` ([#75](https://github.com/stevearc/conform.nvim/issues/75)) ([de58b06](https://github.com/stevearc/conform.nvim/commit/de58b06d434047c6ecd5ec2d52877335d37b05fd)) * Add support for php-cs-fixer ([#78](https://github.com/stevearc/conform.nvim/issues/78)) ([e691eca](https://github.com/stevearc/conform.nvim/commit/e691ecaf41139a68ccb79fde824cb534ca11abd2)) * add templ support ([#73](https://github.com/stevearc/conform.nvim/issues/73)) ([28ecd5c](https://github.com/stevearc/conform.nvim/commit/28ecd5cf9132213417bff41d79477354cb81f50c)) * another utility for extending formatter arguments ([aada09c](https://github.com/stevearc/conform.nvim/commit/aada09c9cfea38187966ce47f34b9008e1104d21)) * new utility function ([9e1fcd5](https://github.com/stevearc/conform.nvim/commit/9e1fcd5cafc42b5dfbe2e942ddbece0dada4e1d0)) ### Bug Fixes * rubocop succeeds even if some errors are not autocorrected ([#74](https://github.com/stevearc/conform.nvim/issues/74)) ([34daf23](https://github.com/stevearc/conform.nvim/commit/34daf23415e9d212697f79506039498db2b35240)) ## [3.5.0](https://github.com/stevearc/conform.nvim/compare/v3.4.1...v3.5.0) (2023-09-22) ### Features * add `bibtex-tidy` ([#69](https://github.com/stevearc/conform.nvim/issues/69)) ([f5e7f84](https://github.com/stevearc/conform.nvim/commit/f5e7f84fb27f05d9a3f3893634cbb6c7f7f89056)) * add dprint ([#71](https://github.com/stevearc/conform.nvim/issues/71)) ([0e2c97a](https://github.com/stevearc/conform.nvim/commit/0e2c97ab640f14f7da92278c731879efcb11f563)) * add mdformat ([#68](https://github.com/stevearc/conform.nvim/issues/68)) ([4a4c927](https://github.com/stevearc/conform.nvim/commit/4a4c92715b174b847ba0fcdccf9dfea71c8ed33e)) * add ruff formatter and improve ruff root finding ([#66](https://github.com/stevearc/conform.nvim/issues/66)) ([44e9e82](https://github.com/stevearc/conform.nvim/commit/44e9e8292d552f9a35498612a93dff934cc8802f)) ### Bug Fixes * `stylelint` and `markdownlint` when there are non-autofixable errors ([#70](https://github.com/stevearc/conform.nvim/issues/70)) ([5454fb5](https://github.com/stevearc/conform.nvim/commit/5454fb5a72a957b550fb7a0f5c4e84684c529920)) ## [3.4.1](https://github.com/stevearc/conform.nvim/compare/v3.4.0...v3.4.1) (2023-09-19) ### Bug Fixes * range formatting for LSP formatters ([#63](https://github.com/stevearc/conform.nvim/issues/63)) ([52280f0](https://github.com/stevearc/conform.nvim/commit/52280f032653e98dd6ecbb61488afcca39671964)) ## [3.4.0](https://github.com/stevearc/conform.nvim/compare/v3.3.0...v3.4.0) (2023-09-18) ### Features * add `squeeze_blanks` ([#62](https://github.com/stevearc/conform.nvim/issues/62)) ([3fa2a7b](https://github.com/stevearc/conform.nvim/commit/3fa2a7be8d91c3f0d7b79dde70d7849518cdc5bf)) * make lsp_fallback behavior more intuitive ([#59](https://github.com/stevearc/conform.nvim/issues/59)) ([1abbb82](https://github.com/stevearc/conform.nvim/commit/1abbb82bb8e519e652d8b31b12a311872e9090d1)) ## [3.3.0](https://github.com/stevearc/conform.nvim/compare/v3.2.0...v3.3.0) (2023-09-17) ### Features * '_' filetype to define fallback formatters ([a589750](https://github.com/stevearc/conform.nvim/commit/a589750635fcc5bb52c7e572cd853446c2c63855)) * add GNU/BSD indent ([#54](https://github.com/stevearc/conform.nvim/issues/54)) ([5abf6c2](https://github.com/stevearc/conform.nvim/commit/5abf6c2c89ff6ed7d17285ec1da759013463bfc7)) * Add rustywind formatter ([#56](https://github.com/stevearc/conform.nvim/issues/56)) ([a839ed1](https://github.com/stevearc/conform.nvim/commit/a839ed1384c21cbd8861f2850b552a4db10ead2f)) * add shellcheck ([#44](https://github.com/stevearc/conform.nvim/issues/44)) ([508ec8a](https://github.com/stevearc/conform.nvim/commit/508ec8a899e039a56f9110011125ab56284db1fa)) * alejandra formatter ([#52](https://github.com/stevearc/conform.nvim/issues/52)) ([e6552b5](https://github.com/stevearc/conform.nvim/commit/e6552b5c9b3a2b12bacb476b00c80c736b9f7963)) * allow running commands in a shell ([#49](https://github.com/stevearc/conform.nvim/issues/49)) ([fbb18a5](https://github.com/stevearc/conform.nvim/commit/fbb18a5b92e2f11aaaef379d74d4a1132a138cb3)) * format_on_save functions can return a callback as the second value ([1a568c6](https://github.com/stevearc/conform.nvim/commit/1a568c66f16650290fffcfbf5aefebe2d8254b83)) * provide a formatexpr ([#55](https://github.com/stevearc/conform.nvim/issues/55)) ([aa38b05](https://github.com/stevearc/conform.nvim/commit/aa38b05575dab57b813ddcd14780f65ff20a6d49)) * utility function to extend the built-in formatter args ([#50](https://github.com/stevearc/conform.nvim/issues/50)) ([cb5f939](https://github.com/stevearc/conform.nvim/commit/cb5f939ab27b2c2ef2e1d4ac6fe16c5ba6332f39)) ### Bug Fixes * `q` keymap in ConformInfo and `codespell` exit codes ([#53](https://github.com/stevearc/conform.nvim/issues/53)) ([d3fe431](https://github.com/stevearc/conform.nvim/commit/d3fe43167c7d96036c8c037ef1b4e03b448efbe7)) * ConformInfo shows available LSP formatters ([3aa2fd5](https://github.com/stevearc/conform.nvim/commit/3aa2fd5f828f8fcabd65605a41953aba1f0f5cb0)) * LSP formatter respects quiet = true ([5e4d258](https://github.com/stevearc/conform.nvim/commit/5e4d258f8eba4090b9a515ee9b77d8647394b2cd)) * unify timeout error message format with LSP ([0d963f8](https://github.com/stevearc/conform.nvim/commit/0d963f82add9ca4faf49b54fc28f57038742ded3)) * use non-deprecated health report functions if available ([#48](https://github.com/stevearc/conform.nvim/issues/48)) ([b436902](https://github.com/stevearc/conform.nvim/commit/b43690264ebcb152365d5b46faa6561f12ea062a)) ## [3.2.0](https://github.com/stevearc/conform.nvim/compare/v3.1.0...v3.2.0) (2023-09-14) ### Features * add `markdownlint`, `stylelint`, `codespell`, and `biome` ([#45](https://github.com/stevearc/conform.nvim/issues/45)) ([580ab18](https://github.com/stevearc/conform.nvim/commit/580ab1880e740f4aebbc72a05350461f3cdef53d)) * add buf as protobuf linter ([#43](https://github.com/stevearc/conform.nvim/issues/43)) ([2b73887](https://github.com/stevearc/conform.nvim/commit/2b73887fd75e1f6efc352cec6bd7e39157c3732e)) * add deno fmt ([#46](https://github.com/stevearc/conform.nvim/issues/46)) ([db7461a](https://github.com/stevearc/conform.nvim/commit/db7461afcf751023adeb346d833f2e5d40a420c4)) * add djlint ([#47](https://github.com/stevearc/conform.nvim/issues/47)) ([ead0257](https://github.com/stevearc/conform.nvim/commit/ead025784c8e31b8e45016e620c2f17a13ff741a)) * latexindent ([#42](https://github.com/stevearc/conform.nvim/issues/42)) ([502a358](https://github.com/stevearc/conform.nvim/commit/502a3583663ede11c8db1e9980db342b117d79f2)) * ruff ([#41](https://github.com/stevearc/conform.nvim/issues/41)) ([fdc4a0f](https://github.com/stevearc/conform.nvim/commit/fdc4a0f05c21012f2445a993ebdad700380dcfbf)) ### Bug Fixes * extra trailing newline for LSP formatters that replace entire file ([e18cdaf](https://github.com/stevearc/conform.nvim/commit/e18cdaf529b94465592d0c2afe1b62bc26155070)) ## [3.1.0](https://github.com/stevearc/conform.nvim/compare/v3.0.0...v3.1.0) (2023-09-13) ### Features * format_on_save and format_after_save can be functions ([dd5b2f2](https://github.com/stevearc/conform.nvim/commit/dd5b2f2f7ca01c2f28239cbbc7f97e6f9024cd94)) ### Bug Fixes * modify diff calculation to handle end-of-file newlines better ([#35](https://github.com/stevearc/conform.nvim/issues/35)) ([00a5288](https://github.com/stevearc/conform.nvim/commit/00a528818463b10d84699b2e0f4a960d5a4aeb5c)) ## [3.0.0](https://github.com/stevearc/conform.nvim/compare/v2.3.0...v3.0.0) (2023-09-08) ### ⚠ BREAKING CHANGES * remove run_all_formatters config option ### Features * add beautysh, taplo, trim_newlines and trim_whitespace ([#29](https://github.com/stevearc/conform.nvim/issues/29)) ([37a2d65](https://github.com/stevearc/conform.nvim/commit/37a2d65bd2ee41540cc426d2cffef6d6f8648357)) * format() can always fall back to LSP formatting ([c3028b3](https://github.com/stevearc/conform.nvim/commit/c3028b327bc44335cc2b5c3014cd6d5c12a54ee4)) * syntax for using first available formatter ([2568d74](https://github.com/stevearc/conform.nvim/commit/2568d746abbadf66a03c62b568ee73d874cd8617)) ### Code Refactoring * remove run_all_formatters config option ([bd1aa02](https://github.com/stevearc/conform.nvim/commit/bd1aa02ef191410b2ea0b3ef5caabe06592d9c51)) ## [2.3.0](https://github.com/stevearc/conform.nvim/compare/v2.2.0...v2.3.0) (2023-09-06) ### Features * format() takes an optional callback ([#21](https://github.com/stevearc/conform.nvim/issues/21)) ([3f34f2d](https://github.com/stevearc/conform.nvim/commit/3f34f2de48e393b2ee289f2c8fa613c7eabae6d8)) ### Bug Fixes * callback should always be called ([eb3ebb6](https://github.com/stevearc/conform.nvim/commit/eb3ebb6d2d114f6476a8f8d21d74f99c6d231a53)) ## [2.2.0](https://github.com/stevearc/conform.nvim/compare/v2.1.0...v2.2.0) (2023-08-31) ### Features * apply changes as text edits using LSP utils ([#18](https://github.com/stevearc/conform.nvim/issues/18)) ([92393f0](https://github.com/stevearc/conform.nvim/commit/92393f02efadfb1d9f97c74c8feb853c1caea9de)) ## [2.1.0](https://github.com/stevearc/conform.nvim/compare/v2.0.0...v2.1.0) (2023-08-30) ### Features * add golines ([#11](https://github.com/stevearc/conform.nvim/issues/11)) ([e1d68a5](https://github.com/stevearc/conform.nvim/commit/e1d68a58fa29d2a24f1a976c3c60521ffb31f32e)) * add perlimports ([#13](https://github.com/stevearc/conform.nvim/issues/13)) ([e6e99af](https://github.com/stevearc/conform.nvim/commit/e6e99af64db3f364086aaf55b8b5854ccd62bac4)) * add perltidy ([#12](https://github.com/stevearc/conform.nvim/issues/12)) ([882b759](https://github.com/stevearc/conform.nvim/commit/882b75994af34fed3c4fe6f1a97ad58b352ec25f)) * add shellharden ([#14](https://github.com/stevearc/conform.nvim/issues/14)) ([863fb46](https://github.com/stevearc/conform.nvim/commit/863fb46fc7a7fa66fafb4bb8fd8093c700c472e5)) * add support for environment variables ([#8](https://github.com/stevearc/conform.nvim/issues/8)) ([03a37f1](https://github.com/stevearc/conform.nvim/commit/03a37f1b53d83af7aee10fc3ffee9f3a05d09e2e)) * display last few lines of the log file in :ConformInfo ([c9327f2](https://github.com/stevearc/conform.nvim/commit/c9327f2af541e4a17a6e2e05682122f8c8455d29)) * formatter config function is passed the buffer number ([#9](https://github.com/stevearc/conform.nvim/issues/9)) ([8b2a574](https://github.com/stevearc/conform.nvim/commit/8b2a5741e07e2d6d5e8103e5e12356d3a9f0b8ba)) * notify when formatter errors, and add notify_on_error config option ([#16](https://github.com/stevearc/conform.nvim/issues/16)) ([08dc913](https://github.com/stevearc/conform.nvim/commit/08dc913fb22d402a98d1d9733536f2876c6f6314)) ### Bug Fixes * shellharden ([#15](https://github.com/stevearc/conform.nvim/issues/15)) ([288068b](https://github.com/stevearc/conform.nvim/commit/288068b1b78c79e64054ef443afbf6f2f5145da4)) ## [2.0.0](https://github.com/stevearc/conform.nvim/compare/v1.1.0...v2.0.0) (2023-08-29) ### ⚠ BREAKING CHANGES * remove ability for formatter list to disable autoformat ### Features * can silence notification when running formatters ([#7](https://github.com/stevearc/conform.nvim/issues/7)) ([a4d793e](https://github.com/stevearc/conform.nvim/commit/a4d793e941e8e497ab9149ed09c946473d795c1b)) * ConformInfo command for debugging formatter status ([1fd547f](https://github.com/stevearc/conform.nvim/commit/1fd547fe98a5100a041106e2bc353363ab0d5ad8)) * range formatting ([cddd536](https://github.com/stevearc/conform.nvim/commit/cddd536e087a9fd3d2c9ea5b0a44e46c7b4b54c2)) ### Bug Fixes * don't show 'no formatters' warning if none configured ([9376d37](https://github.com/stevearc/conform.nvim/commit/9376d37bd7ab456b7df8e3d6f1ba75c05b4e5a8f)) * keep window position stable when LSP formatting ([90e8a8d](https://github.com/stevearc/conform.nvim/commit/90e8a8d63c7d77d1872dca3da720abfa07271054)) * remove unnecessary notify ([6082883](https://github.com/stevearc/conform.nvim/commit/6082883585a5c61c7a5c6697517931bc6e39f546)) * stable ordering when specifying multiple formatters ([69c4495](https://github.com/stevearc/conform.nvim/commit/69c4495ab5ad3c07c3a4f3c2bcac2f070718b4cb)) ### Code Refactoring * remove ability for formatter list to disable autoformat ([d508ae8](https://github.com/stevearc/conform.nvim/commit/d508ae8f46b5b41e2806b412311719a941167c1a)) ## [1.1.0](https://github.com/stevearc/conform.nvim/compare/v1.0.0...v1.1.0) (2023-08-28) ### Features * new formatter: fish_indent ([#5](https://github.com/stevearc/conform.nvim/issues/5)) ([446aa57](https://github.com/stevearc/conform.nvim/commit/446aa570048586f9c13f1ea88e280567f336691e)) ### Bug Fixes * gracefully handle another timeout case ([500d24d](https://github.com/stevearc/conform.nvim/commit/500d24dc1a2447a3c8f3f4f756f40bd27ff0b283)) * no need to save/restore window view ([5bc69d5](https://github.com/stevearc/conform.nvim/commit/5bc69d500a14fb06bf8f36005f76a7825be25931)) ## 1.0.0 (2023-08-25) ### Features * first working version ([eb5987e](https://github.com/stevearc/conform.nvim/commit/eb5987e9dd40ce1e27c9c07e41d09571f1bd876e)) ### Bug Fixes * don't modify files when no styling changes ([08b54ba](https://github.com/stevearc/conform.nvim/commit/08b54ba11e29e6df9f83c02539976331617a412c)) * ensure real buffer numbers get logged ([33ee8ba](https://github.com/stevearc/conform.nvim/commit/33ee8ba8cb6f29caec1edf01fa4987bbae52f18b)) * notification when no formatters available ([a757225](https://github.com/stevearc/conform.nvim/commit/a75722517d17d749a5ee86c8a3bbb098a61265fc)) * set a cwd for stylua ([a22781e](https://github.com/stevearc/conform.nvim/commit/a22781e0c3b609a5f90095f388589744567476c7)) conform.nvim-9.1.0/LICENSE000066400000000000000000000020611505173240700151440ustar00rootroot00000000000000MIT License Copyright (c) 2023 Steven Arcangeli Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. conform.nvim-9.1.0/Makefile000066400000000000000000000023611505173240700156020ustar00rootroot00000000000000## help: print this help message .PHONY: help help: @echo 'Usage:' @sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /' ## all: generate docs, lint, and run tests .PHONY: all all: doc lint test venv: python3 -m venv venv venv/bin/pip install -r scripts/requirements.txt ## doc: generate documentation .PHONY: doc doc: scripts/nvim_doc_tools venv venv/bin/python scripts/main.py generate venv/bin/python scripts/main.py lint ## test: run tests .PHONY: test test: ./run_tests.sh ## lint: run linters and LuaLS typechecking .PHONY: lint lint: scripts/nvim-typecheck-action fastlint ./scripts/nvim-typecheck-action/typecheck.sh --workdir scripts/nvim-typecheck-action lua ## fastlint: run only fast linters .PHONY: fastlint fastlint: scripts/nvim_doc_tools venv venv/bin/python scripts/main.py lint luacheck lua tests --formatter plain stylua --check lua tests scripts/nvim_doc_tools: git clone https://github.com/stevearc/nvim_doc_tools scripts/nvim_doc_tools scripts/nvim-typecheck-action: git clone https://github.com/stevearc/nvim-typecheck-action scripts/nvim-typecheck-action ## clean: reset the repository to a clean state .PHONY: clean clean: rm -rf scripts/nvim_doc_tools scripts/nvim-typecheck-action venv .testenv conform.nvim-9.1.0/README.md000066400000000000000000001573671505173240700154420ustar00rootroot00000000000000# conform.nvim Lightweight yet powerful formatter plugin for Neovim - [Requirements](#requirements) - [Features](#features) - [Installation](#installation) - [Setup](#setup) - [Formatters](#formatters) - [Customizing formatters](#customizing-formatters) - [Magic strings](#magic-strings) - [Recipes](#recipes) - [Debugging](#debugging) - [Advanced topics](#advanced-topics) - [Options](#options) - [Formatter options](#formatter-options) - [API](#api) - [setup(opts)](#setupopts) - [format(opts, callback)](#formatopts-callback) - [list_formatters(bufnr)](#list_formattersbufnr) - [list_formatters_to_run(bufnr)](#list_formatters_to_runbufnr) - [list_all_formatters()](#list_all_formatters) - [get_formatter_info(formatter, bufnr)](#get_formatter_infoformatter-bufnr) - [FAQ](#faq) - [Acknowledgements](#acknowledgements) ## Requirements - Neovim 0.10+ (for older versions, use a [nvim-0.x branch](https://github.com/stevearc/conform.nvim/branches)) ## Features - **Preserves extmarks and folds** - Most formatters replace the entire buffer, which clobbers extmarks and folds, and can cause the viewport and cursor to jump unexpectedly. Conform calculates minimal diffs and applies them using the built-in LSP format utilities. - **Fixes bad-behaving LSP formatters** - Some LSP servers are lazy and simply replace the entire buffer, leading to the problems mentioned above. Conform hooks into the LSP handler and turns these responses into proper piecewise changes. - **Enables range formatting for all formatters** - Since conform calculates minimal diffs, it can perform range formatting [even if the underlying formatter doesn't support it.](doc/advanced_topics.md#range-formatting) - **Simple API** - Conform exposes a simple, imperative API modeled after `vim.lsp.buf.format()`. - **Formats embedded code blocks** - Can format code blocks inside markdown files or similar (see [injected language formatting](doc/advanced_topics.md#injected-language-formatting-code-blocks)) ## Installation conform.nvim supports all the usual plugin managers
lazy.nvim ```lua { 'stevearc/conform.nvim', opts = {}, } ``` For a more thorough configuration involving lazy-loading, see [Lazy loading with lazy.nvim](doc/recipes.md#lazy-loading-with-lazynvim).
Packer ```lua require("packer").startup(function() use({ "stevearc/conform.nvim", config = function() require("conform").setup() end, }) end) ```
Paq ```lua require("paq")({ { "stevearc/conform.nvim" }, }) ```
vim-plug ```vim Plug 'stevearc/conform.nvim' ```
dein ```vim call dein#add('stevearc/conform.nvim') ```
Pathogen ```sh git clone --depth=1 https://github.com/stevearc/conform.nvim.git ~/.vim/bundle/ ```
Neovim native package ```sh git clone --depth=1 https://github.com/stevearc/conform.nvim.git \ "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/pack/conform/start/conform.nvim ```
## Setup At a minimum, you will need to set up some formatters by filetype ```lua require("conform").setup({ formatters_by_ft = { lua = { "stylua" }, -- Conform will run multiple formatters sequentially python = { "isort", "black" }, -- You can customize some of the format options for the filetype (:help conform.format) rust = { "rustfmt", lsp_format = "fallback" }, -- Conform will run the first available formatter javascript = { "prettierd", "prettier", stop_after_first = true }, }, }) ``` Then you can use `conform.format()` just like you would `vim.lsp.buf.format()`. For example, to format on save: ```lua vim.api.nvim_create_autocmd("BufWritePre", { pattern = "*", callback = function(args) require("conform").format({ bufnr = args.buf }) end, }) ``` As a shortcut, conform will optionally set up this format-on-save autocmd for you ```lua require("conform").setup({ format_on_save = { -- These options will be passed to conform.format() timeout_ms = 500, lsp_format = "fallback", }, }) ``` See [conform.format()](#formatopts-callback) for more details about the parameters. Conform also provides a formatexpr, same as the LSP client: ```lua vim.o.formatexpr = "v:lua.require'conform'.formatexpr()" ``` To view configured and available formatters, as well as to see the log file, run `:ConformInfo` ## Formatters You can view this list in vim with `:help conform-formatters`
Expand to see all formatters - [air](https://github.com/posit-dev/air) - R formatter and language server. - [alejandra](https://kamadorueda.com/alejandra/) - The Uncompromising Nix Code Formatter. - [ansible-lint](https://github.com/ansible/ansible-lint) - ansible-lint with --fix. - [asmfmt](https://github.com/klauspost/asmfmt) - Go Assembler Formatter - [ast-grep](https://ast-grep.github.io/) - A CLI tool for code structural search, lint and rewriting. Written in Rust. - [astyle](https://astyle.sourceforge.net/astyle.html) - A Free, Fast, and Small Automatic Formatter for C, C++, C++/CLI, Objective-C, C#, and Java Source Code. - [auto_optional](https://auto-optional.daanluttik.nl/) - Adds the Optional type-hint to arguments where the default value is None. - [autocorrect](https://github.com/huacnlee/autocorrect) - A linter and formatter to help you to improve copywriting, correct spaces, words, and punctuations between CJK. - [autoflake](https://github.com/PyCQA/autoflake) - Removes unused imports and unused variables as reported by pyflakes. - [autopep8](https://github.com/hhatto/autopep8) - A tool that automatically formats Python code to conform to the PEP 8 style guide. - [bake](https://github.com/EbodShojaei/bake) - A Makefile formatter and linter. - [bean-format](https://beancount.github.io/docs/running_beancount_and_generating_reports.html#bean-format) - Reformat Beancount files to right-align all the numbers at the same, minimal column. - [beautysh](https://github.com/lovesegfault/beautysh) - A Bash beautifier for the masses. - [bibtex-tidy](https://github.com/FlamingTempura/bibtex-tidy) - Cleaner and Formatter for BibTeX files. - [bicep](https://github.com/Azure/bicep) - Bicep is a Domain Specific Language (DSL) for deploying Azure resources declaratively. - [biome](https://github.com/biomejs/biome) - A toolchain for web projects, aimed to provide functionalities to maintain them. - [biome-check](https://github.com/biomejs/biome) - A toolchain for web projects, aimed to provide functionalities to maintain them. - [biome-organize-imports](https://github.com/biomejs/biome) - A toolchain for web projects, aimed to provide functionalities to maintain them. - [black](https://github.com/psf/black) - The uncompromising Python code formatter. - [blade-formatter](https://github.com/shufo/blade-formatter) - An opinionated blade template formatter for Laravel that respects readability. - [blue](https://github.com/grantjenks/blue) - The slightly less uncompromising Python code formatter. - [bpfmt](https://source.android.com/docs/setup/reference/androidbp) - Android Blueprint file formatter. - [bsfmt](https://github.com/rokucommunity/brighterscript-formatter) - A code formatter for BrighterScript (and BrightScript). - [buf](https://buf.build/docs/reference/cli/buf/format) - A new way of working with Protocol Buffers. - [buildifier](https://github.com/bazelbuild/buildtools/tree/master/buildifier) - buildifier is a tool for formatting bazel BUILD and .bzl files with a standard convention. - [cabal_fmt](https://hackage.haskell.org/package/cabal-fmt) - Format cabal files with cabal-fmt. - [caramel_fmt](https://caramel.run/manual/reference/cli/fmt.html) - Format Caramel code. - [cbfmt](https://github.com/lukas-reineke/cbfmt) - A tool to format codeblocks inside markdown and org documents. - [cedar](https://github.com/cedar-policy/cedar) - Formats cedar policies. - [clang-format](https://clang.llvm.org/docs/ClangFormat.html) - Tool to format C/C++/… code according to a set of rules and heuristics. - [cljfmt](https://github.com/weavejester/cljfmt) - cljfmt is a tool for detecting and fixing formatting errors in Clojure code. - [cljstyle](https://github.com/greglook/cljstyle) - Formatter for Clojure code. - [cmake_format](https://github.com/cheshirekow/cmake_format) - Parse cmake listfiles and format them nicely. - [codeql](https://docs.github.com/en/code-security/codeql-cli/codeql-cli-manual/query-format) - Format queries and libraries with CodeQL. - [codespell](https://github.com/codespell-project/codespell) - Check code for common misspellings. - [commitmsgfmt](https://gitlab.com/mkjeldsen/commitmsgfmt) - Formats commit messages better than fmt(1) and Vim. - [crlfmt](https://github.com/cockroachdb/crlfmt) - Formatter for CockroachDB's additions to the Go style guide. - [crystal](https://crystal-lang.org/) - Format Crystal code. - [csharpier](https://github.com/belav/csharpier) - The opinionated C# code formatter. - [css_beautify](https://github.com/beautifier/js-beautify) - Beautifier for css. - [cue_fmt](https://cuelang.org) - Format CUE files using `cue fmt` command. - [d2](https://github.com/terrastruct/d2) - D2 is a modern diagram scripting language that turns text to diagrams. - [darker](https://github.com/akaihola/darker) - Run black only on changed lines. - [dart_format](https://dart.dev/tools/dart-format) - Replace the whitespace in your program with formatting that follows Dart guidelines. - [dcm_fix](https://dcm.dev/docs/cli/formatting/fix/) - Fixes issues produced by dcm analyze, dcm check-unused-code or dcm check-dependencies commands. - [dcm_format](https://dcm.dev/docs/cli/formatting/format/) - Formats .dart files. - [deno_fmt](https://deno.land/manual/tools/formatter) - Use [Deno](https://deno.land/) to format TypeScript, JavaScript/JSON and markdown. - [dfmt](https://github.com/dlang-community/dfmt) - Formatter for D source code. - [dioxus](https://github.com/dioxuslabs/dioxus) - Format `rsx!` snippets in Rust files. - [djlint](https://github.com/Riverside-Healthcare/djLint) - ✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks - Handlebars - GoLang. - [docformatter](https://pypi.org/project/docformatter/) - docformatter automatically formats docstrings to follow a subset of the PEP 257 conventions. - [dockerfmt](https://github.com/reteps/dockerfmt) - Dockerfile formatter. a modern dockfmt. - [docstrfmt](https://github.com/LilSpazJoekp/docstrfmt) - reStructuredText formatter. - [doctoc](https://github.com/thlorenz/doctoc) - Generates table of contents for markdown files inside local git repository. - [dprint](https://github.com/dprint/dprint) - Pluggable and configurable code formatting platform written in Rust. - [easy-coding-standard](https://github.com/easy-coding-standard/easy-coding-standard) - ecs - Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer. - [efmt](https://github.com/sile/efmt) - Erlang code formatter. - [elm_format](https://github.com/avh4/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](https://github.com/nebulab/erb-formatter) - Format ERB files with speed and precision. - [erlfmt](https://github.com/WhatsApp/erlfmt) - An automated code formatter for Erlang. - [eslint_d](https://github.com/mantoni/eslint_d.js/) - Like ESLint, but faster. - [fantomas](https://github.com/fsprojects/fantomas) - F# source code formatter. - [findent](https://github.com/wvermin/findent) - Indent, relabel and convert Fortran sources. - [fish_indent](https://fishshell.com/docs/current/cmds/fish_indent.html) - Indent or otherwise prettify a piece of fish code. - [fixjson](https://github.com/rhysd/fixjson) - JSON Fixer for Humans using (relaxed) JSON5. - [fnlfmt](https://git.sr.ht/~technomancy/fnlfmt) - A formatter for Fennel code. - [forge_fmt](https://github.com/foundry-rs/foundry) - Forge is a command-line tool that ships with Foundry. Forge tests, builds, and deploys your smart contracts. - [format-dune-file](https://github.com/ocaml/dune) - Auto-formatter for Dune files. - [format-queries](https://github.com/nvim-treesitter/nvim-treesitter/blob/main/CONTRIBUTING.md#formatting) - Tree-sitter query formatter. - [fourmolu](https://hackage.haskell.org/package/fourmolu) - A fork of ormolu that uses four space indentation and allows arbitrary configuration. - [fprettify](https://github.com/fortran-lang/fprettify) - Auto-formatter for modern fortran source code. - [gawk](https://www.gnu.org/software/gawk/manual/gawk.html) - Format awk programs with gawk. - [gci](https://github.com/daixiang0/gci) - GCI, a tool that controls Go package import order and makes it always deterministic. - [gdformat](https://github.com/Scony/godot-gdscript-toolkit) - A formatter for Godot's gdscript. - [gersemi](https://github.com/BlankSpruce/gersemi) - A formatter to make your CMake code the real treasure. - [ghdl](https://ghdl.github.io/ghdl/) - Open-source analyzer, compiler, simulator and synthesizer for VHDL. - [ghokin](https://github.com/antham/ghokin) - Parallelized formatter with no external dependencies for gherkin. - [gleam](https://github.com/gleam-lang/gleam) - ⭐️ A friendly language for building type-safe, scalable systems! - [gluon_fmt](https://github.com/gluon-lang/gluon) - Code formatting for the gluon programming language. - [gn](https://gn.googlesource.com/gn/) - gn build system. - [gofmt](https://pkg.go.dev/cmd/gofmt) - Formats go programs. - [gofumpt](https://github.com/mvdan/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](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) - Updates your Go import lines, adding missing ones and removing unreferenced ones. - [goimports-reviser](https://github.com/incu6us/goimports-reviser) - Right imports sorting & code formatting tool (goimports alternative). - [gojq](https://github.com/itchyny/gojq) - Pure Go implementation of jq. - [golangci-lint](https://golangci-lint.run/usage/configuration/#fmt) - Fast linters runner for Go (with formatter). - [golines](https://github.com/segmentio/golines) - A golang formatter that fixes long lines. - [google-java-format](https://github.com/google/google-java-format) - Reformats Java source code according to Google Java Style. - [grain_format](https://grain-lang.org/docs/tooling/grain_cli#grain-format) - Code formatter for the grain programming language. - [hcl](https://github.com/hashicorp/hcl) - A formatter for HCL files. - [hindent](https://github.com/mihaimaruseac/hindent) - Haskell pretty printer. - [hledger-fmt](https://github.com/mondeja/hledger-fmt) - An opinionated hledger's journal files formatter. - [html_beautify](https://github.com/beautifier/js-beautify) - Beautifier for html. - [htmlbeautifier](https://github.com/threedaymonk/htmlbeautifier) - A normaliser/beautifier for HTML that also understands embedded Ruby. Ideal for tidying up Rails templates. - [hurlfmt](https://hurl.dev/) - Formats hurl files. - [imba_fmt](https://imba.io/) - Code formatter for the Imba programming language. - [indent](https://www.gnu.org/software/indent/) - GNU Indent. - [injected](doc/advanced_topics.md#injected-language-formatting-code-blocks) - Format treesitter injected languages. - [inko](https://inko-lang.org/) - A language for building concurrent software with confidence - [isort](https://github.com/PyCQA/isort) - Python utility / library to sort imports alphabetically and automatically separate them into sections and by type. - [janet-format](https://github.com/janet-lang/spork) - A formatter for Janet code. - [joker](https://github.com/candid82/joker) - Small Clojure interpreter, linter and formatter. - [jq](https://github.com/stedolan/jq) - Command-line JSON processor. - [js_beautify](https://github.com/beautifier/js-beautify) - Beautifier for javascript. - [jsonnetfmt](https://github.com/google/go-jsonnet/tree/master/cmd/jsonnetfmt) - jsonnetfmt is a command line tool to format jsonnet files. - [just](https://github.com/casey/just) - Format Justfile. - [kcl](https://www.kcl-lang.io/docs/tools/cli/kcl/fmt) - The KCL Format tool modifies the files according to the KCL code style. - [kdlfmt](https://github.com/hougesen/kdlfmt) - A formatter for kdl documents. - [keep-sorted](https://github.com/google/keep-sorted) - keep-sorted is a language-agnostic formatter that sorts lines between two markers in a larger file. - [ktfmt](https://github.com/facebook/ktfmt) - Reformats Kotlin source code to comply with the common community standard conventions. - [ktlint](https://ktlint.github.io/) - An anti-bikeshedding Kotlin linter with built-in formatter. - [kulala-fmt](https://github.com/mistweaverco/kulala-fmt) - An opinionated .http and .rest files linter and formatter. - [latexindent](https://github.com/cmhughes/latexindent.pl) - A perl script for formatting LaTeX files that is generally included in major TeX distributions. - [leptosfmt](https://github.com/bram209/leptosfmt) - A formatter for the Leptos view! macro. - [liquidsoap-prettier](https://github.com/savonet/liquidsoap-prettier) - A binary to format Liquidsoap scripts - [llf](https://repo.or.cz/llf.git) - A LaTeX reformatter / beautifier. - [lua-format](https://github.com/Koihik/LuaFormatter) - Code formatter for Lua. - [mago_format](https://github.com/carthage-software/mago) - Mago is a toolchain for PHP that aims to provide a set of tools to help developers write better code. - [mago_lint](https://github.com/carthage-software/mago) - Mago is a toolchain for PHP that aims to provide a set of tools to help developers write better code. - [markdown-toc](https://github.com/jonschlinkert/markdown-toc) - API and CLI for generating a markdown TOC (table of contents) for a README or any markdown files. - [markdownfmt](https://github.com/shurcooL/markdownfmt) - Like gofmt, but for Markdown. - [markdownlint](https://github.com/DavidAnson/markdownlint) - A Node.js style checker and lint tool for Markdown/CommonMark files. - [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) - A fast, flexible, configuration-based command-line interface for linting Markdown/CommonMark files with the markdownlint library. - [mdformat](https://github.com/executablebooks/mdformat) - An opinionated Markdown formatter. - [mdsf](https://github.com/hougesen/mdsf) - Format markdown code blocks using your favorite code formatters. - [mdslw](https://github.com/razziel89/mdslw) - Prepare your markdown for easy diff'ing by adding line breaks after every sentence. - [mix](https://hexdocs.pm/mix/main/Mix.Tasks.Format.html) - Format Elixir files using the mix format command. - [mojo_format](https://docs.modular.com/mojo/cli/format) - Official Formatter for The Mojo Programming Language - [nginxfmt](https://github.com/slomkowski/nginx-config-formatter) - nginx config file formatter/beautifier written in Python with no additional dependencies. - [nickel](https://nickel-lang.org/) - Code formatter for the Nickel programming language. - [nimpretty](https://github.com/nim-lang/nim) - nimpretty is a Nim source code beautifier that follows the official style guide. - [nixfmt](https://github.com/NixOS/nixfmt) - The official (but not yet stable) formatter for Nix code. - [nixpkgs_fmt](https://github.com/nix-community/nixpkgs-fmt) - nixpkgs-fmt is a Nix code formatter for nixpkgs. - [nomad_fmt](https://developer.hashicorp.com/nomad/docs/commands/fmt) - The fmt commands check the syntax and rewrites Nomad configuration and jobspec files to canonical format. - [nph](https://github.com/arnetheduck/nph) - An opinionated code formatter for Nim. - [npm-groovy-lint](https://github.com/nvuillam/npm-groovy-lint) - Lint, format and auto-fix your Groovy / Jenkinsfile / Gradle files using command line. - [nufmt](https://github.com/nushell/nufmt) - The nushell formatter. - [ocamlformat](https://github.com/ocaml-ppx/ocamlformat) - Auto-formatter for OCaml code. - [ocp-indent](https://github.com/OCamlPro/ocp-indent) - Automatic indentation of OCaml source files. - [odinfmt](https://github.com/DanielGavin/ols) - Auto-formatter for the Odin programming language. - [opa_fmt](https://www.openpolicyagent.org/docs/latest/cli/#opa-fmt) - Format Rego files using `opa fmt` command. - [ormolu](https://hackage.haskell.org/package/ormolu) - A formatter for Haskell source code. - [packer_fmt](https://developer.hashicorp.com/packer/docs/commands/fmt) - The packer fmt Packer command is used to format HCL2 configuration files to a canonical format and style. - [pangu](https://github.com/vinta/pangu.py) - Insert whitespace between CJK and half-width characters. - [perlimports](https://github.com/perl-ide/App-perlimports) - Make implicit Perl imports explicit. - [perltidy](https://github.com/perltidy/perltidy) - Perl::Tidy, a source code formatter for Perl. - [pg_format](https://github.com/darold/pgFormatter) - PostgreSQL SQL syntax beautifier. - [php_cs_fixer](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer) - The PHP Coding Standards Fixer. - [phpcbf](https://phpqa.io/projects/phpcbf.html) - PHP Code Beautifier and Fixer fixes violations of a defined coding standard. - [phpinsights](https://github.com/nunomaduro/phpinsights) - The perfect starting point to analyze the code quality of your PHP projects. - [pint](https://github.com/laravel/pint) - Laravel Pint is an opinionated PHP code style fixer for minimalists. - [prettier](https://github.com/prettier/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](https://github.com/fsouza/prettierd) - prettier, as a daemon, for ludicrous formatting speed. - [pretty-php](https://github.com/lkrms/pretty-php) - The opinionated PHP code formatter. - [prettypst](https://github.com/antonWetzel/prettypst) - Formatter for Typst. - [prolog](https://github.com/jamesnvc/lsp_server) - Language Server Protocol server and formatter for SWI-Prolog. - [puppet-lint](https://github.com/puppetlabs/puppet-lint) - Check that your Puppet manifests conform to the style guide. - [purs-tidy](https://github.com/natefaubion/purescript-tidy) - A syntax tidy-upper for PureScript. - [pycln](https://github.com/hadialqattan/pycln) - A Python formatter for finding and removing unused import statements. - [pyink](https://github.com/google/pyink) - A Python formatter, forked from Black with a few different formatting behaviors. - [pymarkdownlnt](https://github.com/jackdewinter/pymarkdown) - A markdown linter and formatter. - [pyproject-fmt](https://github.com/tox-dev/toml-fmt/tree/main/pyproject-fmt) - Apply a consistent format to your pyproject.toml file with comment support. - [python-ly](https://github.com/frescobaldi/python-ly) - A Python package and commandline tool to manipulate LilyPond files. - [pyupgrade](https://github.com/asottile/pyupgrade) - A tool to automatically upgrade syntax for newer versions of Python. - [qmlformat](https://doc.qt.io/qt-6//qtqml-tooling-qmlformat.html) - A tool that automatically formats QML files. - [reformat-gherkin](https://github.com/ducminh-phan/reformat-gherkin) - Formatter for Gherkin language. - [reorder-python-imports](https://github.com/asottile/reorder-python-imports) - Rewrites source to reorder python imports - [rescript-format](https://rescript-lang.org/) - The built-in ReScript formatter. - [roc](https://github.com/roc-lang/roc) - A fast, friendly, functional language. - [rstfmt](https://github.com/dzhu/rstfmt) - A formatter for reStructuredText. - [rubocop](https://github.com/rubocop/rubocop) - Ruby static code analyzer and formatter, based on the community Ruby style guide. - [rubyfmt](https://github.com/fables-tales/rubyfmt) - Ruby Autoformatter! (Written in Rust) - [ruff_fix](https://docs.astral.sh/ruff/) - An extremely fast Python linter, written in Rust. Fix lint errors. - [ruff_format](https://docs.astral.sh/ruff/) - An extremely fast Python linter, written in Rust. Formatter subcommand. - [ruff_organize_imports](https://docs.astral.sh/ruff/) - An extremely fast Python linter, written in Rust. Organize imports. - [rufo](https://github.com/ruby-formatter/rufo) - Rufo is an opinionated ruby formatter. - [runic](https://github.com/fredrikekre/Runic.jl) - Julia code formatter. - [rustfmt](https://github.com/rust-lang/rustfmt) - A tool for formatting rust code according to style guidelines. - [rustywind](https://github.com/avencera/rustywind) - A tool for formatting Tailwind CSS classes. - [scalafmt](https://github.com/scalameta/scalafmt) - Code formatter for Scala. - [shellcheck](https://github.com/koalaman/shellcheck) - A static analysis tool for shell scripts. - [shellharden](https://github.com/anordal/shellharden) - The corrective bash syntax highlighter. - [shfmt](https://github.com/mvdan/sh) - A shell parser, formatter, and interpreter with `bash` support. - [sleek](https://github.com/nrempel/sleek) - Sleek is a CLI tool for formatting SQL. - [smlfmt](https://github.com/shwestrick/smlfmt) - A custom parser and code formatter for Standard ML. - [snakefmt](https://github.com/snakemake/snakefmt) - a formatting tool for Snakemake files following the design of Black. - [spotless_gradle](https://github.com/diffplug/spotless) - Spotless plugin for Gradle. - [spotless_maven](https://github.com/diffplug/spotless) - Spotless plugin for Maven. - [sql_formatter](https://github.com/sql-formatter-org/sql-formatter) - A whitespace formatter for different query languages. - [sqlfluff](https://github.com/sqlfluff/sqlfluff) - A modular SQL linter and auto-formatter with support for multiple dialects and templated code. - [sqlfmt](https://docs.sqlfmt.com) - 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](https://github.com/quarylabs/sqruff) - sqruff is a SQL linter and formatter written in Rust. - [squeeze_blanks](https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html#cat-invocation) - Squeeze repeated blank lines into a single blank line via `cat -s`. - [standard-clj](https://github.com/oakmac/standard-clojure-style-js) - A JavaScript library to format Clojure code according to Standard Clojure Style. - [standardjs](https://standardjs.com) - JavaScript Standard style guide, linter, and formatter. - [standardrb](https://github.com/standardrb/standard) - Ruby's bikeshed-proof linter and formatter. - [stylelint](https://github.com/stylelint/stylelint) - A mighty CSS linter that helps you avoid errors and enforce conventions. - [styler](https://github.com/devOpifex/r.nvim) - R formatter and linter. - [stylish-haskell](https://github.com/haskell/stylish-haskell) - Haskell code prettifier. - [stylua](https://github.com/JohnnyMorganz/StyLua) - An opinionated code formatter for Lua. - [superhtml](https://github.com/kristoff-it/superhtml) - HTML Language Server and Templating Language Library. - [swift](https://github.com/swiftlang/swift-format) - Official Swift formatter. Requires Swift 6.0 or later. - [swift_format](https://github.com/swiftlang/swift-format) - Official Swift formatter. For Swift 6.0 or later prefer setting the `swift` formatter instead. - [swiftformat](https://github.com/nicklockwood/SwiftFormat) - SwiftFormat is a code library and command-line tool for reformatting `swift` code on macOS or Linux. - [swiftlint](https://github.com/realm/SwiftLint) - A tool to enforce Swift style and conventions. - [syntax_tree](https://github.com/ruby-syntax-tree/syntax_tree) - Syntax Tree is a suite of tools built on top of the internal CRuby parser. - [taplo](https://github.com/tamasfe/taplo) - A TOML toolkit written in Rust. - [templ](https://templ.guide/developer-tools/cli/#formatting-templ-files) - Formats templ template files. - [terraform_fmt](https://www.terraform.io/docs/cli/commands/fmt.html) - The terraform-fmt command rewrites `terraform` configuration files to a canonical format and style. - [terragrunt_hclfmt](https://terragrunt.gruntwork.io/docs/reference/cli-options/#hclfmt) - Format hcl files into a canonical format. - [tex-fmt](https://github.com/WGUNDERWOOD/tex-fmt) - An extremely fast LaTeX formatter written in Rust. - [tlint](https://github.com/tighten/tlint) - Tighten linter for Laravel conventions with support for auto-formatting. - [tofu_fmt](https://opentofu.org/docs/cli/commands/fmt/) - The tofu-fmt command rewrites OpenTofu configuration files to a canonical format and style. - [tombi](https://github.com/tombi-toml/tombi) - TOML Formatter / Linter. - [treefmt](https://github.com/numtide/treefmt) - one CLI to format your repo. - [trim_newlines](https://github.com/stevearc/conform.nvim/blob/master/lua/conform/formatters/trim_newlines.lua) - Trim empty lines at the end of the file. - [trim_whitespace](https://github.com/stevearc/conform.nvim/blob/master/lua/conform/formatters/trim_whitespace.lua) - Trim trailing whitespace. - [twig-cs-fixer](https://github.com/VincentLanglet/Twig-CS-Fixer) - Automatically fix Twig Coding Standards issues - [typespec](https://github.com/microsoft/typespec) - TypeSpec compiler and CLI. - [typos](https://github.com/crate-ci/typos) - Source code spell checker - [typstyle](https://github.com/Enter-tainer/typstyle) - Beautiful and reliable typst code formatter. - [ufmt](https://github.com/omnilib/ufmt) - Safe, atomic formatting with black and µsort. - [uncrustify](https://github.com/uncrustify/uncrustify) - A source code beautifier for C, C++, C#, ObjectiveC, D, Java, Pawn and Vala. - [usort](https://github.com/facebook/usort) - Safe, minimal import sorting for Python projects. - [v](https://vlang.io) - V language formatter. - [verible](https://github.com/chipsalliance/verible/blob/master/verilog/tools/formatter/README.md) - The SystemVerilog formatter. - [vsg](https://github.com/jeremiah-c-leary/vhdl-style-guide) - Style guide enforcement for VHDL. - [xmlformatter](https://github.com/pamoller/xmlformatter) - xmlformatter is an Open Source Python package, which provides formatting of XML documents. - [xmllint](http://xmlsoft.org/xmllint.html) - Despite the name, xmllint can be used to format XML files as well as lint them. - [xmlstarlet](http://xmlstar.sourceforge.net/) - XMLStarlet is a command-line XML toolkit that can be used to format XML files. - [yamlfix](https://github.com/lyz-code/yamlfix) - A configurable YAML formatter that keeps comments. - [yamlfmt](https://github.com/google/yamlfmt) - yamlfmt is an extensible command line tool or library to format yaml files. - [yapf](https://github.com/google/yapf) - Yet Another Python Formatter. - [yew-fmt](https://github.com/schvv31n/yew-fmt) - Code formatter for the Yew framework. - [yq](https://github.com/mikefarah/yq) - YAML/JSON processor - [zigfmt](https://github.com/ziglang/zig) - Reformat Zig source into canonical form. - [ziggy](https://github.com/kristoff-it/ziggy) - A data serialization language for expressing clear API messages, config files, etc. - [ziggy_schema](https://github.com/kristoff-it/ziggy) - A data serialization language for expressing clear API messages, config files, etc. - [zprint](https://github.com/kkinnear/zprint) - Formatter for Clojure and EDN.
## Customizing formatters You can override/add to the default values of formatters ```lua require("conform").setup({ formatters = { yamlfix = { -- Change where to find the command command = "local/path/yamlfix", -- Adds environment args to the yamlfix formatter env = { YAMLFIX_SEQUENCE_STYLE = "block_style", }, }, }, }) -- These can also be set directly require("conform").formatters.yamlfix = { env = { YAMLFIX_SEQUENCE_STYLE = "block_style", }, } -- This can also be a function that returns the config, -- which can be useful if you're doing lazy loading require("conform").formatters.yamlfix = function(bufnr) return { command = require("conform.util").find_executable({ "local/path/yamlfix", }, "yamlfix"), } end ``` In addition to being able to override any of the original properties on the formatter, there is another property for easily adding additional arguments to the format command ```lua require("conform").formatters.shfmt = { append_args = { "-i", "2" }, -- The base args are { "-filename", "$FILENAME" } so the final args will be -- { "-filename", "$FILENAME", "-i", "2" } } -- append_args can be a function, just like args require("conform").formatters.shfmt = { append_args = function(self, ctx) return { "-i", "2" } end, } ``` If you want to overwrite the entire formatter definition and _not_ merge with the default values, pass `inherit = false`. This is also the default behavior if there is no built-in formatter with the given name, which can be used to add your own custom formatters. ```lua require("conform").formatters.shfmt = { inherit = false, command = "shfmt", args = { "-filename", "$FILENAME", "-i", "2" }, } ``` ### Magic strings The following magic strings are available in `args` and `range_args`. They will be dynamically replaced at runtime with the relevant value. - `$FILENAME` - absolute path to the file - `$DIRNAME` - absolute path to the directory that contains the file - `$RELATIVE_FILEPATH` - relative path to the file - `$EXTENSION` - the file extension, e.g. `.py` ## Recipes - [Format command](doc/recipes.md#format-command) - [Autoformat with extra features](doc/recipes.md#autoformat-with-extra-features) - [Command to toggle format-on-save](doc/recipes.md#command-to-toggle-format-on-save) - [Lazy loading with lazy.nvim](doc/recipes.md#lazy-loading-with-lazynvim) - [Leave visual mode after range format](doc/recipes.md#leave-visual-mode-after-range-format) - [Run the first available formatter followed by more formatters](doc/recipes.md#run-the-first-available-formatter-followed-by-more-formatters) ## Debugging - [Background](doc/debugging.md#background) - [Tools](doc/debugging.md#tools) - [Testing the formatter](doc/debugging.md#testing-the-formatter) - [Testing vim.system](doc/debugging.md#testing-vimsystem) ## Advanced topics - [Minimal format diffs](doc/advanced_topics.md#minimal-format-diffs) - [Range formatting](doc/advanced_topics.md#range-formatting) - [Injected language formatting (code blocks)](doc/advanced_topics.md#injected-language-formatting-code-blocks) ## Options A complete list of all configuration 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", } ``` ## Formatter options - [injected](doc/formatter_options.md#injected) - [prettier](doc/formatter_options.md#prettier) - [rustfmt](doc/formatter_options.md#rustfmt) - [yew-fmt](doc/formatter_options.md#yew-fmt) ## API ### setup(opts) `setup(opts)` | Param | Type | Desc | | --------------------- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 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) `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/000077500000000000000000000000001505173240700147055ustar00rootroot00000000000000conform.nvim-9.1.0/doc/advanced_topics.md000066400000000000000000000060701505173240700203600ustar00rootroot00000000000000# 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.txt000066400000000000000000000752671505173240700171320ustar00rootroot00000000000000*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.md000066400000000000000000000137641505173240700171750ustar00rootroot00000000000000# 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: Screenshot 2024-08-07 at 10 03 17 PM 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.md000066400000000000000000000050141505173240700210050ustar00rootroot00000000000000# 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.md000066400000000000000000000134611505173240700166660ustar00rootroot00000000000000# 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/000077500000000000000000000000001505173240700147215ustar00rootroot00000000000000conform.nvim-9.1.0/lua/conform/000077500000000000000000000000001505173240700163645ustar00rootroot00000000000000conform.nvim-9.1.0/lua/conform/errors.lua000066400000000000000000000027511505173240700204100ustar00rootroot00000000000000local 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/000077500000000000000000000000001505173240700205525ustar00rootroot00000000000000conform.nvim-9.1.0/lua/conform/formatters/air.lua000066400000000000000000000005211505173240700220260ustar00rootroot00000000000000local 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.lua000066400000000000000000000003051505173240700231740ustar00rootroot00000000000000---@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.lua000066400000000000000000000004531505173240700236400ustar00rootroot00000000000000---@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.lua000066400000000000000000000003031505173240700225400ustar00rootroot00000000000000---@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.lua000066400000000000000000000005331505173240700230000ustar00rootroot00000000000000---@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.lua000066400000000000000000000006111505173240700225540ustar00rootroot00000000000000local 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.lua000066400000000000000000000004401505173240700241300ustar00rootroot00000000000000---@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.lua000066400000000000000000000004751505173240700236150ustar00rootroot00000000000000---@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.lua000066400000000000000000000004321505173240700232270ustar00rootroot00000000000000---@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.lua000066400000000000000000000006141505173240700230230ustar00rootroot00000000000000---@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.lua000066400000000000000000000003751505173240700220440ustar00rootroot00000000000000---@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.lua000066400000000000000000000003601505173240700221560ustar00rootroot00000000000000---@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.lua000066400000000000000000000005061505173240700234510ustar00rootroot00000000000000---@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.lua000066400000000000000000000003271505173240700231030ustar00rootroot00000000000000---@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.lua000066400000000000000000000003731505173240700235040ustar00rootroot00000000000000---@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.lua000066400000000000000000000004351505173240700223410ustar00rootroot00000000000000---@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.lua000066400000000000000000000006751505173240700234330ustar00rootroot00000000000000local 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.lua000066400000000000000000000010541505173240700256570ustar00rootroot00000000000000local 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.lua000066400000000000000000000006631505173240700223550ustar00rootroot00000000000000local 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.lua000066400000000000000000000007301505173240700223310ustar00rootroot00000000000000local 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.lua000066400000000000000000000006041505173240700243250ustar00rootroot00000000000000local 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.lua000066400000000000000000000006511505173240700222060ustar00rootroot00000000000000local 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.lua000066400000000000000000000004041505173240700223630ustar00rootroot00000000000000---@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.lua000066400000000000000000000004371505173240700223740ustar00rootroot00000000000000---@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.lua000066400000000000000000000005071505173240700220330ustar00rootroot00000000000000---@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.lua000066400000000000000000000004771505173240700234030ustar00rootroot00000000000000---@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.lua000066400000000000000000000003371505173240700231700ustar00rootroot00000000000000return { 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.lua000066400000000000000000000003621505173240700235300ustar00rootroot00000000000000---@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.lua000066400000000000000000000006601505173240700223520ustar00rootroot00000000000000local 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.lua000066400000000000000000000003101505173240700223250ustar00rootroot00000000000000---@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.lua000066400000000000000000000012161505173240700236270ustar00rootroot00000000000000local 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.lua000066400000000000000000000002221505173240700237050ustar00rootroot00000000000000-- 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.lua000066400000000000000000000004241505173240700225340ustar00rootroot00000000000000---@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.lua000066400000000000000000000004141505173240700231050ustar00rootroot00000000000000---@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.lua000066400000000000000000000003521505173240700237050ustar00rootroot00000000000000---@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.lua000066400000000000000000000004321505173240700225230ustar00rootroot00000000000000---@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.lua000066400000000000000000000006531505173240700232330ustar00rootroot00000000000000---@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.lua000066400000000000000000000003541505173240700237650ustar00rootroot00000000000000---@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.lua000066400000000000000000000004141505173240700225430ustar00rootroot00000000000000---@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.lua000066400000000000000000000003341505173240700227360ustar00rootroot00000000000000---@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.lua000066400000000000000000000016471505173240700232450ustar00rootroot00000000000000local 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.lua000066400000000000000000000010301505173240700237270ustar00rootroot00000000000000local 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.lua000066400000000000000000000003341505173240700226770ustar00rootroot00000000000000---@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.lua000066400000000000000000000003661505173240700215670ustar00rootroot00000000000000---@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.lua000066400000000000000000000015661505173240700225350ustar00rootroot00000000000000local 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.lua000066400000000000000000000006341505173240700235620ustar00rootroot00000000000000---@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.lua000066400000000000000000000004601505173240700226660ustar00rootroot00000000000000---@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.lua000066400000000000000000000004041505173240700233660ustar00rootroot00000000000000---@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.lua000066400000000000000000000030431505173240700230500ustar00rootroot00000000000000local 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.lua000066400000000000000000000002731505173240700222110ustar00rootroot00000000000000---@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.lua000066400000000000000000000005141505173240700225700ustar00rootroot00000000000000local 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.lua000066400000000000000000000006001505173240700225350ustar00rootroot00000000000000local 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.lua000066400000000000000000000005241505173240700237470ustar00rootroot00000000000000---@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.lua000066400000000000000000000003071505173240700232330ustar00rootroot00000000000000---@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.lua000066400000000000000000000003211505173240700232560ustar00rootroot00000000000000---@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.lua000066400000000000000000000004311505173240700225260ustar00rootroot00000000000000---@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.lua000066400000000000000000000006661505173240700225650ustar00rootroot00000000000000local 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.lua000066400000000000000000000007601505173240700252600ustar00rootroot00000000000000local 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.lua000066400000000000000000000003141505173240700222060ustar00rootroot00000000000000---@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.lua000066400000000000000000000005171505173240700234050ustar00rootroot00000000000000---@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.lua000066400000000000000000000003501505173240700233730ustar00rootroot00000000000000---@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.lua000066400000000000000000000003641505173240700225510ustar00rootroot00000000000000---@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.lua000066400000000000000000000005671505173240700230660ustar00rootroot00000000000000local 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.lua000066400000000000000000000003461505173240700230700ustar00rootroot00000000000000---@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.lua000066400000000000000000000003311505173240700227010ustar00rootroot00000000000000---@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.lua000066400000000000000000000003511505173240700235460ustar00rootroot00000000000000---@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.lua000066400000000000000000000003071505173240700227350ustar00rootroot00000000000000---@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.lua000066400000000000000000000003141505173240700225410ustar00rootroot00000000000000--@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.lua000066400000000000000000000004741505173240700232320ustar00rootroot00000000000000---@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.lua000066400000000000000000000003441505173240700244140ustar00rootroot00000000000000---@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.lua000066400000000000000000000016741505173240700242300ustar00rootroot00000000000000---@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.lua000066400000000000000000000004751505173240700231330ustar00rootroot00000000000000---@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.lua000066400000000000000000000006241505173240700232730ustar00rootroot00000000000000---@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.lua000066400000000000000000000003471505173240700222120ustar00rootroot00000000000000---@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.lua000066400000000000000000000005041505173240700220160ustar00rootroot00000000000000---@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.lua000066400000000000000000000003361505173240700230620ustar00rootroot00000000000000---@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.lua000066400000000000000000000005031505173240700227060ustar00rootroot00000000000000local 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.lua000066400000000000000000000004041505173240700221710ustar00rootroot00000000000000---@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.lua000066400000000000000000000003721505173240700225360ustar00rootroot00000000000000---@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.lua000066400000000000000000000004021505173240700223360ustar00rootroot00000000000000---@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.lua000066400000000000000000000004011505173240700232420ustar00rootroot00000000000000---@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.lua000066400000000000000000000003071505173240700216610ustar00rootroot00000000000000---@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.lua000066400000000000000000000002511505173240700223670ustar00rootroot00000000000000---@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.lua000066400000000000000000000004631505173240700227410ustar00rootroot00000000000000---@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.lua000066400000000000000000000004541505173240700247600ustar00rootroot00000000000000---@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.lua000066400000000000000000000004451505173240700233030ustar00rootroot00000000000000---@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.lua000066400000000000000000000002641505173240700222170ustar00rootroot00000000000000---@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.lua000066400000000000000000000003761505173240700240120ustar00rootroot00000000000000---@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.lua000066400000000000000000000003101505173240700227070ustar00rootroot00000000000000---@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.lua000066400000000000000000000003761505173240700247440ustar00rootroot00000000000000---@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.lua000066400000000000000000000004311505173240700237230ustar00rootroot00000000000000---@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.lua000066400000000000000000000002641505173240700220250ustar00rootroot00000000000000---@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.lua000066400000000000000000000003451505173240700227100ustar00rootroot00000000000000---@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.lua000066400000000000000000000004041505173240700234510ustar00rootroot00000000000000--@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.lua000066400000000000000000000010331505173240700241060ustar00rootroot00000000000000local 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.lua000066400000000000000000000004331505173240700242610ustar00rootroot00000000000000---@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.lua000066400000000000000000000002371505173240700227400ustar00rootroot00000000000000---@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.lua000066400000000000000000000004511505173240700230330ustar00rootroot00000000000000---@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.lua000066400000000000000000000002711505173240700225360ustar00rootroot00000000000000---@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.lua000066400000000000000000000022441505173240700222220ustar00rootroot00000000000000local 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.lua000066400000000000000000000336661505173240700230600ustar00rootroot00000000000000---@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.lua000066400000000000000000000003421505173240700222140ustar00rootroot00000000000000---@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.lua000066400000000000000000000012731505173240700224200ustar00rootroot00000000000000local 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.lua000066400000000000000000000003151505173240700236430ustar00rootroot00000000000000--@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.lua000066400000000000000000000003631505173240700223710ustar00rootroot00000000000000---@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.lua000066400000000000000000000002601505173240700216650ustar00rootroot00000000000000---@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.lua000066400000000000000000000010351505173240700235600ustar00rootroot00000000000000local 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.lua000066400000000000000000000004311505173240700234420ustar00rootroot00000000000000---@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.lua000066400000000000000000000003101505173240700222340ustar00rootroot00000000000000return { 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.lua000066400000000000000000000004361505173240700220310ustar00rootroot00000000000000---@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.lua000066400000000000000000000003461505173240700225410ustar00rootroot00000000000000---@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.lua000066400000000000000000000004321505173240700234760ustar00rootroot00000000000000---@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.lua000066400000000000000000000004021505173240700223760ustar00rootroot00000000000000---@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.lua000066400000000000000000000004061505173240700225620ustar00rootroot00000000000000---@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.lua000066400000000000000000000004271505173240700233150ustar00rootroot00000000000000---@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.lua000066400000000000000000000006411505173240700235750ustar00rootroot00000000000000---@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.lua000066400000000000000000000003401505173240700232670ustar00rootroot00000000000000---@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.lua000066400000000000000000000005101505173240700252570ustar00rootroot00000000000000local 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.lua000066400000000000000000000003021505173240700220250ustar00rootroot00000000000000---@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.lua000066400000000000000000000003131505173240700233210ustar00rootroot00000000000000---@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.lua000066400000000000000000000004761505173240700235570ustar00rootroot00000000000000---@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.lua000066400000000000000000000005161505173240700232300ustar00rootroot00000000000000---@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.lua000066400000000000000000000011011505173240700236530ustar00rootroot00000000000000---@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.lua000066400000000000000000000003031505173240700236020ustar00rootroot00000000000000---@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.lua000066400000000000000000000007241505173240700246200ustar00rootroot00000000000000---@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.lua000066400000000000000000000006061505173240700237700ustar00rootroot00000000000000---@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.lua000066400000000000000000000003331505173240700230650ustar00rootroot00000000000000---@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.lua000066400000000000000000000004151505173240700222060ustar00rootroot00000000000000---@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.lua000066400000000000000000000003561505173240700224070ustar00rootroot00000000000000---@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.lua000066400000000000000000000005271505173240700220560ustar00rootroot00000000000000---@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.lua000066400000000000000000000004171505173240700235730ustar00rootroot00000000000000---@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.lua000066400000000000000000000004331505173240700231070ustar00rootroot00000000000000---@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.lua000066400000000000000000000003721505173240700225240ustar00rootroot00000000000000---@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.lua000066400000000000000000000004271505173240700233130ustar00rootroot00000000000000---@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.lua000066400000000000000000000003221505173240700225570ustar00rootroot00000000000000---@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.lua000066400000000000000000000003331505173240700236050ustar00rootroot00000000000000---@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.lua000066400000000000000000000004621505173240700232230ustar00rootroot00000000000000---@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.lua000066400000000000000000000003411505173240700220400ustar00rootroot00000000000000---@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.lua000066400000000000000000000007351505173240700243430ustar00rootroot00000000000000---@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.lua000066400000000000000000000003321505173240700224040ustar00rootroot00000000000000---@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.lua000066400000000000000000000004231505173240700235600ustar00rootroot00000000000000---@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.lua000066400000000000000000000003201505173240700233100ustar00rootroot00000000000000---@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.lua000066400000000000000000000010211505173240700227070ustar00rootroot00000000000000---@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.lua000066400000000000000000000003551505173240700227050ustar00rootroot00000000000000---@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.lua000066400000000000000000000004101505173240700225650ustar00rootroot00000000000000---@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.lua000066400000000000000000000004641505173240700233740ustar00rootroot00000000000000---@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.lua000066400000000000000000000003421505173240700223660ustar00rootroot00000000000000---@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.lua000066400000000000000000000004251505173240700236360ustar00rootroot00000000000000---@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.lua000066400000000000000000000003451505173240700231130ustar00rootroot00000000000000---@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.lua000066400000000000000000000003031505173240700232270ustar00rootroot00000000000000---@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.lua000066400000000000000000000006761505173240700237370ustar00rootroot00000000000000local 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.lua000066400000000000000000000011531505173240700225170ustar00rootroot00000000000000local 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.lua000066400000000000000000000007341505173240700236210ustar00rootroot00000000000000local 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.lua000066400000000000000000000005401505173240700222260ustar00rootroot00000000000000local 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.lua000066400000000000000000000046311505173240700231170ustar00rootroot00000000000000local 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.lua000066400000000000000000000037651505173240700232720ustar00rootroot00000000000000local 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.lua000066400000000000000000000005171505173240700233740ustar00rootroot00000000000000local 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.lua000066400000000000000000000003671505173240700233410ustar00rootroot00000000000000---@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.lua000066400000000000000000000004241505173240700225570ustar00rootroot00000000000000---@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.lua000066400000000000000000000004611505173240700235370ustar00rootroot00000000000000---@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.lua000066400000000000000000000003651505173240700232210ustar00rootroot00000000000000---@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.lua000066400000000000000000000005701505173240700224040ustar00rootroot00000000000000local 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.lua000066400000000000000000000005111505173240700224040ustar00rootroot00000000000000---@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.lua000066400000000000000000000004401505173240700241640ustar00rootroot00000000000000---@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.lua000066400000000000000000000007361505173240700240660ustar00rootroot00000000000000local 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.lua000066400000000000000000000004531505173240700232220ustar00rootroot00000000000000---@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.lua000066400000000000000000000007131505173240700232560ustar00rootroot00000000000000--- 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.lua000066400000000000000000000004161505173240700232600ustar00rootroot00000000000000---@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.lua000066400000000000000000000003651505173240700245250ustar00rootroot00000000000000---@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.lua000066400000000000000000000004461505173240700257350ustar00rootroot00000000000000--@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.lua000066400000000000000000000015341505173240700244010ustar00rootroot00000000000000-- 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.lua000066400000000000000000000003721505173240700220420ustar00rootroot00000000000000---@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.lua000066400000000000000000000003441505173240700225750ustar00rootroot00000000000000---@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.lua000066400000000000000000000005701505173240700227300ustar00rootroot00000000000000---@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.lua000066400000000000000000000002421505173240700227430ustar00rootroot00000000000000return { 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.lua000066400000000000000000000002121505173240700222120ustar00rootroot00000000000000-- 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.lua000066400000000000000000000007511505173240700230700ustar00rootroot00000000000000---@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.lua000066400000000000000000000014321505173240700235670ustar00rootroot00000000000000---@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.lua000066400000000000000000000007771505173240700257050ustar00rootroot00000000000000---@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.lua000066400000000000000000000002701505173240700222270ustar00rootroot00000000000000return { 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.lua000066400000000000000000000004521505173240700223760ustar00rootroot00000000000000---@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.lua000066400000000000000000000012521505173240700227610ustar00rootroot00000000000000local 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.lua000066400000000000000000000003451505173240700233270ustar00rootroot00000000000000---@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.lua000066400000000000000000000003221505173240700230440ustar00rootroot00000000000000---@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.lua000066400000000000000000000004341505173240700233630ustar00rootroot00000000000000---@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.lua000066400000000000000000000003541505173240700235500ustar00rootroot00000000000000---@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.lua000066400000000000000000000012621505173240700223770ustar00rootroot00000000000000---@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.lua000066400000000000000000000003201505173240700223530ustar00rootroot00000000000000---@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.lua000066400000000000000000000003211505173240700225530ustar00rootroot00000000000000---@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.lua000066400000000000000000000004141505173240700230640ustar00rootroot00000000000000---@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.lua000066400000000000000000000010151505173240700244440ustar00rootroot00000000000000---@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.lua000066400000000000000000000007451505173240700243250ustar00rootroot00000000000000---@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.lua000066400000000000000000000003501505173240700241350ustar00rootroot00000000000000---@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.lua000066400000000000000000000007311505173240700231000ustar00rootroot00000000000000local 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.lua000066400000000000000000000004351505173240700225650ustar00rootroot00000000000000---@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.lua000066400000000000000000000006621505173240700225670ustar00rootroot00000000000000local 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.lua000066400000000000000000000004671505173240700242770ustar00rootroot00000000000000---@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.lua000066400000000000000000000005321505173240700236230ustar00rootroot00000000000000local 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.lua000066400000000000000000000004501505173240700234110ustar00rootroot00000000000000local 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.lua000066400000000000000000000005141505173240700234010ustar00rootroot00000000000000---@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.lua000066400000000000000000000010201505173240700232750ustar00rootroot00000000000000local 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.lua000066400000000000000000000010301505173240700225710ustar00rootroot00000000000000local 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.lua000066400000000000000000000003421505173240700243740ustar00rootroot00000000000000---@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.lua000066400000000000000000000014051505173240700225760ustar00rootroot00000000000000local 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.lua000066400000000000000000000003711505173240700233010ustar00rootroot00000000000000---@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.lua000066400000000000000000000004331505173240700224110ustar00rootroot00000000000000---@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.lua000066400000000000000000000005001505173240700237540ustar00rootroot00000000000000---@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.lua000066400000000000000000000012261505173240700236230ustar00rootroot00000000000000---@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.lua000066400000000000000000000005501505173240700233000ustar00rootroot00000000000000---@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.lua000066400000000000000000000005411505173240700236220ustar00rootroot00000000000000---@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.lua000066400000000000000000000003241505173240700223730ustar00rootroot00000000000000---@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.lua000066400000000000000000000003511505173240700223750ustar00rootroot00000000000000---@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.lua000066400000000000000000000004711505173240700241260ustar00rootroot00000000000000---@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.lua000066400000000000000000000006401505173240700250070ustar00rootroot00000000000000---@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.lua000066400000000000000000000003461505173240700226440ustar00rootroot00000000000000---@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.lua000066400000000000000000000005611505173240700224110ustar00rootroot00000000000000local 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.lua000066400000000000000000000004271505173240700231030ustar00rootroot00000000000000---@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.lua000066400000000000000000000003411505173240700223650ustar00rootroot00000000000000---@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.lua000066400000000000000000000003361505173240700227250ustar00rootroot00000000000000---@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.lua000066400000000000000000000007141505173240700241360ustar00rootroot00000000000000---@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.lua000066400000000000000000000007131505173240700244450ustar00rootroot00000000000000---@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.lua000066400000000000000000000010401505173240700237400ustar00rootroot00000000000000local 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.lua000066400000000000000000000005271505173240700231150ustar00rootroot00000000000000local 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.lua000066400000000000000000000007311505173240700224340ustar00rootroot00000000000000---@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.lua000066400000000000000000000004011505173240700231420ustar00rootroot00000000000000---@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.lua000066400000000000000000000003401505173240700231470ustar00rootroot00000000000000---@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.lua000066400000000000000000000003721505173240700222320ustar00rootroot00000000000000---@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.lua000066400000000000000000000011311505173240700234640ustar00rootroot00000000000000---@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.lua000066400000000000000000000005221505173240700224300ustar00rootroot00000000000000local 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.lua000066400000000000000000000003221505173240700215170ustar00rootroot00000000000000---@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.lua000066400000000000000000000004531505173240700227070ustar00rootroot00000000000000---@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.lua000066400000000000000000000020711505173240700220540ustar00rootroot00000000000000local 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.lua000066400000000000000000000002221505173240700232620ustar00rootroot00000000000000-- 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.lua000066400000000000000000000004211505173240700237760ustar00rootroot00000000000000---@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.lua000066400000000000000000000004071505173240700227450ustar00rootroot00000000000000---@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.lua000066400000000000000000000004371505173240700234600ustar00rootroot00000000000000---@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.lua000066400000000000000000000003421505173240700227250ustar00rootroot00000000000000---@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.lua000066400000000000000000000003711505173240700227270ustar00rootroot00000000000000---@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.lua000066400000000000000000000005321505173240700222140ustar00rootroot00000000000000---@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.lua000066400000000000000000000012201505173240700226400ustar00rootroot00000000000000local 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.lua000066400000000000000000000003201505173240700217010ustar00rootroot00000000000000---@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.lua000066400000000000000000000003341505173240700225550ustar00rootroot00000000000000---@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.lua000066400000000000000000000004171505173240700224100ustar00rootroot00000000000000---@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.lua000066400000000000000000000004261505173240700237300ustar00rootroot00000000000000---@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.lua000066400000000000000000000007061505173240700226060ustar00rootroot00000000000000---@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.lua000066400000000000000000000046031505173240700175020ustar00rootroot00000000000000local 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.lua000066400000000000000000000003401505173240700210570ustar00rootroot00000000000000return { 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.lua000066400000000000000000000146341505173240700203440ustar00rootroot00000000000000local 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.lua000066400000000000000000000653561505173240700200510ustar00rootroot00000000000000local 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.lua000066400000000000000000000052101505173240700176460ustar00rootroot00000000000000local 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.lua000066400000000000000000000143141505173240700212400ustar00rootroot00000000000000---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.lua000066400000000000000000000533771505173240700204170ustar00rootroot00000000000000local 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.lua000066400000000000000000000177051505173240700202450ustar00rootroot00000000000000---@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.lua000066400000000000000000000172661505173240700200600ustar00rootroot00000000000000local 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/000077500000000000000000000000001505173240700154365ustar00rootroot00000000000000conform.nvim-9.1.0/plugin/conform.lua000066400000000000000000000002421505173240700176020ustar00rootroot00000000000000vim.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.sh000077500000000000000000000015611505173240700165300ustar00rootroot00000000000000#!/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/000077500000000000000000000000001505173240700156275ustar00rootroot00000000000000conform.nvim-9.1.0/scripts/autoformat_doc.lua000066400000000000000000000021471505173240700213440ustar00rootroot00000000000000-- 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.py000077500000000000000000000143341505173240700200030ustar00rootroot00000000000000import 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.py000077500000000000000000000014561505173240700171360ustar00rootroot00000000000000#!/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.lua000066400000000000000000000106351505173240700206570ustar00rootroot00000000000000require("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.txt000066400000000000000000000000421505173240700211070ustar00rootroot00000000000000pyparsing==3.0.9 black isort mypy conform.nvim-9.1.0/tests/000077500000000000000000000000001505173240700153025ustar00rootroot00000000000000conform.nvim-9.1.0/tests/api_spec.lua000066400000000000000000000051461505173240700175760ustar00rootroot00000000000000require("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.sh000077500000000000000000000004461505173240700206360ustar00rootroot00000000000000#!/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/000077500000000000000000000000001505173240700174705ustar00rootroot00000000000000conform.nvim-9.1.0/tests/formatters/prettierd_spec.lua000066400000000000000000000110141505173240700232040ustar00rootroot00000000000000require("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.lua000066400000000000000000000013611505173240700174300ustar00rootroot00000000000000local 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.lua000066400000000000000000000072111505173240700203450ustar00rootroot00000000000000require("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/000077500000000000000000000000001505173240700170675ustar00rootroot00000000000000conform.nvim-9.1.0/tests/injected/block_quote.md000066400000000000000000000000711505173240700217160ustar00rootroot00000000000000text > ```lua > local foo = 'bar' > local bar = 2 > ``` conform.nvim-9.1.0/tests/injected/block_quote.md.formatted000066400000000000000000000000731505173240700237040ustar00rootroot00000000000000text > ```lua > >local foo = 'bar' > local bar = 2< > ``` conform.nvim-9.1.0/tests/injected/combined_injections.md000066400000000000000000000001641505173240700234170ustar00rootroot00000000000000text ```lua local foo = 'bar' ``` ```lua local foo = 'bar' local bar = 3 ``` conform.nvim-9.1.0/tests/injected/combined_injections.md.formatted000066400000000000000000000001701505173240700254000ustar00rootroot00000000000000text ```lua >local foo = 'bar'< ``` ```lua >local foo = 'bar' local bar = 3< ``` conform.nvim-9.1.0/tests/injected/inline.ts000066400000000000000000000003751505173240700207220ustar00rootroot00000000000000foo.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.formatted000066400000000000000000000004111505173240700226750ustar00rootroot00000000000000foo.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.md000066400000000000000000000001341505173240700214000ustar00rootroot000000000000001. item ```lua local function foo() print("hello world") end ``` conform.nvim-9.1.0/tests/injected/list_item.md.formatted000066400000000000000000000001361505173240700233660ustar00rootroot000000000000001. item ```lua >local function foo() print("hello world") end< ``` conform.nvim-9.1.0/tests/injected/simple.md000066400000000000000000000000611505173240700206770ustar00rootroot00000000000000text ```lua local foo = "bar" local bar = 2 ``` conform.nvim-9.1.0/tests/injected/simple.md.formatted000066400000000000000000000000631505173240700226650ustar00rootroot00000000000000text ```lua >local foo = "bar" local bar = 2< ``` conform.nvim-9.1.0/tests/injected_spec.lua000066400000000000000000000054271505173240700206140ustar00rootroot00000000000000require("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.lua000066400000000000000000000011701505173240700204550ustar00rootroot00000000000000vim.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.lua000066400000000000000000000325151505173240700203360ustar00rootroot00000000000000require("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.lua000066400000000000000000000013031505173240700200160ustar00rootroot00000000000000require("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.lua000066400000000000000000000045701505173240700200020ustar00rootroot00000000000000local 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)