Fandom

Vim Tips Wiki

Newlines and nulls in Vim script

Redirected from VimTip1266

1,624pages on
this wiki
Add New Page
Talk0 Share

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Tip 1266 Printable Monobook Previous Next

created 2006 · complexity intermediate · author Eric Arnold · version 5.7


There is often a question as to why newlines aren't doing what the user expects inside Vim script.

When \n is stored in a Vim variable/register/etc, it is stored as a NULL, and then translated back to a real newline under circumstances such as "put".

Try inserting a newline in insert mode, i.e. ^V^J (or ^Q^J if you're using the mswin behavior). You will see a <00> show up.

Now try these to help understand further:

let @a = "a" . "\n" . "b"
or
let @a = "a" . "\x0a" . "b"

and put it into the buffer using "ap or :put a

You should see:

a
b

"put" is especially smart about translating the newlines from NULLs back to 0x0a. Now do:

call setline(".", @a)
or
call append("$", @a)

You should see:

a<00>b

It's not a happy reality, since NULLs and newlines cannot cooexist in Vim script strings in various circumstances.

In Vim 7 you have the option of giving a list to setline() and append(), which solves the line break ambiguity:

call setline(".", [ 'a', 'b' ] )

I'm now using lists everywhere I can, in preference to concatenated strings with newline separators. I usually split() any such strings I find into a list for easier manipulation. This sidesteps all the usual pitfalls trying to handle line breaks manually as embedded characters.

CommentsEdit

A useful function in this context:

:echo strtrans(@a)
a^@b

Another question: Why does s/\r/\r/ change <CR> to <NL>?

This is because Ex commands (as opposed to function calls) are trying to be extra smart about linebreaks. In this case:

let @a = substitute( "a\rb", '\r', '\r', 'g' )
call setline( "$", @a )
a<0d>b

You can see that Vim is still storing the carriage return, but is getting translated on the back end, in this case by the s/\r/\r/ command. I think the \r case is treated specially by the Ex s/ command, since :put a doesn't put 'a' and 'b' on different lines.

The moral of the story is: find out what works, and remember it, because trying to apply universal rules won't work.


Also on Fandom

Random Wiki