瀏覽代碼

add vim surround fork, surrounding, and flags to vimrc to toggle between them

Weiyi Lou 13 年之前
父節點
當前提交
0b350671dc
共有 3 個文件被更改,包括 174 次插入1 次删除
  1. 1 1
      .gitmodules
  2. 167 0
      vim/plugin/surrounding.vim
  3. 6 0
      vim/vimrc

+ 1 - 1
.gitmodules

@@ -27,7 +27,7 @@
 	url = https://github.com/sjl/gundo.vim.git
 [submodule "vim/bundle/surround"]
 	path = vim/bundle/surround
-	url = https://github.com/tpope/vim-surround
+	url = https://github.com/tpope/vim-surround.git
 [submodule "vim/bundle/fugitive"]
 	path = vim/bundle/fugitive
 	url = git://github.com/tpope/vim-fugitive.git

+ 167 - 0
vim/plugin/surrounding.vim

@@ -0,0 +1,167 @@
+" File: surrounding.vim
+" Author: Michael Sanders
+" Description: A heavily modified, simplified fork of surround.vim by Tim Pope.
+
+if exists('g:did_surrounding') || &cp || version < 700
+  finish
+endif
+let g:did_surrounding = 1
+
+nn cs :<c-u>call <SID>ModifySurround(<SID>Input(), <SID>Input())<cr>
+nn ds :<c-u>call <SID>ModifySurround(<SID>Input())<cr>
+xno s :<c-u>call <SID>AddSurround(visualmode(), 1)<cr>
+nn <silent> ys :<c-u>set opfunc=<SID>AddSurround<cr>g@
+nm yss 0ys$
+
+" Return next character typed by user.
+fun s:Input()
+  echoh ModeMsg | echo '-- SURROUND --' | echoh None
+  let c = nr2char(getchar())
+  if c == ' '
+    let c .= nr2char(getchar())
+  endif
+  echo '' | redraw
+  return c == "\<esc>" || c == "\<cr>" ? '' : c
+endf
+
+" Surround selected text with input from user.
+" If a:0 is given, visual mode is assumed to be used; otherwise, an opfunc
+fun s:AddSurround(type, ...)
+  " Deal with motions, if used in normal mode.
+  if !a:0
+    let sel_save = &sel | let &sel = 'inclusive'
+    exe 'norm! `['.(a:type == 'char' ? 'v' : 'V')."`]\<esc>"
+    let sel_save = &sel
+  endif
+  let char = s:Input()
+
+  if a:type ==# 'V' " Line mode
+    let chars = s:Wrap('', char) | let half = len(chars)/2
+    call setline("'<", strpart(chars, 0, half).getline("'<"))
+    call setline("'>", getline("'>").strpart(chars, half))
+  else " Just visual mode
+    let old = @"
+    norm! gvc
+    let @" = s:Wrap(@", char)
+    exe 'norm! '.(virtcol('.') == 1 ? 'P' : 'p')
+    let @" = old
+  endif
+
+  if a:0
+    sil! call repeat#set('1vs'.char)
+    " NOTE: This needs to be fixed -- it needs to save the motion/char used
+    " An opfunc does not appear to give us access to the motion
+    " used, so I'm not sure how to do this.
+    sil! call repeat#set('ys')
+  endif
+endf
+
+" Returns list with pair of characters matching given character.
+"
+" If character is not supported, a list with two empty strings ["", ""]
+" is returned.
+"
+" If character is a "t", the user is asked to input an XML tag and the
+" beginning and end tags are returned in a list. If the character is a
+" capitalized "T", the beginning and end tags returned are separated
+" by newlines.
+fun s:MatchChar(char)
+  if a:char ==# 'b' || a:char == '(' || a:char == ')'
+    return ['(', ')']
+  elseif a:char ==# 'r' || a:char == ']' || a:char == '['
+    return ['[', ']']
+  elseif a:char ==# 'B' || a:char == '{' || a:char == '}'
+    return ['{', '}']
+  elseif a:char ==# 'a' || a:char == '<' || a:char == '>'
+    return ['<', '>']
+  elseif a:char == 't' " Insert tag
+    if !hasmapto('>', 'c')
+      let remapped = 1
+      cno > <cr>
+    endif
+
+    let tag = input('<')
+    if !remapped | let tag = substitute(tag, '>*$', '', '') | endif
+    echo '<'.tag.'>'
+    if remapped
+      sil! cunmap >
+    endif
+
+    let cl = '</'.substitute(tag, ' .*', '', '').'>'
+
+    return a:char ==# 'T' ? ['<'.tag.">\n", "\n".cl] : ['<'.tag.'>', cl]
+  endif
+
+  return a:char =~ '\W' ? [a:char, a:char] : ['', '']
+endf
+
+" Change or delete surrounding characters.
+" "orig" should be the original character to be changed, and a:1 should be the
+" new character is substituting or not given if deleting.
+fun s:ModifySurround(orig, ...)
+  if a:orig == '' | return | endif
+  if a:0 " Save position if replacing characters.
+    if a:1 == '' | return | endif
+    let line = line('.') | let col = col('.')
+  endif
+
+  let char = a:orig
+  if len(char) > 1
+    let space = ' '
+    let char = strpart(char, 1)
+  endif
+
+  if char ==# 'a'
+    let char = '>'
+  elseif char ==# 'r'
+    let char = ']'
+  endif
+
+  let old = @"
+  let @" = ''
+  exe 'norm! d'.v:count1.'i'.char
+
+  " If di<char> failed, quit.
+  if @" == ''
+    let @" = old | return
+  elseif exists('space')
+    let @" = substitute(@",'^\s+\|\s+$', '', 'g')
+  endif
+
+  let oldLine = getline('.')
+  let oldLnum = line('.')
+  let oldLineLen = col('$')
+  if char == '"' || char == "'" || char == '`'
+    exe "norm! i \<esc>\"_d2i".char
+  else
+    exe 'norm! "_da'.char
+  endif
+
+  if a:0 | let @" = s:Wrap(@", a:1) | endif
+  let endLine = col('$')
+  sil exe 'norm! ""'.(col("']") == endLine && col('.')+1 == endLine ? 'p' : 'P')
+
+  let @" = old
+  if exists('space') | let char = ' '.char | endif
+  if a:0
+    sil! call repeat#set('cs'.char.a:1)
+    call cursor(line, col)
+  else
+    sil! call repeat#set('ds'.char)
+  endif
+endf
+
+" Returns string wrapped in the pair of the given character.
+" If character contains a space, it is also wrapped appropriately.
+fun s:Wrap(string, char)
+  if len(a:char) > 1 " Parsing character with a space
+    let space = ' '
+    let chars = s:MatchChar(strpart(a:char, 1))
+  else
+    let space = ''
+    let chars = s:MatchChar(a:char)
+  endif
+  return chars[0].space.a:string.space.chars[1]
+endf
+
+" vim:noet:sw=4:ts=4:ft=vim

+ 6 - 0
vim/vimrc

@@ -228,6 +228,12 @@ endif
 
 let g:gundo_preview_bottom = 1
 
+" Disable tpope's surround
+"let g:loaded_surround = 1
+
+" Disable msander's surrounding, a surround fork
+" (not in bundle, just plugin. Not maintained in 3 years)
+let g:did_surrounding = 1
 
 """"""""
 "" Functions, the Givers of Power (in order of use)