24

Sometimes I see a window open with name scratch.

I know it is some kind of temporary buffer/window.

How can I create one?

:h scratch returns nothing.

6 Answers 6

20

It is probably a scratch buffer, which can be named. From the help:

scratch

Contains text that can be discarded at any time. It is kept when closing the window, it must be deleted explicitly. Settings:

      :setlocal buftype=nofile
      :setlocal bufhidden=hide
      :setlocal noswapfile

The buffer name can be used to identify the buffer, if you give it a meaningful name.

This can be found in :help special-buffers.

5
  • 1
    which :h command used to access this help?
    – wizzup
    Feb 8, 2017 at 13:33
  • 2
    :h buffer, then read down through "Special kinds of buffers". You were on the right track.
    – wbogacz
    Feb 8, 2017 at 13:36
  • 1
    When you open a file using any of the Vim commands, a buffer is automatically created. For example, if you use :edit file to edit a file, a new buffer is automatically created. An empty buffer can be created by entering :enew or :new or :vnew. From Vim buffer FAQ: vim.fandom.com/wiki/Vim_buffer_FAQ
    – NeilG
    Oct 2, 2019 at 23:15
  • 2
    @wizzup :helpgrep scratch turns it up as one of 10 (in my installation) results.
    – Rich
    Oct 3, 2019 at 13:05
  • BTW you can name your scratch buffer with :file <name>. And the bare minimum setting needed is really buftype=nofile, or bt=nofile.
    – KFL
    Apr 11, 2022 at 17:56
10

A 'scratch' buffer is just an informal term for a place to type arbitrary temporary content.

Following the accepted answer and another question, I created the following function in my vimrc.

The function creates a blank buffer in the current window and names it 'scratch'. The scratch buffer is not protected if you try to quit. It will be discarded without prompting even with unsaved changes if you quit Vim or wipe it (:bw).

Put this function in your vimrc. To create a scratch buffer use :call Scratch().

function! Scratch()
    split
    noswapfile hide enew
    setlocal buftype=nofile
    setlocal bufhidden=hide
    "setlocal nobuflisted
    "lcd ~
    file scratch
endfunction

You can test this quickly by yanking the lines and then :@". You can then try :call Scratch().

A split is used so your current buffer is not affected when you create the scratch buffer.

(If you prefer to omit the split from the function then your current buffer would be "hidden" (no longer in a window) when you create the scratch buffer. Vim will still stop and prompt you if you try to quit with unsaved changes in that buffer).

The scratch buffer would normally have the same working directory of the buffer you are in when you call the Scratch function. I've included a commented out line to change the scratch buffer working directory to home. This is for those with funny status lines that may display the path of the current directory as the buffer path. Or just for those who prefer it.

You can set the scratch buffer to be "listed" or "unlisted" (listed by default). If you make it unlisted you won't see it in your :buffers list, but it will be in :buffers!. Uncomment the nobuflisted line if you prefer it to be unlisted. Listed or unlisted, you can always change to your scratch buffer with :b scratch anyway. Making the scratch buffer listed makes it slightly more accessible. For instance :sball will include it in a split.

If you use :bw (buffer wipe) on the scratch buffer Vim will delete the content and remove the buffer without warning. If you use :bd (buffer delete) on the scratch buffer Vim will drop the content without warning and make the buffer unlisted.

You can create multiple scratch buffers. Vim starts to complain but you still end up with additional ones.

1
  • by adding another cmd: function! TmpRatioSplit(ratio) exec winheight(0)/a:ratio."split" endfunction and using that instead of split: exec TmpRatioSplit(3) the scratch buffer is 1/3 of the other buffer, which I find nice. you can also use hsplit instead.
    – EmilBB
    17 hours ago
4

I remember a vim tip (which has been migrated to vim.wikia) on the subject.

The latest version of the function I use to create scratch buffers also sets:

  • 'buflisted' to false
  • 'readonly'

(From my VimL library plugin: lh-vim-lib)

function! lh#buffer#scratch(bname, where) abort
  try
    set modifiable
    " The next function takes care of working around this damn E36
    call lh#window#create_window_with(a:where.' sp '.escape(substitute(a:bname, '\*', '...', 'g'), '#%'))
  catch /.*/
    throw "Can't open a buffer named '".a:bname."'!"
  endtry
  setlocal bt=nofile bh=wipe nobl noswf ro
  return bufnr('%')
endfunction
4

I have created a "Scratch" command

command! Scratch new | setlocal bt=nofile bh=wipe nobl noswapfile nu
0

@Dhruva Sagar has a post about his solution to this problem on his website. Check his post for a complete explanation.

I'm posting the code here, in case his site ever goes offline (I modified the names of the functions slightly):

function! ScratchEdit(cmd, options)
    exe a:cmd tempname()
    setl buftype=nofile bufhidden=wipe nobuflisted
    if !empty(a:options) | exe 'setl' a:options | endif
endfunction
 
command! -bar -nargs=* Sedit call ScratchEdit('edit', <q-args>)
command! -bar -nargs=* Ssplit call ScratchEdit('split', <q-args>)
command! -bar -nargs=* Svsplit call ScratchEdit('vsplit', <q-args>)
command! -bar -nargs=* Stabedit call ScratchEdit('tabe', <q-args>)
1
0

This is building on NeilGs answer, with two changes:

  1. the scratch buffer opens in 1/3 of the window, instead of half-half. I find that to be more how I would like such a scratchpad to behave, not filing up too much space. The ratio can be changed. You can change this to another ratio entirely by putting in another number in TmpRatioSplit(), or make it a vsplit if that's your preference.

  2. it checks if the buffer already exists, and if it does, it switches to it - in the defined ratio. Before I would get an error when I had closed the split because vim tries to open a buffer with the name 'scratch' which already exists.



" to open in 1/3 of the window
function! TmpRatioSplit(ratio)
  exec winheight(0)/a:ratio."split"
endfunction



function! Scratch()
    let scratch_buf = bufnr('scratch')
    if scratch_buf == -1
        exec TmpRatioSplit(3)
        noswapfile hide enew
        setlocal buftype=nofile
        setlocal bufhidden=hide
        file scratch
    else
        let scratch_win = bufwinnr(scratch_buf)
        if scratch_win == -1
            exec TmpRatioSplit(3)
            execute 'buffer ' . scratch_buf
        else
            execute scratch_win . 'wincmd w'
        endif
    endif
endfunction


nnoremap <m-i> :call Scratch()<CR>


New contributor
EmilBB is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
2
  • A command that accepts and uses <mods> would do nicely in terms of split vs vsplit.
    – D. Ben Knoble
    11 hours ago
  • I'm sorry but I don't understand that. Could you elaborate?
    – EmilBB
    7 hours ago

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.