Vim Tips Wiki
(Remove html character entities)
(Change <tt> to <code>, perhaps also minor tweak.)
Line 4: Line 4:
 
|previous=1265
 
|previous=1265
 
|next=1267
 
|next=1267
|created=June 20, 2006
+
|created=2006
 
|complexity=intermediate
 
|complexity=intermediate
 
|author=Eric Arnold
 
|author=Eric Arnold
Line 26: Line 26:
 
</pre>
 
</pre>
   
and put it into the buffer using <tt>"ap</tt> or <tt>:put a</tt>
+
and put it into the buffer using <code>"ap</code> or <code>:put a</code>
   
 
You should see:
 
You should see:
Line 67: Line 67:
   
 
----
 
----
Another question: Why does <tt>s/\r/\r/</tt> change <CR> to <NL>?
+
Another question: Why does <code>s/\r/\r/</code> 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:
 
This is because Ex commands (as opposed to function calls) are trying to be extra smart about linebreaks. In this case:

Revision as of 06:16, 13 July 2012

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.

Comments

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.