diff --git a/README.org b/README.org index cb8b143..d101d2f 100644 --- a/README.org +++ b/README.org @@ -147,6 +147,7 @@ When option ~activities-bookmark-store~ is enabled, an Emacs bookmark is stored + Command ~activities-rename~ renames an activity. + Option ~activities-after-switch-functions~, a hook called after switching to an activity. + Option ~activities-set-frame-name~ sets the frame name after switching to an activity. ([[https://github.com/alphapapa/activities.el/issues/33][#33]]. Thanks to [[https://github.com/jdtsmith][JD Smith]].) ++ Option ~activities-kill-buffers~, when suspending an activity, kills buffers that were only shown in that activity. *Changes* + Default time format in activities list. diff --git a/activities-tabs.el b/activities-tabs.el index 8e02fc6..78c51c5 100644 --- a/activities-tabs.el +++ b/activities-tabs.el @@ -35,6 +35,8 @@ "Records the original value of `tab-bar-tab-face-function'. When `activities-tabs-mode' is enabled.") +(defvar activities-kill-buffers) + ;;;; Customization (defgroup activities-tabs nil @@ -71,6 +73,7 @@ accordingly." (if activities-tabs-mode (progn (tab-bar-mode 1) + (add-hook 'window-configuration-change-hook #'activities-tabs--window-configuration-change) (advice-add #'activities-resume :before #'activities-tabs-before-resume) (pcase-dolist (`(,symbol . ,function) override-map) (advice-add symbol :override function)) @@ -83,6 +86,7 @@ accordingly." (unless activities-tabs-tab-bar-tab-face-function-original (setf activities-tabs-tab-bar-tab-face-function-original tab-bar-tab-face-function tab-bar-tab-face-function #'activities-tabs--tab-bar-tab-face-function))) + (remove-hook 'window-configuration-change-hook #'activities-tabs--window-configuration-change) (advice-remove #'activities-resume #'activities-tabs-before-resume) (pcase-dolist (`(,symbol . ,function) override-map) (advice-remove symbol function)) @@ -97,8 +101,36 @@ accordingly." Its state is not saved, and its frames, windows, and tabs are closed." (activities--switch activity) + (activities-tabs--kill-buffers) (tab-bar-close-tab)) +(defun activities-tabs--window-configuration-change () + "Add frame's windows' buffers to the current tab's `buffer-list' parameter." + (cl-assert tab-bar-mode) + (let ((tab (tab-bar--current-tab-find))) + (walk-windows (lambda (window) + (cl-pushnew (window-buffer window) + (alist-get 'activities-buffer-list (cdr tab))))))) + +(defun activities-tabs--kill-buffers () + ;; TODO: Frame parameter name should be prefixed with `activities'. + "Kill buffers that are only in the current tab's buffer list. +Only does so when `activities-kill-buffers' is non-nil." + (when activities-kill-buffers + (let* ((all-tabs (funcall tab-bar-tabs-function)) + (current-tab (tab-bar--current-tab-find)) + (tab-buffers + (cl-reduce + (lambda (acc tab) + (seq-difference acc (activities-tabs--tab-parameter 'activities-buffer-list tab))) + (remove current-tab all-tabs) + :initial-value (activities-tabs--tab-parameter 'activities-buffer-list current-tab))) + (target-buffers (cl-remove-if (lambda (buffer) + (run-hook-with-args-until-success + 'activities-anti-kill-predicates buffer)) + tab-buffers))) + (mapc #'kill-buffer target-buffers)))) + (defun activities-tabs--switch (activity) "Switch to ACTIVITY. Selects its tab, making one if needed. Its state is not changed." diff --git a/activities.el b/activities.el index f222cd6..31bac0f 100644 --- a/activities.el +++ b/activities.el @@ -284,6 +284,17 @@ prefixes will be added automatically." Only applies when `activities-tabs-mode' is disabled." :type 'boolean) +(defcustom activities-anti-kill-predicates + '(activities-buffer-hidden-p activities-buffer-special-p) + "Predicates which prevent a buffer from being killed. +Used when suspending an activity and `activities-kill-buffers' is +enabled. Each predicate is called with the buffer as its +argument. If any predicate returns non-nil, the buffer is not +killed." + :type '(set (function-item activities-buffer-special-p) + (function-item activities-buffer-hidden-p) + (function :tag "Other predicate"))) + (defcustom activities-anti-save-predicates '(active-minibuffer-window activities--backtrace-visible-p) "Predicates which prevent an activity's state from being saved. @@ -311,6 +322,12 @@ which will cause a message to be printed for such buffers when an activity's state is saved." :type 'boolean) +(defcustom activities-kill-buffers nil + "Kill buffers when suspending an activity. +Kills buffers that have only been shown in that activity's +frame/tab." + :type 'boolean) + ;;;; Commands ;;;###autoload @@ -518,6 +535,7 @@ See option `activities-always-persist'." Its state is not saved, and its frames, windows, and tabs are closed." (activities--switch activity) + (activities--kill-buffers) ;; TODO: Set frame parameter when resuming. (delete-frame)) @@ -792,6 +810,31 @@ Adds `activities-name-prefix'." (when (derived-mode-p 'backtrace-mode) (throw :found t))))))) +(defun activities--kill-buffers () + ;; TODO: Frame parameter name should be prefixed with `activities'. + "Kill buffers that are only in the current frame's/tab's buffer list. +Only does so when `activities-kill-buffers' is non-nil." + (when activities-kill-buffers + (let* ((frame-buffers (cl-reduce (lambda (acc frame) + (seq-difference acc (frame-parameter frame 'buffer-list))) + (remove (selected-frame) (frame-list)) + :initial-value (frame-parameter nil 'buffer-list))) + (target-buffers (cl-remove-if (lambda (buffer) + (run-hook-with-args-until-success + 'activities-anti-kill-predicates buffer)) + frame-buffers))) + (mapc #'kill-buffer target-buffers)))) + +(defun activities-buffer-special-p (buffer) + "Return non-nil if BUFFER is special. +That is, if its name starts with an asterisk." + (string-prefix-p "*" (buffer-name buffer))) + +(defun activities-buffer-hidden-p (buffer) + "Return non-nil if BUFFER is hidden. +That is, if its name starts with a space." + (string-prefix-p " " (buffer-name buffer))) + ;;;; Project support (declare-function project-name "project") diff --git a/activities.info b/activities.info index 5023b0c..39b654a 100644 --- a/activities.info +++ b/activities.info @@ -418,6 +418,8 @@ File: README.info, Node: v06-pre, Next: v051, Up: Changelog switching to an activity. (#33 (https://github.com/alphapapa/activities.el/issues/33). Thanks to JD Smith (https://github.com/jdtsmith).) + • Option ‘activities-kill-buffers’, when suspending an activity, + kills buffers that were only shown in that activity. *Changes* • Default time format in activities list. @@ -639,20 +641,20 @@ Node: Bookmarks10725 Node: FAQ11077 Node: Changelog14153 Node: v06-pre14467 -Node: v05115242 -Node: v0515405 -Node: v0417382 -Node: v03317923 -Node: v03218353 -Node: v03118481 -Node: v0318811 -Node: v0219201 -Node: v01319693 -Node: v01219844 -Node: v01120023 -Node: v0120188 -Node: Development20289 -Node: Copyright assignment20561 +Node: v05115374 +Node: v0515537 +Node: v0417514 +Node: v03318055 +Node: v03218485 +Node: v03118613 +Node: v0318943 +Node: v0219333 +Node: v01319825 +Node: v01219976 +Node: v01120155 +Node: v0120320 +Node: Development20421 +Node: Copyright assignment20693  End Tag Table