Why is my Vim starting in replacemode? - vim

I may have accidentally changed some setting but now I can't figure out what it is.
Behavior:
Whenever I edit an existing file, Vim starts in replace (R) mode. This is new as of this week.
Whenever I do vim nonExistantFile.txt, Vim starts in normal mode
Steps so far to diagnose:
/etc/vimrc has nothing relevant, and specifically does not contain startreplace
/home/<myuser>/.vimrc has nothing relevant, and specifically does not contain startreplace
alias shows nothing vim related
Platform info:
Vim version 7.3.1314
Windows 7 64-Bit
32 Bit Cygwin and Vim binary
Other potentially relevant information:
Some time ago (before this started happening) I copied /etc/vimrc from my CentOS 6.4 machine into the Cygwin /etc/vimrc
I edited some binary files recently
I'm pretty stumped, I can't think of anything else to try.
Update:
I have narrowed the problem down to this /etc/vimrc snippet
Oddly commenting out EITHER of these two commands solves the problem
Vimrc snippet (note: this does have unix line endings):
" Only do this part when compiled with support for autocommands
if has("autocmd")
"<snip>
" When editing a file, always jump to the last cursor position
autocmd BufReadPost *
\ if line("'\"") > 0 && line ("'\"") <= line("$") |
\ exe "normal! g'\"" |
\ endif
" don't write swapfile on most commonly used directories for NFS mounts or USB sticks
autocmd BufNewFile,BufReadPre /media/*,/mnt/* set directory=~/tmp,/var/tmp,/tmp
"<snip>
endif

I mapped nnoremap <ESC> :nohlsearch<CR> in my .vimrc and that caused this behaviour.
Mapping this to <Enter> solved the problem for me.

check ~/.exrc files for initial settings, there must be a flag setting your vi into REPLACE mode at startup!
http://alvinalexander.com/unix/edu/un010003/
cheers!

I added a few newlines and swapped the two commands in /etc/vimrc that seemed to be causing the problem... and this seemed to fix it. I have no idea why.

The following seemed to fix this problem for me. I think that there was some autocommand code that interfered with the cursor position restore, so clearing out previous autocommands as below fixed the problem for me:
function! ResCur()
if line("'\"") <= line("$")
normal! g`"
return 1
endif
endfunction
augroup resCur
autocmd!
autocmd BufWinEnter * call ResCur()
augroup END
http://vim.wikia.com/wiki/Restore_cursor_to_file_position_in_previous_editing_session

Related

Keeping view of edited file after exiting vim

When I quit vim, the display reverts to whatever I was seeing before I entered. On non-vim vi, you keep the vi screen intact except for the bottom line.
Is there an option in vim that allows that latter behaviour?
Vim uses a terminal feature called the alternate screen to write its UI there, and restore the original shell contents (where Vim was launched from) on exit. This is controlled by two ANSI escape sequences (see how does vi restore terminal content after quitting it).
You can disable that from within Vim by clearing the corresponding terminal settings. Put the following into your ~/.vimrc:
set t_ti= t_te=
Alternatively, you could also disable this capability in the terminal; at least the multiplexers screen and tmux allow this. See Prevent Applications Like Vim and Less Clearing Screen on Exit for details.
May be this is what you are looking for, just paste the below commands in your .vimrc. I got it from some where in the net.
" Return to last edit position when opening files
autocmd BufReadPost *
\ if line("'\"") > 0 && line("'\"") <= line("$") |
\ exe "normal! g`\"" |
\ endif

Vim unwanted jump to end of file after write

When I write to a file with :w, vim sometimes (NOT ALWAYS) jumps to the end of the file after the write operation is complete. I don't understand why this happens. I've been going through my .vimrc to see if I have some kind of bug. My .vimrc is quite large so I don't include the full source here, I think the only parts of my .vimrc which are perhaps relevant to this question are the following parts:
nore ; :
inoremap jj <Esc>
" Automatically remove all trailing whitespace.
" Every time the user issues a :w command, Vim will automatically remove all
" trailing whitespace before saving
autocmd BufWritePre * :%s/\s\+$//e
" Restore cursor position
au BufReadPost *
\ if line("'\"") > 0|
\ if line("'\"") <= line("$")|
\ exe("norm '\"")|
\else|
\exe "norm $"|
\endif|
\endif
However I don't see how these parts of my .vimrc can cause the jump behavior after writing, a full source of my .vimrc is available here. I hope somebody has an idea about what is causing the unwanted jump.
Here is a command from my ~/.vimrc:
command! -range=% TR mark `|execute <line1> . ',' . <line2> . 's/\s\+$//'|normal! ``
The trick is to create mark ` before the trimming and jump back to it afterward.
You can change your autocmd to:
autocmd BufWritePre * :mark `|%s/\s\+$//e|normal! ``
Even with #romainl's addition of the mark, this still isn't fully transparent:
the view (of displayed lines) may still change (winsaveview() instead of a mark would fix that)
the :s command clobbers the last search pattern
A plugin (like my DeleteTrailingWhitespace plugin) would provide a more robust solution. (The plugin page has links to alternative plugins.)

How to modify the last-position-jump vimscript to not do it for git commit messages

Here's the script for convenience:
" Uncomment the following to have Vim jump to the last position when
" reopening a file
if has("autocmd")
au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$")
\| exe "normal! g'\"" | endif
endif
The feature is excellent but not when used with certain cases where Vim is invoked as editor: For instance often I write a two line git commit message so the next time I commit it's gonna drop me on the second line and I have to adjust for this.
Similarly many other systems allow you to specify Vim to be used as an editor as part of some process that involves editing a file.
How can we detect this and modify our last-position-jump script? Git's actually kind of special because it uses the .git/COMMIT_EDITMSG file which stays the same across commits which is why this is happening. With a temp file it wouldn't occur on files that Vim hasn't seen before.
This probably makes the task nearly trivial (augment the script with a check if current file == COMMIT_EDITMSG...)
But, a really perfect answer is if we can detect whether Vim is invoked from the command line or if it was opened by a script. Is there a way to tell? I know unix programs can determine if they are running in a term/pseudoterm or not, though either way they do end up receiving input from the terminal.
If you don't want to modify the global rule (like in FDinoff's answer) with all sorts of exceptions, you can also undo the jump by putting the following into ~/.vim/after/ftplugin/gitcommit.vim:
:autocmd BufWinEnter <buffer> normal! gg0
Though I haven't experienced any problems with the above command, even on buffer switches, a more robust version makes the autocmd fire once:
augroup DisableLastPositionJump
autocmd! BufWinEnter <buffer> execute 'normal! gg0' | autocmd! DisableLastPositionJump BufWinEnter <buffer>
augroup END
Git commit messages have the filetype gitcommit.
Just add a check to see if the file is not of the gitcommit filetype for deciding when to jump to the last position.
if has("autocmd")
au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") && &filetype != "gitcommit"
\| exe "normal! g'\"" | endif
endif
If you don't want VIM to remember where you were from the previous commit, set the following in ~/.vimrc:
autocmd FileType gitcommit call setpos('.', [0, 1, 1, 0])
Source: http://vim.wikia.com/wiki/Always_start_on_first_line_of_git_commit_message

Prevent Vim from clearing the clipboard on exit

When I open Vim from a terminal, copy some text to the system clipboard, and exit Vim, the system clipboard gets cleared.
How to keep the copied text in the clipboard?
Synthesizing answers from superuser, just add the following to your .vimrc
autocmd VimLeave * call system("xsel -ib", getreg('+'))
Install Parcellite, or glipper for Gnome and klipper for KDE.
Restart your computer or run it manually.
see: https://wiki.ubuntu.com/ClipboardPersistence
Based on Matt's answer, the following uses xclip instead of xsel:
autocmd VimLeave * call system('echo ' . shellescape(getreg('+')) .
\ ' | xclip -selection clipboard')
I ran into this issue and a related problem where suspending vim with ctrl-z would also clear the clipboard. I've extended Matt's solution to fix both:
set clipboard=unnamedplus
if executable("xsel")
function! PreserveClipboard()
call system("xsel -ib", getreg('+'))
endfunction
function! PreserveClipboadAndSuspend()
call PreserveClipboard()
suspend
endfunction
autocmd VimLeave * call PreserveClipboard()
nnoremap <silent> <c-z> :call PreserveClipboadAndSuspend()<cr>
vnoremap <silent> <c-z> :<c-u>call PreserveClipboadAndSuspend()<cr>
endif
The if executable("xsel") guard is there to avoid errors if xsel is not installed. The nnoremap mapping preserves the clipboard when suspending from normal mode and the vnoremap mapping handles suspending from visual or select modes.
I've confirmed this works on vim 7.4 and 8.0.
Use NeoVim. It by default doesn't clear the clipboard on exit. You will still need to set clipboard=unnamedplus (typically in ~/.config/nvim/init.vim) and have xsel or xclip tools installed.
Keep in mind that some other defaults are different as well.
Please correct me if I'm wrong but from my understandings of Vim...
1) Vim uses registers instead of the clipboard to store copied/cut data.
2) These registers are preserved when exiting vim in a status file but are not accessible outside of the running process unless you manually open the file and inspect its contents
3) Saving stuff to the + registre while Vim runs allows you to paste to other applications.
4) By suspending vim (CTRL-Z) instead of closing it, these registers are still accessible.
Does that provide assistance?
Based on Matt's answer
When using his method copying multiple lines added slashes to the end of lines when pasting.
This should remedy that.
autocmd VimLeave * exe ":!echo " . shellescape(getreg('+')) . " | xclip -selection clipboard"
When i used "shellescape" with "system" newlines kept getting escaped. But that didn't happen when i used exe.
Don't know the real reason. but this worked.

vim restores cursor position; exclude special files

The following code is inside my .vimrc and generally restores the last cursor position of a file I opened with vim:
autocmd BufReadPost *
\ if line("'\"") > 1 && line("'\"") <= line("$") |
\ exe "normal! g`\"" |
\ endif
I really like this feature and want to leave it turned on, except for one file: When commiting with git, vim gets fired up and I can edit the commit message with it. However the commit message file exists before vim starts (and is prefilled), so vim sees it as an existing file and restores the last cursor position (which is usually not where I would like to start to type).
So is there a possibility to modify the above script to exclude the COMMIT_EDITMSG file?
After reading through the manual on auto commands, I noticed that it seems not possible to define the pattern they match to in such a way that they exclude a special pattern. And I also wasn't able to use some variable that contains the current filename, so that I simply expand the existing if to exclude the file.
However, based on the comment by Pavel Shved (about the gg moving to the top of the file) I thought that in the same way it should be possible to simply overwrite the effect of the position restoring, by simply moving it to the top later again. So I came up with this:
autocmd BufReadPost COMMIT_EDITMSG
\ exe "normal! gg"
Placing this after the previous autocmd BufReadPost simply chains the event execution, so vim, after executing the first and restoring the position, reads this and matches it on the excluded filename and uses the gg to move the cursor to the top, basically overwriting the effect of the original autocmd.
And that works just fine :)
I understand you have already come up with a solution but I had the same question and came up with an alternative that doesn't require chaining.
function! PositionCursorFromViminfo()
if !(bufname("%") =~ '\(COMMIT_EDITMSG\)') && line("'\"") > 1 && line("'\"") <= line("$")
exe "normal! g`\""
endif
endfunction
:au BufReadPost * call PositionCursorFromViminfo()
You should probably investigate mksession. You can set up VimEnter/VimLeave auto commands to "do the right thing" when you have specified files on the command line (as when git invokes vim). There are numerous scripts for this floating around, see http://vim.wikia.com/wiki/Working_with_multiple_sessions for example.
Try this, its move cursor to last position
set hidden
Put the following lines instead of your lines in the .vimrc:
au BufWinLeave * mkview
au BufWinEnter * silent loadview
Adding the following to .vimrc worked for me:
au FileType gitcommit au! BufEnter COMMIT_EDITMSG call setpos('.', [0, 1, 1, 0])
(from https://vim.fandom.com/wiki/Always_start_on_first_line_of_git_commit_message)

Resources