Save and restore frames and windows with their buffers in Emacs
Emacs Lisp
326
91 commits
updated Jul 27, 2024
#+TITLE: Burly.el
#+PROPERTY: LOGGING nil
# Note: This readme works with the org-make-toc <https://github.com/alphapapa/org-make-toc> package, which automatically updates the table of contents.
# [[https://melpa.org/#/package-name][file:https://melpa.org/packages/burly-badge.svg]] [[https://stable.melpa.org/#/package-name][file:https://stable.melpa.org/packages/burly-badge.svg]]
#+HTML: <img src="images/beaver.png" align="right">
/See also: [[https://github.com/alphapapa/activities.el][Activities.el]], which provides more advanced functionality. To some extent, it obsoletes this library./
This package provides tools to save and restore frame and window configurations in Emacs, including buffers that may not be live anymore. In this way, it's like a lightweight "workspace" manager, allowing you to easily restore one or more frames, including their windows, the windows' layout, and their buffers.
Internally it uses Emacs's bookmarks system to restore buffers to their previous contents and location. This provides power and extensibility, since many major modes already integrate with Emacs's bookmarks system. However, in case a mode's bookmarking function isn't satisfactory, Burly allows the user to customize buffer-restoring functions for specific modes.
For Org mode, Burly provides such custom functions so that narrowed and indirect Org buffers are properly restored, and headings are located by outline path in case they've moved since a bookmark was made (the [[https://github.com/alphapapa/org-bookmark-heading][org-bookmark-heading]] package also provides this through the Emacs bookmark system, but users may not have it installed, and the functionality is too useful to not include here by default).
Internally, buffers and frame/window configurations are also encoded as URLs, and users may also save and open those URLs instead of using Emacs bookmarks. (The name "Burly" comes from "buffer URL.") For example, a URL to the =Installation/Quelpa= heading in this file, as I'm writing it, looks like this:
#+BEGIN_EXAMPLE
emacs+burly+file:///home/me/src/emacs/burly.el/README.org?pos=2651&outline-path=%28%22Installation%22%20%22Quelpa%22%29&relative-pos=308
#+END_EXAMPLE
In terms of built-in features, Burly may be seen as integrating or leveraging the built-in libraries =bookmark.el=, =window.el=, and =frameset.el=.
* Contents :noexport:
:PROPERTIES:
:TOC: :include siblings
:END:
:CONTENTS:
- [[#installation][Installation]]
- [[#usage][Usage]]
- [[#changelog][Changelog]]
- [[#development][Development]]
- [[#credits][Credits]]
- [[#license][License]]
:END:
* Installation
:PROPERTIES:
:TOC: :depth 0
:END:
** MELPA
If you installed from MELPA, you're done. Just run one of the commands below.
** Quelpa
The easiest way is to install with [[https://github.com/quelpa/quelpa-use-package][quelpa-use-package]], like this:
#+BEGIN_SRC elisp
(use-package burly
:quelpa (burly :fetcher github :repo "alphapapa/burly.el"))
#+END_SRC
** Manual
1. Install version 2.1 or later of the =map= library from GNU ELPA.
2. Copy =burly.el= into a directory in your =load-path=, then ~(require 'burly)~.
* Usage
:PROPERTIES:
:TOC: :depth 0
:END:
** Bookmark commands
Most users will probably use Burly by bookmarking frame and window configurations and accessing them with these commands:
+ =burly-bookmark-frames=: Bookmark the current frames and their window configurations.
+ =burly-bookmark-windows=: Bookmark the current frame's window configuration.
+ =burly-open-bookmark=: Select and open a Burly bookmark.
+ =burly-open-last-bookmark=: Open the last-opened Burly bookmark. Helpful for, e.g. quickly restoring an overview while working on a project.
Note that bookmarks created by Burly are regular Emacs bookmarks, so they can be managed by Emacs's built-in bookmark commands, e.g. =list-bookmarks=, =bookmark-delete=, etc.
** URL commands
These commands work on URL strings. While most users probably won't use these, they may be useful for building custom tooling.
+ =burly-open-url=: Open a Burly URL (at point, or prompt for one), displaying the buffer(s) in the current window or frame.
+ =burly-kill-buffer-url=: Copy BUFFER's URL to the kill ring.
+ =burly-kill-frames-url=: Copy the current frameset's URL to the kill ring.
+ =burly-kill-windows-url=: Copy the current frame's window configuration URL to the kill ring.
** Tab bar
Burly supports Emacs's ~tab-bar-mode~ with ~burly-tabs-mode~. When active, Burly bookmarks are opened in new tabs, and the tabs are named according to the bookmarks. Reopening a Burly bookmark uses the designated tab, if it already exists, and tabs may be reset to their bookmarked state with the command ~burly-reset-tab~ (which you might bind to =C-x t R=).
** Tips
+ You can customize settings in the =burly= group.
+ An Info manual is included with this package.
* Changelog
:PROPERTIES:
:TOC: :depth 0
:END:
** 0.4-pre
*Added*
+ Option ~burly-tabs-after-hook~, run after opening a Burly bookmark in ~burly-tabs-mode~. (Useful for, e.g. integrating with [[https://github.com/alphapapa/bufler.el][Bufler]] to set the new tab's workspace automatically.)
+ Option ~burly-tabs-abbreviate-name~ abbreviates the names of Burly bookmarks when using ~burly-tabs-mode~.
*Fixed*
+ Preservation of window parameter ~window-preserved-size~.
** 0.3
*Added*
+ Command ~burly-tabs-mode~, which integrates Burly with ~tab-bar-mode~. When active, Burly bookmarks are opened in new tabs, and the tabs are named according to the bookmark.
+ Command ~burly-reset-tab~, which resets a tab to the state of the bookmark which opened it.
*Changed*
+ Emacs version 28.1 or later is required.
*Fixed*
+ Buffers that can't be restored by name no longer cause an error which aborts restoration of the rest of the bookmark's buffers.
+ Added workaround for regression in Emacs 28 regarding bookmarks for ~help-mode~ buffers. (See [[https://debbugs.gnu.org/cgi/bugreport.cgi?bug=56643][Emacs bug 56643]].)
+ Removed unadvisable local rebinding of ~alist-get~ in function ~burly-follow-url-org-mode~. An innocent change in Org 9.6 was broken by this, which then broke this when called through Burly. (With thanks to [[https://github.com/yantar92][Ihor Radchenko]] for debugging.)
+ Load default bookmarks file when needed. ([[https://github.com/alphapapa/burly.el/issues/46][#46]]. Thanks to [[https://github.com/zw963][Billy Zheng]] and [[https://github.com/ParetoOptimalDev][ParetoOptimalDev]] for reporting, and to [[https://github.com/tfree87][Thomas Freeman]] for fixing.)
** 0.2
*Added*
+ Bookmark commands use ~completing-read~ and offer existing Burly bookmark names, making it easier to update bookmarks. (Thanks to [[https://github.com/Kungsgeten][Erik Sjöstrand]].)
+ Command =burly-open-last-bookmark=.
+ Option =burly-set-window-persistent-parameters=, which synchronizes =window-persistent-parameters= with =burly-window-persistent-parameters=, ensuring that built-in Emacs commands like =window-toggle-side-windows= persist parameters that are persisted with Burly.
*Changed*
+ Option =burly-window-persistent-parameters='s default value includes more window parameters, like header/mode line, side, slot, etc, making it easier to restore an overview of a project or "workspace."
+ Emacs version 27.1 or later is required.
*Fixed*
+ Narrow Org buffers to correct heading (at the top of the buffer rather than at point).
+ Buffers whose names have multibyte characters. (Fixes [[https://github.com/alphapapa/burly.el/issues/43][#43]]. Thanks to [[https://github.com/ilupin][Liu Hui]] for reporting.)
+ Bind ~print-level~ to nil where ~prin1-to-string~ is used (in case the value is non-nil in a user's config, which would cause truncated values).
** 0.1
Initial release.
* Development
Bug reports, feature requests, suggestions — /oh my/!
* Credits
+ Thanks to [[https://github.com/clemera][Clemens Radermacher]] and [[https://github.com/rswgnu][Robert Weiner]] for their suggestions.
+ Thanks to [[https://github.com/tpeacock19][Trey Peacock]] for extensive feedback on pre-release versions.
* License
GPLv3
* COMMENT Export setup :noexport:
:PROPERTIES:
:TOC: :ignore (this descendants)
:END:
# Copied from org-super-agenda's readme, in which much was borrowed from Org's =org-manual.org=.
#+OPTIONS: broken-links:t *:t
** Info export options
#+TEXINFO_DIR_CATEGORY: Emacs
#+TEXINFO_DIR_TITLE: Burly: (burly)
#+TEXINFO_DIR_DESC: Save and restore window configurations and their buffers
# NOTE: We could use these, but that causes a pointless error, "org-compile-file: File "..README.info" wasn't produced...", so we just rename the files in the after-save-hook instead.
# #+TEXINFO_FILENAME: burly.info
# #+EXPORT_FILE_NAME: burly.texi
** File-local variables
# NOTE: Setting org-comment-string buffer-locally is a nasty hack to work around GitHub's org-ruby's HTML rendering, which does not respect noexport tags. The only way to hide this tree from its output is to use the COMMENT keyword, but that prevents Org from processing the export options declared in it. So since these file-local variables don't affect org-ruby, wet set org-comment-string to an unused keyword, which prevents Org from deleting this tree from the export buffer, which allows it to find the export options in it. And since org-export does respect the noexport tag, the tree is excluded from the info page.
# Local Variables:
# before-save-hook: org-make-toc
# after-save-hook: (lambda nil (when (and (require 'ox-texinfo nil t) (org-texinfo-export-to-info)) (delete-file "README.texi") (rename-file "README.info" "burly.info" t)))
# org-export-initial-scope: buffer
# org-export-with-properties: ()
# org-export-with-title: t
# org-comment-string: "NOTCOMMENT"
# End:
Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.
Emacs Lisp
100.0%
Save and restore frames and windows with their buffers in Emacs
Emacs Lisp
326
91 commits
updated Jul 27, 2024
#+TITLE: Burly.el
#+PROPERTY: LOGGING nil
# Note: This readme works with the org-make-toc <https://github.com/alphapapa/org-make-toc> package, which automatically updates the table of contents.
# [[https://melpa.org/#/package-name][file:https://melpa.org/packages/burly-badge.svg]] [[https://stable.melpa.org/#/package-name][file:https://stable.melpa.org/packages/burly-badge.svg]]
#+HTML: <img src="images/beaver.png" align="right">
/See also: [[https://github.com/alphapapa/activities.el][Activities.el]], which provides more advanced functionality. To some extent, it obsoletes this library./
This package provides tools to save and restore frame and window configurations in Emacs, including buffers that may not be live anymore. In this way, it's like a lightweight "workspace" manager, allowing you to easily restore one or more frames, including their windows, the windows' layout, and their buffers.
Internally it uses Emacs's bookmarks system to restore buffers to their previous contents and location. This provides power and extensibility, since many major modes already integrate with Emacs's bookmarks system. However, in case a mode's bookmarking function isn't satisfactory, Burly allows the user to customize buffer-restoring functions for specific modes.
For Org mode, Burly provides such custom functions so that narrowed and indirect Org buffers are properly restored, and headings are located by outline path in case they've moved since a bookmark was made (the [[https://github.com/alphapapa/org-bookmark-heading][org-bookmark-heading]] package also provides this through the Emacs bookmark system, but users may not have it installed, and the functionality is too useful to not include here by default).
Internally, buffers and frame/window configurations are also encoded as URLs, and users may also save and open those URLs instead of using Emacs bookmarks. (The name "Burly" comes from "buffer URL.") For example, a URL to the =Installation/Quelpa= heading in this file, as I'm writing it, looks like this:
#+BEGIN_EXAMPLE
emacs+burly+file:///home/me/src/emacs/burly.el/README.org?pos=2651&outline-path=%28%22Installation%22%20%22Quelpa%22%29&relative-pos=308
#+END_EXAMPLE
In terms of built-in features, Burly may be seen as integrating or leveraging the built-in libraries =bookmark.el=, =window.el=, and =frameset.el=.
* Contents :noexport:
:PROPERTIES:
:TOC: :include siblings
:END:
:CONTENTS:
- [[#installation][Installation]]
- [[#usage][Usage]]
- [[#changelog][Changelog]]
- [[#development][Development]]
- [[#credits][Credits]]
- [[#license][License]]
:END:
* Installation
:PROPERTIES:
:TOC: :depth 0
:END:
** MELPA
If you installed from MELPA, you're done. Just run one of the commands below.
** Quelpa
The easiest way is to install with [[https://github.com/quelpa/quelpa-use-package][quelpa-use-package]], like this:
#+BEGIN_SRC elisp
(use-package burly
:quelpa (burly :fetcher github :repo "alphapapa/burly.el"))
#+END_SRC
** Manual
1. Install version 2.1 or later of the =map= library from GNU ELPA.
2. Copy =burly.el= into a directory in your =load-path=, then ~(require 'burly)~.
* Usage
:PROPERTIES:
:TOC: :depth 0
:END:
** Bookmark commands
Most users will probably use Burly by bookmarking frame and window configurations and accessing them with these commands:
+ =burly-bookmark-frames=: Bookmark the current frames and their window configurations.
+ =burly-bookmark-windows=: Bookmark the current frame's window configuration.
+ =burly-open-bookmark=: Select and open a Burly bookmark.
+ =burly-open-last-bookmark=: Open the last-opened Burly bookmark. Helpful for, e.g. quickly restoring an overview while working on a project.
Note that bookmarks created by Burly are regular Emacs bookmarks, so they can be managed by Emacs's built-in bookmark commands, e.g. =list-bookmarks=, =bookmark-delete=, etc.
** URL commands
These commands work on URL strings. While most users probably won't use these, they may be useful for building custom tooling.
+ =burly-open-url=: Open a Burly URL (at point, or prompt for one), displaying the buffer(s) in the current window or frame.
+ =burly-kill-buffer-url=: Copy BUFFER's URL to the kill ring.
+ =burly-kill-frames-url=: Copy the current frameset's URL to the kill ring.
+ =burly-kill-windows-url=: Copy the current frame's window configuration URL to the kill ring.
** Tab bar
Burly supports Emacs's ~tab-bar-mode~ with ~burly-tabs-mode~. When active, Burly bookmarks are opened in new tabs, and the tabs are named according to the bookmarks. Reopening a Burly bookmark uses the designated tab, if it already exists, and tabs may be reset to their bookmarked state with the command ~burly-reset-tab~ (which you might bind to =C-x t R=).
** Tips
+ You can customize settings in the =burly= group.
+ An Info manual is included with this package.
* Changelog
:PROPERTIES:
:TOC: :depth 0
:END:
** 0.4-pre
*Added*
+ Option ~burly-tabs-after-hook~, run after opening a Burly bookmark in ~burly-tabs-mode~. (Useful for, e.g. integrating with [[https://github.com/alphapapa/bufler.el][Bufler]] to set the new tab's workspace automatically.)
+ Option ~burly-tabs-abbreviate-name~ abbreviates the names of Burly bookmarks when using ~burly-tabs-mode~.
*Fixed*
+ Preservation of window parameter ~window-preserved-size~.
** 0.3
*Added*
+ Command ~burly-tabs-mode~, which integrates Burly with ~tab-bar-mode~. When active, Burly bookmarks are opened in new tabs, and the tabs are named according to the bookmark.
+ Command ~burly-reset-tab~, which resets a tab to the state of the bookmark which opened it.
*Changed*
+ Emacs version 28.1 or later is required.
*Fixed*
+ Buffers that can't be restored by name no longer cause an error which aborts restoration of the rest of the bookmark's buffers.
+ Added workaround for regression in Emacs 28 regarding bookmarks for ~help-mode~ buffers. (See [[https://debbugs.gnu.org/cgi/bugreport.cgi?bug=56643][Emacs bug 56643]].)
+ Removed unadvisable local rebinding of ~alist-get~ in function ~burly-follow-url-org-mode~. An innocent change in Org 9.6 was broken by this, which then broke this when called through Burly. (With thanks to [[https://github.com/yantar92][Ihor Radchenko]] for debugging.)
+ Load default bookmarks file when needed. ([[https://github.com/alphapapa/burly.el/issues/46][#46]]. Thanks to [[https://github.com/zw963][Billy Zheng]] and [[https://github.com/ParetoOptimalDev][ParetoOptimalDev]] for reporting, and to [[https://github.com/tfree87][Thomas Freeman]] for fixing.)
** 0.2
*Added*
+ Bookmark commands use ~completing-read~ and offer existing Burly bookmark names, making it easier to update bookmarks. (Thanks to [[https://github.com/Kungsgeten][Erik Sjöstrand]].)
+ Command =burly-open-last-bookmark=.
+ Option =burly-set-window-persistent-parameters=, which synchronizes =window-persistent-parameters= with =burly-window-persistent-parameters=, ensuring that built-in Emacs commands like =window-toggle-side-windows= persist parameters that are persisted with Burly.
*Changed*
+ Option =burly-window-persistent-parameters='s default value includes more window parameters, like header/mode line, side, slot, etc, making it easier to restore an overview of a project or "workspace."
+ Emacs version 27.1 or later is required.
*Fixed*
+ Narrow Org buffers to correct heading (at the top of the buffer rather than at point).
+ Buffers whose names have multibyte characters. (Fixes [[https://github.com/alphapapa/burly.el/issues/43][#43]]. Thanks to [[https://github.com/ilupin][Liu Hui]] for reporting.)
+ Bind ~print-level~ to nil where ~prin1-to-string~ is used (in case the value is non-nil in a user's config, which would cause truncated values).
** 0.1
Initial release.
* Development
Bug reports, feature requests, suggestions — /oh my/!
* Credits
+ Thanks to [[https://github.com/clemera][Clemens Radermacher]] and [[https://github.com/rswgnu][Robert Weiner]] for their suggestions.
+ Thanks to [[https://github.com/tpeacock19][Trey Peacock]] for extensive feedback on pre-release versions.
* License
GPLv3
* COMMENT Export setup :noexport:
:PROPERTIES:
:TOC: :ignore (this descendants)
:END:
# Copied from org-super-agenda's readme, in which much was borrowed from Org's =org-manual.org=.
#+OPTIONS: broken-links:t *:t
** Info export options
#+TEXINFO_DIR_CATEGORY: Emacs
#+TEXINFO_DIR_TITLE: Burly: (burly)
#+TEXINFO_DIR_DESC: Save and restore window configurations and their buffers
# NOTE: We could use these, but that causes a pointless error, "org-compile-file: File "..README.info" wasn't produced...", so we just rename the files in the after-save-hook instead.
# #+TEXINFO_FILENAME: burly.info
# #+EXPORT_FILE_NAME: burly.texi
** File-local variables
# NOTE: Setting org-comment-string buffer-locally is a nasty hack to work around GitHub's org-ruby's HTML rendering, which does not respect noexport tags. The only way to hide this tree from its output is to use the COMMENT keyword, but that prevents Org from processing the export options declared in it. So since these file-local variables don't affect org-ruby, wet set org-comment-string to an unused keyword, which prevents Org from deleting this tree from the export buffer, which allows it to find the export options in it. And since org-export does respect the noexport tag, the tree is excluded from the info page.
# Local Variables:
# before-save-hook: org-make-toc
# after-save-hook: (lambda nil (when (and (require 'ox-texinfo nil t) (org-texinfo-export-to-info)) (delete-file "README.texi") (rename-file "README.info" "burly.info" t)))
# org-export-initial-scope: buffer
# org-export-with-properties: ()
# org-export-with-title: t
# org-comment-string: "NOTCOMMENT"
# End:
Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.
Emacs Lisp
100.0%