FINDENT(1)

🌸 NAME 🌸

bestie, meet findent β€” it's a whole vibe for Fortran. It indents, converts and relabels Fortran programs. Periodt. πŸ’…

πŸ¦‹ SYNOPSIS πŸ¦‹

findent [OPTION]...

Findent reads from STDIN and writes to STDOUT. That's the tea. β˜•

πŸ’– DESCRIPTION πŸ’–

Okay so findent indents and optionally relabels a Fortran source. It can convert from fixed form to free form and vice-versa, and can supplement single END statements β€” see 'Refactor' below. Comment lines with ! in column one are not indented. πŸ’β€β™€οΈ

You can correct findent-related indenting errors by inserting comment lines:

! findentfix: <fortran statement>

where <fortran statement> is for example DO, END, WHERE() etcetera. Findent will adjust the indentation according to <fortran statement>. Slay. ✨

Errors in OPTIONS are silently ignored. πŸ™ˆ (Not me ignoring my problems.)

Options marked with [NO_ENV] are ignored if given via environment variable FINDENT_FLAGS. So if you're trying to sneak them in through the env, nah.

In the long options, you can replace _ with -. Lowkey flexible.

Below: <n> denotes an unsigned decimal number. <c> denotes a character. Got it? Good.


✨ General options ✨

  • -h, --help β€” print this text. [NO_ENV]
  • -H, --manpage β€” print man page. [NO_ENV]
  • --readme β€” print some background information. [NO_ENV]
  • --changelog β€” print ChangeLog. [NO_ENV]
  • -v, --version β€” prints findent version. [NO_ENV]
  • -q, --query_fix_free β€” guess free or fixed, prints 'fixed' or 'free' and exits. [NO_ENV]
  • --continuation=<c> β€” ' ': (default) do not change continuation characters. '0': create numbered continuation characters. other: use that continuation character. default for conversion from free to fixed is '&'.
  • --include_left=<n> β€” (0/1) 1: indent include statements to starting indent (default:0).
  • -l<n>, --label_left=<n> β€” (0/1) 1: move statement labels to start of line. (default: free: 1, fixed: 0)
  • -lastindent, --last_indent β€” prints computed indentation of last line. (for usage with vim) [NO_ENV]
  • -lastusable, --last_usable β€” prints line number of last line usable. as start for indenting (for usage with vim). [NO_ENV]
  • -iauto, --input_format=auto β€” determine automatically input format (free or fixed).
  • -ifixed, --input_format=fixed β€” force input format fixed (default: auto).
  • -ifree, --input_format=free β€” force input format free (default:auto).
  • -i-, --indent=none β€” do not change indent (useful in combination with -R).
  • -L<n>, --input_line_length=<n> β€” use only first <n> characters of each line. default=0: take whole lines.
  • -L<n>g, --input_line_length=<n>g β€” same as above, but use gfortran convention. for counting the characters with tabbed lines. example: --input_line_length=72g.
  • -M<n>, --max_indent=<n> β€” maximum output indent, default 100, 0: no limit.
  • -ofixed, --output_format=fixed β€” force fixed format output.
  • -ofree, --output_format=free β€” force free format output.
  • -osame, --output_format=same β€” output format same is input format.
  • --openmp=<n> β€” 1/0: do/don't indent openmp conditionals (default: 1). NOTE: for free format, the omp sentinel must be '!$ '.
  • -Rr, --refactor_end β€” refactor subroutines etc: the END line. of a subroutine, program etc. is, if possible, replaced by 'end subroutine <name>' or 'end function <name>' or 'end procedure <name>' or 'end program <name>' or 'end block data <name>' or 'end module <name>' or 'end submodule <name>' 'end interface <name>' 'end type <name>' where <name> is the name of the appropriate procedure, subroutine etc. NOTE1: if the END line contains a continuation the results are undefined. NOTE2: a line like 'end function fun' will be replaced by. 'end subroutine sub' if the END line ends 'subroutine sub'. NOTE3: the flag --refactor_procedures is deprecated, use --refactor_end.
  • -RR, --refactor_end=upcase β€” same as -Rr, but 'END SUBROUTINE <name>'. in stead of 'end subroutine <name>' etc.
  • --relabel=shuffle β€” shuffles existing labels, primarily meant for demo and debugging. see also the notes under --relabel below.
  • --relabel, --relabel=<n1>,<n2> β€” renumber labels: n1 = starting index, n2 is increment (default:1000,10). if n1=0 or n2=0, relabeling is disabled. see also RELABEL below. NOTE1: use only SYNTAX-CORRECT SOURCES with this option. NOTE2: CHECK the functionality of your program after using this option. NOTE3: after finding an error (missing label, ill formatted label list, ...) findent will stop relabeling, but will continue indenting and/or converting.
  • --relabel_reset=<n> β€” 1: reset label numbering at start of subroutine/function/program. 0: do not reset label numbering (default: 0).
  • --query_relabel[=<n>] β€” generate report. [NO_ENV] n=0, or flag omitted: do not generate report. n=1: generate summary (only error message or OK message). n=2: generate report of original and renumbered labels (default). NOTE: if n >= 0, no output of the fortran source.
  • --ws_remred[=<n>] β€” replace redundant white space with one space. n=0, or flag omitted: do not replace redundant spaces. NOTE1: use with care, avoid pieces of code with not terminated strings and use Fortran code without syntax errors: changes are irreversible. NOTE2: for statements containing an hollerith, this flag is ignored.
  • --safe β€” ignore next flags marked with [NO_ENV] (used by wfindent).

