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.
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
.
: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
:helpgrep scratch
turns it up as one of 10 (in my installation) results.
:file <name>
. And the bare minimum setting needed is really buftype=nofile
, or bt=nofile
.
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.
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
I have created a "Scratch" command
command! Scratch new | setlocal bt=nofile bh=wipe nobl noswapfile nu
This is building on NeilGs answer, with two changes:
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.
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>
<mods>
would do nicely in terms of split vs vsplit.
:help <mods>
; for example, with this command typing :vertical Swiki
ends up running :vertical split
, or :tab Swiki
opens a new tab, etc.
@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>)