Vim Tips Wiki
(Added fix for missing s:)
(Assign tip id + convert to TipNew template)
 
(4 intermediate revisions by 3 users not shown)
Line 1: Line 1:
  +
{{TipNew
{{TipProposed
 
|id=0
+
|id=1635
|previous=0
+
|previous=1634
|next=0
+
|next=1636
 
|created=October 5, 2009
 
|created=October 5, 2009
 
|complexity=basic
 
|complexity=basic
Line 8: Line 8:
 
|version=7.0
 
|version=7.0
 
|subpage=/200910
 
|subpage=/200910
|category1=
+
|category1=Plugin
 
|category2=
 
|category2=
 
}}
 
}}
Line 28: Line 28:
 
"endif
 
"endif
   
  +
" removes JavaFX quoted strings from a line
function! s:SkipJavaFxBlanksAndComments(startline)
 
  +
function! s:removeQuotedStrings(orig_line)
let lnum = a:startline
 
  +
"todo needs to be more robust
while lnum > 1
 
  +
"right now it barely handles double and single quotes, but
let lnum = prevnonblank(lnum)
 
  +
"there could be code interpolation.
if getline(lnum) =~ '\*/\s*$'
 
  +
" see http://java.sun.com/javafx/1/tutorials/core/dataTypes/#string
while getline(lnum) !~ '/\*' && lnum > 1
 
  +
let lnum = lnum - 1
 
  +
let quote1 = matchstr(a:orig_line, "['\"]")
endwhile
 
  +
if getline(lnum) =~ '^\s*/\*'
 
  +
if empty(quote1)
let lnum = lnum - 1
 
else
+
return a:orig_line
break
 
endif
 
elseif getline(lnum) =~ '^\s*//'
 
let lnum = lnum - 1
 
else
 
break
 
 
endif
 
endif
  +
endwhile
 
  +
let escaped_quote = '\\' . quote1
return lnum
 
  +
  +
" replace escaped quotes, for example '\\"'
  +
let line = substitute(a:orig_line, escaped_quote, '__', "g")
 
" call confirm('-->' . line)
  +
  +
" match the quoted token, for example: /'[^']\+'/
  +
let quote_pattern = quote1 . '[^' . quote1 . ']\+' . quote1
  +
  +
" call confirm(quote_pattern)
  +
return substitute(line, quote_pattern, '""', "g")
 
endfunction
 
endfunction
  +
  +
 
function! s:SkipJavaFxBlanksAndComments(startline)
 
let lnum = a:startline
 
while lnum > 1
 
let lnum = prevnonblank(lnum)
 
if getline(lnum) =~ '\*/\s*$'
 
while getline(lnum) !~ '/\*' && lnum > 1
 
let lnum = lnum - 1
  +
endwhile
 
if getline(lnum) =~ '^\s*/\*'
 
let lnum = lnum - 1
 
else
  +
break
  +
endif
 
elseif getline(lnum) =~ '^\s*//'
 
let lnum = lnum - 1
 
else
 
break
 
endif
 
endwhile
 
return lnum
  +
endfunction
  +
  +
" meant to matche the property syntax x : y
  +
let s:property_regex = '^\s*\(\%(\i\|\s\)\+\):\(.*\)$'
   
 
function! GetFxIndent()
 
function! GetFxIndent()
if v:lnum == 1
+
if v:lnum == 1
return indent(v:lnum)
+
return indent(v:lnum)
endif
+
endif
let theCIndent = cindent(v:lnum)
+
let theCIndent = cindent(v:lnum)
"call confirm(indent(v:lnum))
 
   
" If we're in the middle of a comment or at the end of a java-like
+
" If we're in the middle of a comment or at the end of a java-like
" statement or block, use cindent
+
" statement or block, use cindent
if getline(v:lnum) =~ '^\s*[\*/;]'
+
if getline(v:lnum) =~ '^\s*[\*/;]'
return theCIndent
+
return theCIndent
endif
+
endif
  +
 
" find start of previous line, in case it was a continuation line
 
let lnum = s:SkipJavaFxBlanksAndComments(v:lnum - 1)
 
let prev_lnum = lnum
 
while prev_lnum > 1
 
let earlier_prev = s:SkipJavaFxBlanksAndComments(prev_lnum - 1)
 
if getline(earlier_prev) !~ '\%(\i\|\s\),\s*$'
 
break
 
endif
 
let prev_lnum = earlier_prev
 
