Skip to content

Configuration

Create ffmt.toml in your project root, or add [tool.ffmt] to pyproject.toml. Config is searched upward from each formatted file's directory.

Tip

Use ffmt --dump-config to see the resolved configuration for the current directory.

Toggle values

Most options accept three values:

Value Meaning
true Actively apply the rule
false Actively suppress the rule
"preserve" Don't touch -- leave as-is

General options

indent-width (integer)

Number of spaces per indentation level.

Default: 4

! indent-width = 2              ! indent-width = 4
subroutine s_foo()              subroutine s_foo()
  if (.true.) then                  if (.true.) then
    x = 1                              x = 1
  end if                            end if
end subroutine                  end subroutine

line-length (integer)

Maximum line length. Code and comments are wrapped at this limit. Set to 1000 to effectively disable wrapping.

Default: 132

keyword-case ("lower" | "upper" | "preserve")

Case normalization for Fortran keywords.

Default: "lower"

! "lower"                       ! "upper"
if (x == 1) then                IF (x == 1) THEN
    call s_foo()                    CALL s_foo()
end if                          END IF

normalize-keywords (toggle)

Split compound keywords into their canonical two-word form.

Default: true

! true                          ! false
end do                          enddo
end if                          endif
end subroutine s_foo            endsubroutine s_foo

named-ends (toggle)

Add procedure/module name to bare end statements.

Default: true

! true                          ! false
end subroutine s_foo            end subroutine
end function f_bar              end function
end module m_baz                end module

enforce-double-colon (toggle)

Add :: separator to variable declarations that are missing it.

Default: true

! true                          ! false (preserve)
integer :: x                    integer x
real(wp) :: y                   real(wp) y
type(foo) :: bar                type(foo) bar

Does not modify function/subroutine signatures (logical function f_foo is left alone).

modernize-operators (toggle)

Convert legacy Fortran relational operators to modern symbolic form. String-aware -- does not modify operators inside string literals or comments.

Default: true

! true                          ! false (preserve)
if (x == 1) then                if (x .eq. 1) then
if (y /= 0) then               if (y .ne. 0) then
if (z < 10) then               if (z .lt. 10) then
if (w >= 5) then               if (w .ge. 5) then
s = 'x .eq. y'                 s = 'x .eq. y'   ! strings preserved

split-statements (toggle)

Split semicolon-separated statements onto separate lines. The private; public :: idiom is preserved.

Default: false

! true                          ! false (preserve)
x = 1                           x = 1; y = 2; z = 3
y = 2
z = 3
private; public :: s_foo        private; public :: s_foo  ! preserved

rewrap-comments (toggle)

Re-wrap long ! and !! comment blocks at line-length. Doxygen !> / !! blocks are joined and re-wrapped as units. Short consecutive comment lines are merged.

Default: true

! true (line-length = 80)
! This is a long comment that was originally on a single very long line but has
! been wrapped to fit within the line length limit.

! false (preserve)
! This is a long comment that was originally on a single very long line but has been wrapped to fit within the line length limit.

rewrap-code (toggle)

Re-wrap long code lines at line-length using token-aware splitting. Never breaks inside string literals.

Default: true

! true
call s_long_subroutine_name(arg1, arg2, arg3, &
                            & arg4, arg5)

! false (preserve)
call s_long_subroutine_name(arg1, arg2, arg3, arg4, arg5)

align-declarations (boolean)

Vertically align :: in consecutive declaration blocks.

Default: true

! true                          ! false
integer                :: x     integer :: x
real(wp), dimension(3) :: y     real(wp), dimension(3) :: y
logical                :: z     logical :: z

align-comments (boolean)

Vertically align !< inline Doxygen comments in declaration blocks. Enforces a minimum 2-space gap before the comment.

Default: true

! true
integer :: x  !< First variable
real(wp) :: y !< Second variable with long type

! becomes:
integer  :: x  !< First variable
real(wp) :: y  !< Second variable with long type

align-assignments (toggle)

Align = signs across consecutive assignment statements.

Default: false

! true                          ! false
x        = 1                    x = 1
long_var = 2                    long_var = 2
y        = 3                    y = 3

align-ampersand (toggle)

Align trailing & continuation markers at the column limit.

Default: false

! true (line-length = 40)
call s_foo(x,                          &
           & y, z)

