blob: bc7142f4286e60a3112b3a4adfef72c437425ae1 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" Vim indent file
2" Language: VisualBasic (ft=vb) / Basic (ft=basic) / SaxBasic (ft=vb)
3" Author: Johannes Zellner <johannes@zellner.org>
Bram Moolenaarf1dcd142022-12-31 15:30:45 +00004" Maintainer: Michael Soyka (mssr953@gmail.com)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005" Last Change: Fri, 18 Jun 2004 07:22:42 CEST
Bram Moolenaar59c03952010-07-28 12:52:27 +02006" Small update 2010 Jul 28 by Maxim Kim
Bram Moolenaarf1dcd142022-12-31 15:30:45 +00007" 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
Bram Moolenaar071d4272004-06-13 20:20:40 +000010
11if exists("b:did_indent")
12 finish
13endif
14let b:did_indent = 1
15
Bram Moolenaar582fd852005-03-28 20:58:01 +000016setlocal autoindent
Bram Moolenaarf1dcd142022-12-31 15:30:45 +000017setlocal indentexpr=s:VbGetIndent(v:lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018setlocal indentkeys&
Bram Moolenaarf1dcd142022-12-31 15:30:45 +000019setlocal indentkeys+==~else,=~elseif,=~end,=~wend,=~case,=~next,=~select,=~loop
Bram Moolenaar071d4272004-06-13 20:20:40 +000020
Bram Moolenaar582fd852005-03-28 20:58:01 +000021let b:undo_indent = "set ai< indentexpr< indentkeys<"
22
Bram Moolenaar071d4272004-06-13 20:20:40 +000023" Only define the function once.
Bram Moolenaarf1dcd142022-12-31 15:30:45 +000024if exists("*s:VbGetIndent")
Bram Moolenaar071d4272004-06-13 20:20:40 +000025 finish
26endif
27
Bram Moolenaarf1dcd142022-12-31 15:30:45 +000028function s:VbGetIndent(lnum)
29 let this_lnum = a:lnum
30 let this_line = getline(this_lnum)
31
Bram Moolenaar071d4272004-06-13 20:20:40 +000032 " labels and preprocessor get zero indent immediately
Bram Moolenaar071d4272004-06-13 20:20:40 +000033 let LABELS_OR_PREPROC = '^\s*\(\<\k\+\>:\s*$\|#.*\)'
34 if this_line =~? LABELS_OR_PREPROC
35 return 0
36 endif
Bram Moolenaarf1dcd142022-12-31 15:30:45 +000037
38 " Get the current value of "shiftwidth"
39 let bShiftwidth = shiftwidth()
Bram Moolenaar071d4272004-06-13 20:20:40 +000040
41 " Find a non-blank line above the current line.
42 " Skip over labels and preprocessor directives.
Bram Moolenaarf1dcd142022-12-31 15:30:45 +000043 let lnum = this_lnum
Bram Moolenaar071d4272004-06-13 20:20:40 +000044 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
Bram Moolenaarf1dcd142022-12-31 15:30:45 +000057 " 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
Bram Moolenaar071d4272004-06-13 20:20:40 +0000126
127 " Add
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000128 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
Bram Moolenaar071d4272004-06-13 20:20:40 +0000130 endif
131
132 " Subtract
133 if this_line =~? '^\s*\<end\>\s\+\<select\>'
134 if previous_line !~? '^\s*\<select\>'
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000135 let ind = ind - 2 * bShiftwidth
Bram Moolenaar071d4272004-06-13 20:20:40 +0000136 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
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000142 let ind = ind - bShiftwidth
Bram Moolenaar071d4272004-06-13 20:20:40 +0000143 endif
Bram Moolenaar59c03952010-07-28 12:52:27 +0200144 elseif this_line =~? '^\s*\<\(end\|else\|elseif\|until\|loop\|next\|wend\)\>'
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000145 let ind = ind - bShiftwidth
Bram Moolenaar071d4272004-06-13 20:20:40 +0000146 elseif this_line =~? '^\s*\<\(case\|default\)\>'
147 if previous_line !~? '^\s*\<select\>'
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000148 let ind = ind - bShiftwidth
Bram Moolenaar071d4272004-06-13 20:20:40 +0000149 endif
150 endif
151
152 return ind
Bram Moolenaarf1dcd142022-12-31 15:30:45 +0000153endfunction
Bram Moolenaar59c03952010-07-28 12:52:27 +0200154
155" vim:sw=4