parfit: paragraph fit
Callum Dempsey Leach, 2026
**Abstract**
parfit reflows the prose inside code comments to a target width using optimal-fit line breaking, and passes machine-readable directives through unchanged. It is inspired by Adam M. Costello's par (1993) and aims to be a drop-in for the same niche with codebase awareness added.
**1. Introduction**
Code comments tend to accumulate long lines because editors autocomplete faster than humans press return. A reflow tool pipes a block of comments through a line breaker and puts them back at a sensible width. par has done this since 1993. Its greedy line breaker leaves orphan lines, and it does not know that `//go:generate` is a directive rather than prose.
parfit uses the optimal-fit (Knuth-Plass) algorithm to minimise raggedness, and ships a default list of directive patterns for Go, Rust, TypeScript, JavaScript, Python, and shell so tooling annotations are left alone. Custom patterns are accepted via `-s`/`--skip`.
**2. Installation**
```
cargo install parfit
```
Installs a `parfit` binary on `$PATH`.
**3. Synopsis**
```
parfit [OPTIONS] [PATH]...
```
With no `PATH` arguments parfit reads standard input and writes standard output. With one file path it reads that file and writes stdout. With multiple files, directories, or `--recursive`, use `--in-place` to rewrite the files.
**4. Examples**
*Pipe a single block through:*
```
*Reflow one file, preview result on stdout:*
```
parfit foo.go
```
*Reflow one file in place:*
```
parfit --in-place foo.go
```
*Recursively reflow every `.go` file under the current directory in place:*
```
parfit --recursive --in-place --include '*.go' .
```
*Reflow every `.rs` file except anything in `target/`:*
```
parfit --recursive --in-place --include '*.rs' --exclude 'target/*' .
```
Directory walks respect `.gitignore` and other `ignore` rules by default (powered by the same walker as `ripgrep` and `fd`).
**5. Options**
`-w N`, `--width N`
Target width in columns, inclusive of the detected prefix. Default 68.
`-r`, `--recursive`
Walk directories recursively. Required when any path argument is a directory.
`-i`, `--in-place`
Rewrite files in place instead of emitting to stdout. Required when more than one file will be processed.
`--include GLOB`
Glob of file names to include. Repeatable. Applies only when path arguments are given.
`--exclude GLOB`
Glob of file names to exclude. Repeatable.
`-s REGEX`, `--skip REGEX`
Append a regular expression to the skip list. Paragraphs containing any matching line pass through verbatim. Repeatable.
`--no-default-skips`
Disable the built-in directive patterns. Only user patterns supplied via `--skip` remain active.
`-p STRING`, `--prefix STRING`
Force the given string as the comment prefix on every paragraph instead of auto-detecting.
**6. Default skip patterns**
Active unless `--no-default-skips` is given:
```
Go //go:, // +build, //nolint, //noinspection, //lint:
Rust #[, #![
Shell #!/ (shebang)
Python # type:, # noqa, # pragma:
TypeScript // @ts-, // eslint-, /* eslint-
JSDoc // @param, // @returns, // @internal,
// @deprecated, // @see
Generic Lone-URL lines, separator lines (// ----)
```
**7. Prefix detection**
parfit detects the prefix on each paragraph from its first line, matching the leading whitespace followed by one of:
```
/// , //! , // , /** , /* , */ , * , * , #! , # , ;
```
The detected prefix is preserved verbatim on every output line. When multiple consecutive lines share a prefix they are treated as a single paragraph; a blank line or a prefix change ends it.
**8. Editor integration**
parfit is a filter. Any editor that can pipe a visual selection through a command can use it.
- **Vim** — select a comment block, then `:!parfit`.
- **Emacs** — `M-| parfit RET` on a region.
- **VS Code** — bind a key to "Filter Through Command" running parfit.
**9. Differences from par**
- Optimal-fit line breaking rather than greedy. The last line of a paragraph is rarely left short; Knuth-Plass dynamic programming distributes slack evenly.
- Built-in directive awareness. par reformats `//go:generate` just like prose; parfit leaves it alone.
- URL safety. Words containing `://` never split.
- Prefix auto-detection covering the comment markers of the most common programming languages, not just character classes.
- Recursive directory walking with glob filtering and in-place edits.
**10. License**
MIT. See `LICENSE`.
**11. References**
[1] Costello, A.M., "par - a paragraph reformatter", 1993. http://www.nicemice.net/par/
[2] Knuth, D.E. and Plass, M.F., "Breaking Paragraphs into Lines", Software: Practice and Experience, Vol. 11, Issue 11, November 1981, pp. 1119-1184.
[3] textwrap crate (Martin Geisler), used by parfit for the optimal-fit implementation. https://crates.io/crates/textwrap
[4] ignore crate (Andrew Gallant), used by parfit's directory walker. https://crates.io/crates/ignore