7
|
1 " Vim indent file
|
|
2 " Language: VisualBasic (ft=vb) / Basic (ft=basic) / SaxBasic (ft=vb)
|
|
3 " Author: Johannes Zellner <johannes@zellner.org>
|
31579
|
4 " Maintainer: Michael Soyka (mssr953@gmail.com)
|
9
|
5 " Last Change: Fri, 18 Jun 2004 07:22:42 CEST
|
2421
|
6 " Small update 2010 Jul 28 by Maxim Kim
|
31579
|
7 " 2022/12/15: add support for multiline statements.
|
|
8 " 2022/12/21: move VbGetIndent from global to script-local scope
|
|
9 " 2022/12/26: recognize "Type" keyword
|
7
|
10
|
|
11 if exists("b:did_indent")
|
|
12 finish
|
|
13 endif
|
|
14 let b:did_indent = 1
|
|
15
|
233
|
16 setlocal autoindent
|
31579
|
17 setlocal indentexpr=s:VbGetIndent(v:lnum)
|
7
|
18 setlocal indentkeys&
|
31579
|
19 setlocal indentkeys+==~else,=~elseif,=~end,=~wend,=~case,=~next,=~select,=~loop
|
7
|
20
|
233
|
21 let b:undo_indent = "set ai< indentexpr< indentkeys<"
|
|
22
|
7
|
23 " Only define the function once.
|
31579
|
24 if exists("*s:VbGetIndent")
|
7
|
25 finish
|
|
26 endif
|
|
27
|
31579
|
28 function s:VbGetIndent(lnum)
|
|
29 let this_lnum = a:lnum
|
|
30 let this_line = getline(this_lnum)
|
|
31
|
7
|
32 " labels and preprocessor get zero indent immediately
|
|
33 let LABELS_OR_PREPROC = '^\s*\(\<\k\+\>:\s*$\|#.*\)'
|
|
34 if this_line =~? LABELS_OR_PREPROC
|
|
35 return 0
|
|
36 endif
|
31579
|
37
|
|
38 " Get the current value of "shiftwidth"
|
|
39 let bShiftwidth = shiftwidth()
|
7
|
40
|
|
41 " Find a non-blank line above the current line.
|
|
42 " Skip over labels and preprocessor directives.
|
31579
|
43 let lnum = this_lnum
|
7
|
44 while lnum > 0
|
|
45 let lnum = prevnonblank(lnum - 1)
|
|
46 let previous_line = getline(lnum)
|
|
47 if previous_line !~? LABELS_OR_PREPROC
|
|
48 break
|
|
49 endif
|
|
50 endwhile
|
|
51
|
|
52 " Hit the start of the file, use zero indent.
|
|
53 if lnum == 0
|
|
54 return 0
|
|
55 endif
|
|
56
|
31579
|
57 " Variable "previous_line" now contains the text in buffer line "lnum".
|
|
58
|
|
59 " Multi-line statements have the underscore character at end-of-line:
|
|
60 "
|
|
61 " object.method(arguments, _
|
|
62 " arguments, _
|
|
63 " arguments)
|
|
64 "
|
|
65 " and require extra logic to determine the correct indentation.
|
|
66 "
|
|
67 " Case 1: Line "lnum" is the first line of a multiline statement.
|
|
68 " Line "lnum" will have a trailing underscore character
|
|
69 " but the preceding non-blank line does not.
|
|
70 " Line "this_lnum" will be indented relative to "lnum".
|
|
71 "
|
|
72 " Case 2: Line "lnum" is the last line of a multiline statement.
|
|
73 " Line "lnum" will not have a trailing underscore character
|
|
74 " but the preceding non-blank line will.
|
|
75 " Line "this_lnum" will have the same indentation as the starting
|
|
76 " line of the multiline statement.
|
|
77 "
|
|
78 " Case 3: Line "lnum" is neither the first nor last line.
|
|
79 " Lines "lnum" and "lnum-1" will have a trailing underscore
|
|
80 " character.
|
|
81 " Line "this_lnum" will have the same indentation as the preceding
|
|
82 " line.
|
|
83 "
|
|
84 " No matter which case it is, the starting line of the statement must be
|
|
85 " found. It will be assumed that multiline statements cannot have
|
|
86 " intermingled comments, statement labels, preprocessor directives or
|
|
87 " blank lines.
|
|
88 "
|
|
89 let lnum_is_continued = (previous_line =~ '_$')
|
|
90 if lnum > 1
|
|
91 let before_lnum = prevnonblank(lnum-1)
|
|
92 let before_previous_line = getline(before_lnum)
|
|
93 else
|
|
94 let before_lnum = 0
|
|
95 let before_previous_line = ""
|
|
96 endif
|
|
97
|
|
98 if before_previous_line !~ '_$'
|
|
99 " Variable "previous_line" contains the start of a statement.
|
|
100 "
|
|
101 let ind = indent(lnum)
|
|
102 if lnum_is_continued
|
|
103 let ind += bShiftwidth
|
|
104 endif
|
|
105 elseif ! lnum_is_continued
|
|
106 " Line "lnum" contains the last line of a multiline statement.
|
|
107 " Need to find where this multiline statement begins
|
|
108 "
|
|
109 while before_lnum > 0
|
|
110 let before_lnum -= 1
|
|
111 if getline(before_lnum) !~ '_$'
|
|
112 let before_lnum += 1
|
|
113 break
|
|
114 endif
|
|
115 endwhile
|
|
116 if before_lnum == 0
|
|
117 let before_lnum = 1
|
|
118 endif
|
|
119 let previous_line = getline(before_lnum)
|
|
120 let ind = indent(before_lnum)
|
|
121 else
|
|
122 " Line "lnum" is not the first or last line of a multiline statement.
|
|
123 "
|
|
124 let ind = indent(lnum)
|
|
125 endif
|
7
|
126
|
|
127 " Add
|
31579
|
128 if previous_line =~? '^\s*\<\(begin\|\%(\%(private\|public\|friend\)\s\+\)\=\%(function\|sub\|property\|enum\|type\)\|select\|case\|default\|if\|else\|elseif\|do\|for\|while\|with\)\>'
|
|
129 let ind = ind + bShiftwidth
|
7
|
130 endif
|
|
131
|
|
132 " Subtract
|
|
133 if this_line =~? '^\s*\<end\>\s\+\<select\>'
|
|
134 if previous_line !~? '^\s*\<select\>'
|
31579
|
135 let ind = ind - 2 * bShiftwidth
|
7
|
136 else
|
|
137 " this case is for an empty 'select' -- 'end select'
|
|
138 " (w/o any case statements) like:
|
|
139 "
|
|
140 " select case readwrite
|
|
141 " end select
|
31579
|
142 let ind = ind - bShiftwidth
|
7
|
143 endif
|
2421
|
144 elseif this_line =~? '^\s*\<\(end\|else\|elseif\|until\|loop\|next\|wend\)\>'
|
31579
|
145 let ind = ind - bShiftwidth
|
7
|
146 elseif this_line =~? '^\s*\<\(case\|default\)\>'
|
|
147 if previous_line !~? '^\s*\<select\>'
|
31579
|
148 let ind = ind - bShiftwidth
|
7
|
149 endif
|
|
150 endif
|
|
151
|
|
152 return ind
|
31579
|
153 endfunction
|
2421
|
154
|
|
155 " vim:sw=4
|