aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugin/command.vim14
-rw-r--r--plugin/substitute.vim59
2 files changed, 68 insertions, 5 deletions
diff --git a/plugin/command.vim b/plugin/command.vim
new file mode 100644
index 0000000..51633b5
--- /dev/null
+++ b/plugin/command.vim
@@ -0,0 +1,14 @@
+" g: is a command to run a vim command around a text object.
+"
+" For example, to do a substitution inside the current block, one can do:
+"
+" g:iBs/foo/bar/g<cr>
+
+noremap <silent> g: :set operatorfunc=<SID>do_command_around<cr>g@
+
+function! s:do_command_around(str) abort
+ let [_, lnum0, _, _] = getpos("'[")
+ let [_, lnum1, _, _] = getpos("']")
+
+ call feedkeys(printf(":%d,%d ", lnum0, lnum1))
+endfunction
diff --git a/plugin/substitute.vim b/plugin/substitute.vim
index 2c08310..982a76b 100644
--- a/plugin/substitute.vim
+++ b/plugin/substitute.vim
@@ -1,7 +1,56 @@
-" C-s in normal mode will replace all the occurences of the last register with
-" what was typed in the provided body.
-noremap <C-s> :set operatorfunc=DoSubstitution<cr>g@
-function DoSubstitution(str) abort
- exec printf(":'[,']s/%s/%s/g", @", @.)
+" gs will create a substitution command to replace the last yanked string with
+" the last inserted string over a motion.
+"
+" This is useful when renaming a variable for example, one can place the cursor
+" over the varibale to rename and type:
+"
+" ciwnew_variable_name<esc>gsiB
+"
+" and this will replace that variable name with 'new_variable_name' inside the
+" Body.
+
+noremap <silent> gs :set operatorfunc=<SID>do_subst_enter<cr>g@
+vnoremap <silent> gs :call <SID>v_do_subst_enter()<cr>
+
+" gS is like gs, except it:
+"
+" * doesn't feed a newline at the end
+" * doesn't wrap the string to substitue in word boundaries.
+noremap <silent> gS :set operatorfunc=<SID>do_subst_no_enter<cr>g@
+vnoremap <silent> gS :call <SID>v_do_subst_no_enter()<cr>
+
+function! s:do_subst_enter(...) abort
+ call s:do_subst_priv("'[", "']", v:true)
+endfunction
+
+function! s:do_subst_no_enter(...) abort
+ call s:do_subst_priv("'[", "']", v:false)
+endfunction
+
+function! s:v_do_subst_enter(...) abort
+ call s:do_subst_priv("'<", "'>", v:true)
+
+endfunction
+
+function! s:v_do_subst_no_enter(...) abort
+ call s:do_subst_priv("'<", "'>", v:false)
+endfunction
+
+function! s:do_subst_priv(m0, m1, do_enter) abort
+ let [_, lnum0, _, _] = getpos(a:m0)
+ let [_, lnum1, _, _] = getpos(a:m1)
+
+ " Need to call feedkeys() because @. may contain special characters like
+ " backspace.
+ call feedkeys(
+ \ printf(
+ \ ":%d,%d s/\\V%s%s%s/%s/g%s",
+ \ lnum0,
+ \ lnum1,
+ \ a:do_enter ? "\\<" : "",
+ \ escape(@", '/\'),
+ \ a:do_enter ? "\\>" : "",
+ \ escape(@., '/\'),
+ \ a:do_enter ? "\n" : ""))
endfunction