Gregory Seidman wrote:
I'm finding that smartindent is routinely wrong about how I want things to be indented in JS, but I haven't been able to find an indent script. I'd be interested in working on it myself, but I don't know the first thing about how the function referred to when setting indentexpr is expected to behave.Is anyone already working on an indentation file for JavaScript? If so, I'd be interested in helping. If not, would anyone be interested in collaborating on it? --Greg
Hi,I have a pretty working JS indentation script - javascript.vim, but it handles only most common cases. It uses the build in C indentation rules and does a bit of correction. Really much more corrections is required in order to indent JavaScript correctly for all the cases. Maybe C indent is a bad starting point for a complete JavaScript indentation solution. I've also tried using syntax in order to calculate indentation but this attempt lead me to even worth results - javascript.vim.bad. Maybe you can fix the syntax based version, as it is more promising. IIRC some changes were required in the syntax script in order to get better indentation results...
Currently I'm not programming in JavaScript, so I doubt I can devote much time to fixing its indentation script. But probably I will be, so I am interested in having a complete JavaScript indentation solution in Vim.
" Description: ECMAScript indenter " Author: After Johannes Zellner <[EMAIL PROTECTED]> " URL: http://www.zellner.org/vim/indent/html.vim " Last Change: Fri, 7 May 2004 20:00:00 +0200 " Globals: " Only load this indent file when no other was loaded. if exists("b:did_indent") finish endif let b:did_indent = 1 " [-- local settings (must come before aborting the script) --] setlocal indentexpr=ECMAScriptIndentGet(v:lnum) setlocal indentkeys=o,O,*<Return>,<BS>,{,} set cpo-=C fun! <SID>GetSyntax(lnum) let s1Comment = 0 let s2Comment = 0 if &syntax == '' return '' endif let s1 = synIDattr(synID(a:lnum, matchend(getline(a:lnum), '^\s*') + 1, 1), 'name') if s1 == '' let s1 = 'java' endif if s1 =~? 'comment' let s1Comment = 1 endif let s1 = matchstr(s1, '^\(java\)') if strlen(getline(a:lnum)) <= 1 let s2 = s1 let s2Comment = s1Comment else let s2 = synIDattr(synID(a:lnum, match(getline(a:lnum), '\s*$') - 1, 1), 'name') if s2 == '' let s2 = 'java' endif if s2 =~? 'comment' let s2Comment = 1 endif let s2 = matchstr(s2, '^\(java\)') endif if s1Comment && s2Comment return 'comment' endif if s1 == 'java' && s2 == 'java' return 'java' endif if s1 == s2 return s1 endif return '' endfun fun! ECMAScriptIndentGet(lnum) " Syntax of current line let curSyntax = <SID>GetSyntax(a:lnum) let restore_ic=&ic let &ic=1 " ignore case let ind = 0 " Indent in sw multipliers. Added to indent of previous line. let presizeIndent = -1 " Indent in spaces. int is ignores if presizeIndent != -1. " Script source is indented seperatly from commments. if curSyntax == 'java' " Find a non-empty line above the current line. let plnum = prevnonblank(a:lnum - 1) let prevSyntax = <SID>GetSyntax(plnum) " Skip comments. " BUG: will not work when comments is mixed with other text in the same line. while plnum > 0 && (prevSyntax == 'comment' || prevSyntax == '') let plnum = prevnonblank(plnum - 1) let prevSyntax = <SID>GetSyntax(plnum) endwhile " Hit the start of the file, use zero indent. if plnum == 0 presizeIndent = 0 else " Add 1 sw indent for each non closed { or (. let ind = strlen(substitute(getline(plnum), '[^{(]\+', '', 'g')) - \ strlen(substitute(getline(plnum), '[^})]\+', '', 'g')) " let restPos = matchend(getline(plnum), '^\s*}') " if restPos == -1 " let ind = strlen(substitute(getline(plnum), '[^{]\+', '', 'g')) - " \ strlen(substitute(getline(plnum), '[^}]\+', '', 'g')) " else " let rest = strpart(getline(plnum), restPos) " let ind = strlen(substitute(rest, '[^{]\+', '', 'g')) - " \ strlen(substitute(rest, '[^}]\+', '', 'g')) " endif " if match(getline(a:lnum), '^\s*}') == 0 " let ind = ind - strlen(substitute(substitute(getline(a:lnum), '^\s*\([}\s]\+\)', '\1', ''), " \ '\s\+', '', '')) " endif " Also add 1 sw indent if it looks like statement from previous line is continued on current one. This " indent is used only if there is no non closed { or ( found on previous line. if ind == 0 let plClose = (match(getline(plnum), '[;{}]\s*$') != -1) if !plClose " Dont indent more then once for each continues statement. So chech if line previous to previous has " statement end look. Indent only if it does. let pplnum = prevnonblank(plnum - 1) if pplnum == 0 || match(getline(pplnum), '[;{}]\s*$') != -1 let ind = ind + 1 endif else " In case previous line have statement end there is a check required to see if it was extra " indented because of statement spaned across multiple lines. let pplnum = prevnonblank(plnum - 1) if pplnum != 0 && match(getline(pplnum, '[;{}]\s*$') == -1 let ind = ind - 1 endif endif endif endif elseif curSyntax == 'comment' " Find a non-empty line above the current line. let plnum = prevnonblank(a:lnum - 1) let prevSyntax = <SID>GetSyntax(plnum) " Dont skip comments. " BUG: will not work when comments is mixed with other text in the same line. while plnum > 0 && prevSyntax == '' let plnum = plnum - 1 let prevSyntax = <SID>GetSyntax(plnum) endwhile " Align middle part of C style comment with begin part. if a:lnum > 0 && getline(a:lnum) =~ '^\s*\*' " Find comment start let commentStartLine = a:lnum - 1 let secondCommentLine = 1 while commentStartLine > 0 let line = getline(commentStartLine) if line =~ '^\s*/\*' break endif if line =~ '^\s*\*' let secondCommentLine = 0 break endif let commentStartLine = commentStartLine - 1 endwhile " And indent one more space, but only for the first comment line. Other lines get indent from previous " ones - for speed. if secondCommentLine && commentStartLine > 0 let presizeIndent = indent(commentStartLine) + 1 endif endif endif let &ic=restore_ic if presizeIndent != -1 return presizeIndent else return indent(plnum) + (&sw * ind) endif endfun " [-- EOF <runtime>/indent/javascript.vim --]
javascript.vim
Description: application/octetstream