only auto-reload session when I start vim with no parameter - vim

here's a piece of my ~/.vimrc file:
autocmd VimEnter * : call ReadSession()
autocmd VimLeave * : call SaveSession()
function SaveSession()
execute 'mksession! ' . getcwd() . '/.session.vim'
endfunction
function ReadSession()
let session_file = getcwd() . "/.session.vim"
if filereadable( session_file )
execute "so " . session_file
if bufexists(1)
for l in range(1, bufnr('$'))
if bufwinnr(l) == -1
exec 'sbuffer ' . l
endif
endfor
endif
endif
endfunction
So it will reload a session even if I don't want it to
For example I call "vim 1.cpp" in a dirctory I once worked in(editing 2.cpp), then it will first show me 2.cpp
Can I modify the .vimrc so that if I pass parameters to vim, it won't read the session file? thanks!
EDITING:
I added a line
if (argc() > 0)
exec 'bfirst'
endif
but it still don't work.

Checking argc() is indeed the way to go. You can skip the execution of ReadSession() when parameters are passed:
autocmd VimEnter * if argc() == 0 | call ReadSession() | endif
Or put the condition into the ReadSession() function.

Related

Using template files in Vim

I am trying to use a template for Ruby files, by adding this to my .vimrc:
function! RubyTemplate()
" Add pragma comment
call setline(1, '# frozen_string_literal: true')
" Add two empty lines
call append(1, repeat([''], 2))
" Place cursor on line number 3
call cursor(3, 0)
endfunction
autocmd BufNewFile *.rb :call RubyTemplate()
However, this doesn't work and when I open a new Ruby file, it's empty.
Everything works as expected if I issue an :e! afterwards. However, this doesn't work if I add e! to the function, so I have to manually fire it every time.
What am I doing wrong?
You can use a static template file instead of invoking a function.
For instance, you can create a template file for your ruby scripts in your vim directory as ~/.vim/skeletons/ruby.skel, with the desired contents.
1 # frozen_string_literal: true
2
3
Then in your vimrc you should add the following code:
" Skeleton for .rb files
augroup ruby
" Remove all existing autocommands in the group
au!
au BufNewFile *.rb 0r ~/.vim/skeletons/ruby.skel
augroup end
Noah Frederick has an elegant solution that allows us to insert snippets manually or automatically.
It uses ultisnips plugin and two files
" after/plugin/ultisnips_custom.vim
if !exists('g:did_UltiSnips_plugin')
finish
endif
augroup ultisnips_custom
autocmd!
autocmd BufNewFile * silent! call snippet#InsertSkeleton()
augroup END
and
" autoload/snippet.vim
function! s:try_insert(skel)
execute "normal! i_" . a:skel . "\<C-r>=UltiSnips#ExpandSnippet()\<CR>"
if g:ulti_expand_res == 0
silent! undo
endif
return g:ulti_expand_res
endfunction
function! snippet#InsertSkeleton() abort
let filename = expand('%')
" Abort on non-empty buffer or extant file
if !(line('$') == 1 && getline('$') == '') || filereadable(filename)
return
endif
call s:try_insert('skel')
endfunction
In my case, I have done some changes but now if I create an empty python file, for example, I end up with:
An important note: In my case, if vim or neovim is not detecting the filetype correctly, and it can be done with auto commands, your automatic snippet insertion will not work.

Vim: Add two lines after auto shebang

I have set my .vimrc to automatically add a shebang line, as below:
autocmd BufNewFile * execute 'silent! 1s/.*/#!\/usr\/bin\/env ' . (empty(&filetype) ? '' : ' '.&filetype)
However, I would like it to also add two lines below it and go into insert mode. When I simply add $i to the end of the command, as below, I get an error. Ideas?
autocmd BufNewFile * execute 'silent! 1s/.*/#!\/usr\/bin\/env ' . (empty(&filetype) ? '' : ' '.&filetype) $<CR><CR>i
You can use this:
autocmd BufNewFile * if !empty(&filetype) | execute 'silent! 1s/.*/#!\/usr\/bin\/' . &filetype . '\r\r'| :startinsert | endif
Btw, neat thinking, I'm adding this to my vimrc :)

Custom script for git blame from vim

