7

I'm trying to save my session in Vim with relative paths to open files. With cur_dir in sessionoptions, the paths to files will be relative wrt. current directory, but the session file contains cd /path/to/base/directory command:

...
cd /path/to/base
badd +0 relpath1/file
badd +0 relpath2/file
...

If I leave curdir out of sessionoptions, the cd command disappears, but file paths will be absolute:

badd +0 /path/to/base/relpath1/file
badd +0 /path/to/base/relpath2/file

Is there a way to have only relative paths wrt. to whatever was the current directory when the session was created -- without plugins or writing scripts? So that the session file would only have:

badd +0 relpath1/file
badd +0 relpath2/file

My ultimate goal is to have a session file that I can copy around, e.g. from SVN checkout to another.

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
huoneusto
  • 1,164
  • 1
  • 8
  • 19

4 Answers4

6

You can't do that without setting up a wrapper function for it, AFAIK.

E.g. something like:

function! MakeSession()
  let b:sessiondir = getcwd()
  let b:filename = b:sessiondir . '/session.vim'
  exe "mksession! " . b:filename
  exe "edit! " . b:filename
  exe "g:^cd :d"
  exe "x" 
endfunction
Zsolt Botykai
  • 50,406
  • 14
  • 85
  • 110
  • Can you explain `g:^cd :d` a bit? I'm still having issue to make it work. I found this line is critical but have no clue what it does. Thx. – John Chain Feb 22 '19 at 15:59
  • Hi @JohnChain, sure. It is an `ex` mode command that executes line deletion (`d`) globally on every line that matches the regex of `cd ` at the start of line. – Zsolt Botykai Feb 24 '19 at 11:39
  • This function doesn't save multi tabs AND it also closes one split from the active tab, in case of multiple vsplits. – Igor Stoppa May 22 '22 at 12:29
-1

I modified Botykai's answer with an extra line to remove the absolute path globally.

function! MakeSession()
  let b:sessiondir = getcwd()
  let b:filename = b:sessiondir . '/_vimsession'
  exe "mksession! " . b:filename
  exe "edit! " . b:filename
  " Delete the line start with 'cd ...'
  exe "g:^cd :d"
  " Vim complains about b:sessiondir being undefined. So I use getcwd() directly
  " exe "%s:" . b:sessiondir . "::g". Use ':' to avoid path escape
  exe "%s:" . getcwd() . "/::g"
  " Save with 'x'
  exe "x"
endfunction

If someone can improve the function above to narrow down the lines to those only starting with badd, this will be better.

John Chain
  • 658
  • 4
  • 9
-1

I got the same problem and I solve it with the function below inspired by Zsolt Botykai’s solution and John Chain’s solution. Plus, I defined a macro to execute this function with fewer keystroke.

function! MakeSession() 
    let cwd = getcwd()
    let filename = cwd . '/.vim'
    exe "mksession! " . filename
    exe "tabedit! " . filename
    exe "silent g:^cd :d"
    exe "silent g:^lcd :d"
    "exe "silent %s:\V" . cwd . "/::ge"
    " ^ Don’t work because getcwd() expand the ~ while mksession does not !
    exe "silent %s?\\v \\~=/.+/? ?g"
    " ^ backslash need to be protected
    exe "x"
endfunction

nnoremap <leader>mks :call MakeSession()<cr>

The main difference is the regex to remove full path. It is needed because getcwd expands the ~ of home directory, but mksession does not (on Mac OS).

lavalade
  • 329
  • 2
  • 11
-1

The solution is simpler when using curdir instead of sesdir (see :help sessionoptions) because the absolute path occurs only one time in session file (cd path). Hence, the MakeSession function is smaller (I called the session file .vim) :

function! MakeSession()
    exe "mksession! .vim"
    exe "tabedit! .vim"
    exe "silent g:^cd :d"
    exe "x"
endfunction

nnoremap <leader>mks :call MakeSession()<cr>

To choose the name of the session file (execution: :call MakeNamedSession('foo')) :

function! MakeNamedSession(arg)
    let radical = a:arg
    exe "mksession! " . radical . ".vim"
    exe "tabedit! " . radical . ".vim"
    exe "silent g:^cd :d"
    exe "x"
endfunction
lavalade
  • 329
  • 2
  • 11