33

I like to split my vim screen in 3. one :vsplit and one :split. I want these windows and the files I worked on to be saved when I close vim. I also want these windows to automatically load when I start vim.

I tried to install gsessions (just added the file to the plugin folder), but nothing happend. I am new to vim so I don't know exactly how the configuration works.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
ganjan
  • 7,356
  • 24
  • 82
  • 133
  • 3
    Do you know about the built in session management that vim has? It's not automatic but it can save loads of time. `:mksession` before leaving vim, `vim -S Session.vim` to load that session at a later date. – Randy Morris Feb 28 '11 at 15:07
  • A word of caution about auto saving sessions on exit: if you are not careful, you might overwrite a session file with a corrupt one if vim crashes on exit (it happened to me once). – puk Feb 29 '12 at 09:47
  • Or maybe you really wanted to make Vim save when it lost focus but you didn't know you could do that: https://vim.fandom.com/wiki/Auto_save_files_when_focus_is_lost – NeilG Feb 10 '21 at 11:22

10 Answers10

31

I modified 2ck's script slightly to save a .session.vim in your current working directory instead of the directory where your current open file is in.

Also, it checks if the file exists before sourcing it.

fu! SaveSess()
    execute 'mksession! ' . getcwd() . '/.session.vim'
endfunction

fu! RestoreSess()
if filereadable(getcwd() . '/.session.vim')
    execute 'so ' . getcwd() . '/.session.vim'
    if bufexists(1)
        for l in range(1, bufnr('$'))
            if bufwinnr(l) == -1
                exec 'sbuffer ' . l
            endif
        endfor
    endif
endif
endfunction

autocmd VimLeave * call SaveSess()
autocmd VimEnter * nested call RestoreSess()
0andriy
  • 4,183
  • 1
  • 24
  • 37
