I've been using vim for about 3 years and am starting to write my first plugin. I've noticed when looking at the code of other popular plugins that the functions very rarely seem to achieve their aim with lines like:

execute "normal! <some commands>"

Instead opting to use Vim's built in functions. Given the power of Vim's normal mode commands to do so much, what is the general reason for not employing them more often when writing plugins? For example is there a good reason to prefer code (A) or (B) (given that they achieve the same result):

Code (A):

let l = line(".")
let c = col(".")

call search('mysearch')
call setline(line("."), 'better')

call cursor(l, c)

Code (B):

normal! mx

execute "normal! /mysearch/\<CR>"
normal! 0c$better

normal! `x

Code (A) seems a little more readable, and won't clobber the marks (and not the search registers?). Is there a more important reason I'm missing?

  • 2
    I'm with you on the readability (though, being opinion-based, that's not the basis for any answer, of course :) and have my own preference (builtins over norm all the way) but I never stopped to think about what, if any, practical (and fact-based) difference there might be. I wonder if there's any appreciable performance difference in any functionally equivalent cases.
    – B Layer
    Commented Jan 6, 2022 at 22:28
  • 1
    This seems likely to be not a good fit here. But: personally, if I can do it without clobbering marks, I use Ex and Normal mode commands where possible and go towards functions otherwise. Plugins should try their best to not clobber registers, marks, search patterns, settings, etc.
    – D. Ben Knoble
    Commented Jan 7, 2022 at 15:09

2 Answers 2


In no particular order.

  1. Readability Any sequence of normals, except a very short one, is nearly impossible to read and understand. Vimgolf can't lie.
  2. Clobbering registers etc. Quite often there is more things to change than one can even remember of. For example, your code sets at least four(!) registers and six(!) marks. Plus :h changelist and :h jumplist. Sometimes it's good, but usually scripts need to preserve stuff.
  3. Error handling Normals could fail in the middle of a sequence. Also, how do you know if "mysearch" was even found or not?
  4. Behaviour change Many normals work differently depending on user-settable options such as &virtualedit, &selection, &whichwrap, &wrap, &iskeyword and so on. Again, sometimes it's good, but usually it's a pain.
  • 1
    I like the error handling point +1.
    – mattb
    Commented Jan 9, 2022 at 16:03

Not an answer, but I think you'll appreciate it.

let saved_pos = getcurpos()
call search('mysearch')
normal! 0c$better
call setpos('.', saved_pos)

I used "better" functions ("better" - maybe not. Up to you). And mixed/matched normals with scripts. What do you think?

Read this: Master Wq and the Markdown acolyte from https://blog.sanctum.geek.nz/vim-koans/ :)

Scripts beat normal commands in terms of composability. Scripts work with data instead of strings. It's like bash commands vs. powershell commands (if you have experience with that). Or it's like understanding and transforming MEANING vs. characters. That's more univeral, but unfortunately more abstract.

So... if you're building something small, normals are great! And if you're building something large, scripts are great!

  • 1
    Thanks for the answer (+1) - I'm in the process of translating the functions in my plugin from using normal commands to using the built-ins. Holding data and states in variables allows a lot more precision and flexibility and allows me to make progress a lot faster.
    – mattb
    Commented Jan 8, 2022 at 12:55
  • At that point, perhaps :normal! ccbetter.
    – D. Ben Knoble
    Commented Jan 8, 2022 at 16:54
  • 1
    @D.BenKnoble I did have ccbetter in my original example - but I think cc matches the existing indent of the line, unlike setline(). That in itself may be another good argument in favour of using built-ins...
    – mattb
    Commented Jan 9, 2022 at 16:02

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.