fprettier is an auto-formatter for Fortran 90+ code.
fprettier is inspired by fprettify but strives to be:
- ⚡ Fast, especially for large codebases
- 🔧 Actively maintained, with prompt responses to issues
First, install Rust and Cargo by following the instructions at:
Then install fprettier:
cargo install fprettierRun fprettier with no arguments to display the usage information.
Format files in-place:
fprettier -r src/Verify formatting without modifying files — prints the files that would change and exits non-zero if there are any, so CI needs just one step:
fprettier --check -r src/Show what would change as a unified diff, without modifying files:
fprettier --diff -r src/Settings come from three places. Each overrides the one before it:
fprettier.tomlfiles- command-line flags
- an
! fprettier:directive in the file being formatted
fprettier looks for fprettier.toml in your home directory, then in every
directory from the filesystem root down to the file being formatted. Files
found later win, so a fprettier.toml beside the source overrides one at the
top of the repository. Only the keys a file actually sets are applied.
--config PATH uses one file and skips the search.
indent = 4 # spaces per indent level
line_length = 132 # maximum line length
whitespace = 2 # whitespace level, 0-4 (see below)
impose_indent = true # apply indentation
impose_whitespace = true # apply whitespace formatting
strict_indent = true # re-indent IF/DO even when already aligned
indent_fypp = true # indent fypp preprocessor blocks
indent_mod = true # indent module/program/submodule bodies
format_decl = false # normalize spacing around ::
comment_spacing = 1 # spaces before an inline comment
normalize_comment_spacing = false # apply comment_spacing everywhere
enable_replacements = false # convert between .lt. and < style operators
c_relations = false # with enable_replacements, prefer < over .lt.
sort_use = false # sort use statements alphabetically within a group
sort_use_only = false # sort the names in a use ... only: listwhitespace selects a preset: 0 adds no spacing, 1 covers commas,
assignments, relational and logical operators, print/read statements,
intrinsic calls and ::; 2 adds + and -; 3 adds * and /; 4 adds %
and //. The default is 2.
Override individual rules with [whitespace_dict], which wins over the level:
whitespace = 2
[whitespace_dict]
comma = true # after , and ;
assignments = true # around = and =>
relational = true # around <, >, ==, /=, .eq., ...
logical = true # around .and., .or., ...
plusminus = true # around binary + and -
multdiv = false # around binary * and /
print = true # in print/read statements
type = false # around the % component selector
intrinsics = true # before intrinsic call parentheses
decl = true # around ::
concat = false # around //Each key has a matching flag, for example --whitespace-multdiv=true.
Each category takes 0 (leave alone), 1 (lowercase) or 2 (uppercase).
Nothing is converted by default.
[case_dict]
keywords = 1 # if, then, subroutine, integer, ...
procedures = 1 # intrinsics called as functions: sin(x), size(a)
operators = 1 # .and., .eq., .true., ...
constants = 1 # iso_fortran_env and iso_c_binding names: output_unit, c_int
types = 2 # kind= values, literal kind suffixes and exponent letterstypes is narrower than its name suggests. It covers real(kind=dp),
the suffix in 2_int64, and the exponent letter in 1.0e-3 — not derived
type names, and not real(dp) written without kind=:
real(kind=dp) :: a = 2.5e-8_real64 ! types = 2
real(kind=DP) :: a = 2.5E-8_REAL64On the command line, the first four are one flag and types is its own,
because a fifth value would be read as a file name:
fprettier --case 1 1 1 1 --case-types 2 -r src/Nothing is sorted by default. sort_use (--sort-use) sorts use statements
alphabetically, sort_use_only (--sort-use-only) sorts the names in an
only: list. Use either alone or both together:
use foo
use bar
use gamma, only: delta, beta
use beta, only: zulu, alfa => tangobecomes
use bar
use foo
use beta, only: alfa => tango, zulu
use gamma, only: beta, deltaA group is a run of use statements with nothing between them. A blank line, a
comment, a preprocessor directive, or any other statement ends the group and
starts a new one, so use statements in different #:if branches never mix.
Statements marked with !& or inside a !&<…!&> block stay where they are.
Comparison ignores case, and a rename sorts on its local name: c => x sorts
under c. A statement moves as a whole, together with its continuation lines
and its trailing comment.
sort_use_only rewrites the only: list as one logical line, which the usual
line-length splitter then re-breaks — so a hand-broken list is re-flowed. A
statement carrying a comment on a line other than its last is left alone, since
that comment would have nowhere to go.
A comment anywhere in a file overrides everything else for that file:
! fprettier: --indent 2 --line-length 100 --case 1 1 1 1 --case-types 2Directives accept -i/--indent, -l/--line-length, -w/--whitespace,
--case, --case-types, --no-indent, --enable-indent, --no-whitespace
and --enable-whitespace. Only the first directive in a file is used, so put
every option on that one line; later directives are ignored, not merged.
!& at the end of a line leaves that line alone. !&< and !&> mark a block
to leave alone:
matrix = [1, 0, & !&<
0, 1] !&>See CHANGELOG.md.
