[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/workroom a014990432 28/74: Project integration, some refac
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/workroom a014990432 28/74: Project integration, some refactoring, update README |
Date: |
Sun, 27 Nov 2022 16:03:26 -0500 (EST) |
branch: elpa/workroom
commit a0149904322a0f7af634a5a71f650e90051d1609
Author: Akib Azmain Turja <akib@disroot.org>
Commit: Akib Azmain Turja <akib@disroot.org>
Project integration, some refactoring, update README
---
README.org | 21 ++++
workroom.el | 386 ++++++++++++++++++++++++++++++++++++++++++++----------------
2 files changed, 303 insertions(+), 104 deletions(-)
diff --git a/README.org b/README.org
index f4fd182d9e..b0343720b8 100644
--- a/README.org
+++ b/README.org
@@ -57,3 +57,24 @@ All the useful commands can be called with following key
sequences:
Here the prefix key sequence is ~C-x x~, but you can customize
~workroom-command-map-prefix~ to change it.
+
+You might want to remap ~switch-to-buffer~ and ~kill-buffer~ by adding
+the following to your init file:
+
+#+begin_src emacs-lisp
+(global-set-key [remap switch-to-buffer] #'workroom-switch-to-buffer)
+(global-set-key [remap kill-buffer] #'workroom-kill-buffer)
+#+end_src
+
+You can save all your workroom in your desktop by enabling
+~workroom-desktop-save-mode~ mode.
+
+You can create a workroom containing only your project buffer with
+~workroom-switch-to-project-workroom~. You can also enable
+~workroom-auto-project-workroom-mode~, it'll switch to (creating if
+needed) the project's workroom when you open a file.
+
+If you want to completely automate managing workroom buffer list,
+check out the docstrings of ~workroom-buffer-manager-function~,
+~workroom-set-buffer-manager-function~ and
+~workroom-buffer-manager-data~.
diff --git a/workroom.el b/workroom.el
index aa4a7f577d..0d9b8feeb1 100644
--- a/workroom.el
+++ b/workroom.el
@@ -4,7 +4,7 @@
;; Author: Akib Azmain Turja <akib@disroot.org>
;; Version: 1.0
-;; Package-Requires: ((emacs "25.1"))
+;; Package-Requires: ((emacs "25.1") (project "0.3.0"))
;; Keywords: tools, convenience
;; URL: https://codeberg.org/akib/emacs-workroom
@@ -39,6 +39,9 @@
;; possibly in another Emacs session. You can also save your
;; workrooms in your desktop.
+;; Usage
+;; ═════
+
;; There is always a workroom named "master", which contains all live
;; buffers. Removing any buffer from this workroom kills that buffer.
;; You can't kill this workroom, but you can customize the variable
@@ -46,29 +49,54 @@
;; All the useful commands can be called with following key sequences:
-;; Key Command
-;; --------------------------------------
-;; C-x x s `workroom-switch-room'
-;; C-x x S `workroom-switch-view'
-;; C-x x d `workroom-kill'
-;; C-x x D `workroom-kill-view'
-;; C-x x r `workroom-rename'
-;; C-x x R `workroom-rename-view'
-;; C-x x c `workroom-clone'
-;; C-x x C `workroom-clone-view'
-;; C-x x m `workroom-bookmark'
-;; C-x x b `workroom-switch-to-buffer'
-;; C-x x a `workroom-add-buffer'
-;; C-x x k `workroom-kill-buffer'
-;; C-x x K `workroom-remove-buffer'
-
-;; Here the prefix key sequence is "C-x x", but you can customize
+;; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+;; Key Command
+;; ────────────────────────────────────────
+;; `C-x x s' `workroom-switch-room'
+;; `C-x x S' `workroom-switch-view'
+;; `C-x x d' `workroom-kill'
+;; `C-x x D' `workroom-kill-view'
+;; `C-x x r' `workroom-rename'
+;; `C-x x R' `workroom-rename-view'
+;; `C-x x c' `workroom-clone'
+;; `C-x x C' `workroom-clone-view'
+;; `C-x x m' `workroom-bookmark'
+;; `C-x x b' `workroom-switch-to-buffer'
+;; `C-x x a' `workroom-add-buffer'
+;; `C-x x k' `workroom-kill-buffer'
+;; `C-x x K' `workroom-remove-buffer'
+;; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+;; Here the prefix key sequence is `C-x x', but you can customize
;; `workroom-command-map-prefix' to change it.
+;; You might want to remap `switch-to-buffer' and `kill-buffer' by
+;; adding the following to your init file:
+
+;; ┌────
+;; │ (global-set-key [remap switch-to-buffer]
+;; │ #'workroom-switch-to-buffer)
+;; │ (global-set-key [remap kill-buffer] #'workroom-kill-buffer)
+;; └────
+
+;; You can save all your workroom in your desktop by enabling
+;; `workroom-desktop-save-mode' mode.
+
+;; You can create a workroom containing only your project buffer with
+;; `workroom-switch-to-project-workroom'. You can also enable
+;; `workroom-auto-project-workroom-mode', it'll switch to (creating if
+;; needed) the project's workroom when you open a file.
+
+;; If you want to completely automate managing workroom buffer list,
+;; check out the docstrings of `workroom-buffer-manager-function',
+;; `workroom-set-buffer-manager-function' and
+;; `workroom-buffer-manager-data'.
+
;;; Code:
(require 'cl-lib)
(require 'bookmark)
+(require 'project)
;;;; User Options.
@@ -99,8 +127,8 @@ name can be manually changed with `workroom-rename'."
:type 'string)
(defcustom workroom-buffer-handler-alist
- '((bookmark :encoder workroom--encode-buffer-bookmark
- :decoder workroom--decode-buffer-bookmark))
+ '((bookmark :encoder workroom-encode-buffer-bookmark
+ :decoder workroom-decode-buffer-bookmark))
"Alist of functions to encode/decode buffer to/from readable object.
Each element of the list is of the form (IDENTIFIER . (:encoder
@@ -128,9 +156,8 @@ value can't restored."
(defcustom workroom-mode-lighter
'(:eval
- (let ((face (if (member (current-buffer)
- (workroom-buffer-list
- (workroom-current-room)))
+ (let ((face (if (memq (current-buffer) (workroom-buffer-list
+ (workroom-current-room)))
'compilation-info
'warning)))
`(" WR["
@@ -149,22 +176,6 @@ The value is a mode line terminal like `mode-line-format'."
"Normal hook run after switching room or view."
:type 'hook)
-(defcustom workroom-kill-room-hook nil
- "Normal hook run after killing a room."
- :type 'hook)
-
-(defcustom workroom-kill-view-hook nil
- "Normal hook run after killing a view."
- :type 'hook)
-
-(defcustom workroom-rename-room-hook nil
- "Normal hook run after renaming a room."
- :type 'hook)
-
-(defcustom workroom-rename-view-hook nil
- "Normal hook run after renaming a view."
- :type 'hook)
-
(defvar workroom-command-map
(let ((keymap (make-sparse-keymap)))
;; NOTE: Be sure to keep commentary and README up to date.
@@ -225,13 +236,13 @@ The value is a mode line terminal like
`mode-line-format'."
:documentation "Writable window configuration of the view.")
(frame nil :documentation "The frame showing the view, or nil."))
-(defvar workroom--initializing nil
- "Non-nil mean Workroom-Mode is initializing.")
+(defvar workroom--dont-clear-new-view nil
+ "Non-nil mean don't clear empty new views.")
(defvar workroom--rooms nil
"List of currently live workrooms.")
-(defvar workroom--room-history nil
+(defvar workroom-room-history nil
"`completing-read' history list of workroom names.")
(defvar workroom--view-history nil
@@ -256,26 +267,36 @@ that.")
(not (not (workroom-name room))))
(defun workroom-buffer-manager-function (room)
- "Return the function to manage the member buffers of workroom ROOM.
+ "Return the function to manage the member buffers of workroom ROOM."
+ (workroom--room-buffer-manager room))
-The buffer manager is a function taking two or more arguments. The
-function shouldn't be an uninterned symbol or lambda/closure. The
-first argument is ROOM, the workroom. The second one is ACTION, it
-specify what to do. ACTION can any of:
+(defun workroom-set-buffer-manager-function
+ (room function &optional do-not-initialize &rest args)
+ "Set the buffer manager function of workroom ROOM.
+
+FUNCTION is the buffer manager function and ARGS is the arguments to
+it initialization procedure. Call FUNCTION with ROOM, `:initialize',
+followed by ARGS, unless DO-NOT-INITIALIZE is non-nil.
+
+FUNCTION is a function taking two or more arguments. The function
+shouldn't be an uninterned symbol or lambda/closure. The first
+argument is ROOM, the workroom. The second one is ACTION, it specify
+what to do. ACTION can any of:
`:initialize'
- Do initialization for workroom ROOM. No extra arguments.
+ Do initialization for workroom ROOM. Element of ARGS is passed as
+ extra arguments in proper order.
`:list-buffers'
List of member buffers of workroom ROOM. No extra arguments.
`:add-buffer'
Add BUFFER as a member of workroom ROOM. BUFFER is the third
- argument and is a buffer.
+ argument and is a non-member buffer.
`:remove-buffer'
Remove BUFFER from the member list of workroom ROOM. BUFFER is the
- third argument and is a buffer.
+ third argument and is a member buffer.
`:clone'
Clone buffer list from workroom SOURCE to workroom ROOM. SOURCE is
@@ -298,13 +319,11 @@ specify what to do. ACTION can any of:
To set it, use (`setf' (`workroom-buffer-manager-function' ROOM)
FUNCTION), where FUNCTION is the buffer manager function."
- (workroom--room-buffer-manager room))
-
-(gv-define-setter workroom-buffer-manager-function (function room)
- `(let ((wr ,room))
- (when (workroom-default-p wr)
- (error "Cannot change buffer manager of the default workroom"))
- (setf (workroom--room-buffer-manager wr) ,function)))
+ (when (workroom-default-p room)
+ (error "Cannot change buffer manager of the default workroom"))
+ (setf (workroom--room-buffer-manager room) function)
+ (unless do-not-initialize
+ (apply function room :initialize args)))
(defun workroom-buffer-manager-data (room)
"Return the data stored by the buffer manager of workroom ROOM.
@@ -397,8 +416,8 @@ that."
(unless room
(setq room (workroom--make-room
:name name
- :buffer-manager #'workroom-default-buffer-manager))
- (workroom-default-buffer-manager room :initialize)
+ :buffer-manager #'workroom--default-buffer-manager))
+ (workroom--default-buffer-manager room :initialize)
(push room workroom--rooms))
room))
@@ -503,7 +522,7 @@ REQUIRE-MATCH and PREDICATE is same as in
`completing-read'."
(completing-read
(concat prompt (when def (format " (default %s)" def)) ": ")
(mapcar #'workroom-name workroom--rooms) predicate require-match
- nil 'workroom--room-history def))
+ nil 'workroom-room-history def))
(defun workroom--read-to-switch ( prompt &optional def require-match
predicate)
@@ -532,7 +551,7 @@ REQUIRE-MATCH and PREDICATE is same as in
`completing-read'."
(completing-read
(concat prompt (when def (format " (default %s)" def)) ": ")
(mapcar #'workroom-view-name (workroom-view-list room))
- predicate require-match nil 'workroom--room-history def)
+ predicate require-match nil 'workroom-room-history def)
(setf (workroom--room-view-history room)
workroom--view-history))))
@@ -561,8 +580,8 @@ be a string. DEF, REQUIRE-MATCH and PREDICATE is same as in
(read-buffer
prompt def require-match
(lambda (cand)
- (and (member (get-buffer (if (consp cand) (car cand) cand))
- (workroom-buffer-list room))
+ (and (memq (get-buffer (if (consp cand) (car cand) cand))
+ (workroom-buffer-list room))
(or (not predicate) (funcall predicate cand)))))))
(defun workroom--read-non-member-buffer ( room prompt &optional def
@@ -577,8 +596,8 @@ be a string. DEF, REQUIRE-MATCH and PREDICATE is same as in
prompt def require-match
(lambda (cand)
(and (not
- (member (get-buffer (if (consp cand) (car cand) cand))
- (workroom-buffer-list room)))
+ (memq (get-buffer (if (consp cand) (car cand) cand))
+ (workroom-buffer-list room)))
(or (not predicate) (funcall predicate cand)))))))
(defun workroom-read-buffer-function ( prompt &optional def
@@ -679,7 +698,7 @@ If WRITABLE, return a writable object."
;; buffers) before loading it.
(window-state-put (cons (car state) (sanitize (cdr state)))
(frame-root-window) 'safe))
- (unless workroom--initializing
+ (unless workroom--dont-clear-new-view
(delete-other-windows)
(set-window-dedicated-p (selected-window) nil)
(switch-to-buffer "*scratch*"))))
@@ -814,6 +833,13 @@ ROOM is should be workroom object, or a name of a workroom
object."
(workroom-name (cadr (workroom-previous-room-list))))
((car (workroom-previous-room-list))
(workroom-name (car (workroom-previous-room-list)))))))))
+ (setq room
+ (if (stringp room)
+ (if (string-empty-p room)
+ (error
+ "Empty string for workroom name is not allowed")
+ (workroom-get-create room))
+ room))
(workroom-switch-view room nil))
(defun workroom-kill (room)
@@ -850,8 +876,7 @@ ROOM is should be workroom object, or a name of a workroom
object."
(set-frame-parameter
frame 'workroom-previous-room-list
(delete room
- (frame-parameter frame 'workroom-previous-room-list))))
- (run-hooks 'workroom-kill-room-hook))
+ (frame-parameter frame 'workroom-previous-room-list)))))
(defun workroom-kill-view (room view)
"Kill view VIEW of workroom ROOM.
@@ -897,8 +922,7 @@ should be in the workroom ROOM."
room workroom-default-view-name))))
(setf (workroom--view-name view) nil)
(setf (workroom--room-view-list room)
- (delete view (workroom--room-view-list room)))
- (run-hooks 'workroom-kill-view-hook)))
+ (delete view (workroom--room-view-list room)))))
(defun workroom-rename (room new-name)
"Rename workroom ROOM to NEW-NAME.
@@ -920,8 +944,7 @@ ROOM is should be workroom object, or a name of a workroom
object."
room))
(unless (workroom-live-p room)
(signal 'wrong-type-argument `(workroom-live-p . ,room)))
- (setf (workroom--room-name room) new-name)
- (run-hooks 'workroom-rename-room-hook))
+ (setf (workroom--room-name room) new-name))
(defun workroom-rename-view (room view new-name)
"Rename view VIEW of workroom ROOM to NEW-NAME."
@@ -960,8 +983,7 @@ ROOM is should be workroom object, or a name of a workroom
object."
(signal 'wrong-type-argument `(workroom-live-p . ,room)))
(unless (workroom-view-live-p view)
(signal 'wrong-type-argument `(workroom-view-live-p . ,view)))
- (setf (workroom--view-name view) new-name)
- (run-hooks 'workroom-rename-view-hook))
+ (setf (workroom--view-name view) new-name))
(defun workroom-clone (room name)
"Create a clone of workroom ROOM named NAME."
@@ -1045,9 +1067,8 @@ If ROOM is the default workroom, do nothing."
(list (get-buffer-create
(workroom--read-non-member-buffer
(workroom-current-room) "Add buffer: "
- (when (not (member (current-buffer)
- (workroom-buffer-list
- (workroom-current-room))))
+ (unless (memq (current-buffer) (workroom-buffer-list
+ (workroom-current-room)))
(current-buffer))))
nil)))
(setq room (if (stringp room)
@@ -1057,8 +1078,9 @@ If ROOM is the default workroom, do nothing."
(or room (workroom-current-room))))
(unless (workroom-live-p room)
(signal 'wrong-type-argument `(workroom-live-p . ,room)))
- (funcall (workroom--room-buffer-manager room)
- room :add-buffer buffer))
+ (unless (memq buffer (workroom-buffer-list (workroom-current-room)))
+ (funcall (workroom--room-buffer-manager room)
+ room :add-buffer buffer)))
(defun workroom-remove-buffer (buffer &optional room)
"Remove BUFFER from workroom ROOM.
@@ -1074,9 +1096,8 @@ If ROOM is the default workroom, kill buffer."
(workroom--read-member-buffer
(workroom-current-room)
"Remove buffer: "
- (when (member (current-buffer)
- (workroom-buffer-list
- (workroom-current-room)))
+ (when (memq (current-buffer) (workroom-buffer-list
+ (workroom-current-room)))
(current-buffer))
t))
nil)))
@@ -1087,15 +1108,16 @@ If ROOM is the default workroom, kill buffer."
(or room (workroom-current-room))))
(unless (workroom-live-p room)
(signal 'wrong-type-argument `(workroom-live-p . ,room)))
- (funcall (workroom--room-buffer-manager room)
- room :remove-buffer buffer))
+ (when (memq buffer (workroom-buffer-list (workroom-current-room)))
+ (funcall (workroom--room-buffer-manager room)
+ room :remove-buffer buffer)))
(defmacro workroom-define-replacement (fn)
"Define `workroom-FN' as replacement for FN.
The defined function is restricts user to the buffers of current
workroom while selecting buffer by setting `read-buffer' function to
-`workroom-read-buffer-function', unless prefix arg is given."
+`workroom-read-buffer-function', unless prefix argument is given."
`(defun ,(intern (format "workroom-%S" fn)) ()
,(format "Like `%S' but restricted to current workroom.
@@ -1111,11 +1133,12 @@ restrict." fn)
(workroom-define-replacement switch-to-buffer)
(workroom-define-replacement kill-buffer)
-(defun workroom-default-buffer-manager (room action &rest args)
+(defun workroom--default-buffer-manager (room action &rest args)
"The default buffer manager of workrooms.
-Set as the `workroom-buffer-manager-function' of ROOM, which see. The
-value of ACTION and ARGS are also described there."
+Set as the buffer manager function of ROOM with
+`workroom-set-buffer-manager-function', which see. The value of
+ACTION and ARGS are also described there."
(setf (workroom-buffer-manager-data room)
(cl-delete-if-not #'buffer-live-p
(workroom-buffer-manager-data room)))
@@ -1148,11 +1171,12 @@ value of ACTION and ARGS are also described there."
(setf (workroom-buffer-manager-data room)
(copy-sequence buffers))))))
-(defun workroom-default-room-buffer-manager (room action &rest args)
+(defun workroom--default-room-buffer-manager (room action &rest args)
"The buffer manager of the default workroom.
-Set as the `workroom-buffer-manager-function' of ROOM, which see. The
-value of ACTION and ARGS are also described there."
+Set as the buffer manager function of ROOM with
+`workroom-set-buffer-manager-function', which see. The value of
+ACTION and ARGS are also described there."
(pcase action
(:initialize
(cl-destructuring-bind () args
@@ -1175,9 +1199,9 @@ value of ACTION and ARGS are also described there."
;; There can't be two default workrooms, so this function can't
;; manage two workrooms. We'll hand over responsibilities to
;; the default buffer manager.
- (setf (workroom-buffer-manager-function room)
- #'workroom-default-buffer-manager)
- (workroom-default-buffer-manager room :clone (buffer-list))))
+ (workroom-set-buffer-manager-function
+ room #'workroom--default-buffer-manager 'do-not-initialize)
+ (workroom--default-buffer-manager room :clone (buffer-list))))
(:encode
(cl-destructuring-bind () args
;; Nothing, the default workroom can't be encoding (but can
@@ -1188,9 +1212,9 @@ value of ACTION and ARGS are also described there."
;; There can't be two default workrooms, so this function can't
;; manage two workrooms. We'll hand over responsibilities to
;; the default buffer manager.
- (setf (workroom-buffer-manager-function room)
- #'workroom-default-buffer-manager)
- (workroom-default-buffer-manager room :load data buffers)))))
+ (workroom-set-buffer-manager-function
+ room #'workroom--default-buffer-manager 'do-not-initialize)
+ (workroom--default-buffer-manager room :load data buffers)))))
(defun workroom--frame-manage-p (frame)
"Return non-nil if workroom should manage FRAME."
@@ -1219,16 +1243,16 @@ value of ACTION and ARGS are also described there."
(progn
(workroom-mode -1)
(setq workroom-mode t)
- (let ((workroom--initializing t)
+ (let ((workroom--dont-clear-new-view t)
(default-room (workroom-get-default)))
(unless default-room
(setq
default-room
(workroom--make-room
:name workroom-default-room-name
- :buffer-manager #'workroom-default-room-buffer-manager
+ :buffer-manager #'workroom--default-room-buffer-manager
:default-p t))
- (workroom-default-room-buffer-manager
+ (workroom--default-room-buffer-manager
default-room :initialize)
(push default-room workroom--rooms))
(unless (equal (workroom-name default-room)
@@ -1325,13 +1349,13 @@ when ROOM was encoded."
(setq tail (cdr tail))))
(cdr buffers)))
-(defun workroom--encode-buffer-bookmark (buffer)
+(defun workroom-encode-buffer-bookmark (buffer)
"Encode BUFFER using `bookmark-make-record'."
(with-current-buffer buffer
(ignore-errors
(bookmark-make-record))))
-(defun workroom--decode-buffer-bookmark (object)
+(defun workroom-decode-buffer-bookmark (object)
"Decode OBJECT using `bookmark-jump'."
(let* ((buffer nil))
(bookmark-jump object (lambda (buf) (setq buffer buf)))
@@ -1379,7 +1403,7 @@ If NO-OVERWRITE is nil or prefix argument is given, don't
overwrite
any previous bookmark with the same name."
(interactive
(list (workroom--read
- "Workroom" nil t
+ "Bookmark workroom" nil t
(lambda (cand)
(not (equal (workroom-name (workroom-get-default))
(if (consp cand) (car cand) cand)))))
@@ -1502,15 +1526,169 @@ any previous bookmark with the same name."
(frame-list))))
time)))))
-;;;###autoload
(define-minor-mode workroom-desktop-save-mode
"Toggle saving workrooms with desktop mode."
:global t
+ :require 'workroom
(if workroom-desktop-save-mode
(add-hook 'desktop-save-hook
#'workroom--desktop-inject-restore-code)
(remove-hook 'desktop-save-hook
#'workroom--desktop-inject-restore-code)))
+
+;;;; Project Integration.
+
+(defun workroom--project-buffer-manager (room action &rest args)
+ "The buffer manager for a project.
+
+Set as the buffer manager function of ROOM with
+`workroom-set-buffer-manager-function', which see. The value of
+ACTION and ARGS are also described there. This function take an
+argument while setting as the buffer manager, PROJECT, the project."
+ (setf (plist-get (workroom-buffer-manager-data room)
+ :whitelist)
+ (cl-delete-if-not
+ #'buffer-live-p
+ (plist-get (workroom-buffer-manager-data room)
+ :whitelist)))
+ (setf (plist-get (workroom-buffer-manager-data room)
+ :blacklist)
+ (cl-delete-if-not
+ #'buffer-live-p
+ (plist-get (workroom-buffer-manager-data room)
+ :blacklist)))
+ (pcase action
+ (:initialize
+ (cl-destructuring-bind (project) args
+ (setf (workroom-buffer-manager-data room)
+ `(:project ,project))))
+ (:list-buffers
+ (cl-destructuring-bind () args
+ (cl-remove-if
+ (let ((blacklist
+ (plist-get (workroom-buffer-manager-data room)
+ :blacklist)))
+ (lambda (buffer) (memq buffer blacklist)))
+ (append (plist-get (workroom-buffer-manager-data room)
+ :whitelist)
+ (project-buffers
+ (plist-get (workroom-buffer-manager-data room)
+ :project))))))
+ (:add-buffer
+ (cl-destructuring-bind (buffer) args
+ ;; Remove from blacklist.
+ (setf (plist-get (workroom-buffer-manager-data room)
+ :blacklist)
+ (delete buffer
+ (plist-get (workroom-buffer-manager-data room)
+ :blacklist)))
+ ;; If not still in the list, whitelist it.
+ (unless (memq buffer (workroom--project-buffer-manager
+ room :list-buffers))
+ (push buffer (plist-get (workroom-buffer-manager-data room)
+ :whitelist)))))
+ (:remove-buffer
+ (cl-destructuring-bind (buffer) args
+ ;; Remove from whitelist.
+ (setf (plist-get (workroom-buffer-manager-data room)
+ :whitelist)
+ (delete buffer
+ (plist-get (workroom-buffer-manager-data room)
+ :whitelist)))
+ ;; If still in the list, blacklist it.
+ (when (memq buffer (workroom--project-buffer-manager
+ room :list-buffers))
+ (push buffer (plist-get (workroom-buffer-manager-data room)
+ :blacklist)))))
+ (:clone
+ (cl-destructuring-bind (source) args
+ (cl-destructuring-bind (&key project whitelist blacklist)
+ (workroom-buffer-manager-data source)
+ (setf (workroom-buffer-manager-data room)
+ `( :project ,project
+ :whitelist ,(copy-sequence whitelist)
+ :blacklist ,(copy-sequence blacklist))))))
+ (:encode
+ (cl-destructuring-bind () args
+ (cl-destructuring-bind (&key project _whitelist blacklist)
+ (workroom-buffer-manager-data room)
+ `( :project-root ,(project-root project)
+ :blacklist ,(mapcar #'buffer-name blacklist)))))
+ (:load
+ (cl-destructuring-bind (data buffers) args
+ (let ((project (project-current
+ nil (plist-get data :project-root))))
+ (setf (workroom-buffer-manager-data room)
+ `( :project ,project
+ :whitelist ,(cl-set-difference
+ buffers (project-buffers project))
+ :blacklist ,(cl-delete-if
+ #'null
+ (mapcar
+ #'get-buffer
+ (plist-get data :blacklist))))))))))
+
+(defun workroom--project-name (project)
+ "Return a name for project PROJECT."
+ (let ((root (project-root project)))
+ (if (string-match "/\\([^/]+\\)/\\'" root)
+ (match-string 1 root)
+ root)))
+
+(defun workroom-switch-to-project-workroom (name project-root)
+ "Switch to a workroom NAME with all buffers in the current project.
+
+Prompt for PROJECT-ROOT if the project root can't be found, or if the
+prefix argument is given."
+ (interactive
+ (let* ((project
+ (if current-prefix-arg
+ (project-current nil (project-prompt-project-dir))
+ (project-current 'maybe-prompt)))
+ (root (project-root project))
+ (name (workroom--project-name project)))
+ (list
+ (read-string
+ (format-message "Workname name for project `%s': " name)
+ name 'workroom-room-history name)
+ root)))
+ (workroom-switch name)
+ (workroom-set-buffer-manager-function
+ (workroom-current-room) #'workroom--project-buffer-manager nil
+ (project-current nil project-root)))
+
+(defun workroom--project-switch-to-appropiate-room ()
+ "Switch the appropiate workroom for current buffer."
+ (let ((project (project-current))
+ (room nil))
+ (when project
+ (cl-block nil
+ (dolist (wr (workroom-list))
+ (when (and (eq (workroom-buffer-manager-function wr)
+ #'workroom--project-buffer-manager)
+ (equal (plist-get
+ (workroom-buffer-manager-data wr)
+ :project)
+ project))
+ (setq room wr)
+ (cl-return))))
+ (if room
+ (workroom-switch room)
+ (let ((workroom--dont-clear-new-view t))
+ (workroom-switch-to-project-workroom
+ (workroom--project-name project)
+ (project-root project)))))))
+
+(define-minor-mode workroom-auto-project-workroom-mode
+ "Toggle automatically creating project workrooms."
+ :global t
+ :require 'workroom
+ (if workroom-auto-project-workroom-mode
+ (add-hook 'find-file-hook
+ #'workroom--project-switch-to-appropiate-room)
+ (remove-hook 'find-file-hook
+ #'workroom--project-switch-to-appropiate-room)))
+
(provide 'workroom)
;;; workroom.el ends here
- [nongnu] elpa/workroom b28aae7a13 40/74: Add chapter "Project Integration" to manual, (continued)
- [nongnu] elpa/workroom b28aae7a13 40/74: Add chapter "Project Integration" to manual, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom 98d1158ef0 36/74: Fix key binding of "C-d" in command map, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom 8e805c716e 51/74: Bump version to 2.0.2, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom 64da63c1a9 67/74: Add Compat dependency, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom bb74cce814 60/74: Fix error when a frame is killed, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom 1a0dd6b17d 65/74: Use format-prompt to format minibuffer prompts, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom fe38dc8aea 63/74: Bump version to 2.2, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom a82287cd5b 06/74: Add support for dynamic buffer list, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom c38489669e 18/74: Fix the defaults of workroom-switch, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom 78f0d5ee9e 38/74: Accept prefix argument in workroom-kill-with-buffers, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom a014990432 28/74: Project integration, some refactoring, update README,
ELPA Syncer <=
- [nongnu] elpa/workroom 9e486d8102 30/74: Add new command workroom-kill-with-buffers, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom ba1ca498d8 58/74: Switch to most recent workroom when kill the current workroom, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom c9c22ff707 35/74: Update README, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom ff72e2be15 64/74: Remove the use of undefined function, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom 80d9c60ab3 16/74: Fix the keymap issue, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom 94700152e5 13/74: Lower required Emacs version and elaborate README, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom 2b4f883467 43/74: Fix workroom--project-name, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom 731404dee1 32/74: Prefix "C-x x" conflicts, switch to "C-x c", ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom 4e746fcd34 57/74: Bump version to 2.0.4, ELPA Syncer, 2022/11/27
- [nongnu] elpa/workroom f695e59165 47/74: Fix member buffer checking in workroom-kill-with-buffers, ELPA Syncer, 2022/11/27