开发者

auto indent in vim string replacement new line?

I'm using the following command to auto replace some code (adding a new code segment after an existing segment)

%s/my_pattern/\0, \r some_other_text_i_want_to_insert/

The problem is that with the \r, some_other_text_i_want_to_insert gets inserted right after the new line:

mycode(
  some_random_text my_pattern
)

would become

mycode(
   some_random_text my_pattern
some_other_text_i_want_to_insert   <--- this line is NOT indented
)

instead of

mycode(
   some_ra开发者_如何转开发ndom_text my_pattern
   some_other_text_i_want_to_insert  <--- this line is now indented
)

i.e. the new inserted line is not indented.

Is there any option in vim or trick that I can use to indent the newly inserted line?

Thanks.


Try this:

:let @x="some_other_text_i_want_to_insert\n"
:g/my_pattern/normal "x]p

Here it is, step by step:

First, place the text you want to insert in a register...

:let @x="some_other_text_i_want_to_insert\n"

(Note the newline at the end of the string -- it's important.)

Next, use the :global command to put the text after each matching line...

:g/my_pattern/normal "x]p

The ]p normal-mode command works just like the regular p command (that is, it puts the contents of a register after the current line), but also adjusts the indentation to match.

More info:

:help ]p
:help :global
:help :normal


%s/my_pattern/\=submatch(0).", \n".matchstr(getline('.'), '^\s*').'some_other_text'/g

Note that you will have to use submatch and concatenation instead of & and \N. This answer is based on the fact that substitute command puts the cursor on the line where it does the substitution.


How about normal =``?

:%s/my_pattern/\0, \r some_other_text_i_want_to_insert/ | normal =``

<equal><backtick><backtick>: re-index position before latest jump

(Sorry about the strange formatting, escaping backtick is really hard to use here)

To keep them as separate command you could do one of these mappings:

" Equalize and move cursor to end of change - more intuitive for me"
nnoremap =. :normal! =````<CR>

" Equalize and keeps cursor at beginning of change"
nnoremap =. :keepjumps normal! =``<CR>

I read the mapping as "equalize last change" since dot already means "repeat last change".

Or skip the mapping altogether since =`` is only 3 keys with 2 of them being repeats. Easy peasy, lemon squeezy!

References

:help =
:help mark-motions


Kind of a round-about way of achieving the same thing: You could record a macro which finds the next occurance of my_pattern and inserts after it a newline and your replacement string. If auto-indent is turned on, the indent level will be maintained reagardless of where the occurance of my_pattern is found.

Something like this key sequence:

q 1                  # begin recording
/my_pattern/e        # find my_pattern, set cursor to end of match
a                    # append
\nsome_other_text... # the text to append
<esc>                # exit insert mode
q                    # stop recording

Repeated by pressing @1


You can do it in two steps. This is similar to Bill's answer but simpler and slightly more flexible, since you can use part of the original string in the replacement. First substitute and then indent.

:%s/my_pattern/\0, \r some_other_text_i_want_to_insert/

:%g/some_other_text_i_want_to_insert/normal ==

If you use part of the original string with \0,\1, etc. just use the common part of the replacement string for the :global (second) command.


I achieved this by using \s* at the beginning of my pattern to capture the preceding whitespace.

I'm using the vim addon for VSCode, which doesn't seem to match standard vim completely, but for me,

:%s/(\s*)(existing line)/$1$2\n$1added line/g

turns this

mycode{
    existing line
}

into this

mycode{
    existing line
    added line
}

The parentheses in the search pattern define groups which are referenced by $1 and $2. In this case $1 is the white space captured by (\s*). I'm not an expert on different implementations of vim or regex, but as far as I can tell, this way of referencing regex groups is specific to VSCode (or at least not general). More explanation of that here. Using \s* to capture a group of whitespace should be general, though, or at least have a close analog in your environment.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