Using vim Sessions Only With GUI? - vim

My usage-scenario may seem a bit unusual, but here it is: When using vim (it's one of about 4 different editors I use regularly), I use it in two different situations. The first is via the GUI, in which I'll have multiple buffers and have some settings different than when I use it from the command-line (by testing "if has('gui_running')"). The other is when I need to do something short-and-quick, from the command-line, such as make a small change to a dot-file or other type of config.
What I would like to do, is have sessions enabled for the GUI, but have any command-line invocations ignore them. That is, I don't want to bring up the full existing session on a CL invocation, nor do I want it (and whatever buffer/file it involved) to alter the session that the GUI is using. As I'm fairly new to the post-vi-functionality of vim, I'm not really sure how to pull this off.

do your session magic in your .gvimrc and everything else in your .vimrc. The GUI will source both, but the CL version will only source the .vimrc.
The session magic is to set up autocommands to write your session to a file on exit, and reload it by sourcing the file upon entrance.
au VimLeave * mksession ~/.gvimsession
au VimEnter * source ~/.gvimsession

You may want to add a ! to mksession so that you won't get an override error message upon exiting everytime.
au VimLeave * mksession! ~/.gvimsession
au VimEnter * source ~/.gvimsession

Related

Is that correct `vim -S session` will load `.vimrc` again?

I found out all the settings in .vimrc actually are stored in session file. If that is the case, why vim -S session load .vimrc again? Why does vim design like this?
I have some commands in .vimrc and when I use vim -S, it causes problems because those commands should only be run once, not twice.
Thanks a lot.
My problematic vimrc block in mksession:
let g:netrw_banner = 0
let g:netrw_liststyle = 3
let g:netrw_browse_split = 4
let g:netrw_altv = 1
let g:netrw_winsize = 25
augroup ProjectDrawer
autocmd!
autocmd VimEnter * :Vexplore
autocmd TabNew * call feedkeys(":Vexplore\<CR>", 'n')
augroup END
What a session stores
What gets stored in a saved session is controlled by the :help 'sessionoptions' option. It's defaults are very conservative, aimed at not losing any ad-hoc mappings or changed options.
However, most users place their settings in the ~/.vimrc, use plugins and filetype plugins, and generally do not make up mappings or change settings on the fly. If that kind of workflow also applies to you, I'd suggest to remove the following values:
:set sessionoptions-=globals
:set sessionoptions-=localoptions
:set sessionoptions-=options
You may also want to remove buffers and resize, too. That change not just reduces the size of the saved session, it also prevents that an old session overrides any configuration that you've changed in your ~/.vimrc in the meantime.
vimrc reload
So, your ~/.vimrc isn't directly reloaded, but (with default 'sessionoptions'), a lot of options and variables are restored.
By using :augroup followed by :autocmd!, you've also avoided a frequent beginner's mistake: Without that, the autocmds would be redefined on each reload of your ~/.vimrc. The :autocmd! prevents that, and the :augroup makes that apply just to your own group.
sessions and special (plugin) buffers
A session should store all currently open buffers. Regular buffers contain file contents, and these can easily be reloaded when a session is opened again. Unfortunately, plugins (mis-)use buffers for their user interfaces (e.g. a sidebar, as by the netrw plugin), and Vim's session handling is not clever enough to distinguish between the two. But those plugin buffers have no corresponding file; instead, the plugin used command to directly build and modify its contents, often with the help of plugin variables that - see above - either are or aren't saved and restored.
Plugins would have to explicitly handle session restoration; I don't remember any plugin that does this, though. So often, you'll see an "empty" window restored, and the plugin may or may not recognize or reuse that. (And I think that's the problem you're asking about.)
The general recommendation is to close any plugin buffers before saving a session, either manually, or by writing a custom :Mksession wrapper that automates this for you. On session reload, your configuration may then create a fresh, functional plugin window again. (Or you have to trigger that manually.)
Not all the settings from the vimrc are stored in the session file (see :h mksession). The settings you see are specified in the :h sessionoptions option.
You can load a session without loading the vimrc by using vim -u NORC -S; however, you'll quickly see you're missing your desired baseline settings.
Which commands should only be run once? There are specific ways to prevent commands from running twice unnecessarily when sourcing your vimrc.
For instance, if the command that should only be run once is an autocmd you should use an augroup like so:
augroup vimrc
autocmd! " Remove all vimrc autocommands
au BufNewFile,BufRead *.html so <sfile>:h/html.vim
augroup END

Set autocmd for every time I change file

How can I set up a autcmd command for every time I switch to another file?
I want to call to a Rooter command (a plugin for setting the root directory).
What I've tried:
au BufEnter * Rooter
But it's not working always, sometimes when I select a file from MRU for instance.
How can I set up a autcmd command for every time I switch to another file?
From your description, I think you need event BufLeave ?
if your Rooter() is a function,
au BufLeave * call Rooter()
What you are after it is already implemented in the plugin itself:
see: vim-rooter's source code
So no need to implement it yourself. I think you should make plugin, buffer local! so replace all occurances of g:loaded_rooter with b:loaded_rooter in source code. then save, close vim, open and test.

is it possible to set BufLeave autocmd in vim on the fly?

What I want to do:
Inside a file/buffer in vim, especially an unnamed one (for example, created with :enew), sometimes I feel the content I'm writing is worth saving (say, I suddenly want to send it via an email), but don't feel the particular need to save it to a temp file, nor do I trust myself enough to "remember" to save it upon exit.
So I thought, what if I run
autocmd BufLeave * ggvG"+y
in the vim command line once and be free from the fear of losing this content.
But it doesn't work. When I exit vim, the system clipboard reminds intact.
My questions:
does it do anything if we run autocmd on the fly, as opposed to in vimrc?
is there a way to tell vim to "hey, when you exit, run these"?
Thanks a ton!
Two problems:
1) You didn't leave the buffer to go to another buffer (BufLeave); you left Vim (VimLeave).
2) autocmd expects a command, not normal mode keystrokes.
With that in mind,
autocmd VimLeave * normal gg"+yG

