diff options
| author | Daniel Mendler | 2025-01-11 16:36:56 +0100 |
|---|---|---|
| committer | Eli Zaretskii | 2025-01-25 11:43:45 +0200 |
| commit | 5294d450da47734bbe2ca259505674bcae5ff573 (patch) | |
| tree | ed0094e16bacaebdc48f6d98738885a718ef2e86 | |
| parent | 35576fde5670dffe104a6b2a76837a1f0a4c16ce (diff) | |
| download | emacs-5294d450da47734bbe2ca259505674bcae5ff573.tar.gz emacs-5294d450da47734bbe2ca259505674bcae5ff573.zip | |
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)
| -rw-r--r-- | etc/NEWS | 4 | ||||
| -rw-r--r-- | lisp/ibuf-macs.el | 2 | ||||
| -rw-r--r-- | lisp/ibuffer.el | 166 |
3 files changed, 95 insertions, 77 deletions
| @@ -354,6 +354,10 @@ You can now set `asm-comment-char' from 'asm-mode-hook' instead. | |||
| 354 | The variable 'ibuffer-formats' configures the Ibuffer formats. Add | 354 | The variable 'ibuffer-formats' configures the Ibuffer formats. Add |
| 355 | 'recency' to the format to display the column. | 355 | 'recency' to the format to display the column. |
| 356 | 356 | ||
| 357 | *** New value 'title' for the user option 'ibuffer-use-header-line'. | ||
| 358 | Display column titles in the header line if 'ibuffer-use-header-line' is | ||
| 359 | set to 'title'. | ||
| 360 | |||
| 357 | *** New user option 'ibuffer-human-readable-size'. | 361 | *** New user option 'ibuffer-human-readable-size'. |
| 358 | When non-nil, buffer sizes are shown in human readable format. | 362 | When non-nil, buffer sizes are shown in human readable format. |
| 359 | 363 | ||
diff --git a/lisp/ibuf-macs.el b/lisp/ibuf-macs.el index ff3dc755c36..7dbc9b4125a 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'. | |||
| 146 | `(progn | 146 | `(progn |
| 147 | (defun ,(intern (concat "ibuffer-do-sort-by-" (symbol-name name))) () | 147 | (defun ,(intern (concat "ibuffer-do-sort-by-" (symbol-name name))) () |
| 148 | ,(or documentation "No :documentation specified for this sorting method.") | 148 | ,(or documentation "No :documentation specified for this sorting method.") |
| 149 | (interactive) | 149 | (interactive "@") |
| 150 | (setq ibuffer-sorting-mode ',name) | 150 | (setq ibuffer-sorting-mode ',name) |
| 151 | (when (eq ibuffer-sorting-mode ibuffer-last-sorting-mode) | 151 | (when (eq ibuffer-sorting-mode ibuffer-last-sorting-mode) |
| 152 | (setq ibuffer-sorting-reversep (not ibuffer-sorting-reversep))) | 152 | (setq ibuffer-sorting-reversep (not ibuffer-sorting-reversep))) |
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el index 11340d4bd9e..a94d9fddade 100644 --- a/lisp/ibuffer.el +++ b/lisp/ibuffer.el | |||
| @@ -310,8 +310,10 @@ in completion lists of the `ibuffer-jump-to-buffer' command." | |||
| 310 | :type 'boolean) | 310 | :type 'boolean) |
| 311 | 311 | ||
| 312 | (defcustom ibuffer-use-header-line t | 312 | (defcustom ibuffer-use-header-line t |
| 313 | "If non-nil, display a header line containing current filters." | 313 | "If non-nil, display a header line. |
| 314 | :type 'boolean) | 314 | If the variable's value is t, the header line displays the current |
| 315 | filters. For the value `title', display the column titles." | ||
| 316 | :type '(choice boolean (const :tag "Column titles" :value title))) | ||
| 315 | 317 | ||
| 316 | (defcustom ibuffer-default-directory nil | 318 | (defcustom ibuffer-default-directory nil |
| 317 | "The default directory to use for a new Ibuffer buffer. | 319 | "The default directory to use for a new Ibuffer buffer. |
| @@ -2048,59 +2050,90 @@ the value of point at the beginning of the line for that buffer." | |||
| 2048 | (ibuffer-update-format) | 2050 | (ibuffer-update-format) |
| 2049 | (ibuffer-redisplay t)) | 2051 | (ibuffer-redisplay t)) |
| 2050 | 2052 | ||
| 2053 | (defun ibuffer--format-title (element &optional header-line) | ||
| 2054 | (if (stringp element) | ||
| 2055 | element | ||
| 2056 | (pcase-let ((`(,sym ,min ,_max ,align) element)) | ||
| 2057 | ;; Ignore negative MIN, since the titles are left-aligned. | ||
| 2058 | (when (cl-minusp min) | ||
| 2059 | (setq min (- min))) | ||
| 2060 | (let* ((name (or (get sym 'ibuffer-column-name) | ||
| 2061 | (error "Unknown column %s in ibuffer-formats" sym))) | ||
| 2062 | (len (length name)) | ||
| 2063 | (hmap (get sym 'header-mouse-map)) | ||
| 2064 | (strname (if (< len min) | ||
| 2065 | (ibuffer-format-column name | ||
| 2066 | (- min len) | ||
| 2067 | align) | ||
| 2068 | name))) | ||
| 2069 | (when hmap | ||
| 2070 | (setq | ||
| 2071 | strname | ||
| 2072 | (propertize strname 'mouse-face 'highlight 'keymap | ||
| 2073 | (if header-line | ||
| 2074 | (define-keymap "<header-line>" hmap) | ||
| 2075 | hmap)))) | ||
| 2076 | strname)))) | ||
| 2077 | |||
| 2078 | (defun ibuffer--format-summary (element) | ||
| 2079 | (if (stringp element) | ||
| 2080 | (make-string (length element) ?\s) | ||
| 2081 | (pcase-let ((`(,sym ,min ,_max ,align) element)) | ||
| 2082 | ;; Ignore negative MIN, since the summaries are left-aligned. | ||
| 2083 | (when (cl-minusp min) | ||
| 2084 | (setq min (- min))) | ||
| 2085 | (let* ((summary | ||
| 2086 | (if (get sym 'ibuffer-column-summarizer) | ||
| 2087 | (funcall (get sym 'ibuffer-column-summarizer) | ||
| 2088 | (get sym 'ibuffer-column-summary)) | ||
| 2089 | (make-string | ||
| 2090 | (length (get sym 'ibuffer-column-name)) | ||
| 2091 | ?\s))) | ||
| 2092 | (len (length summary))) | ||
| 2093 | (if (< len min) | ||
| 2094 | (ibuffer-format-column summary | ||
| 2095 | (- min len) | ||
| 2096 | align) | ||
| 2097 | summary))))) | ||
| 2098 | |||
| 2051 | (defun ibuffer-update-title-and-summary (format) | 2099 | (defun ibuffer-update-title-and-summary (format) |
| 2052 | (ibuffer-assert-ibuffer-mode) | 2100 | (ibuffer-assert-ibuffer-mode) |
| 2053 | ;; Don't do funky font-lock stuff here | 2101 | ;; Don't do funky font-lock stuff here |
| 2054 | (let ((inhibit-modification-hooks t)) | 2102 | (let ((inhibit-modification-hooks t)) |
| 2055 | (if (get-text-property (point-min) 'ibuffer-title) | 2103 | ;; Insert the title names. |
| 2056 | (delete-region (point-min) | 2104 | (if (eq ibuffer-use-header-line 'title) |
| 2057 | (next-single-property-change | 2105 | (setq header-line-format |
| 2058 | (point-min) 'ibuffer-title))) | 2106 | `("" header-line-indent |
| 2059 | (goto-char (point-min)) | 2107 | ,(propertize " " 'display |
| 2060 | (add-text-properties | 2108 | '(space :align-to header-line-indent-width)) |
| 2061 | (point) | 2109 | ,@(mapcar (lambda (e) (ibuffer--format-title e t)) format))) |
| 2062 | (progn | 2110 | (if (get-text-property (point-min) 'ibuffer-title) |
| 2063 | (let ((opos (point))) | 2111 | (delete-region (point-min) |
| 2064 | ;; Insert the title names. | 2112 | (next-single-property-change |
| 2065 | (dolist (element format) | 2113 | (point-min) 'ibuffer-title))) |
| 2066 | (insert | 2114 | (goto-char (point-min)) |
| 2067 | (if (stringp element) | 2115 | (add-text-properties |
| 2068 | element | 2116 | (point) |
| 2069 | (pcase-let ((`(,sym ,min ,_max ,align) element)) | 2117 | (progn |
| 2070 | ;; Ignore a negative min when we're inserting the title | 2118 | (let ((opos (point))) |
| 2071 | (when (cl-minusp min) | 2119 | (apply #'insert (mapcar #'ibuffer--format-title format)) |
| 2072 | (setq min (- min))) | 2120 | (add-text-properties opos (point) '(ibuffer-title-header t)) |
| 2073 | (let* ((name (or (get sym 'ibuffer-column-name) | 2121 | (insert "\n") |
| 2074 | (error "Unknown column %s in ibuffer-formats" sym))) | 2122 | ;; Add the underlines |
| 2075 | (len (length name)) | 2123 | (let ((str (save-excursion |
| 2076 | (hmap (get sym 'header-mouse-map)) | 2124 | (forward-line -1) |
| 2077 | (strname (if (< len min) | 2125 | (beginning-of-line) |
| 2078 | (ibuffer-format-column name | 2126 | (buffer-substring (point) (line-end-position))))) |
| 2079 | (- min len) | 2127 | (apply #'insert (mapcar |
| 2080 | align) | 2128 | (lambda (c) |
| 2081 | name))) | 2129 | (if (not (or (eq c ?\s) |
| 2082 | (when hmap | 2130 | (eq c ?\n))) |
| 2083 | (setq | 2131 | ?- |
| 2084 | strname | 2132 | ?\s)) |
| 2085 | (propertize strname 'mouse-face 'highlight 'keymap hmap))) | 2133 | str))) |
| 2086 | strname))))) | 2134 | (insert "\n")) |
| 2087 | (add-text-properties opos (point) '(ibuffer-title-header t)) | 2135 | (point)) |
| 2088 | (insert "\n") | 2136 | `(ibuffer-title t font-lock-face ,ibuffer-title-face))) |
| 2089 | ;; Add the underlines | ||
| 2090 | (let ((str (save-excursion | ||
| 2091 | (forward-line -1) | ||
| 2092 | (beginning-of-line) | ||
| 2093 | (buffer-substring (point) (line-end-position))))) | ||
| 2094 | (apply #'insert (mapcar | ||
| 2095 | (lambda (c) | ||
| 2096 | (if (not (or (eq c ?\s) | ||
| 2097 | (eq c ?\n))) | ||
| 2098 | ?- | ||
| 2099 | ?\s)) | ||
| 2100 | str))) | ||
| 2101 | (insert "\n")) | ||
| 2102 | (point)) | ||
| 2103 | `(ibuffer-title t font-lock-face ,ibuffer-title-face)) | ||
| 2104 | ;; Now, insert the summary columns. | 2137 | ;; Now, insert the summary columns. |
| 2105 | (goto-char (point-max)) | 2138 | (goto-char (point-max)) |
| 2106 | (if (get-text-property (1- (point-max)) 'ibuffer-summary) | 2139 | (if (get-text-property (1- (point-max)) 'ibuffer-summary) |
| @@ -2112,27 +2145,7 @@ the value of point at the beginning of the line for that buffer." | |||
| 2112 | (point) | 2145 | (point) |
| 2113 | (progn | 2146 | (progn |
| 2114 | (insert "\n") | 2147 | (insert "\n") |
| 2115 | (dolist (element format) | 2148 | (apply #'insert (mapcar #'ibuffer--format-summary format)) |
| 2116 | (insert | ||
| 2117 | (if (stringp element) | ||
| 2118 | (make-string (length element) ?\s) | ||
| 2119 | (pcase-let ((`(,sym ,min ,_max ,align) element)) | ||
| 2120 | ;; Ignore a negative min when we're inserting the title. | ||
| 2121 | (when (cl-minusp min) | ||
| 2122 | (setq min (- min))) | ||
| 2123 | (let* ((summary | ||
| 2124 | (if (get sym 'ibuffer-column-summarizer) | ||
| 2125 | (funcall (get sym 'ibuffer-column-summarizer) | ||
| 2126 | (get sym 'ibuffer-column-summary)) | ||
| 2127 | (make-string | ||
| 2128 | (length (get sym 'ibuffer-column-name)) | ||
| 2129 | ?\s))) | ||
| 2130 | (len (length summary))) | ||
| 2131 | (if (< len min) | ||
| 2132 | (ibuffer-format-column summary | ||
| 2133 | (- min len) | ||
| 2134 | align) | ||
| 2135 | summary)))))) | ||
| 2136 | (point)) | 2149 | (point)) |
| 2137 | '(ibuffer-summary t))))) | 2150 | '(ibuffer-summary t))))) |
| 2138 | 2151 | ||
| @@ -2197,10 +2210,11 @@ If optional arg SILENT is non-nil, do not display progress messages." | |||
| 2197 | ;; I tried to update this automatically from the mode-line-process format, | 2210 | ;; I tried to update this automatically from the mode-line-process format, |
| 2198 | ;; but changing nil-ness of header-line-format while computing | 2211 | ;; but changing nil-ness of header-line-format while computing |
| 2199 | ;; mode-line-format is asking a bit too much it seems. --Stef | 2212 | ;; mode-line-format is asking a bit too much it seems. --Stef |
| 2200 | (setq header-line-format | 2213 | (unless (eq ibuffer-use-header-line 'title) |
| 2201 | (and ibuffer-use-header-line | 2214 | (setq header-line-format |
| 2202 | ibuffer-filtering-qualifiers | 2215 | (and ibuffer-use-header-line |
| 2203 | ibuffer-header-line-format))) | 2216 | ibuffer-filtering-qualifiers |
| 2217 | ibuffer-header-line-format)))) | ||
| 2204 | 2218 | ||
| 2205 | (defun ibuffer-sort-bufferlist (bmarklist) | 2219 | (defun ibuffer-sort-bufferlist (bmarklist) |
| 2206 | (unless ibuffer-sorting-functions-alist | 2220 | (unless ibuffer-sorting-functions-alist |