Changing location of swap directory for selected files, how to?

36 views
Skip to first unread message

Karthick Gururaj

unread,
Sep 12, 2012, 9:22:39 AM9/12/12
to vim_use
Hello,

I would like to modify the value of 'dir' option for a few specific
files (e.g: all files in directory ~/Foo/). Had 'dir' been a buffer
local option, it would have been a easy thing,
au BufEnter ~/Foo/* set dir=newval

But 'dir' is global across buffers. Can anyone suggest workarounds?

I have tried
au BufEnter ~/Foo/* call ChangeDir()
au BufLeave ~/Foo/* call RevertDir()

function ChangeDir()
let b:tmp=&dir
set dir=newval
endfunction

function RevertDir()
exe 'set dir=' . b:tmp
endfunction

..but BufEnter fires *after* swap file is created.

If you want to know why I'm doing this - it is to prevent .swp files
being created in my DropBox folder (and retain default behavior in all
other cases)

-Karthick

sc

unread,
Sep 12, 2012, 10:12:02 AM9/12/12
to vim...@googlegroups.com
On Wed, Sep 12, 2012 at 06:52:39PM +0530, Karthick Gururaj wrote:
> Hello,

> I would like to modify the value of 'dir' option for a few specific
> files (e.g: all files in directory ~/Foo/). Had 'dir' been a buffer
> local option, it would have been a easy thing,
> au BufEnter ~/Foo/* set dir=newval

> But 'dir' is global across buffers. Can anyone suggest workarounds?

you might consider setting the 'directory' option to a real directory,
then your swapfiles won't pollute the same path of the files you're
editing, and also buys you the advantage of being able to query that
path before a new edit session to see what if anything is already being
edited

you mentioned obtaining default behavior -- the default for 'directory'
is to have real paths and all swapfiles in one place

sc

Karthick Gururaj

unread,
Sep 12, 2012, 10:24:57 AM9/12/12
to vim...@googlegroups.com
Sorry I wasn't clear.

The "default" behavior I was referring to was to let,
set dir=.
I.e., swap files in the same location as the file being edited.

So to rephrase my query, I would like to set,
set dir=~/tmp
for all files in ~/DropBox, and,
set dir=.
for all other files.
Any thoughts on how this can be done? Using BufEnter/BufLeave event
triggers don't work, as noted in the OP.

As you have suggested, I could do,
set dir=~/tmp//
Which is what I think I'll end up with..

Ben Fritz

unread,
Sep 12, 2012, 11:03:09 AM9/12/12
to vim...@googlegroups.com
I bet you could add BufReadPre to your BufEnter autocmd to get it to trigger before swapfile creation. Maybe you'd need to add a BufReadPost to your BufLeave event as well, so that the BufEnter doesn't save the wrong dir option value.

I'm not sure how to make it work when you create a new file. Possibly BufNewFile will work, or you can always create the document outside of Vim before editing.

One workaround might be to set 'noswapfile' globally in your .vimrc, and set 'swapfile' locally on BufEnter, after setting the correct 'dir' option.

Another workaround, which is probably not worth using, is that if a file is loaded with 'readonly' set, Vim doesn't create a swap file until the first change. You might be able to take advantage of this.

Marcin Szamotulski

unread,
Sep 12, 2012, 12:30:45 PM9/12/12
to vim...@googlegroups.com
What about this idea:

function! ChangeSwap()
let dir=&dir
set dir=/tmp
set swapfile!
set swapfile!
let &dir=dir
endfunction

au BufReadPost ../DrobBox/* :call ChangeSwap()

It is not efficient since it recreates the swap file but you could try.

Best,
Marcin




Ben Fritz

unread,
Sep 12, 2012, 2:32:09 PM9/12/12
to vim...@googlegroups.com
On Wednesday, September 12, 2012 10:03:09 AM UTC-5, Ben Fritz wrote:
> On Wednesday, September 12, 2012 8:22:44 AM UTC-5, Karthick wrote:
>
> > Hello,
>
> >
>
> >
>
> >
>
> > I would like to modify the value of 'dir' option for a few specific
>
> >
>
> > files (e.g: all files in directory ~/Foo/). Had 'dir' been a buffer
>
> >
>
> > local option, it would have been a easy thing,
>
> >
>
>
>
> One workaround might be to set 'noswapfile' globally in your .vimrc, and set 'swapfile' locally on BufEnter, after setting the correct 'dir' option.
>
>

I have some slow network shares, so I gave this idea a try to prevent using them for swap files. It seems successful so far, but beware of the crash I observed here: https://groups.google.com/d/topic/vim_dev/ZcJEKqNsVRI/discussion

Here's the code I came up with:

" Make slow network shares on Windows prefer not to use the file's directory
" for swap files
if has('win32')
set noswapfile
autocmd BufReadPre * setlocal noswapfile
autocmd BufEnter {Z,U,W}:{/,\\}* set dir-=. dir+=.
" nested autocmd to enable swap files so SwapExists autocmds fire, too
autocmd BufEnter * nested setlocal swapfile
autocmd BufLeave {Z,U,W}:{/,\\}* set dir-=. dir^=.
endif

Karthick Gururaj

unread,
Sep 13, 2012, 11:18:31 AM9/13/12
to vim...@googlegroups.com
I don't understand the intent here, ChangeSwap() would set all values
back to original by the time the function quits?

Karthick Gururaj

unread,
Sep 13, 2012, 11:32:15 AM9/13/12
to vim...@googlegroups.com
I think the basic assumption here is BufReadPre triggers execute
before swap file is created?

I tried to validate that with the following:

au BufReadPre TEMPTST call Check()
function Check()
sleep 10
endfunction

:e TEMPTST
<type some chars>
" Now delete the buffer
:bd

" Reload buffer to test the autocmd
:e TEMPTST
BufReadPre will now trigger. I was monitoring the directory (in a file
explorer) and saw a swap file being created before the Check()
function returns.

Marcin Szamotulski

unread,
Sep 13, 2012, 11:53:32 AM9/13/12
to vim...@googlegroups.com
The dir option is used when swap file is made. The swap file is made
once. ChangeSwap() acts after reading the file. It sets the dir to where
you want, then the first swapfile! will delete the current swapfile,
the second will create it under the new dir. At the end we can reset
the dir option.

If you want to use it you should test it if dropbox reacts for the short
existence of the first swap file.

Best,
Marcin


Ben Fritz

unread,
Sep 13, 2012, 12:01:23 PM9/13/12
to vim...@googlegroups.com
On Thursday, September 13, 2012 10:32:22 AM UTC-5, Karthick wrote:
>
> > I have some slow network shares, so I gave this idea a try to prevent using them for swap files. It seems successful so far, but beware of the crash I observed here: https://groups.google.com/d/topic/vim_dev/ZcJEKqNsVRI/discussion
>
> >
>
> > Here's the code I came up with:
>
> >
>
> > " Make slow network shares on Windows prefer not to use the file's directory
>
> > " for swap files
>
> > if has('win32')
>
> > set noswapfile
>
> > autocmd BufReadPre * setlocal noswapfile
>
> > autocmd BufEnter {Z,U,W}:{/,\\}* set dir-=. dir+=.
>
> > " nested autocmd to enable swap files so SwapExists autocmds fire, too
>
> > autocmd BufEnter * nested setlocal swapfile
>
> > autocmd BufLeave {Z,U,W}:{/,\\}* set dir-=. dir^=.
>
> > endif
>
> I think the basic assumption here is BufReadPre triggers execute
>
> before swap file is created?
>
>

Yes, that was my assumption, since it's the earliest event I know of when reading a buffer, and :help 'swapfile' indicates that it is buffer-local to allow you to not use swap files when you want to protect confidential information.

>
> I tried to validate that with the following:
>
>
>
> au BufReadPre TEMPTST call Check()
>
> function Check()
>
> sleep 10
>
> endfunction
>
>
>
> :e TEMPTST
>
> <type some chars>
>
> " Now delete the buffer
>
> :bd
>
>
>
> " Reload buffer to test the autocmd
>
> :e TEMPTST
>
> BufReadPre will now trigger. I was monitoring the directory (in a file
>
> explorer) and saw a swap file being created before the Check()
>
> function returns.

Interesting, so I suppose my assumption was invalid. Regardless, since the BufReadPre event triggers before the buffer is read, the swap file created before BufReadPre cannot contain anything from the file itself. I'm not sure what it can contain at that point, actually. It now makes more sense to me why the BufReadPre autocmd is necessary. I had a problem when editing a file the second time, because Vim remembered the 'swapfile' setting from the first time, and I guess it was creating a swap file before the BufReadPre event using the wrong 'dir' setting, since BufEnter hadn't fired yet. Luckily setting 'swapfile' seems to do the same check as if you're editing a file with it already set, so it seems to work as intended. I can edit files much faster on my network shares now, at least, probably because a bunch of text need not be written to the swap file temporarily created before BufReadPre.

I used the :swapname command, by the way, to determine whether my autocmds were properly setting the location of my swap file.

If you need to NEVER create a file in your Dropbox folder, perhaps you could reverse the logic. Set up 'dir' as you want it for Dropbox in your .vimrc, and somehow set it to how you want it otherwise for all other locations using autocmds.

Karthick Gururaj

unread,
Sep 14, 2012, 1:49:45 AM9/14/12
to vim...@googlegroups.com
Ben, Marcin: thanks for trying to work this out so far. My requirement
is that I do need to create new files in DropBox folder and swap files
do not get created (even temporarily) in that folder. From the
discussions here, I think the only solution is to:
set dir=~/tmp//

This is acceptable solution for me, I'll go ahead with that now.
Reply all
Reply to author
Forward
0 new messages