Dragging a tab from one vim window to another

74 views
Skip to first unread message

Matt Tolton

unread,
Jan 22, 2008, 1:11:20 AM1/22/08
to vim...@googlegroups.com
Bjorn,

I have figured out a fairly clean way on the vimscript side of things
to be able to save a tab and then restore. This would allow you to
enable the ability to drag a tab from one vim instance to another, or
to create a new instance from a tab.

If I implement the necessary vimscript, are you willing to put this
capability into MacVim?

Regards,

Matt

Nico Weber

unread,
Jan 22, 2008, 2:58:44 AM1/22/08
to vim...@googlegroups.com
> I have figured out a fairly clean way on the vimscript side of things
> to be able to save a tab and then restore. This would allow you to
> enable the ability to drag a tab from one vim instance to another, or
> to create a new instance from a tab.

Does this keep the undo history?

björn

unread,
Jan 22, 2008, 11:47:15 AM1/22/08
to vim...@googlegroups.com

If you can convince me that it works well, then I'd be more than
willing to implement this feature. So, please outline how this would
work and we'll decide whether it is good enough. It certainly would
be great if we could get this feature in MacVim!

/Björn

Matt Tolton

unread,
Jan 22, 2008, 12:41:48 PM1/22/08
to vim...@googlegroups.com

I wish. I don't think that the undo history is accessible via
vimscript. See http://www.vim.org/sponsor/vote_results.php :)

>
> >
>

Matt Tolton

unread,
Jan 22, 2008, 1:04:02 PM1/22/08
to vim...@googlegroups.com
On Jan 22, 2008 9:47 AM, björn <bjorn.w...@gmail.com> wrote:

> If you can convince me that it works well, then I'd be more than
> willing to implement this feature. So, please outline how this would
> work and we'll decide whether it is good enough. It certainly would
> be great if we could get this feature in MacVim!

I have not tested this yet, but here's what I would do:

In the vim instance the tab is currently in:

1. Ensure all of the buffers on the tab are saved
let saved = 1
windo let saved = saved && !&modified

2. Save the tabpage using mksession.
save sessionoptions
"some of these might be debatable...just be sure that tabpage is not set
set sessionoptions=blank,buffers,folds,options,curdir,help,winsizes
mksession <temp session file>
restore sessionoptions

3. Wipeout the buffers on the tabpage
windo bw

In the vim instance to which the tab was dragged:

4. source <temp session file>

Anyways, while it's not perfect (no undo history and probably some
other things), I think that it could do the trick.

Matt

Nico Weber

unread,
Jan 22, 2008, 1:31:11 PM1/22/08
to vim...@googlegroups.com
> Anyways, while it's not perfect (no undo history and probably some
> other things), I think that it could do the trick.

What if a buffer is opened in several tabs? Would they be wiped from
the other tab pages as well? If so, this might be confusing. If not,
two vim instances would edit the same file (thus the window the tab is
dragged to would show a "file is being edited" dialog, which is weird
too).

Nico

Matt Tolton

unread,
Jan 22, 2008, 1:54:43 PM1/22/08
to vim...@googlegroups.com
Yes. bw will remove the buffer from those tabs as well. And yes, it
might be confusing, but there's not really any other way as far as I
can tell. However, this situation is probably not the norm. We could
pop up a warning the first time someone does it, explaining what the
ramifications might be.

Matt

björn

unread,
Jan 23, 2008, 2:02:17 PM1/23/08
to vim...@googlegroups.com
On 22/01/2008, Matt Tolton <ma...@tolton.com> wrote:
>

Well, it certainly is not perfect. The loss of undo history will seem
weird, but more problematic is the fact that saving/restoring a
session file sometimes takes a looong time.

Anyway, we could attempt your approach but I can't promise that I have
time to implement it just now. If you do manage to put together the
script to handle the loading/saving, then I will look into it when I
have a chance and we can evaluate how well it works.

/Björn

Matt Tolton

unread,
Jan 29, 2008, 6:38:15 PM1/29/08
to vim...@googlegroups.com
All,

Alright. Sorry I didn't get back to this sooner. I have implemented
a few functions to facilitate moving tabs (see below) between windows.
They seem to me to work fairly well. Note that they assume that the
tab being dragged is the currently active one in the window it is
being dragged from. What does everyone else think?

Bjorn, we could just throw these functions into the global gvimrc
right? And then MacVim could call SaveTab with a temporary filename
in one vim session, and then RestoreTab in the other?

Matt