endwhile
  +
  +
" call confirm('current indent is: ' . indent(v:lnum) .
  +
" \ "\ncindent wants it to be: " . theCIndent .
  +
" \ "\nprevious line num: " . prev_lnum)
  +
  +
" let's get rid of the contents of the strings in the line.
  +
let current_line = s:removeQuotedStrings(getline(v:lnum))
  +
let prev_line = s:removeQuotedStrings(getline(prev_lnum))
   
  +
" call confirm('prev_line is: ' . prev_line)
" find start of previous line, in case it was a continuation line
 
 
if current_line =~ '^\s*\]'
let lnum = s:SkipJavaFxBlanksAndComments(v:lnum - 1)
 
let prev_lnum = lnum
+
return indent(prev_lnum) - &sw
while prev_lnum > 1
 
let earlier_prev = s:SkipJavaFxBlanksAndComments(prev_lnum - 1)
 
if getline(earlier_prev) !~ '[\w\s],\s*$'
 
break
 
 
endif
 
endif
let prev_lnum = earlier_prev
 
endwhile
 
   
 
" take care of property-type format x: y
if getline(v:lnum) =~ '^\s*\]'
 
 
let captures = matchlist(prev_line, s:property_regex)
return indent(prev_lnum) - &sw
 
endif
 
   
  +
if ! empty(captures)
" take care of property-type format x: y
 
  +
" call confirm(string(captures))
let captures = matchlist(getline(prev_lnum), '^\([^:]*\):\(.*\)$')
 
if ! empty(captures)
+
if captures[1] =~ '{' || captures[2] =~ '{'
  +
" call confirm("if1")
if captures[1] =~ '{' || captures[2] =~ '{'
 
if captures[2] =~ '}'
+
if captures[2] =~ '}'
" this may be a complete block enclosure on one line
+
" call confirm("if2")
  +
" this may be a complete block enclosure on one line
 
return indent(prev_lnum)
 
else
  +
" call confirm("if3")
 
" a block is starting in the property.
 
return indent(prev_lnum) + &sw
 
endif
  +
" call confirm("if4")
 
elseif captures[0] =~ '^\s*\<\%(var\|def\)\>'
  +
" call confirm("if5")
 
" what we thought was a property-type format was really a
 
" declaration of a variable.
 
return theCIndent
 
elseif current_line =~ '^\s*}'
  +
" call confirm("if6")
 
" the end of the property block
 
return indent(prev_lnum) - &sw
 
elseif captures[0] =~ '['
  +
" call confirm("if7")
 
" the end of the property block
 
return indent(prev_lnum) + &sw
 
else
  +
" call confirm("if8")
 
return indent(prev_lnum)
 
endif
 
" end of property-type format x: y check on prev_line
  +
  +
" call confirm("if9")
 
elseif current_line =~ '^\s*}'
  +
" call confirm("if9a")
 
return indent(prev_lnum) -&sw
 
elseif prev_line =~ '{'
  +
" call confirm("if10")
 
" maybe it's a completely enclosed block.
 
" if so, we can keep the previus indent
 
if prev_line =~ '{[^}]\+}'
  +
" call confirm("if11")
 
return indent(prev_lnum)
 
else
 
return indent(prev_lnum) + &sw
 
endif
  +
 
elseif prev_line =~ '^\s*}'
  +
" call confirm("if12")
 
if current_line =~ '^\s*}'
  +
" call confirm("if13")
  +
"return indent(prev_lnum) -&sw
 
"return theCIndent
  +
else
  +
" call confirm("if14")
  +
return indent(prev_lnum)
 
endif
  +
elseif match(current_line, s:property_regex) > -1
  +
" call confirm("if15")
 
return indent(prev_lnum)
 
return indent(prev_lnum)
else
 
" a block is starting in the property.
 
return indent(prev_lnum) + &sw
 
endif
 
elseif captures[0] =~ '^\s*\%(\<var\>\|\<def\>\)'
 
" what we thought was a property-type format was really a
 
" declaration of a variable.
 
return theCIndent
 
elseif getline(v:lnum) =~ '^\s*}'
 
" the end of the property block
 
return indent(prev_lnum) - &sw
 
elseif captures[0] =~ '['
 
" the end of the property block
 
return indent(prev_lnum) + &sw
 
else
 
return indent(prev_lnum)
 
 
endif
 
endif
  +
" end of property-type format x: y check
 
  +
" call confirm('normal flow')
elseif getline(prev_lnum) =~ '{'
 
  +
