Instant context switching using git and vim sessions.
It basically takes a snapshot of the following:
- All of your vim tabs, buffers, splits, and folds along with their sizes and positions
- The location of your cursor for each buffer
- The actively selected tab/buffer
- Your undo history (each branch's undo history is saved separately)
- Your git stage with all tracked/untracked files and staged/unstaged hunks
When you switch to different branches using :Promiscuous your-branch-name, it takes a snapshot of the current branch and working directory, then checks out the new branch, and loads its corresponding snapshot if one exists.
If no snapshot exists, you are presented with a "fresh" vim instance that only has one tab and an empty buffer.
When :Promiscuous is called with no arguments, an :FZF fuzzy finder window is presented with a list of existing branches. From there we can either select an existing branch, or type out a new branch to checkout.
If you're using tmux then your status line will automatically refresh when :Promiscuous checks out a branch. This is very convenient when you display git information in your status line.
Similar projects:
Load shuber/vim-promiscuous using your favorite plugin manager e.g. Vundle
It currently depends on :FZF, but this dependency will be optional in the future.
:Promiscuous [branch]It's recommended to make a custom key binding for this. I've been using the following mapping:
nmap <leader>gb :Promiscuous<cr>I also use an additional mapping to checkout the previous branch (usually master):
nmap <leader>gg :Promiscuous -<cr>These are the defaults. Feel free to override them.
" The directory to store all sessions and undo history
let g:promiscuous_dir = $HOME . '/.vim/promiscuous'
" The callback used to load a session (receives branch name)
let g:promiscuous_load = 'promiscuous#session#load'
" The prefix prepended to all commit, stash, and log messages
let g:promiscuous_prefix = '[Promiscuous]'
" The callback used to save a session (receives branch name)
let g:promiscuous_save = 'promiscuous#session#save'
" Log all executed commands with echom
let g:promiscuous_verbose = 0set sessionoptions=blank,buffers,curdir,folds,help,tabpages,winsize
set undolevels=1000
set undoreload=10000call promiscuous#helpers#clear()
call promiscuous#git#stash()
call promiscuous#git#commit()
let l:branch_was = promiscuous#git#branch()
call call(g:promiscuous_save, [l:branch_was], {})
call promiscuous#session#clean()
call promiscuous#git#checkout(l:branch)
let l:branch = promiscuous#git#branch()
call call(g:promiscuous_load, [l:branch], {})
call promiscuous#git#commit_pop()
call promiscuous#git#stash_pop()
call promiscuous#tmux#refresh()The output below occurred when switching from master to something-new then back to master.
[Promiscuous] !clear
[Promiscuous] !(git diff --quiet && git diff --cached --quiet) || (git stash save Code_vim_promiscuous_master && git stash apply)
[Promiscuous] !git add . && git commit -am '[Promiscuous]'
[Promiscuous] mksession! /Users/Sean/.vim/promiscuous/Code_vim_promiscuous_master.vim
[Promiscuous] bufdo bd
[Promiscuous] !git checkout - || git checkout -b -
[Promiscuous] source /Users/Sean/.vim/promiscuous/Code_vim_promiscuous_something_new.vim
[Promiscuous] Checkout something-new
[Promiscuous] !clear
[Promiscuous] !(git diff --quiet && git diff --cached --quiet) || (git stash save Code_vim_promiscuous_something_new && git stash apply)
[Promiscuous] !git add . && git commit -am '[Promiscuous]'
[Promiscuous] mksession! /Users/Sean/.vim/promiscuous/Code_vim_promiscuous_something_new.vim
[Promiscuous] bufdo bd
[Promiscuous] !git checkout - || git checkout -b -
[Promiscuous] source /Users/Sean/.vim/promiscuous/Code_vim_promiscuous_master.vim
[Promiscuous] Checkout master
- Fork the project.
- Make your feature addition or bug fix.
- Commit, do not mess with the version or history.
- Send me a pull request. Bonus points for topic branches.
MIT - Copyright © 2015 Sean Huber