Wolph
  • 78,177
  • 11
  • 137
  • 148
  • 4
    I like "syntax on"... but maybe it doesn't belong here? – ErichBSchulz Dec 29 '12 at 03:59
  • 1
    @ErichBSchulz: somehow it didn't turn on syntax highlighting for me without that. But it might be something specific to my setup or something. – Wolph Dec 29 '12 at 23:29
  • Christ that's a lot of trailing spaces. You must have had your terminal fullscreen when you copied that out. – Steven Lu Dec 11 '13 at 18:43
  • I tried adding this to my vimrc but got some very strange interactions with the RestoreSess and my after/plugin/*.vim scripts. Basically whenever it runs RestoreSess, my after/plugin/*.vim scripts fail to run. Can't really figure it out, so I'll have to find another way to autosave my sessions... – Steven Lu Dec 11 '13 at 19:32
  • It shouldn't really interact with the other scripts but restoring the state can have some weird effects. This is pretty much _the_ way of saving/restoring sessions in Vim though, the question is just if the `VimEnter` is the right moment for restoring the session. You can play around with that maybe? – Wolph Dec 11 '13 at 21:06
  • 1
    If you see your syntax highlighting going away on session load then change the last line into "autocmd VimEnter * nested call RestoreSess()" That is add nested before call. Adding it eliminate the need to call "syntax on". Adding it might also fix the problems of other plugins being not loaded. – CDR Aug 01 '15 at 08:09
  • No improvements to add. I made a rather childish 'yeessss!' sound when this worked. btw I'm using this in Vim 8.0 in `cmd.exe`, so in general my hopes that something will work are very low. – icc97 Apr 20 '17 at 22:53
  • I found it useful to add a check for `empty(argv())` in both `SaveSess` and `RestoreSess` to ignore the session if you specify a file parameter e.g. `vim myfile.py` otherwise I found a) you end up with `.session.vim` files all over the place, b) loading in a file with a session caused my Vim to open up all buffers in the session as windows. – icc97 Jun 21 '17 at 19:06
  • **warning** I found loading sessions this way caused (hard to spot) problems with some plugins, [vim-airline](https://github.com/vim-airline/vim-airline) (see the [mistaken bug I raised](https://github.com/vim-airline/vim-airline/issues/1505)) and [UltiSnips](https://github.com/SirVer/ultisnips) and potentially others. I'm not sure if this was because the you need to clear the session after loading a plugin or becuase of some issue with `RestoreSess`. For now I still save the session, but restore the session using the `vim -S .session.vim` command line method for restoring the session. – icc97 Jul 20 '17 at 00:18
  • I still get the same errors even when loading the session via the `-S` arguement. There is another [SO question](https://stackoverflow.com/questions/37984348/make-session-settings-saving-function-play-nice-with-ultisnips) hitting the same problem. – icc97 Jul 20 '17 at 00:56
  • This is amazing! Is there a way to quit vim with an argument that will not save the session? If you are just going in and out of a file? Thanks – MaxxD17 Feb 08 '23 at 16:53
  • @MaxxD17 One option would be to set a variable and skipping the `SaveSess()` if that variable is set. I can't think of a better solution right now – Wolph Feb 12 '23 at 01:16
22

You can do per directory sessions with this is your vimrc:

fu! SaveSess()
    execute 'call mkdir(%:p:h/.vim)'
    execute 'mksession! %:p:h/.vim/session.vim'
endfunction

fu! RestoreSess()
execute 'so %:p:h/.vim/session.vim'
if bufexists(1)
    for l in range(1, bufnr('$'))
        if bufwinnr(l) == -1
            exec 'sbuffer ' . l
        endif
    endfor
endif
endfunction

autocmd VimLeave * call SaveSess()
autocmd VimEnter * call RestoreSess()

That will litter your directories with .vim s, but you can easily modify that. Also, change sbuffer to badd if you don't want new windows for each file and add ssop-=buffers to your vimrc.

Ana
  • 126
  • 2
  • 12
markw
  • 620
  • 3
  • 14
  • Use `autocmd BufEnter,VimLeavePre * call SaveSess()` to avoid losing your session on an irregular close. – user3751385 Jun 08 '15 at 08:21
  • well, can't I just `vim -S ~/.vim/session.vim` (or wherever You keep Your session.vim) instead of using RestoreSess() func? – Jakub Kopyś Sep 28 '17 at 09:54
  • @JakubKopyś Yeah, you could do that, but the advantage of using a function is that you never have to try to remember and type out a long path to the file for your session. Since the SaveSess function always follows the same naming rules as RestoreSess does, it'll always work, and you never have to provide it with a path to the session script. – Thaddaeus Markle Jul 12 '20 at 18:35
  • 1
    for some reason it seems that `vim -S mysession.vim` does not do quite the same as `au VimEnter * exec 'source mysession.vim'`, as the latter results in broken syntax highlighting for me – hesxenon Oct 28 '20 at 09:42
  • You should add the `nested` flag to the VimEnter autocommand in order to properly restore syntax highlighting. This might only apply if your `sessionoptions` excludes `options`. Also, I don't understand the purpose of the for loop. – Big McLargeHuge Jul 09 '21 at 16:20
  • does not seem to work for windows – Rainb Sep 28 '22 at 12:54
8

xolox/vim-session is working well for me. With Vundle:

Plugin 'xolox/vim-misc'
Plugin 'xolox/vim-session'
let g:session_autoload = 'yes'
let g:session_autosave = 'yes'
let g:session_autosave_to = 'default'
let g:session_verbose_messages = 0

Session is stored in ~/.vim/sessions/default.vim.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • The downside of this plugin is that it over-writes session file when you create a new session in any other directory. – Rishabh Agrahari Jun 16 '20 at 10:26
  • @RishabhAgrahari https://www.youtube.com/watch?v=9vSER0O0asc https://github.com/smalinux/dotfiles/blob/e2c6ea24d011b0eecb24ee6865e25258aec1d8f0/.vimrc#L534-L543 – smalinux May 30 '22 at 00:38
7

The autosess plugin works well for this. Also available on GitHub: powerman/vim-plugin-autosess.

From the plugin's description:

Start Vim without file arguments to automatically load previous session for current directory. This make easier work with complex projects - just chdir to project directory and start vim.

When you quit from Vim, if there are more than one open tab/window, session will be automatically saved. This let you edit single files in same directory without breaking your saved session. (Quickfix and vimdiff's windows are ignored.)

If you quit from Vim with no open files, session will be deleted. This let you start usual empty Vim in this directory next time.

Jack Senechal
  • 1,600
  • 2
  • 17
  • 20
2

I have a muscle-memory habit of typing ":q!", which I haven't been able to shake. This gets very tedious, if I've got multiple buffers open in a vi session. So - what I needed was a way of simply recovering where I was when I accidentally shot myself in the foot. Again.

This is slightly complicated by the fact that I might have multiple ssh sessions open at any one time, each with a different set of buffers/windows open in vi. I needed a way of saving the session separately for each different ssh session.

The solution I came up with builds on 2ck's answer, and is as follows. In your ~/.vimrc:

" tty is unique to the ssh session
let my_full_tty=$SSH_TTY
" scoop the number off the end of it
let my_tty_num = matchstr(my_full_tty, '\d\{1,}$')
" create a unique filename
let g:my_vim_session = "~/vim_session." . my_tty_num

fu! SaveSess()
    execute 'mksession! ' . g:my_vim_session
endfunction

fu! RestoreSess()
    let file = expand(g:my_vim_session)
    if filereadable(file)
        execute 'source ' . g:my_vim_session
    endif
endfunction

autocmd VimLeave * call SaveSess()
" only restore the session if the user has -not- requested a specific filename
autocmd VimEnter * if !argc() | call RestoreSess() | endif

But, of course, I don't want loads of ~/vim_session.? lying around, so I periodically cleanup. (I may re-think this, actually, because what happens if my ssh disconnects unexpectedly? hmmm)

In your .bashrc:

trap ~/bash_exit_script.pl EXIT

and in bash_exit_script.pl:

#! /usr/bin/perl

use warnings;
use strict;

my $ssh_tty = $ENV{SSH_TTY};
$ssh_tty =~ /(\d{1,}$)/; 
my $my_tty_number = $1;

my $filename = "/home/dominic.pain/vim_session.$my_tty_number";
if(-e $filename) {
    print "tried to remove $filename...\n";
    system("rm $filename");
}      
else {
    print "Couldn't find $filename\n";
}
WeeDom
  • 324
  • 3
  • 12
  • this is unrelated to the question, but if you want to protect yourself from unexpected disconnections you may want to look into [tmux](http://tmux.sourceforge.net/) or similars :) – garph0 Jan 21 '15 at 10:11
  • I use tmux heavily, already. What I'm protecting against is my own stupidity, where I hit :q! by accident :) – WeeDom Jan 23 '15 at 09:14
2

i use vim for projects and every project have .vim folder in root of my project. and i use startup script for vim

    #!/bin/bash
if [[ $# != 1 ]]
then
    zenity --title "Vim IDE usage error" --error --text "Usage: vim_ide /path/to/project/dir."
    exit 1
fi

if [[ ! -e "$1/.vim/ide.vim" ]]
then
    zenity --title "Vim IDE usage error" --error --text "'$1' is not a Vim IDE project directory."
    exit 1
fi

cd "$1" || { zenity --title "Vim IDE usage error" --error --text "Can't change current directory to Vim IDE project directory '$1'."; exit 1; }

.vim/ide.vim

set sessionoptions-=options
au VimLeave * :mksession! .vim/ide.session
    if getfsize(".vim/ide.session") >= 0
        source .vim/ide.session
    endif

so i start my vim by next command

$~/ide.sh /path/to/project

All my opened files, tabs and even position cursors are saved before exit and restored after start.

RusAlex
  • 8,245
  • 6
  • 36
  • 44
2

With gsessions you still have to save your sessions with \ss before quitting the editor. It will detect saved sessions on startup, and ask you if you want to open them.

  • what do you mean `:ss` or something. I dont know how I save execute the `\ss` command... – ganjan Feb 28 '11 at 21:19
  • You press the keys `\ s s` in normal mode. That will save your session, creating a session file if there isn't any. –  Feb 28 '11 at 21:26
  • It's worth noting that the `\` (standard leader key) and `s s` have to be pressed rapidly following each other otherwise `\` will loose the meaning as `` modifier. – JohnDoe Mar 03 '20 at 19:48
2

tpope's vim-obsession is the best thing for this now, released after the question was originally asked.

Use :Obsess (with optional file/directory name) to start recording to a session file and :Obsess! to stop and throw it away. That's it. Load a session in the usual manner: vim -S, or :source it.

  • Instead of making me remember to capture the session immediately before exiting Vim, allow me to do it at any time, and automatically re-invoke :mksession immediately before exit.
  • Also invoke :mksession whenever the layout changes (in particular, on BufEnter), so that even if Vim exits abnormally, I'm good to go.
  • If I load an existing session, automatically keep it updated as above.
  • If I try to create a new session on top of an existing session, don't refuse to overwrite it. Just do what I mean.
Edward Anderson
  • 13,591
  • 4
  • 52
  • 48
  • 1
    But I still need to remember to start `:Obsess`, and to start vim by doing `vim -S session.vim`. I would like something where it will automatically look for a `session.vim` file and load it and start tracking with Obsess – Max Coplan Apr 17 '20 at 13:45
  • `:Obsess` once per project, yes. `vim -S`, yes (defaults to session.vim). You don't have to remember either of these regularly if you also save/restore a tmux session with tmux-resurrect or tmuxinator. – Edward Anderson Apr 17 '20 at 20:21
1

You can add the following line to your .vimrc file to automatically save the session when you quit Vim with :qa:

au VimLeave * mksession! .session.vim

Then to automatically load it, add this:

autocmd VimEnter * source .session.vim
mrded
  • 4,674
  • 2
  • 34
  • 36
0

Improving on @Wolph here is a more robust code that treats each session for each file separatly:

" vim auto-save session
fu! SaveSess()
    execute 'mksession! ' . getcwd() . '/.' . expand('%:t') . '.vim'
endfunction

fu! RestoreSess()
if filereadable(getcwd() . '/.' . expand('%:t') . '.vim')
    execute 'so ' . getcwd() . '/.' . expand('%:t') . '.vim'
    if bufexists(1)
        for l in range(1, bufnr('$'))
            if bufwinnr(l) == -1
                exec 'sbuffer ' . l
            endif
        endfor
    endif
endif
endfunction

autocmd VimLeavePre * call SaveSess()
autocmd VimEnter * nested call RestoreSess()

Put this code on .vimrc

alexandre1985
  • 1,056
  • 3
  • 13
  • 31