---------------------
" Returns 1 or 0, depending on whether the tab was able to be saved
function! SaveTab(fname)
if &autowrite
windo if &modified | w | endif
else
let allsaved = 1
windo let allsaved = allsaved && !&modified

if !allsaved
return 0
endif
endif

let savedssop = &ssop
let &ssop = 'blank,folds,winsize,help,localoptions'
exe 'mksession' a:fname
let &ssop = savedssop
windo bw
return 1
endfunction

" Try to determine whether the current tab is "fresh" or not.
" A tab is fresh if there is only 1 window which contains an unmodified buffer
" with a blank name.
function! IsTabFresh()
let numwindows = 0
windo let numwindows += 1
if numwindows != 1
return 0
endif

" Ok there's only 1 window. Has it been modified?
if &modified
return 0
endif

" Does the buffer have a filename?
if expand('%') != ''
return 0
endif

return 1
endfunction

" Restore a tab saved in the given session file
function! RestoreTab(fname)
" Reuse the current tab if it is fresh
if !IsTabFresh()
tabnew
endif

" For some reason, vim will ocassionally echo the file names of the
" buffers it is restoring, so use silent to suppress this.
exe 'silent source' a:fname
endfunction

Nico Weber

unread,
Jan 30, 2008, 3:44:39 AM1/30/08
to vim...@googlegroups.com
> Alright. Sorry I didn't get back to this sooner. I have implemented
> a few functions to facilitate moving tabs (see below) between windows.
> They seem to me to work fairly well. Note that they assume that the
> tab being dragged is the currently active one in the window it is
> being dragged from. What does everyone else think?

Perhaps you could check if the buffers visible on the saved tab are
visible in other tabs as well, and return 0 in this case as well
(suppose I have three tabs, all more or less showing the same files.
If I drag one of those tabs to another window, the other two will
disappear and the original window will end up emtpy).

Also, what happens with buffers that are not backed by a file? How
does `mksession` handle those? If I remember correctly, they are not
restored successfully (just checked: I opened a tab with a NERDTree
window, a Tlist window and a BufExplorer window. You could think "this
tab gives me a nice overview of my project, I want to see it all the
time", but when you drag it to another window you'll end up with an
empty tab containing three (text) windows. Perhaps just return 0 if
there are non-file backed buffers visible on the current tab.

I don't know if/how vimscript handles namespaces. If it doesn't, the
functions should have some collisions-preventing prefix, especially if
they are included in $VIM/gvimrc.

Could you write a section in `:h macvim` about when tab moving works
(files in the current tab need to be saved if aw (or awa?) isn't
set, ...), when it doesn't, and what the limitations are (undo history
lost, ...)?

> Bjorn, we could just throw these functions into the global gvimrc
> right? And then MacVim could call SaveTab with a temporary filename
> in one vim session, and then RestoreTab in the other?

Dragging a tab into its own window should be possible as well (as in
Safari 3) ;-)

Nico

Matt Tolton

unread,
Jan 30, 2008, 12:36:38 PM1/30/08
to vim...@googlegroups.com
> > Alright. Sorry I didn't get back to this sooner. I have implemented
> > a few functions to facilitate moving tabs (see below) between windows.
> > They seem to me to work fairly well. Note that they assume that the
> > tab being dragged is the currently active one in the window it is
> > being dragged from. What does everyone else think?
>
> Perhaps you could check if the buffers visible on the saved tab are
> visible in other tabs as well, and return 0 in this case as well
> (suppose I have three tabs, all more or less showing the same files.
> If I drag one of those tabs to another window, the other two will
> disappear and the original window will end up emtpy).

I'm not sure I agree with this...I'd actually probably prefer the
current behavior. What do others think?

> Also, what happens with buffers that are not backed by a file? How
> does `mksession` handle those? If I remember correctly, they are not
> restored successfully (just checked: I opened a tab with a NERDTree
> window, a Tlist window and a BufExplorer window. You could think "this
> tab gives me a nice overview of my project, I want to see it all the
> time", but when you drag it to another window you'll end up with an
> empty tab containing three (text) windows. Perhaps just return 0 if
> there are non-file backed buffers visible on the current tab.

Hmm...yeah that's no good if they just show up as empty windows. I'll do that.

> I don't know if/how vimscript handles namespaces. If it doesn't, the
> functions should have some collisions-preventing prefix, especially if
> they are included in $VIM/gvimrc.

Absolutely. I'll take care of that.

> Could you write a section in `:h macvim` about when tab moving works
> (files in the current tab need to be saved if aw (or awa?) isn't
> set, ...), when it doesn't, and what the limitations are (undo history
> lost, ...)?

Yes I can do that. As for aw vs awa, what do you think?

