]> code.delx.au - gnu-emacs/blobdiff - lisp/ibuffer.el
Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs
[gnu-emacs] / lisp / ibuffer.el
index 9a1f3b9a0dfb85178ee0258392a8cef1764b5315..8e246297ff760601a5c0d151833e3261d7801f7c 100644 (file)
@@ -36,6 +36,7 @@
   (require 'dired))
 
 (require 'font-core)
+(require 'seq)
 
 (require 'ibuffer-loaddefs)
 ;; These come from ibuf-ext.el, which can not be require'd at compile time
@@ -70,7 +71,8 @@ and filter displayed buffers by various criteria."
   :version "22.1"
   :group 'convenience)
 
-(defcustom ibuffer-formats '((mark modified read-only " " (name 18 18 :left :elide)
+(defcustom ibuffer-formats '((mark modified read-only locked
+                                   " " (name 18 18 :left :elide)
                                   " " (size 9 -1 :right)
                                   " " (mode 16 16 :left :elide) " " filename-and-process)
                             (mark " " (name 16 -1) " " filename))
@@ -136,6 +138,7 @@ value for this variable would be
 
 Using \\[ibuffer-switch-format], you can rotate the display between
 the specified formats in the list."
+  :version "25.2"
   :type '(repeat sexp)
   :group 'ibuffer)
 
@@ -157,7 +160,8 @@ elisp byte-compiler."
             (null buffer-file-name))
        italic)
     (30 (memq major-mode ibuffer-help-buffer-modes) font-lock-comment-face)
-    (35 (derived-mode-p 'dired-mode) font-lock-function-name-face))
+    (35 (derived-mode-p 'dired-mode) font-lock-function-name-face)
+    (40 (and (boundp 'emacs-lock-mode) emacs-lock-mode) ibuffer-locked-buffer))
   "An alist describing how to fontify buffers.
 Each element should be of the form (PRIORITY FORM FACE), where
 PRIORITY is an integer, FORM is an arbitrary form to evaluate in the
@@ -279,6 +283,12 @@ Note that this specialized filtering occurs before real filtering."
   :type 'character
   :group 'ibuffer)
 
+(defcustom ibuffer-locked-char ?L
+  "The character to display for locked buffers."
+  :version "25.2"
+  :type 'character
+  :group 'ibuffer)
+
 (defcustom ibuffer-deletion-char ?D
   "The character to display for buffers marked for deletion."
   :type 'character
@@ -470,6 +480,8 @@ directory, like `default-directory'."
     (define-key map (kbd "DEL") 'ibuffer-unmark-backward)
     (define-key map (kbd "M-DEL") 'ibuffer-unmark-all)
     (define-key map (kbd "* *") 'ibuffer-unmark-all)
+    (define-key map (kbd "* c") 'ibuffer-change-marks)
+    (define-key map (kbd "U") 'ibuffer-unmark-all-marks)
     (define-key map (kbd "* M") 'ibuffer-mark-by-mode)
     (define-key map (kbd "* m") 'ibuffer-mark-modified-buffers)
     (define-key map (kbd "* u") 'ibuffer-mark-unsaved-buffers)
@@ -544,6 +556,8 @@ directory, like `default-directory'."
     (define-key map (kbd "% n") 'ibuffer-mark-by-name-regexp)
     (define-key map (kbd "% m") 'ibuffer-mark-by-mode-regexp)
     (define-key map (kbd "% f") 'ibuffer-mark-by-file-name-regexp)
+    (define-key map (kbd "% g") 'ibuffer-mark-by-content-regexp)
+    (define-key map (kbd "% L") 'ibuffer-mark-by-locked)
 
     (define-key map (kbd "C-t") 'ibuffer-visit-tags-table)
 
@@ -565,13 +579,14 @@ directory, like `default-directory'."
     (define-key map (kbd "R") 'ibuffer-do-rename-uniquely)
     (define-key map (kbd "S") 'ibuffer-do-save)
     (define-key map (kbd "T") 'ibuffer-do-toggle-read-only)
-    (define-key map (kbd "U") 'ibuffer-do-replace-regexp)
+    (define-key map (kbd "r") 'ibuffer-do-replace-regexp)
     (define-key map (kbd "V") 'ibuffer-do-revert)
     (define-key map (kbd "W") 'ibuffer-do-view-and-eval)
     (define-key map (kbd "X") 'ibuffer-do-shell-command-pipe)
 
     (define-key map (kbd "k") 'ibuffer-do-kill-lines)
     (define-key map (kbd "w") 'ibuffer-copy-filename-as-kill)
+    (define-key map (kbd "B") 'ibuffer-copy-buffername-as-kill)
 
     (define-key map (kbd "RET") 'ibuffer-visit-buffer)
     (define-key map (kbd "e") 'ibuffer-visit-buffer)
@@ -700,16 +715,10 @@ directory, like `default-directory'."
 
     (define-key-after map [menu-bar view dashes2]
       '("--"))
-    (define-key-after map [menu-bar view diff-with-file]
-      '(menu-item "Diff with file" ibuffer-diff-with-file
-        :help "View the differences between this buffer and its file"))
     (define-key-after map [menu-bar view auto-mode]
       '(menu-item "Auto Mode" ibuffer-auto-mode
         :button (:toggle . ibuffer-auto-mode)
         :help "Attempt to automatically update the Ibuffer buffer"))
-    (define-key-after map [menu-bar view customize]
-      '(menu-item "Customize Ibuffer" ibuffer-customize
-        :help "Use Custom to customize Ibuffer"))
 
     (define-key-after map [menu-bar mark]
       (cons "Mark" (make-sparse-keymap "Mark")))
@@ -717,6 +726,9 @@ directory, like `default-directory'."
     (define-key-after map [menu-bar mark toggle-marks]
       '(menu-item "Toggle marks" ibuffer-toggle-marks
         :help "Unmark marked buffers, and mark unmarked buffers"))
+    (define-key-after map [menu-bar mark change-marks]
+      '(menu-item "Change marks" ibuffer-change-marks
+        :help "Change OLD mark for marked buffers with NEW"))
     (define-key-after map [menu-bar mark mark-forward]
       '(menu-item "Mark" ibuffer-mark-forward
         :help "Mark the buffer at point"))
@@ -756,6 +768,8 @@ directory, like `default-directory'."
         :help "Mark buffers which have not been viewed recently"))
     (define-key-after map [menu-bar mark unmark-all]
       '(menu-item "Unmark All" ibuffer-unmark-all))
+    (define-key-after map [menu-bar mark unmark-all-marks]
+      '(menu-item "Unmark All buffers" ibuffer-unmark-all-marks))
 
     (define-key-after map [menu-bar mark dashes]
       '("--"))
@@ -770,6 +784,13 @@ directory, like `default-directory'."
       '(menu-item "Mark by file name (regexp)..."
         ibuffer-mark-by-file-name-regexp
         :help "Mark buffers whose file name matches a regexp"))
+    (define-key-after map [menu-bar mark ibuffer-mark-by-content-regexp]
+      '(menu-item "Mark by content (regexp)..."
+        ibuffer-mark-by-content-regexp
+        :help "Mark buffers whose content matches a regexp"))
+    (define-key-after map [menu-bar mark mark-by-locked]
+      '(menu-item "Mark by locked buffers..." ibuffer-mark-by-locked
+        :help "Mark all locked buffers"))
 
     map))
 
@@ -820,6 +841,9 @@ directory, like `default-directory'."
     (define-key-after operate-map [do-view-and-eval]
       '(menu-item "Eval (viewing buffer)..." ibuffer-do-view-and-eval
         :help "Evaluate a Lisp form in each marked buffer while viewing it"))
+    (define-key-after operate-map [diff-with-file]
+      '(menu-item "Diff with file" ibuffer-diff-with-file
+                  :help "View the differences between this buffer and its file"))
 
     operate-map))
 
@@ -969,8 +993,7 @@ width and the longest string in LIST."
              (popup-menu ibuffer-mode-groups-popup))
          (let ((inhibit-read-only t))
            (ibuffer-save-marks
-             ;; hm.  we could probably do this in a better fashion
-             (ibuffer-unmark-all ?\r)
+             (ibuffer-unmark-all-marks)
              (save-excursion
                (goto-char eventpt)
                (ibuffer-set-mark ibuffer-marked-char))
@@ -1323,6 +1346,12 @@ With optional ARG, make read-only only if ARG is not negative."
        (lambda (_buf _mark)
         (ibuffer-set-mark-1 ?\s)
         t)))
+     ((not (char-equal mark ?\r))
+      (ibuffer-map-lines
+       (lambda (_buf cmark)
+        (when (char-equal cmark mark)
+          (ibuffer-set-mark-1 ?\s))
+        t)))
      (t
       (ibuffer-map-lines
        (lambda (_buf mark)
@@ -1331,6 +1360,12 @@ With optional ARG, make read-only only if ARG is not negative."
         t)))))
   (ibuffer-redisplay t))
 
+(defun ibuffer-unmark-all-marks ()
+  "Remove all marks from all marked buffers in Ibuffer."
+  (interactive)
+  ;; hm.  we could probably do this in a better fashion
+  (ibuffer-unmark-all ?\r))
+
 (defun ibuffer-toggle-marks (&optional group)
   "Toggle which buffers are marked.
 In other words, unmarked buffers become marked, and marked buffers
@@ -1355,6 +1390,24 @@ group."
     (message "%s buffers marked" count))
   (ibuffer-redisplay t))
 
+(defun ibuffer-change-marks (&optional old new)
+  "Change all OLD marks to NEW marks.
+OLD and NEW are both characters used to mark buffers."
+  (interactive
+   (let* ((cursor-in-echo-area t)
+         (old (progn (message "Change (old mark): ") (read-char)))
+         (new (progn (message  "Change %c marks to (new mark): " old)
+                     (read-char))))
+     (list old new)))
+  (if (or (eq old ?\r) (eq new ?\r))
+      (ding)
+    (let ((count
+           (ibuffer-map-lines
+            (lambda (_buf mark)
+              (when (eq mark old)
+                (ibuffer-set-mark new) t)))))
+      (message "%s marks changed" count))))
+
 (defsubst ibuffer-get-region-and-prefix ()
   (let ((arg (prefix-numeric-value current-prefix-arg)))
     (if (use-region-p) (list (region-beginning) (region-end) arg)
@@ -1398,15 +1451,14 @@ If point is on a group name, this function operates on that group."
        (require 'ibuf-ext)
        (ibuffer-mark-on-buffer #'identity mark it))
     (ibuffer-forward-line 0 t)
-    (let ((inhibit-read-only t))
-      (while (> arg 0)
-       (ibuffer-set-mark mark)
-       (ibuffer-forward-line 1 t)
-       (setq arg (1- arg)))
-      (while (< arg 0)
-       (ibuffer-forward-line -1 t)
-       (ibuffer-set-mark mark)
-       (setq arg (1+ arg))))))
+    (while (> arg 0)
+      (ibuffer-set-mark mark)
+      (ibuffer-forward-line 1 t)
+      (setq arg (1- arg)))
+    (while (< arg 0)
+      (ibuffer-forward-line -1 t)
+      (ibuffer-set-mark mark)
+      (setq arg (1+ arg)))))
 
 (defun ibuffer-set-mark (mark)
   (ibuffer-assert-ibuffer-mode)
@@ -1715,6 +1767,15 @@ If point is on a group name, this function operates on that group."
 
 (defvar ibuffer-inline-columns nil)
 
+(defface ibuffer-locked-buffer
+  '((((background dark)) (:foreground "RosyBrown"))
+    (t (:foreground "brown4")))
+  "*Face used for locked buffers in Ibuffer."
+  :version "25.2"
+  :group 'ibuffer
+  :group 'font-lock-highlighting-faces)
+(defvar ibuffer-locked-buffer 'ibuffer-locked-buffer)
+
 (define-ibuffer-column mark (:name " " :inline t)
   (string mark))
 
@@ -1723,6 +1784,12 @@ If point is on a group name, this function operates on that group."
       (string ibuffer-read-only-char)
     " "))
 
+(define-ibuffer-column locked
+  (:name "L" :inline t :props ('font-lock-face 'ibuffer-locked-buffer))
+  (if (and (boundp 'emacs-lock-mode) emacs-lock-mode)
+      (string ibuffer-locked-char)
+    " "))
+
 (define-ibuffer-column modified (:name "M" :inline t)
   (if (buffer-modified-p)
       (string ibuffer-modified-char)
@@ -1743,7 +1810,13 @@ If point is on a group name, this function operates on that group."
        (cond ((zerop bufs) "No buffers")
             ((= 1 bufs) "1 buffer")
             (t (format "%s buffers" bufs))))))
-  (propertize (buffer-name) 'font-lock-face (ibuffer-buffer-name-face buffer mark)))
+  (let ((string (propertize (buffer-name)
+                            'font-lock-face
+                            (ibuffer-buffer-name-face buffer mark))))
+    (if (not (seq-position string ?\n))
+        string
+      (replace-regexp-in-string
+       "\n" (propertize "^J" 'font-lock-face 'escape-glyph) string))))
 
 (define-ibuffer-column size
   (:inline t
@@ -2337,7 +2410,8 @@ FORMATS is the value to use for `ibuffer-formats'.
     (setq other-window-p t))
   (let ((buf (get-buffer-create (or name "*Ibuffer*"))))
     (if other-window-p
-       (funcall (if noselect (lambda (buf) (display-buffer buf t)) #'pop-to-buffer) buf)
+       (or (and noselect (display-buffer buf t))
+           (pop-to-buffer buf t))
       (funcall (if noselect #'display-buffer #'switch-to-buffer) buf))
     (with-current-buffer buf
       (save-selected-window
@@ -2412,10 +2486,12 @@ Marking commands:
   `\\[ibuffer-mark-forward]' - Mark the buffer at point.
   `\\[ibuffer-toggle-marks]' - Unmark all currently marked buffers, and mark
           all unmarked buffers.
+  `\\[ibuffer-change-marks]' - Change the mark used on marked buffers.
   `\\[ibuffer-unmark-forward]' - Unmark the buffer at point.
   `\\[ibuffer-unmark-backward]' - Unmark the buffer at point, and move to the
           previous line.
-  `\\[ibuffer-unmark-all]' - Unmark all marked buffers.
+  `\\[ibuffer-unmark-all]' - Unmark buffers marked with MARK.
+  `\\[ibuffer-unmark-all-marks]' - Unmark all marked buffers.
   `\\[ibuffer-mark-by-mode]' - Mark buffers by major mode.
   `\\[ibuffer-mark-unsaved-buffers]' - Mark all \"unsaved\" buffers.
           This means that the buffer is modified, and has an associated file.
@@ -2433,6 +2509,8 @@ Marking commands:
   `\\[ibuffer-mark-by-name-regexp]' - Mark buffers by their name, using a regexp.
   `\\[ibuffer-mark-by-mode-regexp]' - Mark buffers by their major mode, using a regexp.
   `\\[ibuffer-mark-by-file-name-regexp]' - Mark buffers by their filename, using a regexp.
+  `\\[ibuffer-mark-by-content-regexp]' - Mark buffers by their content, using a regexp.
+  `\\[ibuffer-mark-by-locked]' - Mark all locked buffers.
 
 Filtering commands: