LISP: Balance unmatched parentheses in Vim
If you a vim guy hacking lisp or scheme the next vimscript could be useful for you. It closes unmatched parentheses on the current line, i.e.:
(define (fact n)
(if (= n 0) 1
(* n (fact (- n 1 ; cursor is on the line
Pressing \) while on the last line will close unbalanced parentheses on that line:
(define (fact n)
(if (= n 0) 1
(* n (fact (- n 1))))) ; cursor is on the line
Here is the vimscript, just put it into your .vimrc:
function! s:rtrim(line) "{{{
return substitute(a:line, '\s*$', '', '')
endfunction "}}}
function! s:find_rside_commentpos(lnum) "{{{
let line = getline(a:lnum)
let col = stridx(line, ';')
while col != -1 &&
\ synIDattr(synID(a:lnum, col, 1), "name") =~ "String"
let col = stridx(line, ';', col + 1)
endwhile
return col
endfunction "}}}
function! s:LISP_close_parens(lnum) "{{{
let save_cursor = getpos(".")
call cursor(a:lnum, col('$'))
let unbalanced = searchpair('(', '', ')', 'rmbcW',
\ "synIDattr(synID(line('.'), col('.'), 0), 'name') =~? ".
\ "'\\(Comment\\|String\\)'")
if unbalanced > 0
let line = getline(a:lnum)
let unbalanced_str = repeat(')', unbalanced)
let col = s:find_rside_commentpos(a:lnum)
if col != -1
let before_comment = strpart(line, 0, col)
let wsp_cnt = strlen(before_comment) - strlen(s:rtrim(before_comment))
let wsp_str = repeat(' ', wsp_cnt)
let comment = strpart(line, col)
call setline(a:lnum,
\ s:rtrim(before_comment).unbalanced_str.wsp_str.comment)
else
let line = s:rtrim(line).unbalanced_str
call setline(a:lnum, line)
endif
endif
call setpos(".", save_cursor)
endfunction "}}}
command! LISPCloseParens call <SID>LISP_close_parens(line('.'))
map <Leader>) :LISPCloseParens<CR>
map <Leader>( :LISPCloseParens<CR>
This is a way better version of my previous attempt (russian) , which is to be frank just bad.