> > Bjorn, we could just throw these functions into the global gvimrc
> > right? And then MacVim could call SaveTab with a temporary filename
> > in one vim session, and then RestoreTab in the other?
>
> Dragging a tab into its own window should be possible as well (as in
> Safari 3) ;-)

Absolutely. If that happens then MacVim will need to open a new Vim
instance and call RestoreTab in it as well.

Matt

Nico Weber

unread,
Jan 31, 2008, 11:41:17 AM1/31/08
to vim...@googlegroups.com
> Yes I can do that. As for aw vs awa, what do you think?

I'd vote for 'awa'.

Nico

Matt Tolton

unread,
Jan 31, 2008, 7:01:34 PM1/31/08
to vim...@googlegroups.com
Ok. Here are modified versions of the functions. Do people approve?

" Returns 1 or 0, depending on whether the tab was able to be saved

function! MacVim_SaveTab(fname)
" verify that all buffers are backed by a file
let backed = 1
windo let backed = !(&bt =~ 'nofile') && backed
if !backed
return 0
endif

" Verify that all of the buffers on the tabpage are saved or save them
" if autowriteall is set
if &autowriteall


windo if &modified | w | endif
else
let allsaved = 1
windo let allsaved = allsaved && !&modified

if !allsaved
return 0
endif
endif

let savedssop = &ssop
let &ssop = 'blank,folds,winsize,help,localoptions'
exe 'mksession' a:fname
let &ssop = savedssop
windo bw
return 1
endfunction

" Try to determine whether the current tab is "fresh" or not.
" A tab is fresh if there is only 1 window which contains an unmodified buffer
" with a blank name.

function! MacVim_IsTabFresh()
let numwindows = tabpagewinnr(tabpagenr(), '$')


if numwindows != 1
return 0
endif

" Ok there's only 1 window. Has it been modified?
if &modified
return 0
endif

" Does the buffer have a filename?
if expand('%') != ''
return 0
endif

return 1
endfunction

" Restore a tab saved in the given session file

function! MacVim_RestoreTab(fname)


" Reuse the current tab if it is fresh

if !MacVim_IsTabFresh()
tabnew
endif

" For some reason, vim will ocassionally echo the file names of the

" buffers it is restoring.


exe 'silent source' a:fname
endfunction

björn

unread,
Feb 4, 2008, 11:57:38 AM2/4/08
to vim...@googlegroups.com

Matt,

I have no further comments at this point in time...I just wanted to
say that I haven't had a chance to look into adding your scripts to
MacVim yet. It will take me some time to look into the
PSMTabBarControl and getting it to move tabs between windows (the
functionality is there, but I will probably have to tweak it a bit).
So, please don't take my (perceived) inactivity as a sign of lack of
enthusiasm for your ideas... :-)

/Björn

Matt Tolton

unread,
Feb 4, 2008, 12:03:10 PM2/4/08
to vim...@googlegroups.com
Great! Thanks for your hard work, Bjorn.

Matt Tolton

unread,
Feb 5, 2008, 5:30:23 PM2/5/08
to vim...@googlegroups.com
I was thinking about this some more. Do you guys think that the
MacVim_SaveTab function should close the vim instance if the active
tab is the only existing tab? My vote would be yes, as this would
make sense.

Additionally, I think that MacVim should support something like the
Safari and Terminal "Merge All Windows" menu items. How should this
be implemented? Should there be another function
MacVim_SaveAllTabs()? Or should MacVim just keep calling SaveTab
until the vim instance closes?

Matt

On Jan 31, 2008 5:01 PM, Matt Tolton <ma...@tolton.com> wrote:

Ben Schmidt

unread,
Feb 5, 2008, 8:46:39 PM2/5/08
to vim...@googlegroups.com
Sorry to weigh into this discussion so late, but I think I should speak up. I'm
hesitant about this feature. I realise you are working hard to safeguard it by
requiring autowriteall and warning the user about undo history being lost, but I'm
still concerned that it perhaps makes it a little too easy to shoot yourself in
the foot (i.e. lose your undo history, or have a Vim instance close and thus lose
your registers, end up with weird things happening if the buffer is displayed in
multiple tabs), and it occurred to me that there might be a better solution, at
least in a large number of cases, or perhaps a compromise position, perhaps not to
implement straight away, but to look towards. What do you guys think of this idea?:

