wrapping text in vim

For long time, I wanted the following functionality in vim: I select text and say "wrap the text by a tag". Now I'm formatting texts for HTML, and this functionality is so much required that I've got it.

Google suggested:

Tip #346: Wrap text in HTML/XML tags after prompting for the tag name

I've put the code from the comment labelled as "David Fishburn, May 8, 2006" to the file tagwrap.vim, and stored the file in the folder $HOME/.vim/plugin. To trigger wraping, I press the button "," three times.


" These mappings and TagSelection function will allow you to place
" an XML tag around either the current word, or the current selected
" text.
" If the visual select is on a single line, the tag is wrapped
" around the text <this>way</this>.  If the visual select extends
" over multiple lines, the tag is wrapped around the text
"     <this>
"     way
"     </this>
"    
" When you are prompted for the tag name, you can enter:
"     Tag name?  p class="classname" attri="bute"
" The select is wrapped with:
"     <p class="classname" attri="bute">
"     Your selection
"     </p>
" Notice the attributes have been stripped from the closing tag.
"
" Use nmap, not nnoremap, since we do want to use an existing mapping
nmap ,,, viw,,,
vnoremap ,,, <Esc>:call TagSelection()<CR>

function! TagSelection()
  let tag = input("Tag name (include attributes)? ")

  if strlen(tag) == 0
      return
  endif

  " Save b register
  let saveB       = @b
  " <C-R> seems to automatically reindent the line for some filetypes
  " this will disable it until we have applied our changes
  let saveIndent  = &indentexpr
  let curl        = line(".")
  let curc        = col(".")
  let &indentexpr = ''

  " If the visual selection is over multiple lines, then place the
  " data between the tags on newlines:
  "    <tag>
  "    data
  "    </tag>
  let newline = ''
  if getline("'>") != getline("'<")
      let newline = "\n"
      let curl  = line("'>")
  endif

  " Strip off all but the first word in the tag for the end tag
  let @b = newline . substitute( tag, '^[ \t"]*\(\<\S*\>\).*', '<\/\1>\e', "" )
  let curc = curc + strlen(@b)
  exec "normal `>a\<C-R>b"

  let @b = substitute( tag, '^[ \t"]*\(\<.*\)', '<\1>\e', "" ) . newline
  let curc = curc + strlen(@b)
  exec "normal `<i\<C-R>b"

  " Now format the area
  exec "normal `<V'>j="

  " Restore b register
  let @b          = saveB
  let &indentexpr = saveIndent

  call cursor(curl, curc)
endfunction
Categories: vim

Updated: