parfit 0.2.0

Paragraph fit — a codebase-aware comment reflow tool that wraps prose with optimal-fit line breaking and leaves directives alone. Inspired by par.
Documentation
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 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