return theCIndent
" maybe it's a completely enclosed block.
 
" if so, we can keep the previus indent
 
if getline(prev_lnum) =~ '{[^}]\+}'
 
return indent(prev_lnum)
 
else
 
return indent(prev_lnum) + &sw
 
endif
 
elseif getline(prev_lnum) =~ '^\s*}'
 
if getline(v:lnum) =~ '^\s*}'
 
return indent(prev_lnum) -&sw
 
else
 
return indent(prev_lnum)
 
endif
 
endif
 
return theCIndent
 
 
endfunction
 
endfunction
  +
   
 
" Set the function to do the work.
 
" Set the function to do the work.
 
setlocal indentexpr=GetFxIndent()
 
setlocal indentexpr=GetFxIndent()
</pre>
 
   
==Comments==
 
This tip arose from a [http://groups.google.com/group/vim_dev/browse_thread/thread/701e01b871760def discussion] on the vim_dev mailing list. The aim of posting the script here is to seek feedback to improve the code. [[User:Black panda|Black panda]] may decide to upload the plugin to vim.org/scripts, and in three months or so, we can evaluate whether to keep this script here. Please make any fixes to the code, or add comments on the [[Talk:JavaFX indent plugin|talk page]]. [[User:JohnBeckett|JohnBeckett]] 04:24, October 8, 2009 (UTC)
 
   
   
 
</pre>
   
 
==Comments==
I think line 14
 
 
This tip arose from a [http://groups.google.com/group/vim_dev/browse_thread/thread/701e01b871760def discussion] on the vim_dev mailing list. The aim of posting the script here is to seek feedback to improve the code. [[User:Black panda|Black panda]] may decide to upload the plugin to vim.org/scripts, and in three months or so, we can evaluate whether to keep this script here.
function! s:SkipJavaFxBlanksAndComments(startline)
 
should read as (so no "s:")
 
function! SkipJavaFxBlanksAndComments(startline)
 
:I've fixed that, but the other way around, by adding the missing "s:" at the function calls. -- [[User:Inkarkat|Inkarkat]] 20:40, November 29, 2009 (UTC)
 
   
  +
Please make any fixes to the code, or add comments on the [[Talk:JavaFX indent plugin|'''talk page''']]. [[User:JohnBeckett|JohnBeckett]] 04:24, October 8, 2009 (UTC)
and line 18
 
while getline(lnum) !~ '/\*' && lnum > 1
 
should read as
 
while getline(lnum) !=~ '/\*' && lnum > 1
 
At least after these corrections it worked for me.
 
Thanks for the script!
 
:Really? !=~ is not a valid Vim expression. -- [[User:Inkarkat|Inkarkat]] 20:40, November 29, 2009 (UTC)
 
[[Category:Plugin]]
 

Latest revision as of 05:01, 15 May 2010

Tip 1635 Printable Monobook Previous Next

created October 5, 2009 · complexity basic · author Black panda · version 7.0


Here is the beginning of a script that helps indenting JavaFX source files. JavaFX is a new GUI-based scripting language developed by Sun Microsystems to compete with Adobe Flash and Microsoft Silverlight.

Please help to improve the code so that it can be included as a plugin at Vim scripts.

set debug=msg,throw
if exists("b:did_indent")
  finish
endif

let b:did_indent = 1
setlocal indentkeys=0{,0},0],!^F,o,O,e

"if exists("*GetFxIndent")
"    finish
"endif

" removes JavaFX quoted strings from a line
function! s:removeQuotedStrings(orig_line)
    "todo needs to be more robust
    "right now it barely handles double and single quotes, but
    "there could be code interpolation.
    " see http://java.sun.com/javafx/1/tutorials/core/dataTypes/#string

    let quote1 = matchstr(a:orig_line, "['\"]")

    if empty(quote1)
        return a:orig_line
    endif

    let escaped_quote = '\\' . quote1

    " replace escaped quotes, for example '\\"'
    let line = substitute(a:orig_line, escaped_quote, '__', "g")
"    call confirm('-->' . line)

    " match the quoted token, for example: /'[^']\+'/
    let quote_pattern = quote1 . '[^' . quote1 . ']\+' . quote1

"    call confirm(quote_pattern)
    return substitute(line, quote_pattern, '""', "g")
endfunction


function! s:SkipJavaFxBlanksAndComments(startline)
    let lnum = a:startline
    while lnum > 1
        let lnum = prevnonblank(lnum)
        if getline(lnum) =~ '\*/\s*$'
            while getline(lnum) !~ '/\*' && lnum > 1
                let lnum = lnum - 1
            endwhile
            if getline(lnum) =~ '^\s*/\*'
                let lnum = lnum - 1
            else
                break
            endif
        elseif getline(lnum) =~ '^\s*//'
            let lnum = lnum - 1
        else
            break
        endif
    endwhile
    return lnum
endfunction

" meant to matche the property syntax  x : y
let s:property_regex =  '^\s*\(\%(\i\|\s\)\+\):\(.*\)$'

function! GetFxIndent()
    if v:lnum == 1
        return indent(v:lnum)
    endif
    let theCIndent = cindent(v:lnum)

    " If we're in the middle of a comment or at the end of a java-like
    " statement or block, use cindent
    if getline(v:lnum) =~ '^\s*[\*/;]'
        return theCIndent
    endif

    " find start of previous line, in case it was a continuation line
    let lnum = s:SkipJavaFxBlanksAndComments(v:lnum - 1)
    let prev_lnum = lnum
    while prev_lnum > 1
        let earlier_prev = s:SkipJavaFxBlanksAndComments(prev_lnum - 1)
        if getline(earlier_prev) !~ '\%(\i\|\s\),\s*$'
            break
        endif
        let prev_lnum = earlier_prev
    endwhile

"    call confirm('current indent is: ' . indent(v:lnum) .
"                \     "\ncindent wants it to be: " . theCIndent .
"                \     "\nprevious line num: " . prev_lnum)

    " let's get rid of the contents of the strings in the line.
    let current_line = s:removeQuotedStrings(getline(v:lnum))
    let prev_line = s:removeQuotedStrings(getline(prev_lnum))

"    call confirm('prev_line is: ' . prev_line)
    if current_line =~ '^\s*\]'
        return indent(prev_lnum) - &sw
    endif

    " take care of property-type format x: y
    let captures = matchlist(prev_line, s:property_regex)

    if ! empty(captures)
"        call confirm(string(captures))
        if captures[1] =~ '{' || captures[2] =~ '{'
"            call confirm("if1")
            if captures[2] =~ '}'
"                call confirm("if2")
                " this may be a complete block enclosure on one line
                return indent(prev_lnum)
            else
"                call confirm("if3")
                " a block is starting in the property.
                return indent(prev_lnum)  + &sw
            endif
"            call confirm("if4")
        elseif captures[0] =~ '^\s*\<\%(var\|def\)\>'
"            call confirm("if5")
            " what we thought was a property-type format was really a
            " declaration of a variable.
            return theCIndent
        elseif current_line =~ '^\s*}'
"                call confirm("if6")
            " the end of the property block
            return indent(prev_lnum) - &sw
        elseif captures[0] =~ '['
"            call confirm("if7")
            " the end of the property block
            return indent(prev_lnum) + &sw
        else
"            call confirm("if8")
            return indent(prev_lnum)
        endif
        " end of property-type format x: y check on prev_line

"        call confirm("if9")
    elseif current_line =~ '^\s*}'
"        call confirm("if9a")
        return indent(prev_lnum) -&sw
    elseif prev_line =~ '{'
"        call confirm("if10")
        " maybe it's a completely enclosed block.
        " if so, we can keep the previus indent
        if prev_line =~ '{[^}]\+}'
"            call confirm("if11")
            return indent(prev_lnum)
        else
            return indent(prev_lnum) + &sw
        endif

    elseif prev_line =~ '^\s*}'
"        call confirm("if12")
        if current_line =~  '^\s*}'
"            call confirm("if13")
            "return indent(prev_lnum) -&sw
            "return theCIndent
        else
"            call confirm("if14")
            return indent(prev_lnum)
        endif
    elseif match(current_line, s:property_regex) > -1
"        call confirm("if15")
        return indent(prev_lnum)
    endif

"    call confirm('normal flow')
    return theCIndent
endfunction


" Set the function to do the work.
setlocal indentexpr=GetFxIndent()



Comments[]

This tip arose from a discussion on the vim_dev mailing list. The aim of posting the script here is to seek feedback to improve the code. Black panda may decide to upload the plugin to vim.org/scripts, and in three months or so, we can evaluate whether to keep this script here.

Please make any fixes to the code, or add comments on the talk page. JohnBeckett 04:24, October 8, 2009 (UTC)