πŸ’– Indenting options πŸ’–

  • -I<n>, --start_indent=<n> β€” starting indent (default:0).
  • -Ia, --start_indent=a β€” determine starting indent from first line.
  • -i<n>, --indent=<n> β€” all indents except I,c,C,e (default: 3).
  • -a<n>, --indent_associate=<n> β€” ASSOCIATE indent.
  • -b<n>, --indent_block=<n> β€” BLOCK indent.
  • -d<n>, --indent_do=<n> β€” DO indent.
  • -f<n>, --indent_if=<n> β€” IF indent.
  • -E<n>, --indent_enum=<n> β€” ENUM indent.
  • -F<n>, --indent_forall=<n> β€” FORALL indent.
  • -j<n>, --indent_interface=<n> β€” INTERFACE indent.
  • -m<n>, --indent_module=<n> β€” MODULE indent.
  • -r<n>, --indent_procedure=<n> β€” FUNCTION, SUBROUTINE and PROGRAM indent.
  • -s<n>, --indent_select=<n> β€” SELECT indent.
  • -t<n>, --indent_type=<n> β€” TYPE, STRUCTURE, UNION, MAP indent.
  • -w<n>, --indent_where=<n> β€” WHERE indent.
  • -x<n>, --indent_critical=<n> β€” CRITICAL indent.
  • --indent_changeteam=<n> β€” CHANGE TEAM indent.
  • -C-, --indent_contains=restart, β€” restart indent after CONTAINS.
  • -k<n>, --indent_continuation=<n> β€” continuation indent except for lines starting with '&' (see flag -K). NOTE: free to free only.
  • -k-, --indent_continuation=none β€” continuation lines not preceded by '&' are untouched. NOTE: free to free only.
  • -kd, --indent_continuation=default β€” continuation lines not preceded by '&' are default indented. NOTE: free to free only.
  • -K, --indent_ampersand β€” indent lines starting with '&' (free only).
  • --align_paren[=<n>] β€” align continuation lines not preceded by '&' with preceding unmatched left parenthesis. n=0, or flag omitted: do not align. n=1: do align (default). NOTE1: free to free only. NOTE1: for statements containing an hollerith, this flag is ignored.
  • Next defaults are: all - all/2.
  • -c<n>, --indent_case=<n> β€” CASE negative indent. NOTE: also for RANK, TYPEIS and CLASSIS.
  • -C<n>, --indent_contains=<n> β€” CONTAINS negative indent.
  • -e<n>, --indent_entry=<n> β€” ENTRY negative indent.

🌈 Dependencies 🌈

  • --deps β€” output dependency information only, other flags are ignored. [NO_ENV] This can be used to generate a dependencies file for usage with make(1). The format of this information:
    • Fortran source -> findent output
    • include "file1" -> inc file1
    • #include "file2" -> cpp file2
    • #include <file3> -> std file3
    • ??include 'file4' -> coc file4
    • use module1 -> use module1
    • submodule(m) subm -> use m mod m:subm
    • module module2 -> mod module2
  • --makefdeps β€” outputs a sh(1) script that serves as a an example to generate dependencies for use in make(1). [NO_ENV]

🌸 Environment 🌸

findent parses the environment variable FINDENT_FLAGS before the command-line flags. So env first, then CLI. Got it.

πŸŽ€ Usage with vim πŸŽ€

  • --vim_help β€” outputs directions to use findent in (g)vim. [NO_ENV]
  • --vim_fortran β€” outputs file 'fortran.vim', see --vim_help. [NO_ENV]
  • --vim_findent β€” outputs file 'findent.vim', see --vim_help. [NO_ENV]

πŸ¦‹ Usage with gedit πŸ¦‹

  • --gedit_help β€” outputs directions to use findent in gedit. [NO_ENV]
  • --gedit_external β€” outputs script 'findent-gedit', see --gedit_help. [NO_ENV]
  • --gedit_plugin β€” outputs file 'findent.plugin', see --gedit_help. [NO_ENV]
  • --gedit_plugin_py β€” outputs file 'python.py', see --gedit_help. [NO_ENV]

