Subversion Repositories programming

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
252 ira 1
" Vim script file                                           vim600:fdm=marker:
2
" FileType:     XML
3
" Author:       Devin Weaver <vim (at) tritarget.com> 
4
" Maintainer:   Devin Weaver <vim (at) tritarget.com>
5
" Last Change:  $Date: 2005/05/14 22:13:22 $
6
" Version:      $Revision: 1.29 $
7
" Location:     http://www.vim.org/scripts/script.php?script_id=301
8
" Licence:      This program is free software; you can redistribute it
9
"               and/or modify it under the terms of the GNU General Public
10
"               License.  See http://www.gnu.org/copyleft/gpl.txt
11
" Credits:      Brad Phelan <bphelan (at) mathworks.co.uk> for completing
12
"                 tag matching and visual tag completion.
13
"               Ma, Xiangjiang <Xiangjiang.Ma (at) broadvision.com> for
14
"                 pointing out VIM 6.0 map <buffer> feature.
15
"               Luc Hermitte <hermitte (at) free.fr> for testing the self
16
"                 install documentation code and providing good bug fixes.
17
"               Guo-Peng Wen for the self install documentation code.
18
 
19
" This script provides some convenience when editing XML (and some SGML)
20
" formated documents.
21
 
22
" Section: Documentation 
23
" ----------------------
24
"
25
" Documentation should be available by ":help xml-plugin" command, once the
26
" script has been copied in you .vim/plugin directory.
27
"
28
" You still can read the documentation at the end of this file. Locate it by
29
" searching the "xml-plugin" string (and set ft=help to have
30
" appropriate syntaxic coloration). 
31
 
32
" Note: If you used the 5.x version of this file (xmledit.vim) you'll need to
33
" comment out the section where you called it since it is no longer used in
34
" version 6.x. 
35
 
36
" TODO: Revamp ParseTag to pull appart a tag a rebuild it properly.
37
" a tag like: <  test  nowrap  testatt=foo   >
38
" should be fixed to: <test nowrap="nowrap" testatt="foo"></test>
39
 
40
"==============================================================================
41
 
42
" Only do this when not done yet for this buffer
43
if exists("b:did_ftplugin")
44
  finish
45
endif
46
let b:did_ftplugin = 1
47
 
48
" WrapTag -> Places an XML tag around a visual selection.            {{{1
49
" Brad Phelan: Wrap the argument in an XML tag
50
" Added nice GUI support to the dialogs. 
51
" Rewrote function to implement new algorythem that addresses several bugs.
52
if !exists("*s:WrapTag") 
53
function s:WrapTag(text)
54
    if (line(".") < line("'<"))
55
        let insert_cmd = "o"
56
    elseif (col(".") < col("'<"))
57
        let insert_cmd = "a"
58
    else
59
        let insert_cmd = "i"
60
    endif
61
    if strlen(a:text) > 10
62
        let input_text = strpart(a:text, 0, 10) . '...'
63
    else
64
        let input_text = a:text
65
    endif
66
    let wraptag = inputdialog('Tag to wrap "' . input_text . '" : ')
67
    if strlen(wraptag)==0
68
        if strlen(b:last_wrap_tag_used)==0
69
            undo
70
            return
71
        endif
72
        let wraptag = b:last_wrap_tag_used
73
        let atts = b:last_wrap_atts_used
74
    else
75
        let atts = inputdialog('Attributes in <' . wraptag . '> : ')
76
    endif
