1" Vim indent file 2" Language: Fortran95 (and Fortran90, Fortran77, F and elf90) 3" Version: 0.38 4" Last Change: 2010 July 21 5" Maintainer: Ajit J. Thakkar <ajit@unb.ca>; <http://www.unb.ca/chem/ajit/> 6" Usage: Do :help fortran-indent from Vim 7 8" Only load this indent file when no other was loaded. 9if exists("b:did_indent") 10 finish 11endif 12let b:did_indent = 1 13 14setlocal indentkeys+==~end,=~case,=~if,=~else,=~do,=~where,=~elsewhere,=~select 15setlocal indentkeys+==~endif,=~enddo,=~endwhere,=~endselect 16setlocal indentkeys+==~type,=~interface 17 18" Determine whether this is a fixed or free format source file 19" if this hasn't been done yet 20if !exists("b:fortran_fixed_source") 21 if exists("fortran_free_source") 22 " User guarantees free source form 23 let b:fortran_fixed_source = 0 24 elseif exists("fortran_fixed_source") 25 " User guarantees fixed source form 26 let b:fortran_fixed_source = 1 27 else 28 " f90 and f95 allow both fixed and free source form 29 " assume fixed source form unless signs of free source form 30 " are detected in the first five columns of the first 250 lines 31 " Detection becomes more accurate and time-consuming if more lines 32 " are checked. Increase the limit below if you keep lots of comments at 33 " the very top of each file and you have a fast computer 34 let s:lmax = 500 35 if ( s:lmax > line("$") ) 36 let s:lmax = line("$") 37 endif 38 let b:fortran_fixed_source = 1 39 let s:ln=1 40 while s:ln <= s:lmax 41 let s:test = strpart(getline(s:ln),0,5) 42 if s:test !~ '^[Cc*]' && s:test !~ '^ *[!#]' && s:test =~ '[^ 0-9\t]' && s:test !~ '^[ 0-9]*\t' 43 let b:fortran_fixed_source = 0 44 break 45 endif 46 let s:ln = s:ln + 1 47 endwhile 48 endif 49endif 50 51" Define the appropriate indent function but only once 52if (b:fortran_fixed_source == 1) 53 setlocal indentexpr=FortranGetFixedIndent() 54 if exists("*FortranGetFixedIndent") 55 finish 56 endif 57else 58 setlocal indentexpr=FortranGetFreeIndent() 59 if exists("*FortranGetFreeIndent") 60 finish 61 endif 62endif 63 64let s:cposet=&cpoptions 65set cpoptions-=C 66 67function FortranGetIndent(lnum) 68 let ind = indent(a:lnum) 69 let prevline=getline(a:lnum) 70 " Strip tail comment 71 let prevstat=substitute(prevline, '!.*$', '', '') 72 73 "Indent do loops only if they are all guaranteed to be of do/end do type 74 if exists("b:fortran_do_enddo") || exists("g:fortran_do_enddo") 75 if prevstat =~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*do\>' 76 let ind = ind + &sw 77 endif 78 if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*end\s*do\>' 79 let ind = ind - &sw 80 endif 81 endif 82 83 "Add a shiftwidth to statements following if, else, case, 84 "where, elsewhere, type and interface statements 85 if prevstat =~? '^\s*\(\d\+\s\)\=\s*\(else\|case\|where\|elsewhere\)\>' 86 \ ||prevstat =~? '^\s*\(\d\+\s\)\=\s*\(type\|interface\)\>' 87 \ || prevstat =~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*if\>' 88 let ind = ind + &sw 89 " Remove unwanted indent after logical and arithmetic ifs 90 if prevstat =~? '\<if\>' && prevstat !~? '\<then\>' 91 let ind = ind - &sw 92 endif 93 " Remove unwanted indent after type( statements 94 if prevstat =~? '\<type\s*(' 95 let ind = ind - &sw 96 endif 97 endif 98 99 "Subtract a shiftwidth from else, elsewhere, case, end if, 100 " end where, end select, end interface and end type statements 101 if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*' 102 \. '\(else\|elsewhere\|case\|end\s*\(if\|where\|select\|interface\|type\)\)\>' 103 let ind = ind - &sw 104 " Fix indent for case statement immediately after select 105 if prevstat =~? '\<select\>' 106 let ind = ind + &sw 107 endif 108 endif 109 110 return ind 111endfunction 112 113function FortranGetFreeIndent() 114 "Find the previous non-blank line 115 let lnum = prevnonblank(v:lnum - 1) 116 117 "Use zero indent at the top of the file 118 if lnum == 0 119 return 0 120 endif 121 122 let ind=FortranGetIndent(lnum) 123 return ind 124endfunction 125 126function FortranGetFixedIndent() 127 let currline=getline(v:lnum) 128 "Don't indent comments, continuation lines and labelled lines 129 if strpart(currline,0,6) =~ '[^ \t]' 130 let ind = indent(v:lnum) 131 return ind 132 endif 133 134 "Find the previous line which is not blank, not a comment, 135 "not a continuation line, and does not have a label 136 let lnum = v:lnum - 1 137 while lnum > 0 138 let prevline=getline(lnum) 139 if (prevline =~ "^[C*!]") || (prevline =~ "^\s*$") 140 \ || (strpart(prevline,5,1) !~ "[ 0]") 141 " Skip comments, blank lines and continuation lines 142 let lnum = lnum - 1 143 else 144 let test=strpart(prevline,0,5) 145 if test =~ "[0-9]" 146 " Skip lines with statement numbers 147 let lnum = lnum - 1 148 else 149 break 150 endif 151 endif 152 endwhile 153 154 "First line must begin at column 7 155 if lnum == 0 156 return 6 157 endif 158 159 let ind=FortranGetIndent(lnum) 160 return ind 161endfunction 162 163let &cpoptions=s:cposet 164unlet s:cposet 165 166" vim:sw=2 tw=130 167