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:
cat foo.go | parfit
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 RETon 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:generatejust 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