Dear Vim developers, I noticed certain cases which cause Vim's indentation for awk to go into an infinite loop. The problem appears when there is a negative brace balance, i.e. more closing braces than opening braces. This can easily happen if one uses a regexp to match a closing brace. Vim then moves upward through the file to find the corresponding opening brace, which does not exist. The loop is missing a break condition for the case that line 0 has been reached. I added it in my patch.
You see for yourself by opening the attached demo.awk and inserting a line below "match". Additionally, I think that strings and computed regexps should not be scanned for matching braces at all when it comes to determining the indentation. I changed the Get_brace_balance function to strip "..." and /.../ while taking into account escape characters. I am novice in writing Vim script and I'd be glad if somebody found a more elegant way of doing this but at least it seems to give proper indentation now. The attached patch should apply to the current version of indent/awk.vim. Cheers, Philipp
{ match($0, /[^)]/) }
--- old/awk.vim 2011-04-02 00:42:52.251063401 +0200 +++ new/awk.vim 2011-04-02 01:49:50.172678039 +0200 @@ -120,6 +120,12 @@ if prev_data =~ ')' && brace_balance < 0 while brace_balance != 0 let prev_lineno = s:Get_prev_line( prev_lineno ) + if prev_lineno <= 0 + " If we reach the start of the file, some parentheses were + " misinterpreted probably. We should leave the otherwise infinite + " loop and do a failsafe indentation. + return 0 + endif let prev_data = getline( prev_lineno ) let brace_balance=brace_balance+s:Get_brace_balance(prev_data,'(',')' ) endwhile @@ -150,8 +156,12 @@ " across multiple lines. function! s:Get_brace_balance( line, b_open, b_close ) - let line2 = substitute( a:line, a:b_open, "", "g" ) - let openb = strlen( a:line ) - strlen( line2 ) + " Remove escaped \, /, and " + let line = substitute( a:line, '\\\\\|\\/\|\\\"', '', 'g') + " Remove strings and computed regexps first to prevent incorrect matches. + let line = substitute( line, '/[^/]*/\|"[^/]*"', '', 'g') + let line2 = substitute( line, a:b_open, "", "g" ) + let openb = strlen( line ) - strlen( line2 ) let line3 = substitute( line2, a:b_close, "", "g" ) let closeb = strlen( line2 ) - strlen( line3 ) return openb - closeb
signature.asc
Description: Digital signature