blob: 465412b167f8732069910de8c5b8e188d1f8c76f [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" Vim indent file
2" Language: Fortran95 (and Fortran90, Fortran77, F and elf90)
3" Version: 0.36
4" URL: http://www.unb.ca/chem/ajit/indent/fortran.vim
Bram Moolenaar910f66f2006-04-05 20:41:53 +00005" Last Change: 2006 Apr. 02
Bram Moolenaar071d4272004-06-13 20:20:40 +00006" Maintainer: Ajit J. Thakkar <ajit@unb.ca>; <http://www.unb.ca/chem/ajit/>
7" Usage: Do :help fortran-indent from Vim
8
9" Only load this indent file when no other was loaded.
10if exists("b:did_indent")
11 finish
12endif
13let b:did_indent = 1
14
Bram Moolenaar071d4272004-06-13 20:20:40 +000015setlocal indentkeys+==~end,=~case,=~if,=~else,=~do,=~where,=~elsewhere,=~select
16setlocal indentkeys+==~endif,=~enddo,=~endwhere,=~endselect
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
Bram Moolenaar910f66f2006-04-05 20:41:53 +000030 " are detected in the first five columns of the first 250 lines
Bram Moolenaar071d4272004-06-13 20:20:40 +000031 " 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
Bram Moolenaar910f66f2006-04-05 20:41:53 +000034 let s:lmax = 250
Bram Moolenaar071d4272004-06-13 20:20:40 +000035 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[0] !~ '[Cc*!#]' && s:test !~ '^ \+[!#]' && 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
Bram Moolenaar910f66f2006-04-05 20:41:53 +000064let s:cposet=&cpoptions
65set cpoptions-=C
66
Bram Moolenaar071d4272004-06-13 20:20:40 +000067function 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("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 and elsewhere statements
85 if prevstat =~? '^\s*\(\d\+\s\)\=\s*\(else\|case\|where\|elsewhere\)\>'
86 \ || prevstat =~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*if\>'
87 let ind = ind + &sw
88 " Remove unwanted indent after logical and arithmetic ifs
89 if prevstat =~? '\<if\>' && prevstat !~? '\<then\>'
90 let ind = ind - &sw
91 endif
92 endif
93
94 "Subtract a shiftwidth from else, elsewhere, case, end if,
95 " end where and end select statements
96 if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*'
97 \. '\(else\|elsewhere\|case\|end\s*\(if\|where\|select\)\)\>'
98 let ind = ind - &sw
99 " Fix indent for case statement immediately after select
100 if prevstat =~? '\<select\>'
101 let ind = ind + &sw
102 endif
103 endif
104
105 return ind
106endfunction
107
108function FortranGetFreeIndent()
109 "Find the previous non-blank line
110 let lnum = prevnonblank(v:lnum - 1)
111
112 "Use zero indent at the top of the file
113 if lnum == 0
114 return 0
115 endif
116
117 let ind=FortranGetIndent(lnum)
118 return ind
119endfunction
120
121function FortranGetFixedIndent()
122 let currline=getline(v:lnum)
123 "Don't indent comments, continuation lines and labelled lines
124 if strpart(currline,0,6) =~ '[^ \t]'
125 let ind = indent(v:lnum)
126 return ind
127 endif
128
129 "Find the previous line which is not blank, not a comment,
130 "not a continuation line, and does not have a label
131 let lnum = v:lnum - 1
132 while lnum > 0
133 let prevline=getline(lnum)
134 if (prevline =~ "^[C*!]") || (prevline =~ "^\s*$")
135 \ || (strpart(prevline,5,1) !~ "[ 0]")
136 " Skip comments, blank lines and continuation lines
137 let lnum = lnum - 1
138 else
139 let test=strpart(prevline,0,5)
140 if test =~ "[0-9]"
141 " Skip lines with statement numbers
142 let lnum = lnum - 1
143 else
144 break
145 endif
146 endif
147 endwhile
148
149 "First line must begin at column 7
150 if lnum == 0
151 return 6
152 endif
153
154 let ind=FortranGetIndent(lnum)
155 return ind
156endfunction
157
158let &cpoptions=s:cposet
159unlet s:cposet
160
161" vim:sw=2 tw=130