At the moment every GUI/Aqua window ('window' from now on) in MacVim represents a
Vim instance. There is a one-to-one correspondence between windows and Vim
processes. But what if a Vim process could have multiple windows? The way you
would do this is simply assign each tabpage to a window. I haven't looked at the
MacVim code at all, but it doesn't strike me as being all that large a change at
least to get minimal functionality. Instead of a Vim process having a single
window, it would have a list of windows. Any operation that ordinarily would
affect the window (change in toolbar, change in menu, change in colourscheme,
etc.) would simply iterate through all the windows instead. A small amount of code
would need to be added so that when you do gt to a tab that isn't in the current
window, the appropriate window is brought to the front, and when you bring a
window to the front with the mouse, the Vim process switches itself to the
appropriate tab (as from Vim's point of view, only one tab and hence one window
would ever be active). A function could also be added to Vim that exposes to
scripts which window a tabpage belongs to, so that mappings could be created to
make 'gt' function only within one window, rather than cycling through all the
windows of the Vim process, and such. Dragging tabs around and splitting and
joining windows would only work for windows belonging to the same Vim instance,
but would, as such, be completely lossless--all undo history, registers,
everything, would be kept. It wouldn't matter if the file is open in multiple
tabs. It would work for unnamed buffers--you could even have the quickfix list in
a separate window.

There are a myriad of possible extensions to this, too. A command could be added
to Vim to separate the windows, allowing, by +clientserver, mvim or such to open a
new window but one that is shared with another Vim instance. In fact, you could
have all your MacVim windows belonging to a single Vim instance if desired--or you
could have multiples. Another command could recombine all windows for an instance
into one. Quickfix window behaviour could be modified so that a new tab, and thus
window, is opened rather than the window split if the file isn't found visible
somewhere in the instance already. Etc., etc.

There would be some oddities to this approach, too, of course. :tabdo would work
for all the tabpages in the Vim instance which would be multiple windows, which
might not be intuitive (especially if gt is mapped not to change windows as I
suggested above). It could also get confusing remembering which of your windows
belong to which Vim process. There also wouldn't be the flexibility of being able
to move tabs between instances, etc. that the approach currently being worked on
has. I can see that this could be desirable, but as I mentioned, I also see that
this could be dangerous, so I would suggest that it should be able to be turned
off--and probably this should be the default, and a warning dialog appear when
turning it on about losing undo history, etc. I would suggest two preferences to
deal with these issues:

1. "Allow tabs to be moved between Vim instances"
2. (available if 1. is enabled) "Force each window to be a separate Vim instance"

I also suggest that if you hold 'option' while dragging a tab away from a window,
it should make a new instance rather than just a new window in the existing instance.

It seems to me that this would be a more desirable and robust solution that could
work long term, be more integrated with Vim itself, and less dangerous to the user.

As you can see, it does incorporate the work currently being done, so we wouldn't
be throwing anything away, but I feel the current approach is definitely second
rate and dangerous and should be disabled by default. I would love to see
something like the more robust approach I suggest here implemented.

Cheers,

Ben.


Send instant messages to your online friends http://au.messenger.yahoo.com

Matt Tolton

unread,
Feb 5, 2008, 9:08:49 PM2/5/08
to vim...@googlegroups.com
Ben,

What you suggest would absolutely be more ideal. It has actually been
towards the top of the vim.org voting list for some time. Someone can
correct me if I'm wrong, but from what I gather it is a non trivial
request.

Even if someone is willing and has the time to do what you describe,
if it is going to take more than a couple of months I really think
that -some- functionality right now is better than none. The feature
has been requested multiple times on this mailing list. It would
certainly be useful to me even with the limitations we have discussed.

A warning dialog that pops up the first time the feature is used
should be enough to detail the pitfalls to the user. People using vim
are not idiots -- in fact, they're usually pretty smart. They can
handle it.

Regards,

Matt

Ben Schmidt

unread,
Feb 5, 2008, 9:53:51 PM2/5/08
to vim...@googlegroups.com
> What you suggest would absolutely be more ideal. It has actually been
> towards the top of the vim.org voting list for some time. Someone can
> correct me if I'm wrong, but from what I gather it is a non trivial
> request.

It's definitely not trivial...but then neither is the current approach. I suspect
it would be easier to do in MacVim than in the other GUIs, though, (i.e. it
wouldn't have to be done in all the GUIs at once and so on, nor within the Vim
source tree on the whole) which is why I think it's worthy of consideration now.

> Even if someone is willing and has the time to do what you describe,
> if it is going to take more than a couple of months I really think
> that -some- functionality right now is better than none.

I agree. And as I said, this functionality would be useful for added flexibility
even if the other approach is implemented, so nothing would be wasted in doing
this first.

