Open hrehfeld opened 3 years ago
This would be a very confusing behavior. It would surely lead to users accidentally overwriting their carefully crafted bookmarks.
What you seem to be wanting is a kind of workspace-switching behavior. Burly could be used as a backend for something like that, and I have some ideas along those lines (e.g. see the recently added burly-open-last-bookmark
command). But they need to be designed thoughtfully. It would also probably make sense to try to integrate it with Emacs 27 tab bars (I'm imagining something like, middle-clicking on a tab would restore to a Burly-bookmarked default state, while left-clicking it would simply change back to that tab's current state).
Anyway, if you really want the behavior you described, you could easily use the variable burly-opened-bookmark-name
to implement it yourself in a simple command.
Thanks for your input!
I'm working on a small package burly-workspaces
, will post here in a few days when I find that it works well enough. I would definitely appreciate your feedback!
Hm, I'm thinking about adding a burly-workspace-mode
feature to this package in the future to integrate it with Emacs 27 tab-bars. It'd be good to avoid namespace conflicts and confusion. Maybe, rather than publishing a new package, we could work together to integrate these ideas into this package.
Basically, my idea is that opening a Burly bookmark would open a new tab with the restored window configuration. Then, switching between window configurations with the tab bar would work normally. But an additional command would restore the current tab's Burly bookmark, like "resetting" the workspace to the bookmarked configuration. I'm thinking, e.g. to bind that to middle-click on the tabs, so left-clicking would select the tab normally, and middle-clicking it would reset it (I don't recall if middle-click is already bound to something on the tabs). Of course, users could also bind it to a key of their choice.
What do you think? Thanks.
It looks interesting, I do wonder how it would interact with bufler though.
Currently I'm using Bufler to store arbitrary workspace information directly in buffer-local variables, and I was starting to wonder how I could use that to get "per-workspace" management (i.e. have a "open workspace" command, that prompts for a list of known workspaces, and then restore them to the last saved state).
For the time being I'm struggling to find time to finish properly https://github.com/alphapapa/bufler.el/pull/53 but the end-goal was kind of the same : I'd like to have a workspace feature integrated with tab-bar where I can save/kill/restore collections of buffer+window configurations. So marking them, saving configurations and restoring configurations are really the 3 steps I'd want.
I didn't think through using bufler to manage workspaces completely, but I'm interested in seeing where this goes.
To go back on topic,
Basically, my idea is that opening a Burly bookmark would open a new tab with the restored window configuration.
That would work nicely, and it'd be nice if there was a switch to automatically save/overwrite the bookmark on window configuration change as well, instead of keeping the bookmark for the middle click feature. That would allow a seamless "get back to workspace" experience imo.
Some of these ideas are exploratory, so I don't know where they will end up. It seems to me that the ideas described here are not directly related to Bufler. To me, Bufler is about automatically grouping buffers for easier manipulation, while Burly is about restoring window and frame configurations and their buffers.
Bufler's "workspace mode" is really internal to Bufler; it only affects which buffers certain Bufler commands offer for completion.
Bufler's "tabs mode" does integrate with the Emacs 27+ tab bar, and I don't know if it would be feasible to have both bufler-tabs-mode
and a hypothetical burly-workspace-mode
or burly-tabs-mode
active at the same time. It might be, because the tab bar code is quite extensible; assuming it's possible, the existing bufler-tabs-mode
code would need to be changed to extend rather than override the relevant tab-bar functions. (Or it might be necessary to enhance the tab-bar library to allow for more extensibility and co-existence of such extensions. I don't think it was quite designed with that in mind.)
I'd like to have a workspace feature integrated with tab-bar where I can save/kill/restore collections of buffer+window configurations. So marking them, saving configurations and restoring configurations are really the 3 steps I'd want.
Yes, that's basically my idea, and I think it belongs in Burly rather than Bufler.
That would work nicely, and it'd be nice if there was a switch to automatically save/overwrite the bookmark on window configuration change as well, instead of keeping the bookmark for the middle click feature. That would allow a seamless "get back to workspace" experience imo.
We could certainly offer an option for that. I guess that might require each Burly bookmark to have multiple states, like a "reset-to" state and a "last-used" state, because the appeal of Burly, to me, is being able to restore a certain state, not whatever arrangement of buffers I happened to have opened last--that arrangement is constantly changing as I use different commands, view different files and buffers, etc.
Hm, I'm thinking about adding a
burly-workspace-mode
feature to this package in the future to integrate it with Emacs 27 tab-bars. It'd be good to avoid namespace conflicts and confusion. Maybe, rather than publishing a new package, we could work together to integrate these ideas into this package.
Yep, I was about to ask that. :+1:
Basically, my idea is that opening a Burly bookmark would open a new tab with the restored window configuration. Then, switching between window configurations with the tab bar would work normally. But an additional command would restore the current tab's Burly bookmark, like "resetting" the workspace to the bookmarked configuration. I'm thinking, e.g. to bind that to middle-click on the tabs, so left-clicking would select the tab normally, and middle-clicking it would reset it (I don't recall if middle-click is already bound to something on the tabs). Of course, users could also bind it to a key of their choice.
Hmm, I don't use tabs at all, so it's hard for me to talk about good workflows there. It sounds like a variable like burly-restore-function
might come in handy to distinguish between "open a new tab and apply workspace" and just "apply workspace"?
I'm currently just trying to model eyebrowse behavior, which is basically as I described:
burly-opened-bookmark-name
is updated accordingly.This is what I have so far, the ability to toggle via minor mode was just added, might still be broken:
(defvar burly-workspaces-prefix "Workspace " "How to name the
automatic workspaces")
;;(setq burly-workspaces-prefix "Workspace ")
(defun burly-workspaces--bookmark-exists (name) (bookmark-get-bookmark name 'no-error))
(defun burly-workspaces--burly-open-bookmark-advice (name)
"Before `burly-open-bookmark' bookmark the previously loaded
bookmark. With a prefix argument `ARG' or if the new `name' is
not a bookmark yet , don't save and just switch."
(cl-assert name "No name given to advice!")
(let ((command-is-prefxed current-prefix-arg)
(current-exists burly-opened-bookmark-name)
(target-already-opened (string-equal name burly-opened-bookmark-name))
(target-exists (burly-workspaces--bookmark-exists name)))
;;(message "burly-workspaces--burly-open-bookmark-advice %S %S %S %S" name command-is-prefxed target-already-opened target-exists)
(unless (or command-is-prefxed
target-already-opened
(not target-exists)
(not current-exists))
(burly-bookmark-windows burly-opened-bookmark-name))
))
(defun burly-workspaces--burly-bookmark-windows-advice (name)
"After `burly-bookmark-windows', set `burly-opened-bookmark-name' to the name of the newly saved bookmark."
(let* ((bookmark-name (or name bookmark-current-bookmark))
(already-open (string-equal bookmark-name burly-opened-bookmark-name)))
(cl-assert bookmark-name)
;;(message "burly-workspaces--burly-bookmark-windows-advice %S %S" bookmark-name already-open)
(unless already-open
(setq burly-opened-bookmark-name bookmark-name))))
(defun burly-workspaces-do (arg num)
"Switch to workspace bookmark `num' after saving the opened workspace bookmark, or with `prefix-arg' write a new workspace bookmark `num'."
(interactive "P")
(let ((name (concat burly-bookmark-prefix burly-workspaces-prefix (number-to-string num))))
(burly-open-bookmark name)
))
(defun burly-workspaces-do-0 (arg) "See `burly-workspaces-do'." (interactive "P") (burly-workspaces-do arg 0))
(defun burly-workspaces-do-1 (arg) "See `burly-workspaces-do'." (interactive "P") (burly-workspaces-do arg 1))
(defun burly-workspaces-do-2 (arg) "See `burly-workspaces-do'." (interactive "P") (burly-workspaces-do arg 2))
(defun burly-workspaces-do-3 (arg) "See `burly-workspaces-do'." (interactive "P") (burly-workspaces-do arg 3))
(defun burly-workspaces-do-4 (arg) "See `burly-workspaces-do'." (interactive "P") (burly-workspaces-do arg 4))
(defun burly-workspaces-do-5 (arg) "See `burly-workspaces-do'." (interactive "P") (burly-workspaces-do arg 5))
(defun burly-workspaces-do-6 (arg) "See `burly-workspaces-do'." (interactive "P") (burly-workspaces-do arg 6))
(defun burly-workspaces-do-7 (arg) "See `burly-workspaces-do'." (interactive "P") (burly-workspaces-do arg 7))
(defun burly-workspaces-do-8 (arg) "See `burly-workspaces-do'." (interactive "P") (burly-workspaces-do arg 8))
(defun burly-workspaces-do-9 (arg) "See `burly-workspaces-do'." (interactive "P") (burly-workspaces-do arg 9))
(defvar burly-workspaces-mode-map (make-sparse-keymap) "Keymap
for `burly-workspaces-mode'.")
(define-minor-mode burly-workspaces-mode
"FIXME"
:global t
:lighter " bws"
:keymap burly-workspaces-mode-map
(if burly-workspaces-mode
(progn
(advice-add #'burly-bookmark-windows :after #'burly-workspaces--burly-bookmark-windows-advice)
(advice-add #'burly-open-bookmark :before #'burly-workspaces--burly-open-bookmark-advice))
(progn
(advice-remove #'burly-bookmark-windows #'burly-workspaces--burly-bookmark-windows-advice)
(advice-remove #'burly-open-bookmark #'burly-workspaces--burly-open-bookmark-advice))))
(defun burly-workspaces-setup-numeric-keys (prefix-keys)
(define-key burly-workspaces-mode-map (kbd (concat prefix-keys " 0")) #'burly-workspaces-do-0)
(define-key burly-workspaces-mode-map (kbd (concat prefix-keys " 1")) #'burly-workspaces-do-1)
(define-key burly-workspaces-mode-map (kbd (concat prefix-keys " 2")) #'burly-workspaces-do-2)
(define-key burly-workspaces-mode-map (kbd (concat prefix-keys " 3")) #'burly-workspaces-do-3)
(define-key burly-workspaces-mode-map (kbd (concat prefix-keys " 4")) #'burly-workspaces-do-4)
(define-key burly-workspaces-mode-map (kbd (concat prefix-keys " 5")) #'burly-workspaces-do-5)
(define-key burly-workspaces-mode-map (kbd (concat prefix-keys " 6")) #'burly-workspaces-do-6)
(define-key burly-workspaces-mode-map (kbd (concat prefix-keys " 7")) #'burly-workspaces-do-7)
(define-key burly-workspaces-mode-map (kbd (concat prefix-keys " 8")) #'burly-workspaces-do-8)
(define-key burly-workspaces-mode-map (kbd (concat prefix-keys " 9")) #'burly-workspaces-do-9))
;; my config
(burly-workspaces-setup-numeric-keys "C-. e")
It would probably be much better to just use the numeric argument for numeric switching... hmmm.
Oh, this will get horribly confused when opening multiple frames and restoring workspaces, as burly-opened-bookmark is shared between frames, I guess.
What's the recommended way for frame-local variables?
What's the recommended way for frame-local variables?
Probably the Frame Parameter API
@hrehfeld FYI, I'm not interested in imitating Perspective's design, with numbered workspaces and that sort of thing. If that's what you're looking for, then you'll need to do that part on your own. And, if you're going to do that, then rather than writing your own workspace package, I'd suggest looking into extending Perspective to use Burly as a backend to restore buffers. I designed Burly so that its functions can easily be used in other packages.
What I'm more interested in doing is using Burly to integrate with and extend existing Emacs tools, like how it currently integrates bookmarks with window and frame configurations. Integrating with tab-bar seems like a natural next step.
In any case, I'd ask that you not publish a package named burly-SOMETHING
. The design you've shared so far really has nothing to do with Burly, per se; that it uses Burly as a backend to restore buffers is incidental. And using burly
as a prefix would imply that it's part of this project, and of course, could cause namespace conflicts.
Having said that, I'm of course happy for you to use Burly in your project, and I'll be glad to help you if I can.
I'd like to have a workspace feature integrated with tab-bar where I can save/kill/restore collections of buffer+window configurations. So marking them, saving configurations and restoring configurations are really the 3 steps I'd want.
Yes, that's basically my idea, and I think it belongs in Burly rather than Bufler.
I’ve been thinking about it a bit more recently, and I think the main limitation today in burly is that you’d need specific machinery in the frames part of the code.
In my current workflow, a workspace is a tab where all buffers share a buffer-local parameter (they belong to the same bufler workspace, and actually when I switch on the tab, the bufler-workspace of the frame changes to match it). A session is set of workspaces, i.e. it is the frame that holds multiple tabs. Maybe it’s not the correct way, but it’s how I will use the words session and workspace
When I save a workspace, I need to actually save a single tab, but tabs
are frame-parameters. The only way to save a workspace is to save a frameset, with all the other tabs.
When I restore a workspace, I need to restore the buffers in the buffer-list
that belonged to the workspace, but buffer-list
is a frame-parameter. So if I want to restore the buffers in a new tab, I need some logic to fuse the current buffer-list
with the one I want to restore.
It’s more complex than what I’d like, so for the time being I think I’ll only focus on saving/restoring sessions in my endeavours.
Trying to save/restore "workspaces as individual tabs" might have some tricks hidden.
For saving, I think having some way to specify a predicate
function (that takes a buffer as parameter) to burly-frames-url
would be nice, so that one can choose to keep a subset of parameters on save.
Maybe that’s already what burly-window-persistent-parameters
and burly-frameset-filter-alist
do, my next exploration step is to go through these parameters and see what I can do
Restoring, which in my mind means "fuse 2 sets of frame-parameters in 1 frame", is not clear enough in my head to have an opinion other than "it’s going to be complex".
e.g: I restored burly bookmark
foo
, then restore burly bookmarkbar
. Please give me the option to automatically save the old bookmarkfoo
before switching to the new one.Ideally,
C-u burly-open-bookmark
toggles the behavior, and which behavior is the default is configurable.