77
    if (visualmode() ==# 'V')
78
        let text = strpart(a:text,0,strlen(a:text)-1)
79
        if (insert_cmd ==# "o")
80
            let eol_cmd = ""
81
        else
82
            let eol_cmd = "\<Cr>"
83
        endif
84
    else
85
        let text = a:text
86
        let eol_cmd = ""
87
    endif
88
    if strlen(atts)==0
89
        let text = "<".wraptag.">".text."</".wraptag.">"
90
        let b:last_wrap_tag_used = wraptag
91
        let b:last_wrap_atts_used = ""
92
    else
93
        let text = "<".wraptag." ".atts.">".text."</".wraptag.">"
94
        let b:last_wrap_tag_used = wraptag
95
        let b:last_wrap_atts_used = atts
96
    endif
97
    execute "normal! ".insert_cmd.text.eol_cmd
98
endfunction
99
endif
100
 
101
" NewFileXML -> Inserts <?xml?> at top of new file.                  {{{1
102
if !exists("*s:NewFileXML")
103
function s:NewFileXML( )
104
    " Where is g:did_xhtmlcf_inits defined?
105
    if &filetype == 'xml' || (!exists ("g:did_xhtmlcf_inits") && exists ("g:xml_use_xhtml") && (&filetype == 'html' || &filetype == 'xhtml'))
106
        if append (0, '<?xml version="1.0"?>')
107
            normal! G
108
        endif
109
    endif
110
endfunction
111
endif
112
 
113
 
114
" Callback -> Checks for tag callbacks and executes them.            {{{1
115
if !exists("*s:Callback")
116
function s:Callback( xml_tag, isHtml )
117
    let text = 0
118
    if a:isHtml == 1 && exists ("*HtmlAttribCallback")
119
        let text = HtmlAttribCallback (a:xml_tag)
120
    elseif exists ("*XmlAttribCallback")
121
        let text = XmlAttribCallback (a:xml_tag)
122
    endif       
123
    if text != '0'
124
        execute "normal! i " . text ."\<Esc>l"
125
    endif
126
endfunction
127
endif
128
 
129
 
130
" IsParsableTag -> Check to see if the tag is a real tag.            {{{1
131
if !exists("*s:IsParsableTag")
132
function s:IsParsableTag( tag )
133
    " The "Should I parse?" flag.
134
    let parse = 1
135
 
136
    " make sure a:tag has a proper tag in it and is not a instruction or end tag.
137
    if a:tag !~ '^<[[:alnum:]_:\-].*>$'
138
        let parse = 0
139
    endif
140
 
141
    " make sure this tag isn't already closed.
142
    if strpart (a:tag, strlen (a:tag) - 2, 1) == '/'
143
        let parse = 0
144
    endif
145
 
146
    return parse
147
endfunction
148
endif
149
 
150
 
151
" ParseTag -> The major work hourse for tag completion.              {{{1
152
if !exists("*s:ParseTag")
153
function s:ParseTag( )
154
    " Save registers
155
    let old_reg_save = @"
156
    let old_save_x   = @x
157
 
158
    if (!exists("g:xml_no_auto_nesting") && strpart (getline ("."), col (".") - 2, 2) == '>>')
159
        let multi_line = 1
160
        execute "normal! \"xX"
161
    else
162
        let multi_line = 0
163
    endif
164
 
165
    let @" = ""
166
    execute "normal! \"xy%%"
167
    let ltag = @"
168
    if (&filetype == 'html' || &filetype == 'xhtml') && (!exists ("g:xml_no_html"))
169
        let html_mode = 1
170
        let ltag = substitute (ltag, '[^[:graph:]]\+', ' ', 'g')
171
        let ltag = substitute (ltag, '<\s*\([^[:alnum:]_:\-[:blank:]]\=\)\s*\([[:alnum:]_:\-]\+\)\>', '<\1\2', '')
172
    else
173
        let html_mode = 0
174
    endif
175
 
176
    if <SID>IsParsableTag (ltag)
177
        " find the break between tag name and atributes (or closing of tag)
178
        " Too bad I can't just grab the position index of a pattern in a string.
179
        let index = 1
180
        while index < strlen (ltag) && strpart (ltag, index, 1) =~ '[[:alnum:]_:\-]'
181
            let index = index + 1
182
        endwhile
183
 
184
        let tag_name = strpart (ltag, 1, index - 1)
185
        if strpart (ltag, index) =~ '[^/>[:blank:]]'
186
            let has_attrib = 1
187
        else
188
            let has_attrib = 0
189
        endif
190
 
191
        " That's (index - 1) + 2, 2 for the '</' and 1 for the extra character the
192
        " while includes (the '>' is ignored because <Esc> puts the curser on top
193
        " of the '>'
194
        let index = index + 2
195
 
196
        " print out the end tag and place the cursor back were it left off
197
        if html_mode && tag_name =~? '^\(img\|input\|param\|frame\|br\|hr\|meta\|link\|base\|area\)$'
198
            if has_attrib == 0
199
                call <SID>Callback (tag_name, html_mode)
200
            endif
201
            if exists ("g:xml_use_xhtml")
202
                execute "normal! i /\<Esc>l"
203
            endif
204
        else
205
            if multi_line
206
                " Can't use \<Tab> because that indents 'tabstop' not 'shiftwidth'
207
                " Also >> doesn't shift on an empty line hence the temporary char 'x'
208
                let com_save = &comments
209
                set comments-=n:>
210
                execute "normal! a\<Cr>\<Cr>\<Esc>kAx\<Esc>>>$\"xx"
211
                execute "set comments=" . com_save
212
 
213
                " restore registers
214
                let @" = old_reg_save
215
                let @x = old_save_x
216
 
217
                startinsert!
218
                return ""
219
            else
220
                if has_attrib == 0
221
                    call <SID>Callback (tag_name, html_mode)
222
                endif
223
                execute "normal! a</" . tag_name . ">\<Esc>" . index . "h"
224
            endif
225
        endif
226
    endif
227
 
228
    " restore registers
229
    let @" = old_reg_save
230
    let @x = old_save_x
231
 
232
    if col (".") < strlen (getline ("."))
233
        execute "normal! l"
234
        startinsert
235
    else
236
        startinsert!
237
    endif
238
endfunction
239
endif
240
 
241
 
242
" ParseTag2 -> Experimental function to replace ParseTag             {{{1
243
"if !exists("*s:ParseTag2")
244
"function s:ParseTag2( )
245
    " My thought is to pull the tag out and reformat it to a normalized tag
246
    " and put it back.
247
"endfunction
248
"endif
249
 
250
 
251
" BuildTagName -> Grabs the tag's name for tag matching.             {{{1
252
if !exists("*s:BuildTagName")
253
function s:BuildTagName( )
254
  "First check to see if we Are allready on the end of the tag. The / search
255
  "forwards command will jump to the next tag otherwise
256
 
257
  " Store contents of register x in a variable
258
  let b:xreg = @x 
259
 
260
  exec "normal! v\"xy"
261
  if @x=='>'
262
     " Don't do anything
263
  else
264
     exec "normal! />/\<Cr>"
265
  endif
266
 
267
  " Now we head back to the < to reach the beginning.
268
  exec "normal! ?<?\<Cr>"
269
 
270
  " Capture the tag (a > will be catured by the /$/ match)
271
  exec "normal! v/\\s\\|$/\<Cr>\"xy"
272
 
273
  " We need to strip off any junk at the end.
274
  let @x=strpart(@x, 0, match(@x, "[[:blank:]>\<C-J>]"))
275
 
276
  "remove <, >
277
  let @x=substitute(@x,'^<\|>$','','')
278
 
279
  " remove spaces.
280
  let @x=substitute(@x,'/\s*','/', '')
281
  let @x=substitute(@x,'^\s*','', '')
282
 
283
  " Swap @x and b:xreg
284
  let temp = @x
285
  let @x = b:xreg
286
  let b:xreg = temp
287
endfunction
288
endif
289
 
290
" TagMatch1 -> First step in tag matching.                           {{{1 
291
" Brad Phelan: First step in tag matching.
292
if !exists("*s:TagMatch1")
293
function s:TagMatch1()
294
  " Save registers
295
  let old_reg_save = @"
296
 
297
  "Drop a marker here just in case we have a mismatched tag and
298
  "wish to return (:mark looses column position)
299
  normal! mz
300
 
301
  call <SID>BuildTagName()
302
 
303
  "Check to see if it is an end tag. If it is place a 1 in endtag
304
  if match(b:xreg, '^/')==-1
305
    let endtag = 0
306
  else
307
    let endtag = 1  
308
  endif
309
 
310
 " Extract the tag from the whole tag block
311
 " eg if the block =
312
 "   tag attrib1=blah attrib2=blah
313
 " we will end up with 
314
 "   tag
315
 " with no trailing or leading spaces
316
 let b:xreg=substitute(b:xreg,'^/','','g')
317
 
318
 " Make sure the tag is valid.
319
 " Malformed tags could be <?xml ?>, <![CDATA[]]>, etc.
320
 if match(b:xreg,'^[[:alnum:]_:\-]') != -1
321
     " Pass the tag to the matching 
322
     " routine
323
     call <SID>TagMatch2(b:xreg, endtag)
324
 endif
325
 " Restore registers
326
 let @" = old_reg_save
327
endfunction
328
endif
329
 
330
 
331
" TagMatch2 -> Second step in tag matching.                          {{{1
332
" Brad Phelan: Second step in tag matching.
333
if !exists("*s:TagMatch2")
334
function s:TagMatch2(tag,endtag)
335
  let match_type=''
336
 
337
  " Build the pattern for searching for XML tags based
338
  " on the 'tag' type passed into the function.
339
  " Note we search forwards for end tags and
340
  " backwards for start tags
341
  if a:endtag==0
342
     "let nextMatch='normal /\(<\s*' . a:tag . '\(\s\+.\{-}\)*>\)\|\(<\/' . a:tag . '\s*>\)'
343
     let match_type = '/'
344
  else
345
     "let nextMatch='normal ?\(<\s*' . a:tag . '\(\s\+.\{-}\)*>\)\|\(<\/' . a:tag . '\s*>\)'
346
     let match_type = '?'
347
  endif
348
 
349
  if a:endtag==0
350
     let stk = 1 
351
  else
352
     let stk = 1
353
  end
354
 
355
 " wrapscan must be turned on. We'll recored the value and reset it afterward.
356
 " We have it on because if we don't we'll get a nasty error if the search hits
357
 " BOF or EOF.
358
 let wrapval = &wrapscan
359
 let &wrapscan = 1
360
 
361
  "Get the current location of the cursor so we can 
362
  "detect if we wrap on ourselves
363
  let lpos = line(".")
364
  let cpos = col(".")
365
 
366
  if a:endtag==0
367
      " If we are trying to find a start tag
368
      " then decrement when we find a start tag
369
      let iter = 1
370
  else
371
      " If we are trying to find an end tag
372
      " then increment when we find a start tag
373
      let iter = -1
374
  endif
375
 
376
  "Loop until stk == 0. 
377
  while 1 
378
     " exec search.
379
     " Make sure to avoid />$/ as well as /\s$/ and /$/.
380
     exec "normal! " . match_type . '<\s*\/*\s*' . a:tag . '\([[:blank:]>]\|$\)' . "\<Cr>"
381
 
382
     " Check to see if our match makes sence.
383
     if a:endtag == 0
384
         if line(".") < lpos
385
             call <SID>MisMatchedTag (0, a:tag)
386
             break
387
         elseif line(".") == lpos && col(".") <= cpos
388
             call <SID>MisMatchedTag (1, a:tag)
389
             break
390
         endif
391
     else
392
         if line(".") > lpos
393
             call <SID>MisMatchedTag (2, '/'.a:tag)
394
             break
395
         elseif line(".") == lpos && col(".") >= cpos
396
             call <SID>MisMatchedTag (3, '/'.a:tag)
397
             break
398
         endif
399
     endif
400
 
401
     call <SID>BuildTagName()
402
 
403
     if match(b:xreg,'^/')==-1
404
        " Found start tag
405
        let stk = stk + iter 
406
     else
407
        " Found end tag
408
        let stk = stk - iter
409
     endif
410
 
411
     if stk == 0
412
        break
413
     endif    
414
  endwhile
415
 
416
  let &wrapscan = wrapval
417
endfunction
418
endif
419
 
420
" MisMatchedTag -> What to do if a tag is mismatched.                {{{1
421
if !exists("*s:MisMatchedTag")
422
function s:MisMatchedTag( id, tag )
423
    "Jump back to our formor spot
424
    normal! `z
425
    normal zz
426
    echohl WarningMsg
427
    " For debugging
428
    "echo "Mismatched tag " . a:id . ": <" . a:tag . ">"
429
    " For release
430
    echo "Mismatched tag <" . a:tag . ">"
431
    echohl None
432
endfunction
433
endif
434
 
435
" DeleteTag -> Deletes surrounding tags from cursor.                 {{{1
436
" Modifies mark z
437
if !exists("*s:DeleteTag")
438
function s:DeleteTag( )
439
    if strpart (getline ("."), col (".") - 1, 1) == "<"
440
        normal! l
441
    endif
442
    if search ("<[^\/]", "bW") == 0
443
        return
444
    endif
445
    normal! mz
446
    normal \5
447
    normal! d%`zd%
448
endfunction
449
endif
450
 
451
" VisualTag -> Selects Tag body in a visual selection.                {{{1
452
" Modifies mark z
453
if !exists("*s:VisualTag")
454
function s:VisualTag( ) 
455
    if strpart (getline ("."), col (".") - 1, 1) == "<"
456
	normal! l
457
    endif
458
    if search ("<[^\/]", "bW") == 0
459
	return
460
    endif
461
    normal! mz
462
    normal \5
463
    normal! %
464
    exe "normal! " . visualmode()
465
    normal! `z
466
endfunction
467
endif
468
 
469
" Section: Doc installation {{{1
470
" Function: s:XmlInstallDocumentation(full_name, revision)              {{{2
471
"   Install help documentation.
472
" Arguments:
473
"   full_name: Full name of this vim plugin script, including path name.
474
"   revision:  Revision of the vim script. #version# mark in the document file
475
"              will be replaced with this string with 'v' prefix.
476
" Return:
477
"   1 if new document installed, 0 otherwise.
478
" Note: Cleaned and generalized by guo-peng Wen
479
"'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
480
 
481
function! s:XmlInstallDocumentation(full_name, revision)
482
    " Name of the document path based on the system we use:
483
    if (has("unix"))
484
        " On UNIX like system, using forward slash:
485
        let l:slash_char = '/'
486
        let l:mkdir_cmd  = ':silent !mkdir -p '
487
    else
488
        " On M$ system, use backslash. Also mkdir syntax is different.
489
        " This should only work on W2K and up.
490
        let l:slash_char = '\'
491
        let l:mkdir_cmd  = ':silent !mkdir '
492
    endif
493
 
494
    let l:doc_path = l:slash_char . 'doc'
495
    "let l:doc_home = l:slash_char . '.vim' . l:slash_char . 'doc'
496
 
497
    " Figure out document path based on full name of this script:
498
    let l:vim_plugin_path = fnamemodify(a:full_name, ':h')
499
    "let l:vim_doc_path   = fnamemodify(a:full_name, ':h:h') . l:doc_path
500
    let l:vim_doc_path    = matchstr(l:vim_plugin_path, 
501
            \ '.\{-}\ze\%(\%(ft\)\=plugin\|macros\)') . l:doc_path
502
    if (!(filewritable(l:vim_doc_path) == 2))
503
        echomsg "Doc path: " . l:vim_doc_path
504
        execute l:mkdir_cmd . l:vim_doc_path
505
        if (!(filewritable(l:vim_doc_path) == 2))
506
            " Try a default configuration in user home:
507
            "let l:vim_doc_path = expand("~") . l:doc_home
508
            let l:vim_doc_path = matchstr(&rtp,
509
                  \ escape($HOME, '\') .'[/\\]\%(\.vim\|vimfiles\)')
510
            if (!(filewritable(l:vim_doc_path) == 2))
511
                execute l:mkdir_cmd . l:vim_doc_path
512
                if (!(filewritable(l:vim_doc_path) == 2))
513
                    " Put a warning:
514
                    echomsg "Unable to open documentation directory"
515
                    echomsg " type :help add-local-help for more informations."
516
                    return 0
517
                endif
518
            endif
519
        endif
520
    endif
521
 
522
    " Exit if we have problem to access the document directory:
523
    if (!isdirectory(l:vim_plugin_path)
524
        \ || !isdirectory(l:vim_doc_path)
525
        \ || filewritable(l:vim_doc_path) != 2)
526
        return 0
527
    endif
528
 
529
    " Full name of script and documentation file:
530
    let l:script_name = 'xml.vim'
531
    let l:doc_name    = 'xml-plugin.txt'
532
    let l:plugin_file = l:vim_plugin_path . l:slash_char . l:script_name
533
    let l:doc_file    = l:vim_doc_path    . l:slash_char . l:doc_name
534
 
535
    " Bail out if document file is still up to date:
536
    if (filereadable(l:doc_file)  &&
537
        \ getftime(l:plugin_file) < getftime(l:doc_file))
538
        return 0
539
    endif
540
 
541
    " Prepare window position restoring command:
542
    if (strlen(@%))
543
        let l:go_back = 'b ' . bufnr("%")
544
    else
545
        let l:go_back = 'enew!'
546
    endif
547
 
548
    " Create a new buffer & read in the plugin file (me):
549
    setl nomodeline
550
    exe 'enew!'
551
    exe 'r ' . l:plugin_file
552
 
553
    setl modeline
554
    let l:buf = bufnr("%")
555
    setl noswapfile modifiable
556
 
557
    norm zR
558
    norm gg
559
 
560
    " Delete from first line to a line starts with
561
    " === START_DOC
562
    1,/^=\{3,}\s\+START_DOC\C/ d
563
 
564
    " Delete from a line starts with
565
    " === END_DOC
566
    " to the end of the documents:
567
    /^=\{3,}\s\+END_DOC\C/,$ d
568
 
569
    " Remove fold marks:
570
    % s/{\{3}[1-9]/    /
571
 
572
    " Add modeline for help doc: the modeline string is mangled intentionally
573
    " to avoid it be recognized by VIM:
574
    call append(line('$'), '')
575
    call append(line('$'), ' v' . 'im:tw=78:ts=8:ft=help:norl:')
576
 
577
    " Replace revision:
578
    exe "normal :1,5s/#version#/ v" . a:revision . "/\<CR>"
579
 
580
    " Save the help document:
581
    exe 'w! ' . l:doc_file
582
    exe l:go_back
583
    exe 'bw ' . l:buf
584
 
585
    " Build help tags:
586
    exe 'helptags ' . l:vim_doc_path
587
 
588
    return 1
589
endfunction
590
" }}}2
591
 
592
let s:revision=
593
      \ substitute("$Revision: 1.29 $",'\$\S*: \([.0-9]\+\) \$','\1','')
594
silent! let s:install_status =
595
    \ s:XmlInstallDocumentation(expand('<sfile>:p'), s:revision)
596
if (s:install_status == 1)
597
    echom expand("<sfile>:t:r") . '-plugin v' . s:revision .
598
        \ ': Help-documentation installed.'
599
endif
600
 
601
 
602
" Mappings and Settings.                                             {{{1
603
" This makes the '%' jump between the start and end of a single tag.
604
setlocal matchpairs+=<:>
605
 
606
" Have this as an escape incase you want a literal '>' not to run the
607
" ParseTag function.
608
if !exists("g:xml_tag_completion_map")
609
    inoremap <buffer> <LocalLeader>. >
610
    inoremap <buffer> <LocalLeader>> >
611
endif
612
 
613
" Jump between the beggining and end tags.
614
nnoremap <buffer> <LocalLeader>5 :call <SID>TagMatch1()<Cr>
615
nnoremap <buffer> <LocalLeader>% :call <SID>TagMatch1()<Cr>
616
vnoremap <buffer> <LocalLeader>5 <Esc>:call <SID>VisualTag()<Cr>
617
vnoremap <buffer> <LocalLeader>% <Esc>:call <SID>VisualTag()<Cr>
618
 
619
" Wrap selection in XML tag
620
vnoremap <buffer> <LocalLeader>x "xx:call <SID>WrapTag(@x)<Cr>
621
nnoremap <buffer> <LocalLeader>d :call <SID>DeleteTag()<Cr>
622
 
623
" Parse the tag after pressing the close '>'.
624
if !exists("g:xml_tag_completion_map")
625
    inoremap <buffer> > ><Esc>:call <SID>ParseTag()<Cr>
626
else
627
    execute "inoremap <buffer> " . g:xml_tag_completion_map . " ><Esc>:call <SID>ParseTag()<Cr>"
628
endif
629
 
630
augroup xml
631
    au!
632
    au BufNewFile * call <SID>NewFileXML()
633
augroup END
634
"}}}1
635
finish
636
 
637
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
638
" Section: Documentation content                                          {{{1
639
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
640
=== START_DOC
641
*xml-plugin.txt*  Help edit XML and SGML documents.                  #version#
642
 
643
				   XML Edit {{{2 ~
644
 
645
A filetype plugin to help edit XML and SGML documents.
646
 
647
This script provides some convenience when editing XML (and some SGML
648
including HTML) formated documents. It allows you to jump to the beginning
649
or end of the tag block your cursor is in. '%' will jump between '<' and '>'
650
within the tag your cursor is in. When in insert mode and you finish a tag
651
(pressing '>') the tag will be completed. If you press '>' twice it will
652
complete the tag and place the cursor in the middle of the tags on it's own
653
line (helps with nested tags).
654
 
655
Usage: Place this file into your ftplugin directory. To add html support
656
Sym-link or copy this file to html.vim in your ftplugin directory. To activte
657
the script place 'filetype plugin on' in your |.vimrc| file. See |ftplugins|
658
for more information on this topic.
659
 
660
If the file edited is of type "html" and "xml_use_html" is  defined then the
661
following tags will not auto complete:
662
<img>, <input>, <param>, <frame>, <br>, <hr>, <meta>, <link>, <base>, <area>
663
 
664
If the file edited is of type 'html' and 'xml_use_xhtml' is defined the above
665
tags will autocomplete the xml closing staying xhtml compatable.
666
ex. <hr> becomes <hr /> (see |xml-plugin-settings|)
667
 
668
NOTE: If you used the VIM 5.x version of this file (xmledit.vim) you'll need
669
to comment out the section where you called it. It is no longer used in the
670
VIM 6.x version. 
671
 
672
Known Bugs {{{2 ~
673
 
674
- This script will modify registers ". and "x; register "" will be restored.
675
- < & > marks inside of a CDATA section are interpreted as actual XML tags
676
  even if unmatched.
677
- Although the script can handle leading spaces such as < tag></ tag> it is
678
  illegal XML syntax and considered very bad form.
679
- Placing a literal `>' in an attribute value will auto complete dispite that
680
  the start tag isn't finished. This is poor XML anyway you should use
681
  &gt; instead.
682
- The matching algorithm can handle illegal tag characters where as the tag
683
  completion algorithm can not.
684
 
685
------------------------------------------------------------------------------
686
							 *xml-plugin-mappings*
687
Mappings {{{2 ~
688
 
689
<LocalLeader> is a setting in VIM that depicts a prefix for scripts and
690
plugins to use. By default this is the backslash key `\'. See |mapleader|
691
for details.
692
 
693
<LocalLeader>x
694
	Visual - Place a custom XML tag to suround the selected text. You
695
	need to have selected text in visual mode before you can use this
696
	mapping. See |visual-mode| for details.
697
 
698
<LocalLeader>.   or      <LocalLeader>>
699
        Insert - Place a literal '>' without parsing tag.
700
 
701
<LocalLeader>5   or      <LocalLeader>%
702
        Normal or Visual - Jump to the begining or end tag.
703
 
704
<LocalLeader>d
705
        Normal - Deletes the surrounding tags from the cursor. >
706
            <tag1>outter <tag2>inner text</tag2> text</tag1>
707
                    ^
708
<       Turns to: >
709
            outter <tag2>inner text</tag2> text
710
            ^
711
<
712
 
713
------------------------------------------------------------------------------
714
							 *xml-plugin-settings*
715
Options {{{2 ~
716
 
717
(All options must be placed in your |.vimrc| prior to the |ftplugin|
718
command.)
719
 
720
xml_tag_completion_map
721
	Use this setting to change the default mapping to auto complete a
722
	tag. By default typing a literal `>' will cause the tag your editing
723
	to auto complete; pressing twice will auto nest the tag. By using
724
	this setting the `>' will be a literal `>' and you must use the new
725
	mapping to perform auto completion and auto nesting. For example if
726
	you wanted Control-L to perform auto completion inmstead of typing a
727
	`>' place the following into your .vimrc: >
728
            let xml_tag_completion_map = "<C-l>"
729
<
730
xml_no_auto_nesting
731
	This turns off the auto nesting feature. After a completion is made
732
	and another `>' is typed xml-edit automatically will break the tag
733
	accross multiple lines and indent the curser to make creating nested
734
	tqags easier. This feature turns it off. Enter the following in your
735
	.vimrc: >
736
            let xml_no_auto_nesting = 1
737
<
738
xml_use_xhtml
739
	When editing HTML this will auto close the short tags to make valid
740
	XML like <hr /> and <br />. Enter the following in your vimrc to
741
	turn this option on: >
742
            let xml_use_xhtml = 1
743
<
744
xml_no_html
745
	This turns of the support for HTML specific tags. Place this in your
746
        .vimrc: >
747
            let xml_no_html = 1
748
<
749
------------------------------------------------------------------------------
750
							*xml-plugin-callbacks*
751
Callback Functions {{{2 ~
752
 
753
A callback function is a function used to customize features on a per tag
754
basis. For example say you wish to have a default set of attributs when you
755
type an empty tag like this:
756
    You type: <tag>
757
    You get:  <tag default="attributes"></tag>
758
 
759
This is for any script programmers who wish to add xml-plugin support to
760
there own filetype plugins.
761
 
762
Callback functions recive one attribute variable which is the tag name. The
763
all must return either a string or the number zero. If it returns a string
764
the plugin will place the string in the proper location. If it is a zero the
765
plugin will ignore and continue as if no callback existed.
766
 
767
The following are implemented callback functions:
768
 
769
HtmlAttribCallback
770
	This is used to add default attributes to html tag. It is intended
771
	for HTML files only.
772
 
773
XmlAttribCallback
774
	This is a generic callback for xml tags intended to add attributes.
775
 
776
							     *xml-plugin-html*
777
Callback Example {{{2 ~
778
 
779
The following is an example of using XmlAttribCallback in your .vimrc
780
>
781
        function XmlAttribCallback (xml_tag)
782
            if a:xml_tag ==? "my-xml-tag"
783
                return "attributes=\"my xml attributes\""
784
            else
785
                return 0
786
            endif
787
        endfunction
788
<
789
The following is a sample html.vim file type plugin you could use:
790
>
791
  " Vim script file                                       vim600:fdm=marker:
792
  " FileType:   HTML
793
  " Maintainer: Devin Weaver <vim (at) tritarget.com>
794
  " Location:   http://www.vim.org/scripts/script.php?script_id=301
795
 
796
  " This is a wrapper script to add extra html support to xml documents.
797
  " Original script can be seen in xml-plugin documentation.
798
 
799
  " Only do this when not done yet for this buffer
800
  if exists("b:did_ftplugin")
801
    finish
802
  endif
803
  " Don't set 'b:did_ftplugin = 1' because that is xml.vim's responsability.
804
 
805
  let b:html_mode = 1
806
 
807
  if !exists("*HtmlAttribCallback")
808
  function HtmlAttribCallback( xml_tag )
809
      if a:xml_tag ==? "table"
810
          return "cellpadding=\"0\" cellspacing=\"0\" border=\"0\""
811
      elseif a:xml_tag ==? "link"
812
          return "href=\"/site.css\" rel=\"StyleSheet\" type=\"text/css\""
813
      elseif a:xml_tag ==? "body"
814
          return "bgcolor=\"white\""
815
      elseif a:xml_tag ==? "frame"
816
          return "name=\"NAME\" src=\"/\" scrolling=\"auto\" noresize"
817
      elseif a:xml_tag ==? "frameset"
818
          return "rows=\"0,*\" cols=\"*,0\" border=\"0\""
819
      elseif a:xml_tag ==? "img"
820
          return "src=\"\" width=\"0\" height=\"0\" border=\"0\" alt=\"\""
821
      elseif a:xml_tag ==? "a"
822
          if has("browse")
823
	      " Look up a file to fill the href. Used in local relative file
824
	      " links. typeing your own href before closing the tag with `>'
825
	      " will override this.
826
              let cwd = getcwd()
827
              let cwd = substitute (cwd, "\\", "/", "g")
828
              let href = browse (0, "Link to href...", getcwd(), "")
829
              let href = substitute (href, cwd . "/", "", "")
830
              let href = substitute (href, " ", "%20", "g")
831
          else
832
              let href = ""
833
          endif
834
          return "href=\"" . href . "\""
835
      else
836
          return 0
837
      endif
838
  endfunction
839
  endif
840
 
841
  " On to loading xml.vim
842
  runtime ftplugin/xml.vim
843
<
844
=== END_DOC
845
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
846
" v im:tw=78:ts=8:ft=help:norl:
847
" vim600: set foldmethod=marker  tabstop=8 shiftwidth=2 softtabstop=2 smartindent smarttab  :
848
"fileencoding=iso-8859-15