Change end-of-line format for dos-mac-unix
From Vim Tips Wiki
Tip 26 Previous Tip • Next Tip
Created: March 5, 2001 Complexity: basic Author: scrott Minimum version: 6.0 Karma: 2031/784 Imported from: Tip#26
If you work in a mixed environment (Unix and DOS or Windows), you will often see ^M when you open a file. Under Unix, a line is supposed to be terminated with an LF (linefeed) character, but DOS/Windows use CR LF (carriage return followed by linefeed). Sometimes, LF is written as NL (newline).
If Vim believes that a file has unix format, any CR will display as ^M (because CR is Ctrl-M).
Vim supports three file formats: unix (lines end with LF), dos (lines end with CR LF), and mac (lines end with CR).
Use :set ffs? to see the value of your ffs (fileformats) option. :help 'ffs' explains how Vim interprets a file when it is read.
Use :set ff? to see the value of ff (fileformat) for the current buffer. This setting show how Vim interpreted the file when it was read. If you change ff, the file will be written with different line endings when you next write the file. See :help 'ff'.
Some programs create files with inconsistent line endings. For example, the first few lines may end with LF, and Vim will decide the file has the unix file format. But later lines may use CR LF and Vim may show the CR as ^M.
To replace every CR with LF (when searching, \r matches CR, but when replacing, \r inserts LF):
:%s/\r/\r/g
To delete every ^M from the buffer:
:%s/\r//g
The \r is two characters that are interpreted as the single character CR (:help /\r). The above command will delete all CR characters, regardless of where they occur in a line.
To delete ^M only when it occurs at the end of a line:
:%s/\r$//
To delete ^M at line endings, and replace it with a space everywhere else:
:%s/\r$// :%s/\r/ /g
It is possible to use an actual CR instead of the two characters \r in the above commands. To enter a CR, you type Ctrl-V Ctrl-M (or Ctrl-Q Ctrl-M under Windows). However, using \r is easier, and is the recommended procedure.
[edit] Unix users
Under Unix, you may find that a Vim script does not work because you have downloaded a script that contains Carriage Return (CR) characters. Each CR displays as ^M, and will cause some scripts to fail.
If you put script.vim in your plugin directory, you may not see any useful error messages about CR characters. You can source the script after starting Vim (for example, :source ~/.vim/plugin/script.vim) to see if errors including "^M" are shown.
If there are many files that you need to fix, you can use the Unix dos2unix utility, for example:
cd .vim dos2unix */*.vim # Or, if run as root, you can preserve timestamps: dos2unix -p */*.vim
[edit] Comments
TO DO
Explain use of:
:set ff=unix :set ff=dos
The following reads file foo.txt using dos file format (CR LF is the expected line ending, but LF will also be accepted as a line ending). The second command writes the file using the unix file format, so every line will end with LF only. So this converts from dos format (or a mixture of dos/unix), to unix format.
:e ++ff=dos foo.txt :w ++ff=unix
The following converts from mac format to unix format.
:e ++ff=mac foo.txt :w ++ff=unix
To process, say, all *.txt files in the current directory:
vim *.txt :set hidden :bufdo %s/\r$//e :bufdo %s/\r/ /eg :xa
Suppose you do not want to change the file, but you want to hide the ^M characters. You can use:
:hi SpecialKey guifg=bg
Unfortunately, this hides all special characters.
If you want to remove ^M at the end of each line, yet have Vim regard the file as unchanged, enter:
:%s/\r$//e | set nomod
The e flag means no error occurs if no matches are found. Also see :help 'mod'.
The following is a little dangerous as it attempts to delete all CR characters from every file that you open. You could put this in your vimrc file.
" Delete one or more CR at the end of each line. autocmd BufRead * silent! %s/\r\+$// " Alternative: Also delete trailing whitespace. autocmd BufRead * silent! %s/[\r \t]\+$//
If you want to write a file with no linebreak at the end:
:set noeol bin
Now, when you write the file, the last line will have no line ending. You do not normally want this. Every line, including the last, should have a line ending.
I had a bunch of HTML files that needed to be converted. As they were all open I just did the following:
:bufdo! set ff=unix | update
You can display the file format for the current buffer in the status line:
set statusline=%<%f%h%m%r%=%{&ff}\ %l,%c%V\ %P
All I care about is if the file format is not unix. If it's not, I want a big red warning. That way I'm not the jerk who checks in a file that causes every line to get modified by the diff patch.
So, I added this to my existing statusline:
%9*%{&ff=='unix'?'':&ff.'\ format'}%*
Here's what is does:
%9*
\- Change highlighting to user setting #9 (see :he hl-User1..9)
%{
\- Begin evaluating as expression until } is encountered
&ff=='unix'?'':&ff.'\ format'
\- This is a ternary that returns either an empty string, or 'XX format'
}
\- This marks the end of the expression
%*
\- Restores normal highlight
So, how do you use it? First I call:
:set statusline?
Which returns:
statusline=%<%f :: %{TagName()} %(%h%m%r %)%=%-15.15(%l,%c%V%)%P
But, remember that if you want to set a status line you must escape all white space. So that line would have to be entered as:
statusline=%<%f\ ::\ %{TagName()}\ %(%h%m%r\ %)%=%-15.15(%l,%c%V%)%P
So when I added my modification I have:
:set statusline=%<%f\ :%9*%{&ff=='unix'?'':&ff.'\ format'}%*:\ %{TagName()}\ %(%h%m%r\ %)%=%-15.15(%l,%c%V%)%P
But then, to make the user highlighting #9 big and red I started by viewing all the existing highlighting configurations (I'm too lazy to write my own) by calling:
:hi
The entry titled ErrorMsg looked good to me so I copied its settings which were:
term=standout cterm=bold ctermfg=7 ctermbg=1
I then called:
:hi User9 term=standout cterm=bold ctermfg=7 ctermbg=1
Now my status line is unchanged and uncluttered, unless I have opened a dos file. That's pretty cool.
I wrote this in REAL basic terms, because I really wish someone had explained it to me like this. I hope it's well received.
If you always want a particular file to have, say, dos file format, you can put a modeline in that file. For example, add this line (a C-style comment) near the beginning or end of the file:
/* vim: set ff=dos: */
[edit] Hide unwanted text
Here is a technique to hide ^M line endings by highlighting them with the Ignore highlight group. This is from a tip that was proposed by Frienddaniel (the tip has been merged to here).
:match Ignore /\r$/
Any ^M characters that are embedded within lines (not at the line endings) will be displayed as normal because they are problems that need to be fixed.
Note If ^M characters are at the end of every line, Vim should open the file in DOS file format. If you see the ^M, there are probably a few lines that do not have one, and the file has been opened in Unix file format. If this is the case, delete all the ^M characters with a simple :s command, and save the file (after :set fileformat=dos if desired). Just hiding the problem with a highlight group is probably a bad idea. If you hide the problem, you will never know if a file has pesky line endings that might screw up your regular expressions (^M doesn't match at the end of line '$' atom), plugins (TagList, for example, has no idea where to jump in a file with inconsistent line endings), or even your use of the file (some compilers, interpreters, parsers, etc will get thrown for a loop with unexpected line-endings, makefiles refuse to work, and all sorts of other trouble can happen). You should always prefer fixing a problem over hiding it!
Categories: Review | VimTip | Windows | Todo