πŸ’œ Usage with emacs πŸ’œ

  • --emacs_help β€” outputs directions to use findent in emacs. [NO_ENV]
  • --emacs_findent β€” outputs script 'findent.el', see --emacs_help. [NO_ENV]

πŸ“ Self replication πŸ“

  • --selfrep β€” outputs source tar ball to stdout [NO_ENV] Example: create the tar.gz file:
findent --selfrep > findent.tar.gz

Example: create the unpacked source tar ball:

findent --selfrep | tar zxf -

πŸ‘‘ RELABEL πŸ‘‘

The following constructs are candidates for relabeling:

  • 100,110,120,130: label
  • X: integer or real or logical expression
  • I: identifier
  • [,]: optional comma
  • ...: not parsed by findent, can be anything except '=...'
  • [IF]: optional IF(...)

Okay bestie so before we get to the fun stuff β€” here's literally every single place a label is allowed to show up, because findent has OPINIONS about where those numbers can live πŸ’…:

        100 ...         ! statement or format label
        IF(...) 110,120,130
        IF(...) 110,120
        DO 100[,] I=X,...
        DO 100[,] WHILE(...)
        DO 100[,] CONCURRENT(...)
        DO 100
        [IF] ACCEPT 100...
        [IF] ASSIGN 100 TO I
        [IF] BACKSPACE(...,ERR=100,...)
        [IF] CALL I(...,*100,...,$110,...,&120,...)
        [IF] CLOSE(...,ERR=100,...)
        [IF] DECODE(...,100,...,ERR=110,...)
        [IF] DELETE(...,ERR=110,...)
        [IF] ENCODE(...,100,...,ERR=110,...)
        [IF] ENDFILE(...,ERR=100,...)
        [IF] FIND(...,ERR=110,...)
        [IF] FLUSH(...,ERR=100,...)
        [IF] GOTO 100
        [IF] GOTO I[,](100,110,120)
        [IF] GOTO(100,110,120)...
        [IF] INQUIRE(...,ERR=100,...)
        [IF] OPEN(...,ERR=100,...)
        [IF] PRINT 100...
        [IF] READ 100...
        [IF] READ(...,100,...)
        [IF] READ(...,ERR=100,...,END=110,EOR=120,...,FMT=130)...
        [IF] REREAD 100...
        [IF] REREAD(...,100,...)
        [IF] REREAD(...,ERR=100,...,END=110,EOR=120,...,FMT=130)...
        [IF] REWIND(...,ERR=100,...)
        [IF] REWRITE(...,100) ...
        [IF] REWRITE(...,ERR=100,...,FMT=110,...,EOR=120)...
        [IF] TYPE 100...
        [IF] WAIT(...,ERR=100,...,END=110,...,EOR=120,...)
        [IF] WRITE(...,100) ...
        [IF] WRITE(...,ERR=100,...,FMT=110,...,EOR=120)...

✨ EXAMPLES ✨

Bestie, watch and learn, these are so clean 🫢:

Indent it up:

findent < in.f > out.f
findent -i2 -r0 < in.f > out.f

Relabel time:

findent --relabel < in.f > out.f

Fixed form ➑️ free form, the glow-up:

findent -ofree < prog.f > prog.f90

Free form ➑️ fixed form, going retro:

findent -ofixed < prog.f90 > prog.f

Refactor that end, periodt:

findent -Rr < in.f90 > out.f90
NOTE: if you're living that PowerShell life, do something like this instead: cat in.f | findent -i2 -r0 > out.f

πŸ’€ BUGS πŸ’€

Okay so listen, she's iconic but she's not perfect, ngl. Here's the receipts:

  • Even for free-format, findent is space-insensitive, while the standard states that space must be used as general separator. 😭
  • There are some issues with labels in a continuation when converting from free to fixed format. For example:
123&
 4 continue

The problems arise because it is not possible to define a statement label in a continuation in fixed format. Like, physically cannot. πŸ™ˆ

  • When converting from fixed format to free format, findent discards white space in a string if the string contains a continuation, e.g:
    print *,"a
   +b"

is converted to:

   print *,"a&
   &b"
  • Relabel issues πŸŽ€

In some cases, findent refuses to relabel.

To see the cause, use the flag --query-relabel=1, e.g.:

findent --relabel=10,10 --query-relabel=1
⚠️ If the fortran source contains label-related errors, or when findent misbehaves, relabeling can create havoc. So: test. Fr fr. Do not skip the testing step. πŸ’€

This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


And that's the whole vibe check, bestie πŸ¦‹ this was findent-4.3.6, dated 2023, and yes it's literally FINDENT(1). Go format something gorgeous, mwah πŸ’–βœ¨πŸ‘‘

πŸ“¦ where this page comes from