neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

fortran.vim (7906B)


      1 " Vim indent file
      2 " Language:	Fortran 2023 (and Fortran 2018, 2008, 2003, 95, 90, 77, 66)
      3 " Version:	(v50) 2023 December 22
      4 " Maintainers:	Ajit J. Thakkar <ajit@unb.ca>; <https://ajit.ext.unb.ca/>
      5 " 	        Joshua Hollett <j.hollett@uwinnipeg.ca>
      6 " Usage:	For instructions, do :help fortran-indent from Vim
      7 " Credits:
      8 "  Version 0.1 was created in September 2000 by Ajit Thakkar.
      9 "  Since then, useful suggestions and contributions have been made, in order, by:
     10 "  Albert Oliver Serra, Takuya Fujiwara, Philipp Edelmann, Eisuke Kawashima,
     11 "  Louis Cochen, and Doug Kearns.
     12 
     13 " Only load this indent file when no other was loaded.
     14 if exists("b:did_indent")
     15  finish
     16 endif
     17 let b:did_indent = 1
     18 
     19 let s:cposet=&cpoptions
     20 set cpoptions&vim
     21 let b:undo_indent = "setl inde< indk<"
     22 
     23 setlocal indentkeys+==~end,=~case,=~if,=~else,=~do,=~where,=~elsewhere,=~select
     24 setlocal indentkeys+==~endif,=~enddo,=~endwhere,=~endselect,=~elseif
     25 setlocal indentkeys+==~interface,=~forall,=~associate,=~block,=~enum,=~critical
     26 setlocal indentkeys+==~endforall,=~endassociate,=~endblock,=~endenum,=~endcritical
     27 if exists("b:fortran_indent_more") || exists("g:fortran_indent_more")
     28  setlocal indentkeys+==~function,=~subroutine,=~module,=~contains,=~program
     29  setlocal indentkeys+==~endfunction,=~endsubroutine,=~endmodule
     30  setlocal indentkeys+==~endprogram
     31 endif
     32 
     33 " Determine whether this is a fixed or free format source file
     34 " if this hasn't been done yet using the priority:
     35 " buffer-local value
     36 " > global value
     37 " > file extension as in Intel ifort, gcc (gfortran), NAG, Pathscale, and Cray compilers
     38 if !exists("b:fortran_fixed_source")
     39  if exists("fortran_free_source")
     40    " User guarantees free source form
     41    let b:fortran_fixed_source = 0
     42  elseif exists("fortran_fixed_source")
     43    " User guarantees fixed source form
     44    let b:fortran_fixed_source = 1
     45  elseif expand("%:e") =~? '^f\%(90\|95\|03\|08\)$'
     46    " Free-form file extension defaults as in Intel ifort, gcc(gfortran), NAG, Pathscale, and Cray compilers
     47    let b:fortran_fixed_source = 0
     48  elseif expand("%:e") =~? '^\%(f\|f77\|for\)$'
     49    " Fixed-form file extension defaults
     50    let b:fortran_fixed_source = 1
     51  else
     52    " Modern fortran compilers still allow both fixed and free source form
     53    " Assume fixed source form unless signs of free source form
     54    " are detected in the first five columns of the first s:lmax lines.
     55    " Detection becomes more accurate and time-consuming if more lines
     56    " are checked. Increase the limit below if you keep lots of comments at
     57    " the very top of each file and you have a fast computer.
     58    let s:lmax = 500
     59    if ( s:lmax > line("$") )
     60      let s:lmax = line("$")
     61    endif
     62    let b:fortran_fixed_source = 1
     63    let s:ln=1
     64    while s:ln <= s:lmax
     65      let s:test = strpart(getline(s:ln),0,5)
     66      if s:test !~ '^[Cc*]' && s:test !~ '^ *[!#]' && s:test =~ '[^ 0-9\t]' && s:test !~ '^[ 0-9]*\t'
     67 let b:fortran_fixed_source = 0
     68 break
     69      endif
     70      let s:ln = s:ln + 1
     71    endwhile
     72  endif
     73 endif
     74 
     75 " Define the appropriate indent function but only once
     76 if (b:fortran_fixed_source == 1)
     77  setlocal indentexpr=FortranGetFixedIndent()
     78  if exists("*FortranGetFixedIndent")
     79    let &cpoptions = s:cposet
     80    unlet s:cposet
     81    finish
     82  endif
     83 else
     84  setlocal indentexpr=FortranGetFreeIndent()
     85  if exists("*FortranGetFreeIndent")
     86    let &cpoptions = s:cposet
     87    unlet s:cposet
     88    finish
     89  endif
     90 endif
     91 
     92 function FortranGetIndent(lnum)
     93  let ind = indent(a:lnum)
     94  let prevline=getline(a:lnum)
     95  " Strip tail comment
     96  let prevstat=substitute(prevline, '!.*$', '', '')
     97  let prev2line=getline(a:lnum-1)
     98  let prev2stat=substitute(prev2line, '!.*$', '', '')
     99 
    100  "Indent do loops only if they are all guaranteed to be of do/end do type
    101  if exists("b:fortran_do_enddo") || exists("g:fortran_do_enddo")
    102    if prevstat =~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*do\>'
    103      let ind = ind + shiftwidth()
    104    endif
    105    if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*end\s*do\>'
    106      let ind = ind - shiftwidth()
    107    endif
    108  endif
    109 
    110  "Add a shiftwidth to statements following if, else, else if, case, class,
    111  "where, else where, forall, type, interface and associate statements
    112  if prevstat =~? '^\s*\(case\|class\s\+is\|else\|else\s*if\|else\s*where\)\>'
    113 \ ||prevstat=~? '^\s*\(type\|rank\|interface\|associate\|enum\|critical\)\>'
    114 \ ||prevstat=~? '^\s*change\s\+team\>'
    115 \ ||prevstat=~?'^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*\(forall\|where\|block\)\>'
    116 \ ||prevstat=~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*if\>'
    117     let ind = ind + shiftwidth()
    118    " Remove unwanted indent after logical and arithmetic ifs
    119    if prevstat =~? '\<if\>' && prevstat !~? '\<then\>'
    120      let ind = ind - shiftwidth()
    121    endif
    122    " Remove unwanted indent after type( statements
    123    if prevstat =~? '^\s*type\s*('
    124      let ind = ind - shiftwidth()
    125    endif
    126  endif
    127 
    128  "Indent program units unless instructed otherwise
    129  if !exists("b:fortran_indent_less") && !exists("g:fortran_indent_less")
    130    let prefix='\(\(pure\|impure\|elemental\|recursive\)\s\+\)\{,2}'
    131    let type='\(\(integer\|real\|double\s\+precision\|complex\|logical'
    132          \.'\|character\|type\|class\)\s*\S*\s\+\)\='
    133    if prevstat =~? '^\s*\(contains\|submodule\|program\)\>'
    134            \ ||prevstat =~? '^\s*'.'module\>\(\s*\procedure\)\@!'
    135            \ ||prevstat =~? '^\s*'.prefix.'subroutine\>'
    136            \ ||prevstat =~? '^\s*'.prefix.type.'function\>'
    137            \ ||prevstat =~? '^\s*'.type.prefix.'function\>'
    138      let ind = ind + shiftwidth()
    139    endif
    140    if getline(v:lnum) =~? '^\s*contains\>'
    141          \ ||getline(v:lnum)=~? '^\s*end\s*'
    142          \ .'\(function\|subroutine\|module\|submodule\|program\)\>'
    143      let ind = ind - shiftwidth()
    144    endif
    145  endif
    146 
    147  "Subtract a shiftwidth from else, else if, elsewhere, case, class, end if,
    148  " end where, end select, end forall, end interface, end associate,
    149  " end enum, end type, end block, end team and end type statements
    150  if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*'
    151        \. '\(else\|else\s*if\|else\s*where\|case\|class\|rank\|type\s\+is\|'
    152        \. 'end\s*\(if\|where\|select\|interface\|critical\|team\|'
    153        \. 'type\|forall\|associate\|enum\|block\)\)\>'
    154    let ind = ind - shiftwidth()
    155    " Fix indent for case statement immediately after select
    156    if prevstat =~? '\<select\s*\(case\|type\)\>'
    157      let ind = ind + shiftwidth()
    158    endif
    159  endif
    160 
    161  "First continuation line
    162  if prevstat =~ '&\s*$' && prev2stat !~ '&\s*$'
    163    let ind = ind + shiftwidth()
    164  endif
    165  "Line after last continuation line
    166  if prevstat !~ '&\s*$' && prev2stat =~ '&\s*$' && prevstat !~? '\<then\>'
    167    let ind = ind - shiftwidth()
    168  endif
    169 
    170  return ind
    171 endfunction
    172 
    173 function FortranGetFreeIndent()
    174  "Find the previous non-blank line
    175  let lnum = prevnonblank(v:lnum - 1)
    176 
    177  "Use zero indent at the top of the file
    178  if lnum == 0
    179    return 0
    180  endif
    181 
    182  let ind=FortranGetIndent(lnum)
    183  return ind
    184 endfunction
    185 
    186 function FortranGetFixedIndent()
    187  let currline=getline(v:lnum)
    188  "Don't indent comments, continuation lines and labelled lines
    189  if strpart(currline,0,6) =~ '[^ \t]'
    190    let ind = indent(v:lnum)
    191    return ind
    192  endif
    193 
    194  "Find the previous line which is not blank, not a comment,
    195  "not a continuation line, and does not have a label
    196  let lnum = v:lnum - 1
    197  while lnum > 0
    198    let prevline=getline(lnum)
    199    if (prevline =~ "^[C*!]") || (prevline =~ "^\s*$")
    200 \ || (strpart(prevline,5,1) !~ "[ 0]")
    201      " Skip comments, blank lines and continuation lines
    202      let lnum = lnum - 1
    203    else
    204      let test=strpart(prevline,0,5)
    205      if test =~ "[0-9]"
    206 " Skip lines with statement numbers
    207 let lnum = lnum - 1
    208      else
    209 break
    210      endif
    211    endif
    212  endwhile
    213 
    214  "First line must begin at column 7
    215  if lnum == 0
    216    return 6
    217  endif
    218 
    219  let ind=FortranGetIndent(lnum)
    220  return ind
    221 endfunction
    222 
    223 let &cpoptions = s:cposet
    224 unlet s:cposet
    225 
    226 " vim:sw=2 tw=130