summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2021-12-18 22:29:57 +0800
committerJSDurand <mmemmew@gmail.com>2021-12-18 22:29:57 +0800
commit761b527a83cf37f821f4b687c2614175aab1387b (patch)
tree44269538d8c5766fc4948106510fdd1758902d61
parent5e5d32cfddbf4a312c246eb7e81b617db5adb252 (diff)
ibuffer: protect buffers
* ibuffer.el (durand-default-clear-passlist, durand-clear-passlist): Add a default value variable. (durand-reset-clearlist): Add a function to reset since we are starting to manipulate this variable. (durand-born-equal): Buffer-OR-Name equal. (durand-ibuffer-clear): Make sure the dashboard buffer is correctly recentered, even if it is not displayed right after the clearing operation. (durand-ibuffer-reset-marks): Reset the mark of the current line if this mark is added "automagically" by the macro which defines an ibuffer operation. (durand-ibuffer-restore-mark-before-advice): Check if there are no marks before the operation. In this case a mark will be "automagically" added, and we need to remove that mark later. (ibuffer-do-protect): Protect marked buffers so that they will not be cleared automatically. (ibuffer-do-unprotect): Unprotect the buffers so we can clear them quickly again. (ibuffer-mode-map): Bind the operations. (durand-directory): Modify this filter so that it works correctly.
-rw-r--r--ibuffer.el151
1 files changed, 131 insertions, 20 deletions
diff --git a/ibuffer.el b/ibuffer.el
index 928bc4b..f270a69 100644
--- a/ibuffer.el
+++ b/ibuffer.el
@@ -73,11 +73,20 @@ If the optional ARG is non-nil, then produce an IBUFFER buffer
(list (cons 'used-mode
(buffer-local-value 'major-mode (current-buffer))))))))
+;;;; clear buffers
+
;;;###autoload
(defvar durand-clear-passlist nil
"The list of buffers that should not be deleted \
automatically.")
+;;;###autoload
+(defvar durand-default-clear-passlist
+ (list dashboard-buffer-name
+ "*Group*"
+ ".newsrc-dribble")
+ "The default value for `durand-clear-passlist'.")
+
;; from dashboard.el
(defvar dashboard-buffer-name)
@@ -85,10 +94,47 @@ automatically.")
((null dashboard-buffer-name)
(setq dashboard-buffer-name "")))
-(setq durand-clear-passlist
- (list dashboard-buffer-name
- "*Group*"
- ".newsrc-dribble"))
+(setq durand-clear-passlist durand-default-clear-passlist)
+
+;;;###autoload
+(defun durand-reset-clearlist ()
+ "Reset `durand-clear-passlist' to `durand-default-clear-passlist'."
+ (interactive)
+ (setq durand-clear-passlist durand-default-clear-passlist))
+
+(autoload #'durand-member "common.el")
+
+;;;###autoload
+(defun durand-born-equal (x y)
+ "Return t if two buffers or names X and Y are equal.
+X and Y could be a buffer or a string that represents the name of
+a buffer.
+
+BORN is an abbreviation of \"Buffer OR Name\"."
+ (let ((flag 0))
+ (cond
+ ((stringp x) (setq flag (logior flag 1)))
+ ((bufferp x))
+ ((error "X is not a string nor a buffer")))
+ (cond
+ ((stringp y) (setq flag (logior flag 2)))
+ ((bufferp y))
+ ((error "Y is not a string nor a buffer")))
+ (cond
+ ;; both are buffers
+ ((= flag 0) (eq x y))
+ ;; X = string, Y = buffer
+ ((= flag 1) (string= x (buffer-name y)))
+ ;; X = buffer, Y = string
+ ((= flag 2) (string= (buffer-name x) y))
+ ;; both are strings
+ ((= flag 3) (string= x y))
+ ((error "Invalid flag: %d" flag)))))
+
+;; This is not defined via `define-ibuffer-op' as this is supposed to
+;; clear ALL buffers by default, not only operating on marked buffers,
+;; which is the default behaviour for functions defined by
+;; `define-ibuffer-op'.
;;;###autoload
(defun durand-ibuffer-clear (&optional arg)
@@ -107,15 +153,16 @@ derived modes of `ibuffer-mode'.")))
(cond
((durand-member (buffer-name buffer)
durand-clear-passlist
- #'string=))
+ #'durand-born-equal))
((kill-buffer buffer)))))
(cons
(current-buffer)
(mapcar #'car (ibuffer-current-state-list))))
- (with-current-buffer dashboard-buffer-name
- (let ((inhibit-message t))
- (goto-char (point-max))
- (recenter -1))))
+ (let ((current (current-buffer)))
+ (pop-to-buffer dashboard-buffer-name '((display-buffer-same-window)))
+ (goto-char (point-max))
+ (recenter -1)
+ (pop-to-buffer current '((display-buffer-same-window)))))
(t
(mapc (function
(lambda (buffer-and-mark)
@@ -124,13 +171,74 @@ derived modes of `ibuffer-mode'.")))
ibuffer-marked-char)
(durand-member (buffer-name (car buffer-and-mark))
durand-clear-passlist
- #'string=)))
+ #'durand-born-equal)))
((kill-buffer (car buffer-and-mark))))))
(cons
(cons (current-buffer) 32)
(ibuffer-current-state-list)))
(ibuffer-update nil t))))
+;;;; Protect buffers
+
+;; NOTE: I know there is `emacs-lock-mode' which seems to do the same
+;; thing. But in my opinion my needs are different: indeed I do not
+;; want to kill certain buffers, which functionality appears to be
+;; covered by the afore-mentionned mode, but in fact, I am actually
+;; not trying to protect those buffers from `kill-buffer'. I might
+;; actually delete those buffers at a later point, without first
+;; unprotecting them. The purpose of this protection is to ensure
+;; that the specific operation that I define here for ibuffer does
+;; kill those protected buffers.
+
+;;;###autoload
+(defvar durand-ibuffer-reset-marks nil
+ "Whether to reset the marks in ibuffer.")
+
+;;;###autoload
+(defun durand-ibuffer-restore-mark-before-advice ()
+ (ibuffer-assert-ibuffer-mode)
+ (cond
+ ((null (ibuffer-marked-buffer-names))
+ (setq durand-ibuffer-reset-marks t))))
+
+;;;###autoload
+(define-ibuffer-op ibuffer-do-protect ()
+ "Add the marked buffers to `durand-clear-passlist'."
+ (:opstring "protected"
+ :active-opstring "protect"
+ :modifier-p nil
+ :after (cond
+ (durand-ibuffer-reset-marks
+ (setq durand-ibuffer-reset-marks nil)
+ (ibuffer-set-mark 32)))
+ :complex t)
+ (cond
+ ((durand-member buf durand-clear-passlist #'durand-born-equal) nil)
+ ((setq durand-clear-passlist (cons buf durand-clear-passlist)) t)))
+
+(advice-add #'ibuffer-do-protect :before
+ #'durand-ibuffer-restore-mark-before-advice)
+
+(define-ibuffer-op ibuffer-do-unprotect ()
+ "Remove the marked buffers from `durand-clear-passlist'."
+ (:opstring "unprotected"
+ :active-opstring "unprotect"
+ :modifier-p nil
+ :after (cond
+ (durand-ibuffer-reset-marks
+ (setq durand-ibuffer-reset-marks nil)
+ (ibuffer-set-mark 32)))
+ :complex t)
+ (cond
+ ((durand-member buf durand-clear-passlist #'durand-born-equal)
+ (setq durand-clear-passlist (delq buf durand-clear-passlist))
+ t)))
+
+(advice-add #'ibuffer-do-unprotect :before
+ #'durand-ibuffer-restore-mark-before-advice)
+
+;;; key-bindings
+
(define-key global-map (vector 24 2) #'ibuffer)
(define-key global-map (vector ?\s-h) #'ibuffer)
(define-key global-map (vector ?\M-\s-b) #'switch-to-buffer-same-mode)
@@ -142,6 +250,11 @@ derived modes of `ibuffer-mode'.")))
(define-key ibuffer-mode-map (vector ?d) #'ibuffer-do-delete)
(define-key ibuffer-mode-map (vector ?D) #'ibuffer-mark-for-delete)
(define-key ibuffer-mode-map (vector ?c) #'durand-ibuffer-clear)
+(define-key ibuffer-mode-map (vector ?C) #'durand-reset-clearlist)
+;; open paren is bound to proect
+(define-key ibuffer-mode-map (vector 40) #'ibuffer-do-protect)
+;; close paren is bound to unprotect
+(define-key ibuffer-mode-map (vector 41) #'ibuffer-do-unprotect)
;;; filter for bongo
@@ -175,18 +288,16 @@ QUALIFIER.
For a buffer not associated with a file, this matches against the
value of `default-directory' in that buffer."
(:description "directory name"
- :reader (read-from-minibuffer "Filter by directory name (regex): "))
+ :reader (read-from-minibuffer
+ "Filter by directory name (regex): "))
(ibuffer-aif (with-current-buffer buf (ibuffer-buffer-file-name))
(let ((dirname (expand-file-name (file-name-directory it))))
- (when dirname
- (string-match-p
- (expand-file-name qualifier)
- dirname)))
- (when (with-current-buffer buf default-directory)
- (string-match-p (expand-file-name qualifier)
- (expand-file-name
- (with-current-buffer buf
- default-directory))))))
+ (cond (dirname (string-match-p qualifier dirname))))
+ (when (buffer-local-value default-directory buf)
+ (string-match-p
+ qualifier
+ (expand-file-name
+ (buffer-local-value buf default-directory))))))
;;;###autoload
(defun durand-bongo-set-filter ()