I want a minimum way of using git blame from vim (I don't want to use the whole Fugitive plugin). What I have right now is this:
This function is from the vim help page and enables me to open shell commands in a scratch buffer.
function! s:ExecuteInShell(command)
let command = join(map(split(a:command), 'expand(v:val)'))
let winnr = bufwinnr('^' . command . '$')
silent! execute winnr < 0 ? 'botright new ' . fnameescape(command) : winnr . 'wincmd w'
setlocal buftype=nowrite bufhidden=wipe nobuflisted noswapfile nowrap number
echo 'Execute ' . command . '...'
silent! execute 'silent %!'. command
silent! execute 'resize ' . line('$')
silent! redraw
silent! execute 'au BufUnload <buffer> execute bufwinnr(' . bufnr('#') . ') . ''wincmd w'''
silent! execute 'nnoremap <silent> <buffer> <LocalLeader>r :call <SID>ExecuteInShell(''' . command . ''')<CR>'
echo 'Shell command ' . command . ' executed.'
endfunction
command! -complete=shellcmd -nargs=+ Shell call s:ExecuteInShell(<q-args>)
Together with the above function I would like to do:
noremap <leader>b :Shell git blame -L line(".") - 5, line(".") + 5 %<cr>
to get a git blame window for the rows around the cursor position in the current buffer.
Now I have two questions:
1: How can I make the scratch buffer that opens read-only so I can close it using only q? I would like to make this change in the function so that all: Shell commands can be closed with q.
2: How can i get line(".") - 5 expand into current line - 5 row number?
To make a buffer read-only and not modifiable, you can put
setlocal readonly nomodifiable
at the end of your function.
In the case of your next question, you can use execute and eval
noremap <leader>b :execute "Shell git blame -L " . eval(line(".")-5)) . ",+10 %"<cr>
I recommend to read these descriptions, and help in general:
:h execute
:h eval
:h readonly
:h nomodifiable
Also here is the link to the mentioned function on wikia.
I use a simple hack to get my vim git integration:
This solves my git commit/add , blame and op.
map <F5> :!git add %;git commit -m "commit" %<CR>
map <F3> :!git blame % > %.blame<CR>:vsplit %.blame<CR>
map <F4> :!git log --abbrev-commit % > %.log<CR>:vsplit %.log<CR>
i have something here, the script can be copied and added to the .vimrc file.
command Blame will run git blame on the current file, will split the screen and put the result of 'git blame -w' into the lower buffer (buffer is put into read only mode), your cursor will be in the blame buffer (current line as in source file)
while in the lower buffer: GShow will split the lower screen and open the commit 'git show -w [hash]' for the current line in the right hand buffer (buffer again in read only mode).
"======================================================
" Function runs git blame on file in current buffer and
" puts output into a new window
" move to current line in git output
" (can't edit output)
"======================================================
command! -nargs=* Blame call s:GitBlame()
function! s:GitBlame()
let cmdline = "git blame -w " . bufname("%")
let nline = line(".") + 1
botright new
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
execute "$read !" . cmdline
setlocal nomodifiable
execute "normal " . nline . "gg"
execute "set filetype=cpp"
endfunction
"======================================================
" function runs git show on report of git blame;
" the first token of a line is taken as SHA checsum of the
" git commit
"======================================================
command! -nargs=* GShow call s:GitShowFromBlame()
function! s:GitShowFromBlame()
let curline = getline( "." )
let tokens = split(curline)
let cmdline = "git show -w " . tokens[0]
"botright new
"topleft new
"vsplit new
"vnew new
vertical new
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
execute "$read !" . cmdline
setlocal nomodifiable
execute "normal 1gg"
execute "set filetype=cpp"
endfunction
My take on this
fun! GbSyncLines(is_ow2bw)
let l:ow = getbufvar(+expand('<abuf>'), 'origWindow')
let l:bw = getbufvar(+expand('<abuf>'), 'blameWindow')
let l:origLine=line('.', win_getid(l:ow))
let l:blameLine=line('.', win_getid(l:bw))
if a:is_ow2bw == 1
eval win_execute(win_getid(l:bw), "windo call cursor(" . l:origLine . ", 0)")
else
eval win_execute(win_getid(l:ow), "windo call cursor(" . l:blameLine . ", 0)")
endif
endfun
fun! GbMake(view, origWindow)
let l:origWindow=a:origWindow
let l:file_dir=expand('#'.winbufnr(a:origWindow).':h')
let l:file_name=expand('#'.winbufnr(a:origWindow).':t')
let l:origLine=line('.', win_getid(a:origWindow))
sil exe a:view
setl buftype=nofile bufhidden=wipe
exe "lcd ".l:file_dir
exe "0r ! git blame " . l:file_name
setl nomodifiable
setl nonumber norelativenumber
if v:shell_error != 0
exe l:origWindow . "wincmd w"
return
end
eval searchpos('(')
eval searchpairpos('(', '', ')')
norm! gE
exe "vertical resize " . col('.')
let l:blameWindow = winnr()
let b:blameWindow = winnr()
let b:origWindow = a:origWindow
let l:origLine=line('.', win_getid(b:origWindow))
eval cursor(l:origLine , 1)
nnoremap <buffer> <C-]> :call GcommitShow(expand("<cword>"), line(".")) <CR>
au BufWipeout <buffer> call win_execute(win_getid(getbufvar(+expand('<abuf>'), 'origWindow')), "windo setl scrollbind&")
au WinEnter <buffer> :call GbSyncLines(1)
au WinLeave <buffer> :call GbSyncLines(0)
setl scrollbind
exe a:origWindow . "wincmd w"
setl scrollbind
exe "syncbind"
if a:view == "enew"
exe l:blameWindow . "wincmd w"
end
endfun
fun! GcommitShowClose()
let l:w=getbufvar(expand('<abuf>'), 'origWindow')
let l:l=getbufvar(expand('<abuf>'), 'origLine')
let l:v=getbufvar(expand('<abuf>'), 'origView')
eval GbMake("enew", l:w)
eval winrestview(l:v)
eval cursor(l:l, 1)
endfun
fun! GcommitShow(commit, linenr)
let l:origWindow=b:origWindow
let l:viewsave=winsaveview()
sil exe "enew | setlocal buftype=nofile | setlocal bufhidden=wipe | 0r ! git show " . a:commit
setl nomodifiable
setl nonumber norelativenumber
if v:shell_error != 0
eval GbMake('enew', l:origWindow)
return
end
let b:origWindow=l:origWindow
let b:origLine=a:linenr
let b:origView=l:viewsave
nnoremap <buffer> <C-O> :call GcommitShowClose()<CR>
eval cursor(1, 1)
endfun
fun! Gb()
eval GbMake('vnew', winnr())
endfun
command! Gb call Gb()
while in the blame window, CTRL+] shortcut will show git show for commit the cursor is on. Then CTRL+O will get back to the git blame.
Note lcd on start - command will work even when you are not in the git dir. The gist

Vim split causes syntax highlight to turn on

I am trying to write a function to cause vim to open the relative header/source file in a split window.
What I have works (see below) apart from the file it opens in the split doesn't have syntax highlighting.
function! SplitOther()
let s:fname = expand("%:p:r")
if expand("%:e") == "h"
set splitright
exe "vsplit" fnameescape(s:fname . ".cpp")
elseif expand("%:e") == "cpp"
set nosplitright
exe "vsplit" fnameescape(s:fname . ".h")
endif
endfunction
autocmd! BufReadPost *.h,*.cpp call SplitOther()
I have tried appending syntax on to the command (just before the endfunction) but that doesn't seem to want to work.
I think it happens when the file isn't in a buffer before splitting? I'm not 100% sure though.
Edit
I change my function to have allow the definition of file pairs, I'm not sure if it will change my question at all so here's the extended version:
function! SplitOther()
let s:pairs = [ [ "h", "cpp" ], [ "vert", "frag" ] ]
let s:fname = expand("%:p:r")
for [s:left, s:right] in s:pairs
if expand("%:e") == s:left
set splitright
exe "vsplit" fnameescape(s:fname . "." . s:right)
elseif expand("%:e") == s:right
set nosplitright
exe "vsplit" fnameescape(s:fname . "." . s:left)
endif
endfor
endfunction
autocmd! BufReadPost * call SplitOther()
Got it!
When the file was being loaded into the vsplit it's filetype wasn't being set.
I noted that when vsplit is called the new split grabs focus and that is the window that does not have syntax highlighting so you can simply add exe "filetype" "detect" at the end of the function to tell vim to detect the filetype of the current window.
The result:
function! SplitOther()
let s:pairs = [ [ "h", "cpp" ], [ "vert", "frag" ] ]
let s:fname = expand("%:p:r")
for [s:left, s:right] in s:pairs
if expand("%:e") == s:left
set splitright
exe "vsplit" fnameescape(s:fname . "." . s:right)
break
elseif expand("%:e") == s:right
set nosplitright
exe "vsplit" fnameescape(s:fname . "." . s:left)
break
endif
endfor
exe "filetype" "detect"
endfunction
autocmd! BufRead * call SplitOther()
The problem is that filetype detection is triggered by an autocmd, but by default, autocommands do not nest (cp. :help autocmd-nested).
Also, by using :autocmd! with a bang, you're clearing all other such global autocmds; this might affect other customizations or plugins! You should define your own scope via :augroup, then it's safe. Taken together:
augroup MyAltSplitPlugin
autocmd! BufReadPost * nested call SplitOther()
augroup END

Can an autocmd be turned on/off?

I have follwing in my .vimrc to hightlight all words that matches the one on current cursor
autocmd CursorMoved * silent! exe printf('match Search /\<%s\>/', expand('<cword>'))
But sometimes it is a little annoying, so I'd like to map a key to turn on or off it, e.g. <F10>
How can I do this?
Clear the autocommand and remove highlight:
nmap <f8> :autocmd! CursorMoved<cr> :call clearmatches()<cr>
and to turn it back on using a different key:
nmap <f9> :autocmd CursorMoved * silent! exe printf('match Search /\<%s\>/', expand('<cword>'))<cr>
Put the following in your .vimrc:
let g:toggleHighlight = 0
function! ToggleHighlight(...)
if a:0 == 1 "toggle behaviour
let g:toggleHighlight = 1 - g:toggleHighlight
endif
if g:toggleHighlight == 0 "normal action, do the hi
silent! exe printf('match Search /\<%s\>/', expand('<cword>'))
else
"do whatever you need to clear the matches
"or nothing at all, since you are not printing the matches
endif
endfunction
autocmd CursorMoved * call ToggleHighlight()
map <F8> :call ToggleHighlight(1)<CR>
The idea is, if you call the function with an argument it changes the behavior to print/no print.
The autocommand just uses the last setting because the function there is called without an argument.

Resources