`vimdiff` not compatible with autocmd?

I was used to use vimdiff and loading the compared files.
Now, on vimdiff execution, it happens:
"a" [readonly] 5454L, 269796C
"b" [readonly] 241L, 10170C
Press ENTER or type command to continue
The only configuration change is the introduction of these two autocmd instructions:
autocmd BufNewFile * call s:Function()
autocmd BufReadPre * call s:Function()
Can this be a normal behavior? Can it be a mistake of mine? Can be something depending on Vim versioning? Can the desired configuration change be combined with a straightforward vimdiff load (no ENTER key needed to continue)?
The dreaded hit-enter prompt is usually triggered by additional :echo[msg] commands, here inside your s:Function(). Either remove them, or silence the output via :silent:
autocmd BufNewFile * silent call s:Function()
If you want to keep whatever messages are displayed in your function, you can set your 'cmdheight' option higher to allow displaying more messages before the "hit enter" prompt appears. This, and other suggestions here: http://vim.wikia.com/wiki/Avoiding_the_"Hit_ENTER_to_continue"_prompts

How to automatically change keyboard layout on switch to vim normal-mode?

Sometimes I use vim to write non-US text, and when I wanna use any command in normal mode, I need to change layout to US. It's possible to do that automatically?
PS. I can do mapping like this, but in this case command looks like :ц instead :w - not pretty and typo-risk.
Update
I don't want to use keymap option, because I prefer switch languages by CapsLock.
I've try to write autocmd for InsertLeave event, but failed...
Update 2
Probably anybody know, why the following not work?
function SetUsLayout()
!setxkbmap us,ru
endfunction
autocmd InsertLeave * call SetUsLayout()
:help langmap
is likely to provide all the info you need.
Looks like, that cross-platform solution doesn't exist... So, under KDE I use the following:
function! SetUsLayout()
silent !qdbus org.kde.keyboard /Layouts setLayout us > /dev/null
endfunction
autocmd InsertLeave * call SetUsLayout()
For me, using qdbus is the best option. I've made a simple but fragile plugin that works really well for me: https://github.com/ironhouzi/bikey-vim/tree/master/plugin
I call it fragile, since it doesn't have much robustness to it if anybody else wants to use it.
I mostly want English when I'm using Vim, with a few exceptions. When I want to write in my native language, I hit 'leader'-k and my airline status bar will show that I've switched language. When the language is not English, the script will ensure that every time I enter insert mode, my native language is set through qdbus. Every time I leave insert mode, the language is set back to English. It also supports individual settings between buffers. Even though this might not be the best way to do things, I thought I'd share it, in case someone else might get some use out of it.
In Ubuntu I use the following:
function! SetUsLayout()
silent !qdbus org.gnome.SettingsDaemon.Keyboard /org/gnome/SettingsDaemon/Keyboard org.gnome.SettingsDaemon.Keyboard.SetInputSource 0 > /dev/null
endfunction
autocmd InsertLeave * call SetUsLayout()
or shorter
silent !gsettings set org.gnome.desktop.input-sources current 0

Resources