3

When saving a session with :mksession and :sourceing it back, the content of [No Name] unnamed buffers is lost.

I like to sometimes write temporary throwaway code or notes on a unnamed or scratch buffer, for the length of my session.

Just like Sublime Text saves the content of "untitled new tabs" when quitting and reopening it, is there a way/workaround/hack/plugin to save the state of unnamed buffers in Vim?

1
  • 1
    You want to save 'temporary throwaway code'. I'm confused.
    – Antony
    Commented Jun 17, 2016 at 2:48

2 Answers 2

6

You could use the following function. It is extremely hacky and I haven't tested it plenty but it seems to work.

The idea is to create a command :Mksession which will work like the original :mksession but will also save the unnamed buffers.

(Note that I had some inspiration from this answer

To do so it will call a function which does the following:

  • First handle the argument so that you can call the command with of without a filename as argument
  • Execute the original :mksession
  • Use a list which will contain the content of the unnamed buffer
  • Use a command which will test the name of each buffers. When the name is empty, getline() is used to add the content of the buffer to the list of contents.
  • Finally for each set of line, instructions are added to the session file to create a new buffer and put the content into it.

Add theses lines to your .vimrc:

function! MkSession(...)
    " Handle the argument
    if empty(a:000)
        let filename = "Session.vim"
    else
        let filename = fnameescape(a:1)
    endif

    " Create the session file according to the argument passed
    execute 'mksession! ' . filename

    " The list containing the lines on the unnmaed buffers
    let noname_buffers = []

    " Get the lines of all the unnamed buffers in the list
    execute "silent! bufdo \| if expand('%')=='' \| call add(noname_buffers, getline(1, '$')) \| endif"

    " For each set of lines
    " Add into the session file a line creating an empty buffer
    " and a line adding its content
    for lines in noname_buffers
        call system('echo "enew" >> '.filename)
        call system('echo "call append(0, [\"'. join(lines, '\",\"') .'\"])" >>'. filename)
    endfor

endfunction

command! -nargs=? Mksession call MkSession(<f-args>)

You can then simply call the command like that:

:Mksession

Or with a file name

:Mksession mysession.vim

Edit

As @DJ McMayhem pointed it out in the comments you can even add this line to your .vimrc:

cnoremap mksession Mksession

This would make ̀ :mksession(without capitalizedm) behave like the:Mksessioncommand we just defined (with capitalizedM`).

I mentioned it because for some user it could be seen as an advantage. However I would not recommend to use it: it hides the fact that you're using a custom function and if a side-effect appears it could add some difficulty to debug a problem.

7
  • I don't understand what you mean: the command you show makes Mksession (with capitalized M) call the builtin mksession which doesn't save the unnamed buffer. I'm probably missing your point.
    – statox
    Commented Jun 17, 2016 at 19:11
  • I might be wrong (I don't have a computer with me right now) but I think that when you define a user command the first letter has to be capitalized. (to avoid confusion with built in commands). I even think that you have to use a plug-in to create user-defined commands which are not capitalized. (but once again I can't test it right now so I'm not 100% sure)
    – statox
    Commented Jun 17, 2016 at 19:20
  • Alright, let's try this one more time. You could do :cnoremap mksession Mksession That's what I meant to say.
    – DJMcMayhem
    Commented Jun 17, 2016 at 19:22
  • Now I agree with you! :-) That's indeed a possibility. Im not sure that it's really a good idea because I might be good to remember that you're not using the built in feature (and thus might expect some side effects) but if one is really annoyed by the capitalized M it is possible to do that. Thanks for your suggestions!
    – statox
    Commented Jun 17, 2016 at 19:26
  • 1
    Thanks for this amazing answer! I tried to adapt the code to make it remember unnamed buffer/tab positions so that loading the session would look exactly the same as when Vim was exited, but this was too tedious. I finally switched to a more dedicated advanced session management tool (tmux) Commented Jun 21, 2016 at 21:56
2

Vim workarounds:

  • write temporary notes/code in predefined system-wide or project-wide files (possibly with the help of some custom functions/mappings)
  • use a Vim note-taking plugin

In both cases notes are saved in files, so when reopening your session their content will not be lost. When starting a new unit of work, just erase the previous content of the files (possibly with some automation).

External workaround:

Use a dedicated external session management tool, like tmux (which also does a lot of other stuff that one would not necessarily care about). I eventually chose this solution and am happy with it. Not only does it save the state of my Vim, but also the state of all my other console tabs/windows.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.