bufferlo
bufferlo copied to clipboard
Suggestion: In README or Wiki show how restored tabs can be put in tab groups
tab-bar has the concept of tab groups. I wanted to automatically put some restored tabs in their respective tab groups. As it took some effort to find out how to do this, I suggest that it would be good to document how to do this, somewhere. This is what I came up with:
-
I installed package "tab-bar-groups"
-
I then added something like as follows to my emacs init file: `(defun jw/tab-bar-group (bookmark-name effective-bookmark-name new-frame-p frame) "For each tab in tab-bar-tabs, conditionally add tab to a tab-group" ;; (interactive) (cl-loop for tab in (tab-bar-tabs) do (let ((current-tab-name (cdr (assq 'name tab)))) (cond ((string-match-p (rx "partition") current-tab-name) (tab-bar-groups-assign-group "thermo" tab)) ((string-match-p (rx "thermodyna") current-tab-name) (tab-bar-groups-assign-group "thermo" tab)) ((string-match-p (rx "Gibbs free") current-tab-name) (tab-bar-groups-assign-group "thermo" tab)) ((string-match-p (rx "internal ene") current-tab-name) (tab-bar-groups-assign-group "thermo" tab)) ((string-match-p (rx "state func") current-tab-name) (tab-bar-groups-assign-group "thermo" tab)) ((string-match-p (rx "generalized") current-tab-name) (tab-bar-groups-assign-group "anal" tab)) ((string-match-p (rx "total deriva") current-tab-name) (tab-bar-groups-assign-group "anal" tab)) (t t)))))
(add-hook 'bufferlo-bookmark-frame-handler-functions 'jw/tab-bar-group) `
Thanks for the contribution! I agree with you. It's a good idea to document this. Maybe we can make a Wiki article.
Just to clarify, you used this package: https://github.com/fritzgrabo/tab-bar-groups ...because Emacs has also has tab groups since version 28.
Ah I see, with the package, it seems that you use the integrated tabs in Emacs 28+ and you have just some additional functionality with the package. (If I see it correctly, in Emacs 28+ it is recommended to use tab-bar-change-tab-group instead of tab-bar-groups-assign-group.)
In the long term, Bufferlo should probably be able to remember tab groups in bookmarks.
Any group assigned to a tab is stored in the bufferlo tab bookmark.
The question of which tabs belong to which groups is definitely a user preference and not a responsibility for bufferlo, in my view.
For example, in my configuration, I assign a tab's group based on its project-current with some additional customizations for buffers that are in a project ignore list, and for buffers that do not belong to a project, but for which I use a project.el backend for non-projects to benefit from the cache so I avoid repeated project.el probing costs. This is a dynamic process and if, for example, in a tab I switch from a buffer that's in project A to a buffer that's in project B, the tab is reassigned to project B.
The Emacs tab-bar can keep tabs with the same group together. See tab-bar-tab-post-change-group-functions which has as its default '(tab-bar-move-tab-to-group).
There are packages that could be used in your configuration to do some other type of tab-bar group assignment.
tab-bar-change-tab-group has an inconvenient interface: One can not provide a tab as an argument, one has to specify a tab-number.
That's a small matter of programming. Would you like me to write a function that does that? In any case, the command tab-bar-change-tab-group operates on the current tab when invoked interactively, and no tab number is needed.
@johanwiden I see you've attached your tab-bar grouping function to bufferlo-bookmark-frame-handler-functions but I imagine instead you might want it to be called whenever creating any tab whether the tab is under bufferlo control or not? There is a tab-bar hook called tab-bar-tab-post-open-functions that might suit you.
I tried tab-bar-tab-post-open-functions, but could not get that to work, when called during bufferlo-bm-frame-load.
It would be good to document how one can retrieve the tab-bar group from the bufferlo bookmark.
In the end I imagine that there will be several different use cases:
- Automatically assign tabs to groups, when tabs are restored
- Assign a tab to a group when it is created
- ... So one could start by documenting how to do some of these use cases, and then add more as they come up. I think it is better to show how to do each use case, instead of showing one complicated function that does them all.
bufferlo stores a tab-bar tab group and will automatically assign it to the newly opened tab if your post-open hook hasn't already assigned one. If you assign an "explicit" name that takes precedence as is the default behavior for tab-bar itself. All of this works fine for me.
Which part of tab-bar-tab-post-open-functions didn't work and does it work on any newly opened tab?
Here's what's in mine
(defun my/tab-bar-tab-post-open-function (tab)
(my/tab-bar-set-id nil tab)
(my/tab-bar-tab-set-project-and-group tab 'maybe-sort))
(add-hook 'tab-bar-tab-post-open-functions #'my/tab-bar-tab-post-open-function)
If you need to, you can also test to see if a tab was cloned and from what tab
(when (eq tab-bar-new-tab-choice 'clone)
(let* ((tabs (funcall tab-bar-tabs-function))
(orig-tab (nth (tab-bar--tab-index-recent 1) tabs)))
...etc...
Which part of tab-bar-tab-post-open-functions didn't work and does it work on any newly opened tab?
During restore, it restored some, but not all tabs. Some tabs were put in tab-groups, but not all. Perhaps this was due to me using tab-bar-groups-assign-group (?)
Anyhow, I will have a look/try with your suggested my/tab-bar-tab-post-open-function, or something similar. But that will be tomorrow.
Also, my bufferlo-bookmark-tab-handler-functions and bufferlo-bookmark-frame-handler-functions are empty.
Ah, I wasn't aware that the tab-group is already stored in the bufferlo bookmark. 👍
I tested it now. Tab-group restoration is partially broken (so @johanwiden, you are right, we have a problem here).
It does work for tab bookmarks (at least when bufferlo-bookmark-tab-replace-policy set to 'new), but not for frame bookmarks.
Frame bookmarks: Tab-group restoration is simply missing. This should fix it: https://github.com/florommel/bufferlo/commit/9005e46493f85ddb519b9ce2910fc15559fa28fb (tested only superficially)
Tab bookmarks:
The tab group is not restored when bufferlo-bookmark-tab-replace-policy is set to 'replace (the default) or when it is 'prompt and we choose replace interactively. The same applies to explicit tab names.
https://github.com/florommel/bufferlo/blob/2c3c5ec3d3eec20efbf23b08ecf78c9d174bdcd8/bufferlo.el#L2713-L2727
This behavior is probably okay, since the tab already exists and might have an existing tab-group. It's maybe also compatible with previous bufferlo versions. However, we could make this configurable.
I haven't looked at sets yet.
Sets use the underlying frame and tab code so there should be zero difference.
I have now for branch fix-tab-group-restore verified restore of tab-group. See attached file. Almost everything i tested, worked. The following did not work as expected:
- Restore of a bookmark set, where one tab-bookmark has an assigned tab-group.
- The tabs were restored, in a new frame, but no tab was in a tab-group.
- Use of hook tab-bar-tab-post-open-functions, when restoring frame:
- It tried reassigning tab-group for some tabs, but this had no effect.
- Note: Reassigning tab-group is perhaps not very useful, when restoring, given that frame restore already handles the tab-groups stored in the bookmark. I just wanted to see if it worked. On the positive side: All tabs were restored.
- It tried reassigning tab-group for some tabs, but this had no effect.
Tabs loaded from sets automatically set bufferlo-bookmark-tab-replace-policy 'replace so that would explain the behavior. The situation this helps with is if you open a tab bookmark that is in a set, and then open a set, it assumes you want to reload the tab. Prompting when loading a set was cumbersome, so this was a compromise.
There is a way, though, and perhaps restoring the group was an oversight. We have a variable called bufferlo--bookmark-set-loading, which, when non-nil, can be used to influence the behavior of tab/frame restoration when we know a set is being loaded so we could enable 'replace to overwrite tab-group (and tab-name).
It's also possible that when the policy is 'replace that we just replace group/name even if it's not in a set.
There is an updated version of the branch where the tab-group restoration in frame bookmarks is configurable (Commit ad405fa)
* Restore of a bookmark set, where one tab-bookmark has an assigned tab-group. * The tabs were restored, in a new frame, but no tab was in a tab-group.
The tab group (and also the explicit tab name) are currently not restored for tab bookmarks (only for tabs in frame bookmarks). Maybe we should add this. We could add another config switch (similar to the one for frame bookmarks) to allow this (and another one for the explicit tab name). What do you think @shipmints?
* Use of hook tab-bar-tab-post-open-functions, when restoring frame: * It tried reassigning tab-group for some tabs, but this had no effect.
If I understand it correctly, this should work now (with ad405fa) when bufferlo-bookmark-restore-tab-group is set to 'if-nil (the default).
I have been using the branch, since it was created, and have used the functionality a lot, with no problems detected. So I believe that the branch works OK, and should be merged.
see #44
With this change we always restore the tab groups now by default (I think that this makes sense), but there are user options to turn it off (for frame and for tab bookmarks).
@johanwiden
The fix is now on the main branch (not yet released). We have decided to have the tab-group restoration off by default (for backwards compatibilit). The final name of the config option is bufferlo-bookmark-restore-tab-groups. Make sure to set bufferlo-bookmark-restore-tab-groups to t before updating to keep your current tab groups saved with your bookmarks.
Thanks! The main branch now appears to handle tab group restoration without problems. I have not tested thoroughly though.