├── .gitignore
├── .travis.yml
├── Gemfile
├── Rakefile
├── VimFlavor
├── autoload
└── operator
│ └── replace.vim
├── doc
└── operator-replace.txt
├── plugin
└── operator
│ └── replace.vim
└── t
├── basics.vim
├── register.vim
└── selection.vim
/.gitignore:
--------------------------------------------------------------------------------
1 | .vim-flavor
2 | Gemfile.lock
3 | VimFlavor.lock
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | rvm:
3 | - 2.1.5
4 | script: rake ci
5 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'vim-flavor', '~> 2.0'
4 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env rake
2 |
3 | task :ci => [:dump, :test]
4 |
5 | task :dump do
6 | sh 'vim --version'
7 | end
8 |
9 | task :test do
10 | sh 'bundle exec vim-flavor test'
11 | end
12 |
--------------------------------------------------------------------------------
/VimFlavor:
--------------------------------------------------------------------------------
1 | flavor 'kana/vim-operator-user', '~> 0.1'
2 |
3 | group :development do
4 | flavor 'kana/vim-textobj-line'
5 | end
6 |
7 | # vim: filetype=ruby
8 |
--------------------------------------------------------------------------------
/autoload/operator/replace.vim:
--------------------------------------------------------------------------------
1 | " operator-replace - Operator to replace text with register content
2 | " Version: 0.0.5
3 | " Copyright (C) 2009-2015 Kana Natsuno
4 | " License: MIT license {{{
5 | " Permission is hereby granted, free of charge, to any person obtaining
6 | " a copy of this software and associated documentation files (the
7 | " "Software"), to deal in the Software without restriction, including
8 | " without limitation the rights to use, copy, modify, merge, publish,
9 | " distribute, sublicense, and/or sell copies of the Software, and to
10 | " permit persons to whom the Software is furnished to do so, subject to
11 | " the following conditions:
12 | "
13 | " The above copyright notice and this permission notice shall be included
14 | " in all copies or substantial portions of the Software.
15 | "
16 | " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | " OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | " IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | " CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 | " TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 | " SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | " }}}
24 | " Interface "{{{1
25 | function! operator#replace#do(motion_wise) "{{{2
26 | let visual_command = s:visual_command_from_wise_name(a:motion_wise)
27 |
28 | let put_command = (s:deletion_moves_the_cursor_p(
29 | \ a:motion_wise,
30 | \ getpos("']")[1:2],
31 | \ len(getline("']")),
32 | \ [line('$'), len(getline('$'))]
33 | \ )
34 | \ ? 'p'
35 | \ : 'P')
36 |
37 | if !s:is_empty_region(getpos("'["), getpos("']"))
38 | let original_selection = &g:selection
39 | let &g:selection = 'inclusive'
40 | execute 'normal!' '`['.visual_command.'`]"_d'
41 | let &g:selection = original_selection
42 | end
43 | execute 'normal!' '"'.operator#user#register().put_command
44 | return
45 | endfunction
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | " Misc. "{{{1
55 | " s:deletion_moves_the_cursor_p(motion_wise) "{{{2
56 | function! s:deletion_moves_the_cursor_p(motion_wise,
57 | \ motion_end_pos,
58 | \ motion_end_last_col,
59 | \ buffer_end_pos)
60 | let [buffer_end_line, buffer_end_col] = a:buffer_end_pos
61 | let [motion_end_line, motion_end_col] = a:motion_end_pos
62 |
63 | if a:motion_wise ==# 'char'
64 | return ((a:motion_end_last_col == motion_end_col)
65 | \ || (buffer_end_line == motion_end_line
66 | \ && buffer_end_col <= motion_end_col))
67 | elseif a:motion_wise ==# 'line'
68 | return buffer_end_line == motion_end_line
69 | elseif a:motion_wise ==# 'block'
70 | return 0
71 | else
72 | echoerr 'E2: Invalid wise name:' string(a:wise_name)
73 | return 0
74 | endif
75 | endfunction
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | function! s:is_empty_region(begin, end) "{{{2
85 | " Whenever 'operatorfunc' is called, '[ is always placed before '] even if
86 | " a backward motion is given to g@. But there is the only one exception.
87 | " If an empty region is given to g@, '[ and '] are set to the same line, but
88 | " '[ is placed after '].
89 | return a:begin[1] == a:end[1] && a:end[2] < a:begin[2]
90 | endfunction
91 |
92 |
93 |
94 |
95 | function! s:visual_command_from_wise_name(wise_name) "{{{2()
96 | if a:wise_name ==# 'char'
97 | return 'v'
98 | elseif a:wise_name ==# 'line'
99 | return 'V'
100 | elseif a:wise_name ==# 'block'
101 | return "\"
102 | else
103 | echoerr 'E1: Invalid wise name:' string(a:wise_name)
104 | return 'v' " fallback
105 | endif
106 | endfunction
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | " __END__ "{{{1
116 | " vim: foldmethod=marker
117 |
--------------------------------------------------------------------------------
/doc/operator-replace.txt:
--------------------------------------------------------------------------------
1 | *operator-replace.txt* Operator to replace text with register content
2 |
3 | Version 0.0.5
4 | Script ID: 2782
5 | Copyright (C) 2009-2015 Kana Natsuno
6 | License: MIT license {{{
7 | Permission is hereby granted, free of charge, to any person obtaining
8 | a copy of this software and associated documentation files (the
9 | "Software"), to deal in the Software without restriction, including
10 | without limitation the rights to use, copy, modify, merge, publish,
11 | distribute, sublicense, and/or sell copies of the Software, and to
12 | permit persons to whom the Software is furnished to do so, subject to
13 | the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included
16 | in all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 | }}}
26 |
27 | CONTENTS *operator-replace-contents*
28 |
29 | Introduction |operator-replace-introduction|
30 | Interface |operator-replace-interface|
31 | Key Mappings |operator-replace-key-mappings|
32 | Examples |operator-replace-examples|
33 | Bugs |operator-replace-bugs|
34 | Changelog |operator-replace-changelog|
35 |
36 |
37 |
38 |
39 | ==============================================================================
40 | INTRODUCTION *operator-replace-introduction*
41 |
42 | *operator-replace* is a Vim plugin to provide an operator to replace
43 | a specified text with register content. This is shortcut for several types of
44 | operations such as "d{motion}P" and "c{motion}{register}".
45 |
46 |
47 | Requirements:
48 | - Vim 7.2 or later
49 | - |operator-user| 0.1.0 or later
50 | https://github.com/kana/vim-operator-user
51 |
52 | Latest version:
53 | https://github.com/kana/vim-operator-replace
54 |
55 |
56 |
57 |
58 | ==============================================================================
59 | INTERFACE *operator-replace-interface*
60 |
61 | ------------------------------------------------------------------------------
62 | KEY MAPPINGS *operator-replace-key-mappings*
63 |
64 | ["x](operator-replace){motion} *(operator-replace)*
65 | Replace text that {motion} moves over with register x.
66 |
67 |
68 |
69 |
70 | ==============================================================================
71 | EXAMPLES *operator-replace-examples*
72 |
73 | (A) At first, you have to map arbitrary key sequences to
74 | |(operator-replace)| like the following:
75 | >
76 | map _ (operator-replace)
77 | <
78 |
79 | (B) Suppose that you edit a buffer with the following content:
80 | (note that "^" indicates the cursor position)
81 | >
82 | (herb oil pepper) salt water
83 | ^
84 | <
85 | If you yank "sugar" into register x, now you can replace any text with the
86 | yanked text. For example:
87 |
88 | To replace the 2nd word:
89 | >
90 | w"x_iw
91 | <
92 | To replace inside the parens:
93 | >
94 | "x_ib
95 | <
96 | To replace the cursor line:
97 | >
98 | "x__
99 | <
100 |
101 |
102 |
103 |
104 | ==============================================================================
105 | BUGS *operator-replace-bugs*
106 |
107 | - Combinations of wises of {motion} and register content are not considered
108 | well, especially with blockwise ones.
109 |
110 | - See also |operator-user-bugs|.
111 |
112 |
113 |
114 |
115 | ==============================================================================
116 | CHANGELOG *operator-replace-changelog*
117 |
118 | 0.0.5 2015-02-25T00:48:14+09:00 *operator-replace-changelog-0.0.5*
119 | - Fix a bug that any register given to |(operator-replace)| is
120 | ignored if the operator is combined with any custom text object
121 | defined by |textobj-user|.
122 | - |operator-user| 0.1.0 or later is now required.
123 |
124 | 0.0.4 2013-03-05T22:30:01+09:00 *operator-replace-changelog-0.0.4*
125 | - Fix to delete a proper range of text for environments which
126 | 'selection' is set to "exclusive".
127 |
128 | 0.0.3 2012-11-29T20:19:45+09:00 *operator-replace-changelog-0.0.3*
129 | - Fix to correctly handle empty region. For example,
130 | |(operator-replace)| with |it| on text such as ""
131 | did not work correctly.
132 |
133 | 0.0.2 2012-03-24T14:14:37+09:00 *operator-replace-changelog-0.0.2*
134 | - Refine the internal structure.
135 |
136 | 0.0.1 2009-09-16T07:59:40+09:00 *operator-replace-changelog-0.0.1*
137 | - Fix edge case bugs. Now replaacing at the end of line or the end of
138 | buffer work as you expect.
139 |
140 | 0.0.0 2009-09-06T10:13:20+09:00 *operator-replace-changelog-0.0.0*
141 | - Initial version.
142 |
143 |
144 |
145 |
146 | ==============================================================================
147 | vim:tw=78:ts=8:ft=help:norl:fen:fdl=0:fdm=marker:
148 |
--------------------------------------------------------------------------------
/plugin/operator/replace.vim:
--------------------------------------------------------------------------------
1 | " operator-replace - Operator to replace text with register content
2 | " Version: 0.0.5
3 | " Copyright (C) 2009-2015 Kana Natsuno
4 | " License: MIT license {{{
5 | " Permission is hereby granted, free of charge, to any person obtaining
6 | " a copy of this software and associated documentation files (the
7 | " "Software"), to deal in the Software without restriction, including
8 | " without limitation the rights to use, copy, modify, merge, publish,
9 | " distribute, sublicense, and/or sell copies of the Software, and to
10 | " permit persons to whom the Software is furnished to do so, subject to
11 | " the following conditions:
12 | "
13 | " The above copyright notice and this permission notice shall be included
14 | " in all copies or substantial portions of the Software.
15 | "
16 | " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | " OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | " IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | " CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 | " TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 | " SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | " }}}
24 |
25 | if exists('g:loaded_operator_replace')
26 | finish
27 | endif
28 |
29 |
30 |
31 |
32 | call operator#user#define('replace', 'operator#replace#do')
33 |
34 |
35 |
36 |
37 | let g:loaded_operator_replace = 1
38 |
39 | " __END__
40 | " vim: foldmethod=marker
41 |
--------------------------------------------------------------------------------
/t/basics.vim:
--------------------------------------------------------------------------------
1 | runtime! plugin/operator/*.vim
2 |
3 |
4 |
5 |
6 | describe 'Named key mappings'
7 | it 'is available in proper modes'
8 | let lhs = '(operator-replace)'
9 | Expect maparg(lhs, 'c') ==# ''
10 | Expect maparg(lhs, 'i') ==# ''
11 | Expect maparg(lhs, 'n') =~# 'operator#replace#'
12 | Expect maparg(lhs, 'o') ==# 'g@'
13 | Expect maparg(lhs, 'v') =~# 'operator#replace#'
14 | end
15 | end
16 |
17 |
18 |
19 |
20 | describe '(operator-replace) with block {motion}'
21 | " FIXME: NIY - but what result I expect for this case?
22 | end
23 |
24 |
25 |
26 |
27 | describe '(operator-replace) with char {motion}'
28 | before
29 | tabnew
30 | let @" = 'qux'
31 | let @s = 'waldo'
32 | put ='foo bar baz'
33 | end
34 |
35 | after
36 | tabclose!
37 | end
38 |
39 | it 'works fine with block {register} content'
40 | SKIP 'FIXME: NIY - but what result I expect for this case?'
41 | end
42 |
43 | it 'works fine with char {register} content (1)'
44 | " {operator}{characterwise-motion} without register designation
45 | execute 'normal' "\(operator-replace)e"
46 | Expect getline('.') ==# 'qux bar baz'
47 | Expect [getreg('"'), getregtype('"')] ==# ['qux', 'v']
48 | Expect [getreg('s'), getregtype('s')] ==# ['waldo', 'v']
49 | end
50 |
51 | it 'works fine with char {register} content (2)'
52 | " {characterwise-Visual}{operator} without register designation
53 | execute 'normal' "ve\(operator-replace)"
54 | Expect getline('.') ==# 'qux bar baz'
55 | Expect [getreg('"'), getregtype('"')] ==# ['qux', 'v']
56 | Expect [getreg('s'), getregtype('s')] ==# ['waldo', 'v']
57 | end
58 |
59 | it 'works fine with char {register} content (3)'
60 | " {operator}{characterwise-motion} with register designation
61 | execute 'normal' "\"s\(operator-replace)e"
62 | Expect getline('.') ==# 'waldo bar baz'
63 | Expect [getreg('"'), getregtype('"')] ==# ['qux', 'v']
64 | Expect [getreg('s'), getregtype('s')] ==# ['waldo', 'v']
65 | end
66 |
67 | it 'works fine with char {register} content (4)'
68 | " {characterwise-Visual}{operator} with register designation
69 | execute 'normal' "ve\"s\(operator-replace)"
70 | Expect getline('.') ==# 'waldo bar baz'
71 | Expect [getreg('"'), getregtype('"')] ==# ['qux', 'v']
72 | Expect [getreg('s'), getregtype('s')] ==# ['waldo', 'v']
73 | end
74 |
75 | it 'works fine with char {register} content (5)'
76 | " {operator}{characterwise-motion} including the end of buffer
77 | execute 'normal' "\"s\(operator-replace)$"
78 | Expect getline('.') ==# 'waldo'
79 | Expect [getreg('"'), getregtype('"')] ==# ['qux', 'v']
80 | Expect [getreg('s'), getregtype('s')] ==# ['waldo', 'v']
81 | end
82 |
83 | it 'works fine with char {register} content (6)'
84 | " {characterwise-Visual}{operator} including the end of buffer
85 | execute 'normal' "v$\"s\(operator-replace)"
86 | Expect getline('.') ==# 'waldo'
87 | Expect [getreg('"'), getregtype('"')] ==# ['qux', 'v']
88 | Expect [getreg('s'), getregtype('s')] ==# ['waldo', 'v']
89 | end
90 |
91 | it 'works fine with line {register} content'
92 | SKIP 'FIXME: NIY - but what result I expect for this case?'
93 | end
94 | end
95 |
96 |
97 |
98 |
99 | describe '(operator-replace) with line {motion}'
100 | before
101 | tabnew
102 | put ='foo foo foo'
103 | put ='bar bar bar'
104 | put ='baz baz baz'
105 | 1 delete _
106 | 2
107 | let @" = "qux\n"
108 | let @s = "waldo\n"
109 | end
110 |
111 | after
112 | tabclose!
113 | end
114 |
115 | it 'works fine with block {register} content'
116 | SKIP 'FIXME: NIY - but what result I expect for this case?'
117 | end
118 |
119 | it 'works fine with char {register} content'
120 | SKIP 'FIXME: NIY - but what result I expect for this case?'
121 | end
122 |
123 | it 'works fine with line {register} content (1)'
124 | " {operator}{linewise-motion} without register designation
125 | execute 'normal' "\(operator-replace)\(operator-replace)"
126 | Expect getline(1) ==# 'foo foo foo'
127 | Expect getline(2) ==# 'qux'
128 | Expect getline(3) ==# 'baz baz baz'
129 | Expect line('$') == 3
130 | Expect [getreg('"'), getregtype('"')] ==# ["qux\n", 'V']
131 | Expect [getreg('s'), getregtype('s')] ==# ["waldo\n", 'V']
132 | end
133 |
134 | it 'works fine with line {register} content (2)'
135 | " {linewise-Visual}{operator} without register designation
136 | execute 'normal' "Vw\(operator-replace)"
137 | Expect getline(1) ==# 'foo foo foo'
138 | Expect getline(2) ==# 'qux'
139 | Expect getline(3) ==# 'baz baz baz'
140 | Expect line('$') == 3
141 | Expect [getreg('"'), getregtype('"')] ==# ["qux\n", 'V']
142 | Expect [getreg('s'), getregtype('s')] ==# ["waldo\n", 'V']
143 | end
144 |
145 | it 'works fine with line {register} content (3)'
146 | " {operator}{linewise-motion} with register designation
147 | execute 'normal' "\"s\(operator-replace)\(operator-replace)"
148 | Expect getline(1) ==# 'foo foo foo'
149 | Expect getline(2) ==# 'waldo'
150 | Expect getline(3) ==# 'baz baz baz'
151 | Expect line('$') == 3
152 | Expect [getreg('"'), getregtype('"')] ==# ["qux\n", 'V']
153 | Expect [getreg('s'), getregtype('s')] ==# ["waldo\n", 'V']
154 | end
155 |
156 | it 'works fine with line {register} content (4)'
157 | " {linewise-Visual}{operator} with register designation
158 | execute 'normal' "Ve\"s\(operator-replace)"
159 | Expect getline(1) ==# 'foo foo foo'
160 | Expect getline(2) ==# 'waldo'
161 | Expect getline(3) ==# 'baz baz baz'
162 | Expect line('$') == 3
163 | Expect [getreg('"'), getregtype('"')] ==# ["qux\n", 'V']
164 | Expect [getreg('s'), getregtype('s')] ==# ["waldo\n", 'V']
165 | end
166 |
167 | it 'works fine with line {register} content (5)'
168 | " {operator}{linewise-motion} including the end of buffer
169 | execute 'normal' "\(operator-replace)j"
170 | Expect getline(1) ==# 'foo foo foo'
171 | Expect getline(2) ==# 'qux'
172 | Expect line('$') == 2
173 | Expect [getreg('"'), getregtype('"')] ==# ["qux\n", 'V']
174 | Expect [getreg('s'), getregtype('s')] ==# ["waldo\n", 'V']
175 | end
176 |
177 | it 'works fine with line {register} content (6)'
178 | " {linewise-Visual}{operator} including the end of buffer
179 | execute 'normal' "Vk\(operator-replace)"
180 | Expect getline(1) ==# 'qux'
181 | Expect getline(2) ==# 'baz baz baz'
182 | Expect line('$') == 2
183 | Expect [getreg('"'), getregtype('"')] ==# ["qux\n", 'V']
184 | Expect [getreg('s'), getregtype('s')] ==# ["waldo\n", 'V']
185 | end
186 | end
187 |
188 |
189 |
190 |
191 | describe '(operator-replace) with empty region'
192 | before
193 | tabnew
194 | end
195 |
196 | after
197 | tabclose!
198 | end
199 |
200 | it 'replaces a given empty region with a register content'
201 | let @" = 'foo'
202 |
203 | normal! o---
204 | execute 'normal' "\(operator-replace)it"
205 | Expect getline('.') ==# 'foo
'
206 |
207 | normal! o-
208 | execute 'normal' "\(operator-replace)it"
209 | Expect getline('.') ==# 'foo
'
210 |
211 | normal! o
212 | execute 'normal' "\(operator-replace)it"
213 | Expect getline('.') ==# 'foo
'
214 |
215 | normal! oxyz
216 | execute 'normal' "0fz\(operator-replace)Fx"
217 | Expect getline('.') ==# 'fooz
'
218 | end
219 | end
220 |
--------------------------------------------------------------------------------
/t/register.vim:
--------------------------------------------------------------------------------
1 | runtime! plugin/operator/*.vim
2 | runtime! plugin/textobj/*.vim
3 |
4 | describe '(operator-replace)'
5 | before
6 | new
7 | 0 put =' foo bar baz '
8 | let @" = '"""'
9 | let @a = 'aaa'
10 | map _ (operator-replace)
11 | end
12 |
13 | after
14 | close!
15 | end
16 |
17 | context 'with a built-in text object'
18 | it 'uses a given register'
19 | Expect getline('.') ==# ' foo bar baz '
20 | normal! fa
21 | normal "a_iw
22 | Expect getline('.') ==# ' foo aaa baz '
23 | end
24 | end
25 |
26 | context 'with a custom text object'
27 | it 'uses a given register'
28 | Expect getline('.') ==# ' foo bar baz '
29 | normal "a_il
30 | Expect getline('.') ==# ' aaa '
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/t/selection.vim:
--------------------------------------------------------------------------------
1 | runtime! plugin/operator/*.vim
2 |
3 | describe '(operator-replace)'
4 | before
5 | new
6 |
7 | function! b:.go(selection)
8 | let original_selection = &g:selection
9 | let &g:selection = a:selection
10 |
11 | put ='abcd'
12 | let @" = 'xyz'
13 | execute 'normal' "viw\(operator-replace)e"
14 | Expect getline('.') ==# 'xyz'
15 |
16 | let &g:selection = original_selection
17 | endfunction
18 | end
19 |
20 | after
21 | close!
22 | end
23 |
24 | it 'works properly with &selection == "inclusive"'
25 | call b:.go('inclusive')
26 | end
27 |
28 | it 'works properly with &selection == "exclusive"'
29 | call b:.go('exclusive')
30 | end
31 | end
32 |
--------------------------------------------------------------------------------