aboutsummaryrefslogblamecommitdiff
path: root/autoload/regex_escape.vim
blob: 6acff6b86c4fdcb95ce6b99a7f1f05678d7cb808 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16















                                                                              
              













                                                                         
                         
                                                              
                                        
      
                         




                                                                            
                                             


                                                
                               


                                                                            
                                            


                                                                        
                    


                                                                           


                                    








                                                                           
" Define Vim pattern character classes of characters that should have an
" escape character added before them to make them literal, for use in
" substitute()
let s:classes = {
      \ 'bre': '[][\.*?^$]',
      \ 'ere': '[][\.*?^$+{}()/]',
      \ 'vim': '[][\.*^$~]'
      \ }

" This function does the actual translation, defined as 'operatorfunc' for the
" mapping in both normal and visual mode
function! regex_escape#Operatorfunc(type) abort

  " Save the current value of the unnamed register and the current value of
  " the 'clipboard' and 'selection' options into a dictionary for restoring
  " after this is all done
  let save = {
        \ 'register': @@,
        \ 'clipboard': &clipboard,
        \ 'selection': &selection
        \ }

  " Don't involve any system clipboard for the duration of this function
  set clipboard-=unnamed
  set clipboard-=unnamedplus

  " Ensure that we include end-of-line and final characters in selections
  set selection=inclusive

  " Select or re-select text, depending on how we were invoked
  if a:type ==# 'line'
    silent normal! '[V']y
  elseif a:type ==# 'block'  " Typically doesn't work too well
    silent execute "normal! `[\<C-V>`]y"
  else
    silent normal! `[v`]y
  endif

  " Determine the regex flavor to use; if one is defined for the buffer, use
  " that; failing that, if one is defined globally in g:regex_escape_flavor,
  " use that; failing that, just use 'bre'
  let flavor = get(b:, 'regex_escape_flavor',
        \ get(g:, 'regex_escape_flavor', 'bre'))

  " Get the corresponding character class
  let class = s:classes[flavor]

  " Perform the substitution on the unnamed register's contents, inserting a
  " backslash before every instance of any character in that class
  let @@ = substitute(@@, class, '\\&', 'g')

  " Paste our substituted changes back in over the top of the previously
  " selected text, by reselecting it before the paste
  silent normal! gvp

  " Restore contents of the unnamed register and the previous values of the
  " 'clipboard' and 'selection' options.
  let @@ = save['register']
  let &clipboard = save['clipboard']
  let &selection = save['selection']

endfunction

" Expression mapping target function; set the 'operatorfunc' and return the
" key sequence to active it
function! regex_escape#Map() abort
  set operatorfunc=regex_escape#Operatorfunc
  return 'g@'
endfunction