I'm trying to map a command in my vimrc to remove the carriage return character ^M that I sometimes see in files. :%s/^M//g (^M from ctrl-v, ctrl-m) works pretty easily when I'm in the file, but when I save that in my vimrc, it's no good.
nmap ,dm :%s/^M//g <cr>
I'm guessing it's because ^M is interpretted differently when mapped via vimrc, so I tried escaping it with \, to no avail. How can I map this command so that it removes the carriage return characters?
FWIW, I'm using gVim on Windows.
Almost every vim user reaches a moment he wants to solve this issue elegantly and one thing I figured out is that we also need a solution to get rid of ^M and keep the cursor position at once.
Personally I use a function to preserve my cursor position, because when we get rid of ^M the cursor position will change:
" preserve function
if !exists('*Preserve')
function! Preserve(command)
try
let l:win_view = winsaveview()
"silent! keepjumps keeppatterns execute a:command
silent! execute 'keeppatterns keepjumps ' . a:command
finally
call winrestview(l:win_view)
endtry
endfunction
endif
The propper function to get rid of ^M
" dos2unix ^M
if !exists('*Dos2unixFunction')
fun! Dos2unixFunction() abort
"call Preserve('%s/ $//ge')
call Preserve(":%s/\x0D$//e")
set ff=unix
set bomb
set encoding=utf-8
set fileencoding=utf-8
endfun
endif
com! Dos2Unix :call Dos2unixFunction()
As you can see we are using \x0D$ instead of ^M, which is the hexadecimal code for the ^M
The option set bomb helps considering the file as UTF-8 help here. It helps solving encoding issues.
The function "Preserve" can also be used to many other stuff like reindenting the whole file without "moving" our cursor
command! -nargs=0 Reindent :call Preserve('exec "normal! gg=G"')
The above line will set a "Reindent" command with no arguments "-nargs=0". By the way feel free to stell some pieces of my init.vim here
NOTE: It is worth mention the "ifs" preceding the two functions above, it is called guard, it helps us to avoid loading functions twice in the memory, thus, keeping our vim/neovim responsible as much as possible.
Related
I want to highlight trailing space at the end of a line in vim. The following command works:
:match Error /\v\s+\n/
But I'm having trouble mapping this to a key:
nnoremap <leader>w :execute "normal! :match Error " . '/\v\s+\n/' . "\<cr>"
Vim responds with:
E114: Missing quote: "\
E15: Invalid expression: "normal! :match Error " . '/\v\s+\n/' . "\
Update:
Having just seen this: http://vim.wikia.com/wiki/Highlight_unwanted_spaces I've got the mapping working, by just writing:
nnoremap <leader>w :match Error /\v\s+\n/<cr>
Can anyone explaing what the problem is with the original execute normal! ... construct which prevents it from working?
your mapping
I think it should be
nnoremap <leader>w :execute "normal! :match Error " . '/\v\s+\n/' . "\<lt>cr>"<cr>
:help <lt> I am not super aware of exactly why this is needed (once upon a time, my executes, too, were not working, as I had \<esc> and \<cr> in my execute "normal! .."s. Just know that in place or <cr>, you need to use \<lt>cr> for <cr> in this construct.
You also need the <cr> at the end to actually run the :execute ".."<cr> command.
easier solution
Also, I think it's easier to just put
set listchars=trail:·
set list
in your vimrc, and then you will be able to see trailing white space.
Personally, I have set listchars=trail:·,tab:»\ ,extends:» in my vimrc.
and an easy regex search (/\s\+$) reveals the white space, which you can easily delete with d$ ("delete 'till end"). Then once you do that, you can press n. to "go to next" then "repeat" the d$.
cool tip
Once you highlight your search pattern, you can even dgn to "select next occurrence and delete it" in one go -- then you can just repeatedly press . until nothing happens ... :help gn. Also, mess around with cgn; it's pretty neat stuff.
Cheers.
Let me jump right in.
What I'm trying to do is simply print out the file path of any open buffer when I exit vim. This is useful because I often open other files in vim buffers with a vim script I wrote that can search through my codebase for a specific function call.
I figure I can set up an autocommand, either for when I open a file or when I leave vim, and use the output from :ls to list all currently open buffers. The problem that I'm having is that I can't get any output to show up in terminal. I have tried various combinations of :!echo in my function, but to no avail. I have been trying something like the following in my .vimrc
function! PrintFileName()
:!echo "hello"
:exec "!echo world"
"... etc
endfunction
au BufRead * call PrintFileName()
Both :!echo foobar and :call PrintFileName() work for me if I do it from the command line. I also figure I might have to use some form of silent/redraw! so I don't have to hit enter to continue.
Really the main problem here is that I can't see a way to get output to stdout from inside my function and called by an autocommand.
Thanks for any help.
Okay, so I've found this solution, which works as long as I enter vim from the last line of my terminal. Otherwise this prints out a line below the current line and will get overwritten when you press enter. If anyone knows how to fix that let me know, otherwise I will use this.
function! PrintBuffers()
redir => files
:ls
redir END
" Regex to strip out everything from :ls but the buffer filenames
let files = substitute(files, '^[^"]*"', '', 'g')
let files = substitute(files, '"[^"]*\n[^"]*"', '\n', 'g')
let files = substitute(files, '"[^"]*$','','g')
" This is the magic line
exe '!echo; echo ' . shellescape(&t_te . files)
endfunction
au VimLeave * call PrintBuffers()
*Note - As I'm writing this, I realize that this won't display the right path if you did a :cd at some point. So I guess its pretty fragile, but it does the job.
I'm looking for some sort of plugin/vi-code that detects if there are any ^M ( carriage returns? ) in any files or any sort of indication that the line endings are not unix, and if so either remove them or run dos2unix on the file.
I need this to work automatically before/during the file opening.
Also, for the people who are going to suggest ways of converting the line endings manually, one answer points out do :set ff=unix but this doesn't kill ^M in a unix file, I think.
And isn't there a trick to using :%s/^M//g because using a literal ^ wont match the char?
The function below is interesting because
it keeps the cursor to its original position
put it in your. vimrc
" dos2unix ^M
fun! Dos2unixFunction()
let _s=#/
let l = line(".")
let c = col(".")
try
set ff=unix
w!
"%s/\%x0d$//e
catch /E32:/
echo "Sorry, the file is not saved."
endtry
let #/=_s
call cursor(l, c)
endfun
com! Dos2Unix keepjumps call Dos2unixFunction()
au BufReadPost * keepjumps call Dos2unixFunction()
Since you flagged this git - you can have git convert line ending s on checkin/out automatically (http://www.kernel.org/pub/software/scm/git/docs/git-config.html)
ps. The trick to doing ^M in a replace is
:%s/{Ctrl+V}{Ctrl+M}//{Enter}
If you want to replace any ^M in any file you open, an autocmd like the following in you vimrc could help:
au BufReadPost * %s/^M//g
Inserting the ^M as has been indicated in the previous answer.
I often want to wipe all buffers loaded with a given extension (usually .rej files produced by patch). Just doing :bw[!] *.rej will complain if there is more than one match. Does anyone have any good tips? Currently I either repeatedly use :bw *.rej + tab-complete or, if there are a lot of buffers, use :ls and :bw a set of buffers by number.
Globbing in vim is a bit difficult (apart from for files on the file system). Therefore, the best way seems to be to convert the wildcard into a regular expression and then check each buffer in the buffer list to see whether it matches. Something like this:
" A command to make invocation easier
command! -complete=buffer -nargs=+ BWipe call BWipe(<f-args>)
function! BWipe(...)
let bufnames = []
" Get a list of all the buffers
for bufnumber in range(0, bufnr('$'))
if buflisted(bufnumber)
call add(bufnames, bufname(bufnumber))
endif
endfor
for argument in a:000
" Escape any backslashes, dots or spaces in the argument
let this_argument = escape(argument, '\ .')
" Turn * into .* for a regular expression match
let this_argument = substitute(this_argument, '\*', '.*', '')
" Iterate through the buffers
for buffername in bufnames
" If they match the provided regex and the buffer still exists
" delete the buffer
if match(buffername, this_argument) != -1 && bufexists(buffername)
exe 'bwipe' buffername
endif
endfor
endfor
endfunction
It can be used as:
:BWipe *.rej
or:
:BWipe *.c *.h
By the way, I ended up going with a very low-tech solution (I personally like to modify vim as little as possible so that I am at home on any machine):
I added a mapping:
:map <C-f> :bw *.rej
Then I repeatedly press
<C-f> <Tab> <CR>
a little bit around the corner, but works for me, with a lot of files:
:mksession!
:q
vi Session.vim
a) remove all 'badd' lines with files you do not want
b) :wq
vim -S Session.vim # restart with the state you had, but without the files
Do CTRL-A to insert all the matches of the pattern in front of the cursor. See :help c_CTRL-A. For example, if you have the files a.rej, b.rej, and c.rej loaded, then doing
:bw *.rej<C-A>
will leave you with
:bw a.rej b.rej c.rej
Then you can press Enter to wipe those buffers.
Any idea on how to delete all the spaces and tabs at the end of all my lines in my code using vim? I sometimes use commands to add things at the end of my lines, but sometimes, because of these unexpected blanks (that is, I put these blanks there inadvertently while coding), which serve no purpose whatsoever, these commands don't do the right job... so i'd like to get rid of the blanks once and for all using some vim command. Thanks in advance!
In vim:
:%s/\s\+$//
Explanation:
: command
% apply to entire file
s search and replace
/\s\+$/ regex for one or more whitespace characters followed by the end of a line
// replacement value of an empty string
I use this function :
func! DeleteTrailingWS()
exe "normal mz"
%s/\s\+$//ge
exe "normal `z"
endfunc
Leader,w to remove trailing white spaces
noremap <leader>w :call DeleteTrailingWS()<CR>
Remove trailing white spaces when saving a python file:
autocmd BufWrite *.py :call DeleteTrailingWS()