> A warning dialog that pops up the first time the feature is used
> should be enough to detail the pitfalls to the user.

I don't think this is enough. I think it needs to be able to be switched off. I
don't know about others, but in my day to day work, I can easily accidentally grab
a tab and tear it off rather than just clicking it or such, and if that causes my
undo history to be lost, and registers to be different, I will not be happy, even
if I had been warned earlier! Because Vim is so reliable and makes it so hard to
lose work, I do make extensive use of its undo functionality, and expect that if
something is going to be lost it will only happen after I set some option or add a
bang to a command or something like that--it should be harder than just dragging
with the mouse. I would be happy with a 'first use' dialog that drew attention to
a preference that could switch it off.

> People using vim are not idiots

On the whole, I agree. But there are definitely some exceptions out there! :-)

> in fact, they're usually pretty smart. They can handle it.

Well, yes and no. I think this is why we're having this discussion: a number of
smart users would not want to handle it, but would want it turned off, I think.
Smart users protect themselves against easy data loss. They do backups; they use
reliable software; they use unprivileged user accounts for their everyday work.
Vim is a great and reliable tool, and it would be sad to me to see MacVim
compromise that through a feature like this that can't be disabled.

Matt Tolton

unread,
Feb 5, 2008, 11:56:05 PM2/5/08
to vim...@googlegroups.com
> It's definitely not trivial...but then neither is the current approach. I suspect

I'd disagree there...I don't think that the current method is
particularly difficult, especially relative to what you propose.

> with the mouse. I would be happy with a 'first use' dialog that drew attention to
> a preference that could switch it off.

Sounds good to me.

> Well, yes and no. I think this is why we're having this discussion: a number of
> smart users would not want to handle it, but would want it turned off, I think.
> Smart users protect themselves against easy data loss. They do backups; they use
> reliable software; they use unprivileged user accounts for their everyday work.
> Vim is a great and reliable tool, and it would be sad to me to see MacVim
> compromise that through a feature like this that can't be disabled.

True, and it's always best to accommodate as many people as possible. :)

So, I guess we proceed as we have been until someone has the
expertise, time, and willingness to implement something similar to
what you suggest? (This may be me sometime in the future...I get
google 20% time soon!)

Regards,

Matt

Ben Schmidt

unread,
Feb 6, 2008, 12:09:19 AM2/6/08
to vim...@googlegroups.com
> So, I guess we proceed as we have been until someone has the
> expertise, time, and willingness to implement something similar to
> what you suggest? (This may be me sometime in the future...I get
> google 20% time soon!)

That sounds good to me, Matt.

björn

unread,
Feb 6, 2008, 11:37:32 AM2/6/08
to vim...@googlegroups.com

Ben,

I am afraid that even if I tried, I would not be able to
satisfactorily reply to this post. So I won't try and please don't be
upset with me, but the short answer to what you are suggesting is "it
is not feasible".

If Vim had a notion of multiple (GUI-)windows then your suggestions
would work (as Matt mentioned this feature has been requested multiple
times, whether it ever will be implemented is another matter).
However, without it I would say it is just not a very good idea (I had
a prototype that did something similar to what you are suggesting...it
was a nightmare) and I pretty much came up with the current solution
for MacVim because of this very issue.

As for Matt's solution to dragging tabs. I also have my reservations
and at the moment I will not enable this by default (if/when I get it
working) because of the pitfalls that you have already mentioned (of
course there will be an option in the prefs to enable it). However, I
think it is simple enough to implement that it is worth a try.

The only (possible) solution to the "dragging tabs" problem that I can
see that would actually work is to somehow be able to serialize (for a
lack of a better word) an entire tab structure in Vim and then pass on
that raw data to another Vim process via a distributed object call.
The big problem here is serialization...is it feasible to save all the
relevant state pertaining to one tab? I haven't checked that out, but
it depends entirely on how the tabs are implement in Vim (I know very
little of the Vim source myself). Also, "de-serialization" would not
be entirely trivial, I am sure. However, this certainly seems like a
much easier thing to implement than "multi-windows" in Vim (that is a
guess on my behalf). Still, it would most likely be difficult.

To conclude; if Vim is made multi-windows aware then all (most) of our
problems would be solvable, but it would also make MacVim extinct (in
a way). Without it we will have to work very hard to get around the
problems we are facing (MacVim itself is a testament to this fact I
would say) and we might not even be able to find adequate solutions.

I hope that sheds some light on the issue. My apologies if I seem
condescending; that is certainly not my intention, but I would have to
go into too much detail to qualify all my statements.

/Björn

Reply all
Reply to author
Forward
0 new messages