# Neoformat [![Build Status](https://travis-ci.org/sbdchd/neoformat.svg?branch=master)](https://travis-ci.org/sbdchd/neoformat)

A (Neo)vim plugin for formatting code.

Neoformat uses a variety of formatters for many filetypes. Currently, Neoformat
will run a formatter using the current buffer data, and on success it will
update the current buffer with the formatted text. On a formatter failure,
Neoformat will try the next formatter defined for the filetype.

By using `getbufline()` to read from the current buffer instead of file,
Neoformat is able to format your buffer without you having to `:w` your file first.
Also, by using `setline()`, marks, jumps, etc. are all maintained after formatting.

Neoformat supports both sending buffer data to formatters via stdin, and also
writing buffer data to `/tmp/` for formatters to read that do not support input
via stdin.

## Basic Usage

Format the entire buffer, or visual selection of the buffer

```viml
:Neoformat
```

Or specify a certain formatter (must be defined for the current filetype)

```viml
:Neoformat jsbeautify
```

Or format a visual selection of code in a different filetype

**Note:** you must use a ! and pass the filetype of the selection

```viml
:Neoformat! python
```

You can also pass a formatter to use

```viml
:Neoformat! python yapf
```

Or perhaps run a formatter on save

```viml
augroup fmt
  autocmd!
  autocmd BufWritePre * undojoin | Neoformat
augroup END
```

