0

Suppose I have a file with the following text:

aaa
bbb
ccc
bbb
ccc
eee

I need to add a missing line ddd after the second occurrence of ccc.

For that reason, use of the built-in search() function, as suggested here, won't work, because that will find the first occurrence.

I have the beginnings of a vimscript function:

function! addLine()
  normal /bbb
  normal /bbb
  " MISSING LINE
  wq!
endfunction

Is it possible to do this just using normal mode etc? If so, how?

6
  • Successive calls to search() should find the next occurrences. call search("bbb") | call search("bbb") or for i in range(10) | call search("bbb") | endfor, etc. Commented Apr 1, 2019 at 3:38
  • If I do search("ccc") | search("bbb") I seem to end up at the first bbb not the second? Commented Apr 1, 2019 at 3:45
  • Which line did you start from? Starting from the first line, :call search("ccc") | call search("bbb") gets me to line 4 (the second bbb). Commented Apr 1, 2019 at 3:46
  • Hmmm yes seems to behave differently if called from command mode inside the file as opposed to inside a function. Commented Apr 1, 2019 at 3:48
  • Ah, I see. Try search("ccc", "e") instead - it should move the cursor to the end of the match, but it seems that behaviour varies depending on it was called, so specifying that behaviour explicitly using the e flag should fix that. Commented Apr 1, 2019 at 3:54

3 Answers 3

2

With :normal, any presses of Enter (Carriage Return, <CR>) or Escape needed by the normal mode command need to passed to it. So /... command would look like:

exec "normal /bbb\<cr>"

You need the Enter, without it the / command gets cancelled.

So your function would look like:

exec "normal /ccc\<cr>noddd\<esc>"

(Pressing n to repeat the search, then o to start input in the next line, then Escape to exit insert mode.)

Or split into multiple :normals:

exec "normal /ccc\<cr>"
exec "normal /ccc\<cr>"
exec "normal oddd\<esc>"

You have to be careful that the text being inserted here doesn't have strings that might be special.

Sign up to request clarification or add additional context in comments.

Comments

0

Aside from Muru's excellent and helpful answer, I wanted to provide the actual code:

function! AddLine()
  normal /bbb\<cr>n/ccc\<cr>oddd\<esc>
  wq!
endfunction

Note that:

  • \<cr> appears as ^M in the file and is entered as CTRL-v then CTRL-m.
  • \<esc> appears as ^[ in the file and is entered as CTRL-v then ESC.

To understand the script normal /bbb\<cr>n/ccc\<cr>oddd\<esc>:

  • /bbb\<cr> - find the first line bbb
  • n - find the next match
  • /ccc\<cr> - find the next line ccc
  • o - enter insert mode and enter the text:
  • ddd
  • \<esc\> - exit insert mode.

This can be rewritten using the Vim functions as:

function! AddLine()
  call search("bbb")
  call search("bbb")
  let l:foundline = search("ccc")
  call append(l:foundline, "ddd")
  wq!
endfunction

Both of those functions correctly edit the file as required, although of course I do agree that the use of Vim functions is cleaner. If you can remember all the functions!

See also:

1 Comment

Remembering is what :help is for
0

I was trying to do the same thing. And didn't find the answers. But when iwas trying a few things i found a solution.

I know and hope that you have already find the answer but the others here is the thing to do :

When you are in the vimscript menu, just press esc, then +

At this point you can add new content. To be sure that it's working, you can see an "insert mode" at the bottom of the screen from the vimscript menu. Hope that it helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.