" File : EasyHtml.vim
" Last Change: 2001 Dec 02
" Maintainer: Gontran BAERTS
" Version: 0.4
"
" Please don't hesitate to correct my english :)
" Send corrections to
"
"-----------------------------------------------------------------------------
" Description: With EasyHtml, you no longer need to look for tags attributes,
" attributes values or CSS properties values while editing HTML files.
" EasyHtml let you select the right attribute or value by showing you an
" attributes/values list for the tag/attribute/CSS property under the cursor.
"
"-----------------------------------------------------------------------------
" To Enable: Normally, this file will reside in your plugins directory and be
" automatically sourced. If not, you must manually source this file" using :
" source EasyHtml.vim
"
"-----------------------------------------------------------------------------
" Usage: To display the attributes/values list, move the cursor on the
" tag, attribute, or CSS property word and hit key.
" Use :
"
" - h,j,k,l or ,,, keys to change selected
" item.
" - / or , keys scroll list one page
" downward/forward.
" - or select the first item.
" - or select the last item.
" - add selected item and exit from items list.
" - q or to exit without adding selected item.
"
" Deprecated attributes as declared by W3C are red highlighted, while right
" attributes are blue highlighted.
"
" Set g:easyHtmlSplitRight variable to 0 or 1 to open items list at left
" or right of current buffer. By default, use splitright setting.
"
" Set g:eh_singlequote variable to 0 or 1 to use double or single quote when
" adding attributes (For example id="" or id='')
"
" Set g:eh_incsearch variable to 0 or 1 to dis- or en-able incremental list
" search. This feature allows to select an item by typing its beginning. When
" this is enable, 'q', 'h', 'j', 'k' and 'l' keys aren't used to exit from list
" and to move highlighting. Use 'Q', '', '', '' and ''
" instead.
"
"-----------------------------------------------------------------------------
" Updates:
" in version 0.4
" - Added values for the "style" attribute (CSS2 properties)
" - Added values for CSS2 properties
" - and are now usable to move highlight through the list
" - When adding a value for an attribute, current attribute value (if exists)
" is replaced by the selected one, except for "style" attribute for which
" values are append
" - Set g:eh_singlequote variable to 0 or 1 to use double or single quote when
" adding attributes (For example id="" or id='')
"
" in version 0.3
" - Attributes list updated
" - Don't display attributes list for closing tags
" - Now, display values list when hitting with cursor on attribute word
" (for some attributes only).
"
" in version 0.2.1
" - Fix global modifiable setting instead of local
"
" in version 0.2
" - Attributes list is now alphabetically sorted
" - Hitting allows to display attributes list in Insert mode too
" - Allows to select an attribute by incremental search :-)
" For example, with tag, typing "onk" (normal mode) in the attributes
" list buffer automatically select "onkeydown" attribute. Use backspace
" () to remove characters. This behavior is enable by setting
" g:eh_incsearch variable to 1. Warning : when incremental attribute search
" is on, 'q', 'h', 'j', 'k' and 'l' keys aren't used to exit from list and
" to move highlighting. Use 'Q', '', '', '' and ''
" instead.
" - Check for attributes list already opened, and reuse it
"
" in version 0.1
" - First version " Has this already been loaded ?
if exists("loaded_easyhtml")
finish
endif
let loaded_easyhtml=1
if !exists("g:easyHtmlSplitRight")
let g:easyHtmlSplitRight = &splitright
endif
if !exists("g:eh_incsearch")
let g:eh_incsearch = 0
endif
if !exists("g:eh_singlequote")
let g:eh_singlequote = 0
endif
:nmap :call LaunchEasyHtml()
:imap :call LaunchEasyHtml()
"**
" Script Variables:
"**
let s:srch = ""
let s:maxAttrLength = 0
let s:currentPos = 2
" HTML tags and their attributs
let s:coreattrs = "id=\"\" class=\"\" style=\"\" title=\"\""
let s:i18n = "lang=\"\" dir=\"\""
let s:events = "onclick=\"\" ondblclick=\"\" onmousedown=\"\" onmouseup=\"\" onmouseover=\"\" onmousemove=\"\" onmouseout=\"\" onkeypress=\"\" onkeydown=\"\" onkeyup=\"\""
let s:cellhalign = "align=\"\" char=\"\" charoff=\"\""
let s:cellvalign = "valign=\"\""
let s:attrs = "%coreattrs %i18n %events"
let s:HTMLTags = " pivot
let d = d - 1
endwhile
if g != d
let tabEnt = ReplaceListItem( tabEnt, g, GetListItem( tabEnt, d ) )
let tabEnt = ReplaceListItem( tabEnt, d, pivot )
let g = g + 1
endif
while GetListItem( tabEnt, g ) < pivot
let g = g + 1
endwhile
if g != d
let tabEnt = ReplaceListItem( tabEnt, d, GetListItem( tabEnt, g ) )
let tabEnt = ReplaceListItem( tabEnt, g, pivot )
let d = d - 1
endif
endwhile
if a:deb < g-1
let tabEnt = QuickSortList( tabEnt, a:deb, g-1 )
endif
if a:fin > g+1
let tabEnt = QuickSortList( tabEnt, g+1, a:fin )
endif
return tabEnt
endfunction
"**
" LaunchEasyHtml:
" Search if there are attributs for word under cursor, and display them in a
" new buffer.
"**
function! LaunchEasyHtml()
" Look for attributs for the current word
call s:SearchAttributes()
" If the longest attribut length is 0, there is no attribut for the
" current word
if s:maxAttrLength == 0
echohl ErrorMsg
echo "No attributes\\values found. (If it's a closing tag, try on opening tag.)"
echohl NONE
return
endif
" Is there an attributs list already running ?
let BufNr = bufnr( '--\ EasyHtml\ --' )
if BufNr != -1
let CurBufNr = bufnr("%")
while CurBufNr != BufNr
wincmd w
let CurBufNr = bufnr("%")
endwhile
else
" Save the user's settings for splitright
let savesplitright = &splitright
" Configure vertical splitting side
let &splitright = g:easyHtmlSplitRight
" Open new vertical window with right size
execute s:maxAttrLength . 'vnew --\ EasyHtml\ --'
" Restore user settings
let &splitright = savesplitright
" Turn off the swapfile, set the buffer type so that it won't get
" written, and so that it will get deleted when it gets hidden.
setlocal modifiable
setlocal noswapfile
setlocal buftype=nowrite
setlocal bufhidden=delete
setlocal nonumber
" Don't wrap around long lines
setlocal nowrap
" No need for any insertmode abbreviations, since we don't allow
" insertions anyway!
iabc
" Highlighting
syntax match selectedAttribut /^<.*>$/
syntax match deprecatedAttribut /^(.*)$/
syntax match hiddenX /X/
hi selectedAttribut guibg=lightblue guifg=black
hi deprecatedAttribut guibg=lightred guifg=black
let color= s:GetBgColor()
if color != ""
exe "hi hiddenX guibg=" . color . " guifg=" . color
endif
" Set up mappings for this buffer
nnoremap :call MoveSelect( line(".")-1 )
nnoremap :call MoveSelect( line(".")-1 )
nnoremap :call MoveSelect( line(".")+1 )
nnoremap :call MoveSelect( line(".")+1 )
nnoremap :call PageUp()
nnoremap :call PageDown()
nnoremap :call MoveSelect( 1 )
nnoremap :call MoveSelect( line("$") )
nnoremap :call MoveSelect( 1 )
nnoremap :call MoveSelect( line("$") )
nnoremap :call AddItem()
nnoremap <2-LeftMouse> :call AddItem()
nnoremap :call CloseWindow()
" If incremental search required, initialize it
if( g:eh_incsearch == 1 )
nnoremap Q :call CloseWindow()
nnoremap :call SelectSearch( "" )
let char = 97
while char < 123
exe "nnoremap " . nr2char(char) . " :call SelectSearch( '" . nr2char(char) . "' )"
let char = char + 1
endwhile
else
nnoremap h :call MoveSelect( line(".")-1 )
nnoremap k :call MoveSelect( line(".")-1 )
nnoremap l :call MoveSelect( line(".")+1 )
nnoremap j :call MoveSelect( line(".")+1 )
nnoremap q :call CloseWindow()
endif
endif
" Reset incremental search
let s:srch = ""
" Fill attributs list
call s:ShowAttributes()
" User don't need to modify content
setlocal nomodifiable
endfunction
"**
" SearchAttributes:
" Look for attributs for word under cursor. tr
"**
function! s:SearchAttributes()
" Ignore case
let l:CurrentCase = &ignorecase
set ignorecase
let l:CurrentIkw = &iskeyword
let s:attributs = ""
let s:maxAttrLength = 0
let s:listSep = ","
let l:attributsLine = ""
setlocal iskeyword +=<
if match( expand(""), '^<' ) == 0 " Is it a tag ?
let s:itemtype = "T" " Yes, a tag
let l:attributsLine = GetListMatchItem( s:HTMLTags, expand("") . ' ' )
else
setlocal iskeyword -=<
setlocal iskeyword +=-,=
if match( expand(""), '=$' ) != -1 " or an attribute ?
let s:itemtype = "A" " Yes, an attribute
let l:attributsLine = GetListMatchItem( s:TagsAttributs, expand("") . '" ' )
else
setlocal iskeyword -==
setlocal iskeyword +=:
if match( expand(""), ':' ) != -1 " or a CSS property ?
let s:itemtype = "C" " Yes, a CSS property
let l:attributsLine = GetListMatchItem( s:CSSProperties, '\<' . matchstr( expand(""), '^.\{-}:' ) . ' ' )
endif
endif
endif
if l:attributsLine != ""
let s:listSep = " "
let l:attributsLine = RemoveListItem( l:attributsLine, 0 )
if l:attributsLine != ""
" Attributes values are already sorted and expanded
if s:itemtype != "A"
" Insert %xxxx variables content
let l:attribut = matchstr( l:attributsLine, '%[^ ]\+' )
while l:attribut != ""
exe "let l:attributsLine = substitute( l:attributsLine, '" .l:attribut. "', s:" . strpart( l:attribut, 1 ) . ", '')"
let l:attribut = matchstr( l:attributsLine, '%[^ ]\+' )
endwhile " Sort items
let l:attributsLine = QuickSortList( l:attributsLine, 0, GetListCount(l:attributsLine)-1 )
endif
let l:attribut = GetListItem( l:attributsLine, 0 )
while l:attribut != ""
" Keep max length
if s:maxAttrLength < strlen( l:attribut )
let s:maxAttrLength = strlen( l:attribut )
endif
" Remove current attribut
let l:attributsLine = RemoveListItem( l:attributsLine, 0 )
" Is it a depracated attribute ?
set noignorecase
if l:attribut =~ "-D"
let l:attribut = substitute( l:attribut, "-D", "", "")
let s:attributs = s:attributs . "X" . l:attribut . " \n"
else
let s:attributs = s:attributs . " " . l:attribut . " \n"
endif
" Next attribut
let l:attribut = GetListItem( l:attributsLine, 0 )
endwhile
endif
" If longest attribute size is zero, then there is no attribute
" for this tag
if s:maxAttrLength != 0
let s:maxAttrLength = s:maxAttrLength + 2
endif
endif
let &iskeyword = l:CurrentIkw
let &ignorecase = l:CurrentCase
endfunction
"**
" ShowAttributes:
" Display attributs list in current buffer.
"**
function! s:ShowAttributes()
" Prevent a report of our actions from showing up
let oldRep=&report
let save_sc = &sc
set report=10000 nosc
setlocal modifiable
" Erase content
%delete
" Put content of register f after the cursor
put! =s:attributs
" Erase last line
exe "normal G"
d
" Move to first item
call s:MoveSelect(1)
set nomodifiable
" Restore config
let &report=oldRep
let &sc = save_sc
endfunction
"**
" AddItem:
" Add selected item to tag/attribute/CSS2 property.
"**
function! s:AddItem()
let l:CurrentCase = &ignorecase
set noignorecase
" Get attribute and clean it
let save_f=@f
let @f = substitute( getline("."), '[<>X]', '', "g" )
let @f = substitute( @f, '^(', '', "g" )
let @f = substitute( @f, ' \+)$', '', "g" )
let @f = substitute( @f, ' ', '', "g" )
let &ignorecase = l:CurrentCase
" Go to previous window
wincmd p
" if it's a tag, put attribute at end of tag
if s:itemtype == "T"
if g:eh_singlequote == 1
let @f = substitute( @f , '"', "'", 'g' )
endif
let @f = ' ' . @f
exec 'normal f>"fP'
elseif s:itemtype == "A" " If it's an attribute ...
if g:eh_singlequote == 0
let quote = '"'
else
let quote = "'"
endif
if expand("") !~ 'style' " ... append selected value to it for style
exec 'normal 2f' .quote. 'dT' .quote. '"fP'
else " ... or replace current value by selected value
exec 'normal f' .quote. '"fp'
endif
elseif s:itemtype == "C" " If it's an CSS property, add value to it
exec 'normal f:"fgp'
endif
startinsert
" Return to attributes window
wincmd p
let @f=save_f
" Close window
call s:CloseWindow()
endfunction
"**
" MoveSelect:
" Move highlight to line newLineNumber.
"
" Parameter:
" newLineNumber line number to highlight.
"**
function! s:MoveSelect( newLineNumber )
if( a:newLineNumber < 1 || a:newLineNumber > line("$") )
return
endif
setlocal modifiable
" Restore current line
if( exists("s:currentLine") )
call setline( ".", s:currentLine )
endif
" Go to new line
let s:currentPos = a:newLineNumber
exec s:currentPos
" Save new current line
let s:currentLine = getline(".")
let modifiedLine = s:currentLine
" Complete string with spaces
let len = strlen(l:modifiedLine)
while len < s:maxAttrLength
let modifiedLine = modifiedLine . " "
let len = len + 1
endwhile
" Is it a deprecated attribute marked with 'X' ?
if l:modifiedLine =~ "^X"
let modifiedLine = substitute( modifiedLine, "^X", "(", "" )
let modifiedLine = substitute( modifiedLine, " $", ")", "" )
else
let modifiedLine = substitute( modifiedLine, "^ ", "<", "" )
let modifiedLine = substitute( modifiedLine, " $", ">", "" )
endif
call setline( ".", l:modifiedLine )
setlocal nomodifiable
endfunction
"**
" PageDown:
" Move highlight one page down.
"**
function! s:PageDown()
exe "normal L"
let pos = line(".")
exe "normal ''"
call s:MoveSelect( pos )
exe "normal zt"
endfunction
"**
" PageUp:
" Move highlight one page up.
"**
function! s:PageUp()
exe "normal H"
let pos = line(".")
exe "normal ''"
call s:MoveSelect( pos )
exe "normal zb"
endfunction
"**
" CloseWindow:
" Clear unused variables and highlights, reinit variables for next use and
" close current window.
"**
function! s:CloseWindow()
unlet s:currentLine
unlet s:attributs
let s:maxAttrLength = 0
let s:currentPos = 2
highlight clear selectedAttribut
highlight clear deprecatedAttribut
highlight clear hiddenX
wincmd q
endfunction
"**
" GetBgColor:
" Try to get background color (may be not sure)
"**
function! s:GetBgColor()
let bgColor = synIDattr(synIDtrans(synID(1, 1, 1)), "bg")
if bgColor == ""
if &background == "light"
let bgColor = "white"
else
let bgColor = "black"
endif
endif
return bgColor
endfunction
"**
" SelectSearch:
" Used for incremental attribut search
"
" Parameter:
" Char character to add to current search pattern
"**
function! s:SelectSearch( char )
if a:char == "" && s:srch != ""
let s:srch = strpart( s:srch, 0, strlen( s:srch )-1 )
else
let s:srch = s:srch . a:char
endif
let linenr = line(".")
if s:srch != ""
1
let findlinenr = search( '\(\<\|X\)'.s:srch, "W" )
exe ":".linenr
if findlinenr != 0
echo "Attributs search : " . s:srch
call s:MoveSelect( findlinenr )
else
echohl ErrorMsg
echo "No attribut for \"" . s:srch . "\" (use backspace)"
echohl NONE
endif
endif
endfunction