The `undojoin` command will put changes made by Neoformat into the same
`undo-block` with the latest preceding change. See
[Managing Undo History](#managing-undo-history).

## Install
The best way to install Neoformat is with your favorite plugin manager for Vim, such as [vim-plug](https://github.com/junegunn/vim-plug):
```viml
Plug 'sbdchd/neoformat'
```

## Current Limitation(s)

If a formatter is either not configured to use `stdin`, or is not able to read
from `stdin`, then buffer data will be written to a file in `/tmp/neoformat/`,
where the formatter will then read from

## Config [Optional]

Define custom formatters.

Options:

| name               | description                                                                                                       | default | optional / required |
| ------------------ | ----------------------------------------------------------------------------------------------------------------- | ------- | ------------------- |
| `exe`              | the name the formatter executable in the path                                                                     | n/a     | **required**        |
| `args`             | list of arguments                                                                                                 | \[]     | optional            |
| `replace`          | overwrite the file, instead of updating the buffer                                                                | 0       | optional            |
| `stdin`            | send data to the stdin of the formatter                                                                           | 0       | optional            |
| `stderr`           | capture stderr output from formatter                                                                              | 0       | optional            |
| `no_append`        | do not append the `path` of the file to the formatter command, used when the `path` is in the middle of a command | 0       | optional            |
| `env`              | list of environment variable definitions to be prepended to the formatter command                                 | \[]     | optional            |
| `valid_exit_codes` | list of valid exit codes for formatters who do not respect common unix practices                                  | \[0]    | optional            |

Example:

```viml
let g:neoformat_python_autopep8 = {
            \ 'exe': 'autopep8',
            \ 'args': ['-s 4', '-E'],
            \ 'replace': 1 " replace the file, instead of updating buffer (default: 0),
            \ 'stdin': 1, " send data to stdin of formatter (default: 0)
            \ 'env': ["DEBUG=1"], " prepend environment variables to formatter command
            \ 'valid_exit_codes': [0, 23],
            \ 'no_append': 1,
            \ }

let g:neoformat_enabled_python = ['autopep8']
```

Configure enabled formatters.

```viml
let g:neoformat_enabled_python = ['autopep8', 'yapf', 'docformatter']
```

Have Neoformat use &formatprg as a formatter

```viml
let g:neoformat_try_formatprg = 1
```

Enable basic formatting when a filetype is not found. Disabled by default.

```viml
" Enable alignment
let g:neoformat_basic_format_align = 1

" Enable tab to spaces conversion
let g:neoformat_basic_format_retab = 1

" Enable trimmming of trailing whitespace
let g:neoformat_basic_format_trim = 1
```

Run all enabled formatters (by default Neoformat stops after the first formatter
succeeds)

```viml
let g:neoformat_run_all_formatters = 1
```

Above options can be activated or deactivated per buffer. For example:

```viml
    " runs all formatters for current buffer without tab to spaces conversion
    let b:neoformat_run_all_formatters = 1
    let b:neoformat_basic_format_retab = 0
```

Have Neoformat only msg when there is an error

```viml
let g:neoformat_only_msg_on_error = 1
```

When debugging, you can enable either of following variables for extra logging.

```viml
let g:neoformat_verbose = 1 " only affects the verbosity of Neoformat
" Or
let &verbose            = 1 " also increases verbosity of the editor as a whole
```

## Adding a New Formatter

Note: you should replace everything `{{ }}` accordingly

1. Create a file in `autoload/neoformat/formatters/{{ filetype }}.vim` if it does not
   already exist for your filetype.

2. Follow the following format

See Config above for options

```viml
function! neoformat#formatters#{{ filetype }}#enabled() abort
    return ['{{ formatter name }}', '{{ other formatter name for filetype }}']
endfunction

function! neoformat#formatters#{{ filetype }}#{{ formatter name }}() abort
    return {
        \ 'exe': '{{ formatter name }}',
        \ 'args': ['-s 4', '-q'],
        \ 'stdin': 1
        \ }
endfunction

function! neoformat#formatters#{{ filetype }}#{{ other formatter name }}() abort
  return {'exe': {{ other formatter name }}
endfunction
```

## Managing Undo History

If you use an `autocmd` to run Neoformat on save, and you have your editor
configured to save automatically on `CursorHold` then you might run into
problems reverting changes. Pressing `u` will undo the last change made by
Neoformat instead of the change that you made yourself - and then Neoformat
will run again redoing the change that you just reverted. To avoid this
problem you can run Neoformat with the Vim `undojoin` command to put changes
made by Neoformat into the same `undo-block` with the preceding change. For
example:

```viml
augroup fmt
  autocmd!
  autocmd BufWritePre * undojoin | Neoformat
augroup END
```

When `undojoin` is used this way pressing `u` will "skip over" the Neoformat
changes - it will revert both the changes made by Neoformat and the change
that caused Neoformat to be invoked.

## Supported Filetypes

- Arduino
  - [`uncrustify`](http://uncrustify.sourceforge.net),
    [`clang-format`](http://clang.llvm.org/docs/ClangFormat.html),
    [`astyle`](http://astyle.sourceforge.net)
- Assembly
  - [`asmfmt`](https://github.com/klauspost/asmfmt)
- Bazel
  - [`buildifier`](https://github.com/bazelbuild/buildtools/blob/master/buildifier/README.md)
- Beancount
  - [`bean-format`](https://beancount.github.io/docs/running_beancount_and_generating_reports.html#bean-format)
- Bib
  - [bibclean](https://github.com/tobywf/bibclean)
- C
  - [`uncrustify`](http://uncrustify.sourceforge.net),
    [`clang-format`](http://clang.llvm.org/docs/ClangFormat.html),
    [`astyle`](http://astyle.sourceforge.net)
- C#
  - [`uncrustify`](http://uncrustify.sourceforge.net),
    [`astyle`](http://astyle.sourceforge.net),
    [`clang-format`](http://clang.llvm.org/docs/ClangFormat.html)
- C++
  - [`uncrustify`](http://uncrustify.sourceforge.net),
    [`clang-format`](http://clang.llvm.org/docs/ClangFormat.html),
    [`astyle`](http://astyle.sourceforge.net)
- Cabal
  - [`cabal-fmt`](https://github.com/phadej/cabal-fmt)
- CMake
  - [`cmake_format`](https://github.com/cheshirekow/cmake_format)
- Crystal
  - `crystal tool format` (ships with [`crystal`](http://crystal-lang.org))
- CSS
  - `css-beautify` (ships with [`js-beautify`](https://github.com/beautify-web/js-beautify)),
    [`prettydiff`](https://github.com/prettydiff/prettydiff),
    [`stylefmt`](https://github.com/morishitter/stylefmt),
    [`stylelint`](https://stylelint.io/),
    [`csscomb`](http://csscomb.com),
    [`prettier`](https://github.com/prettier/prettier)
- CSV
  - [`prettydiff`](https://github.com/prettydiff/prettydiff)
- D
  - [`uncrustify`](http://uncrustify.sourceforge.net),
    [`dfmt`](https://github.com/Hackerpilot/dfmt)
- Dart
  - [`dartfmt`](https://www.dartlang.org/tools/)
- Dhall
  - [`dhall format`](https://dhall-lang.org)
- dune
  - [`dune format`](https://github.com/ocaml/dune)
- Elixir
  - [`mix format`](https://hexdocs.pm/mix/master/Mix.Tasks.Format.html)
- Elm
  - [`elm-format`](https://github.com/avh4/elm-format)
- Erlang
  - [`erlfmt`](https://github.com/WhatsApp/erlfmt)
- Fish
  - [`fish_indent`](http://fishshell.com)
- F#
  - [`fantomas`](https://github.com/fsprojects/fantomas)
- GDScript
  - [`gdformat`](https://github.com/Scony/godot-gdscript-toolkit)
- Gleam
  - [`gleam format`](https://github.com/gleam-lang/gleam/)
- Go
  - [`gofmt`](https://golang.org/cmd/gofmt/),
    [`goimports`](https://godoc.org/golang.org/x/tools/cmd/goimports),
    [`gofumpt`](https://github.com/mvdan/gofumpt),
    [`gofumports`](https://github.com/mvdan/gofumpt)
- GLSL
  - [`clang-format`](http://clang.llvm.org/docs/ClangFormat.html)
- GraphQL
  - [`prettier`](https://github.com/prettier/prettier)
- Haskell
  - [`stylishhaskell`](https://github.com/jaspervdj/stylish-haskell),
    [`hindent`](https://github.com/chrisdone/hindent),
    [`hfmt`](https://github.com/danstiner/hfmt),
    [`brittany`](https://github.com/lspitzner/brittany),
    [`sortimports`](https://github.com/evanrelf/sort-imports),
    [`floskell`](https://github.com/ennocramer/floskell)
    [`ormolu`](https://github.com/tweag/ormolu)
    ```vim
    let g:ormolu_ghc_opt=["TypeApplications", "RankNTypes"]
    ```
  - You must use formatter's name without "`-`"
    ```vim
    " right
    let g:neoformat_enabled_haskell = ['sortimports', 'stylishhaskell']
    " wrong
    let g:neoformat_enabled_haskell = ['sort-imports', 'stylish-haskell']
    ```
- Puppet
  - [`puppet-lint`](https://github.com/rodjek/puppet-lint)
- PureScript
  - [`purty`](https://gitlab.com/joneshf/purty)
- HTML
  - `html-beautify` (ships with [`js-beautify`](https://github.com/beautify-web/js-beautify)),
    [`prettier`](https://github.com/prettier/prettier),
    [`prettydiff`](https://github.com/prettydiff/prettydiff)
- Jade
  - [`pug-beautifier`](https://github.com/vingorius/pug-beautifier)
- Java
  - [`uncrustify`](http://uncrustify.sourceforge.net),
    [`astyle`](http://astyle.sourceforge.net),
    [`prettier`](https://github.com/prettier/prettier)
- JavaScript
  - [`js-beautify`](https://github.com/beautify-web/js-beautify),
    [`prettier`](https://github.com/prettier/prettier),
    [`prettydiff`](https://github.com/prettydiff/prettydiff),
    [`clang-format`](http://clang.llvm.org/docs/ClangFormat.html),
    [`esformatter`](https://github.com/millermedeiros/esformatter/),
    [`prettier-eslint`](https://github.com/kentcdodds/prettier-eslint-cli),
    [`eslint_d`](https://github.com/mantoni/eslint_d.js),
    [`standard`](https://standardjs.com/),
    [`semistandard`](https://github.com/standard/semistandard),
    [`deno fmt`](https://deno.land/manual/tools/formatter),
- JSON
  - [`js-beautify`](https://github.com/beautify-web/js-beautify),
    [`prettydiff`](https://github.com/prettydiff/prettydiff),
    [`prettier`](https://github.com/prettier/prettier),
    [`jq`](https://stedolan.github.io/jq/),
    [`fixjson`](https://github.com/rhysd/fixjson)
- Kotlin
  - [`ktlint`](https://github.com/shyiko/ktlint),
    [`prettier`](https://github.com/prettier/prettier)
- LaTeX
  - [`latexindent`](https://github.com/cmhughes/latexindent.pl)
- Less
  - [`csscomb`](http://csscomb.com),
    [`prettydiff`](https://github.com/prettydiff/prettydiff),
    [`prettier`](https://github.com/prettier/prettier),
    [`stylelint`](https://stylelint.io/)
- Lua
  - [`luaformatter`](https://github.com/LuaDevelopmentTools/luaformatter)
  - [`lua-fmt`](https://github.com/trixnz/lua-fmt)
  - [`lua-format`](https://github.com/Koihik/LuaFormatter)
- Markdown
  - [`remark`](https://github.com/wooorm/remark)
    [`prettier`](https://github.com/prettier/prettier)
- Matlab
  - [`matlab-formatter-vscode`](https://github.com/affenwiesel/matlab-formatter-vscode)
- Nginx
  - [nginxbeautifier](https://github.com/vasilevich/nginxbeautifier)
- Nim
  - `nimpretty` (ships with [`nim`](https://nim-lang.org/))
- Nix
  - [`nixfmt`](https://github.com/serokell/nixfmt)
  - [`nixpkgs-fmt`](https://github.com/nix-community/nixpkgs-fmt)
- Objective-C
  - [`uncrustify`](http://uncrustify.sourceforge.net),
    [`clang-format`](http://clang.llvm.org/docs/ClangFormat.html),
    [`astyle`](http://astyle.sourceforge.net)
- OCaml
  - [`ocp-indent`](http://www.typerex.org/ocp-indent.html),
    [`ocamlformat`](https://github.com/ocaml-ppx/ocamlformat)
- Pandoc Markdown
  - [`pandoc`](https://pandoc.org/MANUAL.html)
- Pawn
  - [`uncrustify`](http://uncrustify.sourceforge.net)
- Perl
  - [`perltidy`](http://perltidy.sourceforge.net)
- PHP
  - [`php_beautifier`](http://pear.php.net/package/PHP_Beautifier),
    [`php-cs-fixer`](http://cs.sensiolabs.org/),
    [`phpcbf`](https://github.com/squizlabs/PHP_CodeSniffer)
- PowerShell
  - [`PSScriptAnalyzer`](https://github.com/PowerShell/PSScriptAnalyzer),
    [`PowerShell-Beautifier`](https://github.com/DTW-DanWard/PowerShell-Beautifier)
- Proto
  - [`clang-format`](http://clang.llvm.org/docs/ClangFormat.html)
- Pug (formally Jade)
  - [`pug-beautifier`](https://github.com/vingorius/pug-beautifier)
- Python
  - [`yapf`](https://github.com/google/yapf),
    [`autopep8`](https://github.com/hhatto/autopep8),
    [`black`](https://github.com/psf/black),
    [`pydevf`](https://github.com/fabioz/PyDev.Formatter),
    [`isort`](https://github.com/timothycrosley/isort),
    [`docformatter`](https://github.com/myint/docformatter),
    [`pyment`](https://github.com/dadadel/pyment)
- R
  - [`styler`](https://github.com/r-lib/styler),
    [`formatR`](https://github.com/yihui/formatR)
- Reason
  - [`refmt`](https://github.com/facebook/reason)
  - [`bsrefmt`](https://github.com/bucklescript/bucklescript)
- Ruby
  - [`rufo`](https://github.com/ruby-formatter/rufo),
    [`ruby-beautify`](https://github.com/erniebrodeur/ruby-beautify),
    [`rubocop`](https://github.com/bbatsov/rubocop)
- Rust
  - [`rustfmt`](https://github.com/rust-lang-nursery/rustfmt)
- Sass
  - [`sass-convert`](http://sass-lang.com/documentation/#executables),
    [`stylelint`](https://stylelint.io/),
    [`csscomb`](http://csscomb.com)
- Sbt
  - [`scalafmt`](http://scalameta.org/scalafmt/)
- Scala
  - [`scalariform`](https://github.com/scala-ide/scalariform),
    [`scalafmt`](http://scalameta.org/scalafmt/)
- SCSS
  - [`sass-convert`](http://sass-lang.com/documentation/#executables),
    [`stylelint`](https://stylelint.io/),
    [`stylefmt`](https://github.com/morishitter/stylefmt),
    [`prettydiff`](https://github.com/prettydiff/prettydiff),
    [`csscomb`](http://csscomb.com),
    [`prettier`](https://github.com/prettier/prettier)
- Shell
  - [`shfmt`](https://github.com/mvdan/sh)
    ```vim
    let g:shfmt_opt="-ci"
    ```
- SQL
  - [`sqlfmt`](https://github.com/jackc/sqlfmt),
    `sqlformat` (ships with [sqlparse](https://github.com/andialbrecht/sqlparse)),
    `pg_format` (ships with [pgFormatter](https://github.com/darold/pgFormatter))
- Starlark
  - [`buildifier`](https://github.com/bazelbuild/buildtools/blob/master/buildifier/README.md)
- Svelte
  - [`prettier-plugin-svelte`](https://github.com/UnwrittenFun/prettier-plugin-svelte)
- Swift
  - [`Swiftformat`](https://github.com/nicklockwood/SwiftFormat)
- Terraform
  - [`terraform`](https://www.terraform.io/docs/commands/fmt.html),
- TypeScript
  - [`tsfmt`](https://github.com/vvakame/typescript-formatter),
    [`prettier`](https://github.com/prettier/prettier),
    [`prettier-eslint`](https://github.com/kentcdodds/prettier-eslint-cli),
    [`tslint`](https://palantir.github.io/tslint),
    [`eslint_d`](https://github.com/mantoni/eslint_d.js),
    [`clang-format`](http://clang.llvm.org/docs/ClangFormat.html),
    [`deno fmt`](https://deno.land/manual/tools/formatter)
- V
  - `v fmt` (ships with [`v`](https://vlang.io))
- VALA
  - [`uncrustify`](http://uncrustify.sourceforge.net)
- Vue
  - [`prettier`](https://github.com/prettier/prettier)
- XHTML
  - [`tidy`](http://www.html-tidy.org),
    [`prettydiff`](https://github.com/prettydiff/prettydiff)
- XML
  - [`tidy`](http://www.html-tidy.org),
    [`prettydiff`](https://github.com/prettydiff/prettydiff),
    [`prettier`](https://github.com/prettier/prettier)
- YAML
  - [`pyaml`](https://pypi.python.org/pypi/pyaml),
    [`prettier`](https://github.com/prettier/prettier)
- zig
  - [`zig fmt`](https://github.com/ziglang/zig)
- zsh
  - [`shfmt`](https://github.com/mvdan/sh)
    ```vim
    let g:shfmt_opt="-ci"
    ```