! false
call s_foo(x, &
           & y, z)

compact-declarations (toggle)

Remove blank lines between consecutive declarations within the same scope.

Default: true

compact-use (toggle)

Remove blank lines between consecutive use statements.

Default: true

use-formatting (toggle)

Reformat use, only: imports to one item per line. Accepts true, "one-per-line", false, or "preserve".

Default: false

! true / "one-per-line"
use m_foo, only: &
    & s_bar, &
    & s_baz, &
    & f_qux

! false (preserve)
use m_foo, only: s_bar, s_baz, f_qux

end-of-line ("lf" | "crlf" | "preserve")

Normalize line endings.

Default: "lf"

space-after-comment (toggle)

Ensure a space after ! in regular comments (!comment -> ! comment). Does not affect !$acc, !<, !>, !!, or !&.

Default: true

collapse-double-spaces (boolean)

Collapse runs of multiple spaces to a single space in code (not in strings or comments).

Default: true

keyword-paren-space (toggle)

Add a space between control-flow keywords and (.

Default: true

! true                          ! false
if (x == 1) then                if(x == 1) then
call s_foo()                    call s_foo()
allocate (x(n))                 allocate(x(n))

unicode-to-ascii (boolean)

Replace Unicode Greek letters and math symbols with LaTeX equivalents in comments.

Default: true

fypp-list-commas (toggle)

Normalize comma spacing inside Fypp '[...]' list arguments.

Default: true

indent-fypp (boolean)

Indent Fypp preprocessor blocks (#:if, #:for, #:call).

Default: true

indent-module (boolean)

Indent the body of module and program blocks.

Default: true


Whitespace options

The [whitespace] section controls spacing around specific operators. All accept true, false, or "preserve".

relational (toggle)

Space around ==, /=, <, <=, >, >=.

Default: true

! true                          ! false
if (x == 1) then                if (x==1) then

logical (toggle)

Space around .and., .or., .not., .eqv., .neqv..

Default: true

! true                          ! false
if (a .and. b) then             if (a.and.b) then

plusminus (toggle)

Space around binary + and -.

Default: true

! true                          ! false
x = a + b - c                  x = a+b-c

multdiv (toggle)

Space around * and /.

Default: false

! true                          ! false
x = a * b / c                  x = a*b/c

power (toggle)

Space around **.

Default: false

! true                          ! false
x = a ** 2                     x = a**2

assignment (toggle)

Space around = in assignments.

Default: true

! true                          ! false
x = 1                           x=1

pointer (toggle)

Space around =>.

Default: true

concatenation (toggle)

Space around // (string concatenation).

Default: true

! true                          ! false
s = 'hello' // ' world'        s = 'hello'//' world'

declaration (toggle)

Space around :: in declarations.

Default: true

! true                          ! false
integer :: x                    integer::x

comma (toggle)

Space after ,.

Default: true

! true                          ! false
call s_foo(x, y, z)            call s_foo(x,y,z)

slice-colon (toggle)

Space around : in array slices.

Default: false

! true                          ! false
x(1 : n)                       x(1:n)

File options

extensions (list of strings)

File extensions to treat as Fortran source.

Default: ["fpp", "f90", "F90", "f95", "f03", "F", "F95", "F03"]

exclude (list of strings)

Glob patterns to exclude from formatting.

Default: []

[files]
exclude = ["generated/**", "third_party/**"]

respect-gitignore (boolean)

Skip files listed in .gitignore.

Default: true


Example configurations

Minimal (MFC-style)

indent-width = 2
line-length = 132
keyword-case = "lower"

Strict modernization

indent-width = 4
line-length = 132
keyword-case = "lower"
modernize-operators = true
enforce-double-colon = true
split-statements = true
use-formatting = "one-per-line"

Preserve-heavy (minimal changes)

keyword-case = "preserve"
normalize-keywords = "preserve"
rewrap-comments = "preserve"
rewrap-code = "preserve"
modernize-operators = false
enforce-double-colon = false

[whitespace]
relational = "preserve"
logical = "preserve"
plusminus = "preserve"
assignment = "preserve"

pyproject.toml

[tool.ffmt]
indent-width = 4
line-length = 132
keyword-case = "lower"

[tool.ffmt.whitespace]
relational = true
multdiv = false