aboutsummaryrefslogtreecommitdiff
path: root/autoload
diff options
context:
space:
mode:
Diffstat (limited to 'autoload')
-rw-r--r--autoload/regex_escape.vim69
1 files changed, 69 insertions, 0 deletions
diff --git a/autoload/regex_escape.vim b/autoload/regex_escape.vim
new file mode 100644
index 0000000..06b3c07
--- /dev/null
+++ b/autoload/regex_escape.vim
@@ -0,0 +1,69 @@
+" 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 l: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'
+ execute "normal! '[V']y"
+ elseif a:type ==# 'block' " Typically doesn't work too well
+ execute "normal! `[\<C-V>`]y" "
+ else
+ execute "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 l:flavor = get(b:, 'regex_escape_flavor',
+ \ get(g:, 'regex_escape_flavor', 'bre'))
+
+ " Get the corresponding character class
+ let l:class = s:classes[l:flavor]
+
+ " Perform the substitution on the unnamed register's contents, inserting a
+ " backslash before every instance of any character in that class
+ let @@ = substitute(@@, l:class, '\\&', 'g')
+
+ " Paste our substituted changes back in over the top of the previously
+ " selected text, by reselecting it before the paste
+ normal! gvp
+
+ " Restore contents of the unnamed register and the previous values of the
+ " 'clipboard' and 'selection' options.
+ let @@ = l:save['register']
+ let &clipboard = l:save['clipboard']
+ let &selection = l: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