blob: 7a6b04f28096776e486c5bf688eca20cd98fef4c [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" Vim indent file
2" Language: Fortran95 (and Fortran90, Fortran77, F and elf90)
Bram Moolenaareb3593b2006-04-22 22:33:57 +00003" Version: 0.37
Bram Moolenaar071d4272004-06-13 20:20:40 +00004" URL: http://www.unb.ca/chem/ajit/indent/fortran.vim
Bram Moolenaarc81e5e72007-05-05 18:24:42 +00005" Last Change: 2006 Nov 16
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
Bram Moolenaareb3593b2006-04-22 22:33:57 +000017setlocal indentkeys+==~type,=~interface
Bram Moolenaar071d4272004-06-13 20:20:40 +000018
19" Determine whether this is a fixed or free format source file
20" if this hasn't been done yet
21if !exists("b:fortran_fixed_source")
22 if exists("fortran_free_source")
23 " User guarantees free source form
24 let b:fortran_fixed_source = 0
25 elseif exists("fortran_fixed_source")
26 " User guarantees fixed source form
27 let b:fortran_fixed_source = 1
28 else
29 " f90 and f95 allow both fixed and free source form
30 " assume fixed source form unless signs of free source form
Bram Moolenaar910f66f2006-04-05 20:41:53 +000031 " are detected in the first five columns of the first 250 lines
Bram Moolenaar071d4272004-06-13 20:20:40 +000032 " Detection becomes more accurate and time-consuming if more lines
33 " are checked. Increase the limit below if you keep lots of comments at
34 " the very top of each file and you have a fast computer
Bram Moolenaar910f66f2006-04-05 20:41:53 +000035 let s:lmax = 250
Bram Moolenaar071d4272004-06-13 20:20:40 +000036 if ( s:lmax > line("$") )
37 let s:lmax = line("$")
38 endif
39 let b:fortran_fixed_source = 1
40 let s:ln=1
41 while s:ln <= s:lmax
42 let s:test = strpart(getline(s:ln),0,5)
43 if s:test[0] !~ '[Cc*!#]' && s:test !~ '^ \+[!#]' && s:test =~ '[^ 0-9\t]'
44 let b:fortran_fixed_source = 0
45 break
46 endif
47 let s:ln = s:ln + 1
48 endwhile
49 endif
50endif
51
52" Define the appropriate indent function but only once
53if (b:fortran_fixed_source == 1)
54 setlocal indentexpr=FortranGetFixedIndent()
55 if exists("*FortranGetFixedIndent")
56 finish
57 endif
58else
59 setlocal indentexpr=FortranGetFreeIndent()
60 if exists("*FortranGetFreeIndent")
61 finish
62 endif
63endif
64
Bram Moolenaar910f66f2006-04-05 20:41:53 +000065let s:cposet=&cpoptions
66set cpoptions-=C
67
Bram Moolenaar071d4272004-06-13 20:20:40 +000068function FortranGetIndent(lnum)
69 let ind = indent(a:lnum)
70 let prevline=getline(a:lnum)
71 " Strip tail comment
72 let prevstat=substitute(prevline, '!.*$', '', '')
73
74 "Indent do loops only if they are all guaranteed to be of do/end do type
Bram Moolenaarc81e5e72007-05-05 18:24:42 +000075 if exists("b:fortran_do_enddo") || exists("g:fortran_do_enddo")
Bram Moolenaar071d4272004-06-13 20:20:40 +000076 if prevstat =~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*do\>'
77 let ind = ind + &sw
78 endif
79 if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*end\s*do\>'
80 let ind = ind - &sw
81 endif
82 endif
83
84 "Add a shiftwidth to statements following if, else, case,
Bram Moolenaareb3593b2006-04-22 22:33:57 +000085 "where, elsewhere, type and interface statements
Bram Moolenaar071d4272004-06-13 20:20:40 +000086 if prevstat =~? '^\s*\(\d\+\s\)\=\s*\(else\|case\|where\|elsewhere\)\>'
Bram Moolenaareb3593b2006-04-22 22:33:57 +000087 \ ||prevstat =~? '^\s*\(\d\+\s\)\=\s*\(type\|interface\)\>'
Bram Moolenaar071d4272004-06-13 20:20:40 +000088 \ || prevstat =~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*if\>'
89 let ind = ind + &sw
90 " Remove unwanted indent after logical and arithmetic ifs
91 if prevstat =~? '\<if\>' && prevstat !~? '\<then\>'
92 let ind = ind - &sw
93 endif
Bram Moolenaareb3593b2006-04-22 22:33:57 +000094 " Remove unwanted indent after type( statements
95 if prevstat =~? '\<type\s*('
96 let ind = ind - &sw
97 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000098 endif
99
100 "Subtract a shiftwidth from else, elsewhere, case, end if,
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000101 " end where, end select, end interface and end type statements
Bram Moolenaar071d4272004-06-13 20:20:40 +0000102 if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*'
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000103 \. '\(else\|elsewhere\|case\|end\s*\(if\|where\|select\|interface\|type\)\)\>'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000104 let ind = ind - &sw
105 " Fix indent for case statement immediately after select
106 if prevstat =~? '\<select\>'
107 let ind = ind + &sw
108 endif
109 endif
110
111 return ind
112endfunction
113
114function FortranGetFreeIndent()
115 "Find the previous non-blank line
116 let lnum = prevnonblank(v:lnum - 1)
117
118 "Use zero indent at the top of the file
119 if lnum == 0
120 return 0
121 endif
122
123 let ind=FortranGetIndent(lnum)
124 return ind
125endfunction
126
127function FortranGetFixedIndent()
128 let currline=getline(v:lnum)
129 "Don't indent comments, continuation lines and labelled lines
130 if strpart(currline,0,6) =~ '[^ \t]'
131 let ind = indent(v:lnum)
132 return ind
133 endif
134
135 "Find the previous line which is not blank, not a comment,
136 "not a continuation line, and does not have a label
137 let lnum = v:lnum - 1
138 while lnum > 0
139 let prevline=getline(lnum)
140 if (prevline =~ "^[C*!]") || (prevline =~ "^\s*$")
141 \ || (strpart(prevline,5,1) !~ "[ 0]")
142 " Skip comments, blank lines and continuation lines
143 let lnum = lnum - 1
144 else
145 let test=strpart(prevline,0,5)
146 if test =~ "[0-9]"
147 " Skip lines with statement numbers
148 let lnum = lnum - 1
149 else
150 break
151 endif
152 endif
153 endwhile
154
155 "First line must begin at column 7
156 if lnum == 0
157 return 6
158 endif
159
160 let ind=FortranGetIndent(lnum)
161 return ind
162endfunction
163
164let &cpoptions=s:cposet
165unlet s:cposet
166
167" vim:sw=2 tw=130