From 62a5a6baa138b268fa67813fd023e923edba710f Mon Sep 17 00:00:00 2001 From: Daniel Mendler Date: Sat, 11 Jan 2025 16:36:56 +0100 Subject: [PATCH] ibuffer: Display column titles in header line If the option `ibuffer-use-header-line' is set to `title', display column titles in the header line. * lisp/ibuffer.el (ibuffer--format-title) (ibuffer--format-summary): New functions extracted from `ibuffer-update-title-and-summary'. (ibuffer-update-title-and-summary): Use them. (ibuffer-update): Do not always override `header-line-format'. (ibuffer-use-header-line): Update docstring and option `:type'. * lisp/ibuf-macs.el (define-ibuffer-sorter): Add "@" to the interactive specification for clicks on the header line. * etc/NEWS: Announce the change. (Bug#75497) (cherry picked from commit 5294d450da47734bbe2ca259505674bcae5ff573) --- etc/NEWS | 4 ++ lisp/ibuf-macs.el | 2 +- lisp/ibuffer.el | 166 +++++++++++++++++++++++++--------------------- 3 files changed, 95 insertions(+), 77 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 157c96393f4..4f19e506f9e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -254,6 +254,10 @@ You can now set `asm-comment-char' from 'asm-mode-hook' instead. The variable 'ibuffer-formats' configures the Ibuffer formats. Add 'recency' to the format to display the column. +*** New value 'title' for the user option 'ibuffer-use-header-line'. +Display column titles in the header line if 'ibuffer-use-header-line' is +set to 'title'. + *** New user option 'ibuffer-human-readable-size'. When non-nil, buffer sizes are shown in human readable format. diff --git a/lisp/ibuf-macs.el b/lisp/ibuf-macs.el index 2d5ef651340..9c43411e46d 100644 --- a/lisp/ibuf-macs.el +++ b/lisp/ibuf-macs.el @@ -146,7 +146,7 @@ value if and only if `a' is \"less than\" `b'. `(progn (defun ,(intern (concat "ibuffer-do-sort-by-" (symbol-name name))) () ,(or documentation "No :documentation specified for this sorting method.") - (interactive "" ibuffer-mode) + (interactive "@" ibuffer-mode) (setq ibuffer-sorting-mode ',name) (when (eq ibuffer-sorting-mode ibuffer-last-sorting-mode) (setq ibuffer-sorting-reversep (not ibuffer-sorting-reversep))) diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el index e911edcdfc1..c36804c1033 100644 --- a/lisp/ibuffer.el +++ b/lisp/ibuffer.el @@ -310,8 +310,10 @@ in completion lists of the `ibuffer-jump-to-buffer' command." :type 'boolean) (defcustom ibuffer-use-header-line t - "If non-nil, display a header line containing current filters." - :type 'boolean) + "If non-nil, display a header line. +If the variable's value is t, the header line displays the current +filters. For the value `title', display the column titles." + :type '(choice boolean (const :tag "Column titles" :value title))) (defcustom ibuffer-default-directory nil "The default directory to use for a new Ibuffer buffer. @@ -2050,59 +2052,90 @@ the value of point at the beginning of the line for that buffer." (ibuffer-update-format) (ibuffer-redisplay t)) +(defun ibuffer--format-title (element &optional header-line) + (if (stringp element) + element + (pcase-let ((`(,sym ,min ,_max ,align) element)) + ;; Ignore negative MIN, since the titles are left-aligned. + (when (cl-minusp min) + (setq min (- min))) + (let* ((name (or (get sym 'ibuffer-column-name) + (error "Unknown column %s in ibuffer-formats" sym))) + (len (length name)) + (hmap (get sym 'header-mouse-map)) + (strname (if (< len min) + (ibuffer-format-column name + (- min len) + align) + name))) + (when hmap + (setq + strname + (propertize strname 'mouse-face 'highlight 'keymap + (if header-line + (define-keymap "" hmap) + hmap)))) + strname)))) + +(defun ibuffer--format-summary (element) + (if (stringp element) + (make-string (length element) ?\s) + (pcase-let ((`(,sym ,min ,_max ,align) element)) + ;; Ignore negative MIN, since the summaries are left-aligned. + (when (cl-minusp min) + (setq min (- min))) + (let* ((summary + (if (get sym 'ibuffer-column-summarizer) + (funcall (get sym 'ibuffer-column-summarizer) + (get sym 'ibuffer-column-summary)) + (make-string + (length (get sym 'ibuffer-column-name)) + ?\s))) + (len (length summary))) + (if (< len min) + (ibuffer-format-column summary + (- min len) + align) + summary))))) + (defun ibuffer-update-title-and-summary (format) (ibuffer-assert-ibuffer-mode) ;; Don't do funky font-lock stuff here (let ((inhibit-modification-hooks t)) - (if (get-text-property (point-min) 'ibuffer-title) - (delete-region (point-min) - (next-single-property-change - (point-min) 'ibuffer-title))) - (goto-char (point-min)) - (add-text-properties - (point) - (progn - (let ((opos (point))) - ;; Insert the title names. - (dolist (element format) - (insert - (if (stringp element) - element - (pcase-let ((`(,sym ,min ,_max ,align) element)) - ;; Ignore a negative min when we're inserting the title - (when (cl-minusp min) - (setq min (- min))) - (let* ((name (or (get sym 'ibuffer-column-name) - (error "Unknown column %s in ibuffer-formats" sym))) - (len (length name)) - (hmap (get sym 'header-mouse-map)) - (strname (if (< len min) - (ibuffer-format-column name - (- min len) - align) - name))) - (when hmap - (setq - strname - (propertize strname 'mouse-face 'highlight 'keymap hmap))) - strname))))) - (add-text-properties opos (point) '(ibuffer-title-header t)) - (insert "\n") - ;; Add the underlines - (let ((str (save-excursion - (forward-line -1) - (beginning-of-line) - (buffer-substring (point) (line-end-position))))) - (apply #'insert (mapcar - (lambda (c) - (if (not (or (eq c ?\s) - (eq c ?\n))) - ?- - ?\s)) - str))) - (insert "\n")) - (point)) - `(ibuffer-title t font-lock-face ,ibuffer-title-face)) + ;; Insert the title names. + (if (eq ibuffer-use-header-line 'title) + (setq header-line-format + `("" header-line-indent + ,(propertize " " 'display + '(space :align-to header-line-indent-width)) + ,@(mapcar (lambda (e) (ibuffer--format-title e t)) format))) + (if (get-text-property (point-min) 'ibuffer-title) + (delete-region (point-min) + (next-single-property-change + (point-min) 'ibuffer-title))) + (goto-char (point-min)) + (add-text-properties + (point) + (progn + (let ((opos (point))) + (apply #'insert (mapcar #'ibuffer--format-title format)) + (add-text-properties opos (point) '(ibuffer-title-header t)) + (insert "\n") + ;; Add the underlines + (let ((str (save-excursion + (forward-line -1) + (beginning-of-line) + (buffer-substring (point) (line-end-position))))) + (apply #'insert (mapcar + (lambda (c) + (if (not (or (eq c ?\s) + (eq c ?\n))) + ?- + ?\s)) + str))) + (insert "\n")) + (point)) + `(ibuffer-title t font-lock-face ,ibuffer-title-face))) ;; Now, insert the summary columns. (goto-char (point-max)) (if (get-text-property (1- (point-max)) 'ibuffer-summary) @@ -2114,27 +2147,7 @@ the value of point at the beginning of the line for that buffer." (point) (progn (insert "\n") - (dolist (element format) - (insert - (if (stringp element) - (make-string (length element) ?\s) - (pcase-let ((`(,sym ,min ,_max ,align) element)) - ;; Ignore a negative min when we're inserting the title. - (when (cl-minusp min) - (setq min (- min))) - (let* ((summary - (if (get sym 'ibuffer-column-summarizer) - (funcall (get sym 'ibuffer-column-summarizer) - (get sym 'ibuffer-column-summary)) - (make-string - (length (get sym 'ibuffer-column-name)) - ?\s))) - (len (length summary))) - (if (< len min) - (ibuffer-format-column summary - (- min len) - align) - summary)))))) + (apply #'insert (mapcar #'ibuffer--format-summary format)) (point)) '(ibuffer-summary t))))) @@ -2199,10 +2212,11 @@ If optional arg SILENT is non-nil, do not display progress messages." ;; I tried to update this automatically from the mode-line-process format, ;; but changing nil-ness of header-line-format while computing ;; mode-line-format is asking a bit too much it seems. --Stef - (setq header-line-format - (and ibuffer-use-header-line - ibuffer-filtering-qualifiers - ibuffer-header-line-format))) + (unless (eq ibuffer-use-header-line 'title) + (setq header-line-format + (and ibuffer-use-header-line + ibuffer-filtering-qualifiers + ibuffer-header-line-format)))) (defun ibuffer-sort-bufferlist (bmarklist) (unless ibuffer-sorting-functions-alist -- 2.39.5