* bug#69305: outline-minor-mode for tabulated-list-mode
@ 2024-02-21 17:34 Juri Linkov
2024-02-21 19:12 ` Eli Zaretskii
0 siblings, 1 reply; 37+ messages in thread
From: Juri Linkov @ 2024-02-21 17:34 UTC (permalink / raw)
To: 69305
[-- Attachment #1: Type: text/plain, Size: 474 bytes --]
[From emacs-devel]
>> +(defcustom Buffer-menu-group-by nil
>> + "If non-nil, buffers are grouped by function."
>> + :type 'function
>> + :group 'Buffer-menu
>> + :version "30.1")
>
> Please consider letting users choose a symbol, not a function. Each
> symbol can be mapped to a function, but having a user option whose
> values are functions makes it harder for users to customize the
> option.
Ok, now the type is changed to 'symbol'. Here is the complete patch:
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: tabulated-list-groups.patch --]
[-- Type: text/x-diff, Size: 10258 bytes --]
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 70d1a40f836..bb2100dbb4d 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -1239,6 +1239,21 @@ Tabulated List Mode
above form when called with no arguments.
@end defvar
+@defvar tabulated-list-groups
+This buffer-local variable specifies the groups of entries displayed in
+the Tabulated List buffer. Its value should be either a list, or a
+function.
+
+If the value is a list, each list element corresponds to one group, and
+should have the form @w{@code{(@var{group-name} @var{entries})}}, where
+@var{group-name} is a string inserted before all group entries, and
+@var{entries} have the same format as @code{tabulated-list-entries}
+(see above).
+
+Otherwise, the value should be a function which returns a list of the
+above form when called with no arguments.
+@end defvar
+
@defvar tabulated-list-revert-hook
This normal hook is run prior to reverting a Tabulated List buffer. A
derived mode can add a function to this hook to recompute
diff --git a/etc/NEWS b/etc/NEWS
index 7b248c3fe78..b549eab9f0b 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1332,6 +1332,11 @@ will return the URL for that bug.
This allows for rcirc logs to use a custom timestamp format, than the
chat buffers use by default.
+---
+*** New user option 'Buffer-menu-group-by'.
+It splits buffers by groups that are displayed with headings in
+Outline minor mode.
+
---
*** New command 'Buffer-menu-toggle-internal'.
This command toggles the display of internal buffers in Buffer Menu mode;
@@ -1997,6 +2002,10 @@ inside 'treesit-language-source-alist', so that calling
It may be useful, for example, for the purposes of bisecting a
treesitter grammar.
++++
+** New buffer-local variable 'tabulated-list-groups'.
+It prints and sorts the groups of entries separately.
+
\f
* Changes in Emacs 30.1 on Non-Free Operating Systems
diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el
index e13c3b56b4e..62717c4625b 100644
--- a/lisp/buff-menu.el
+++ b/lisp/buff-menu.el
@@ -95,6 +95,18 @@ Buffer-menu-use-frame-buffer-list
:group 'Buffer-menu
:version "22.1")
+(defcustom Buffer-menu-group-by nil
+ "If non-nil, buffers are grouped by function.
+This function takes one argument: a list of entries in the same format
+as in `tabulated-list-entries', and should return a list in the format
+suitable for `tabulated-list-groups'. Also when this variable is non-nil,
+then `outline-minor-mode' is enabled in the Buffer Menu. Then with the
+default value of `outline-regexp' you can use Outline minor mode commands
+to show/hide groups of buffers."
+ :type 'symbol
+ :group 'Buffer-menu
+ :version "30.1")
+
(defvar-local Buffer-menu-files-only nil
"Non-nil if the current Buffer Menu lists only file buffers.
This is set by the prefix argument to `buffer-menu' and related
@@ -674,7 +684,12 @@ list-buffers-noselect
(setq Buffer-menu-buffer-list buffer-list)
(setq Buffer-menu-filter-predicate filter-predicate)
(list-buffers--refresh buffer-list old-buffer)
- (tabulated-list-print))
+ (tabulated-list-print)
+ (when tabulated-list-groups
+ (setq-local outline-minor-mode-cycle t
+ outline-minor-mode-highlight t
+ outline-minor-mode-use-buttons 'in-margins)
+ (outline-minor-mode 1)))
buffer))
(defun Buffer-menu-mouse-select (event)
@@ -750,7 +765,11 @@ list-buffers--refresh
`("Mode" ,Buffer-menu-mode-width t)
'("File" 1 t)))
(setq tabulated-list-use-header-line Buffer-menu-use-header-line)
- (setq tabulated-list-entries (nreverse entries)))
+ (setq tabulated-list-entries (nreverse entries))
+ (when Buffer-menu-group-by
+ (setq tabulated-list-groups
+ (seq-group-by Buffer-menu-group-by
+ tabulated-list-entries))))
(tabulated-list-init-header))
(defun tabulated-list-entry-size-> (entry1 entry2)
diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el
index 9884a2fc24b..a78e1726c26 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -139,6 +139,21 @@ tabulated-list-entries
arguments and must return a list of the above form.")
(put 'tabulated-list-entries 'permanent-local t)
+(defvar-local tabulated-list-groups nil
+ "Groups displayed in the current Tabulated List buffer.
+This should be either a function, or a list.
+If a list, each element has the form (GROUP-NAME ENTRIES),
+where:
+
+ - GROUP-NAME is a group name as a string, which is displayed
+ at the top line of each group.
+
+ - ENTRIES is a list described in `tabulated-list-entries'.
+
+If `tabulated-list-groups' is a function, it is called with no
+arguments and must return a list of the above form.")
+(put 'tabulated-list-groups 'permanent-local t)
+
(defvar-local tabulated-list-padding 0
"Number of characters preceding each Tabulated List mode entry.
By default, lines are padded with spaces, but you can use the
@@ -427,6 +444,9 @@ tabulated-list-print
specified by `tabulated-list-sort-key'. It then erases the
buffer and inserts the entries with `tabulated-list-printer'.
+If `tabulated-list-groups' is non-nil, each group of entries
+is sorted separately after printing the group header line.
+
Optional argument REMEMBER-POS, if non-nil, means to move point
to the entry with the same ID element as the current line.
@@ -437,6 +457,9 @@ tabulated-list-print
`tabulated-list-put-tag'). Don't use this immediately after
changing `tabulated-list-sort-key'."
(let ((inhibit-read-only t)
+ (groups (if (functionp tabulated-list-groups)
+ (funcall tabulated-list-groups)
+ tabulated-list-groups))
(entries (if (functionp tabulated-list-entries)
(funcall tabulated-list-entries)
tabulated-list-entries))
@@ -447,7 +470,14 @@ tabulated-list-print
(setq saved-col (current-column)))
;; Sort the entries, if necessary.
(when sorter
- (setq entries (sort entries sorter)))
+ (if groups
+ (setq groups
+ (mapcar (lambda (group)
+ (cons (car group) (sort (cdr group) sorter)))
+ groups))
+ (setq entries (sort entries sorter))))
+ (unless (functionp tabulated-list-groups)
+ (setq tabulated-list-groups groups))
(unless (functionp tabulated-list-entries)
(setq tabulated-list-entries entries))
;; Without a sorter, we have no way to just update.
@@ -459,6 +489,25 @@ tabulated-list-print
(unless tabulated-list-use-header-line
(tabulated-list-print-fake-header)))
;; Finally, print the resulting list.
+ (if groups
+ (dolist (group groups)
+ (insert (car group) ?\n)
+ (when-let ((saved-pt-new (tabulated-list-print-entries
+ (cdr group) sorter update entry-id)))
+ (setq saved-pt saved-pt-new)))
+ (setq saved-pt (tabulated-list-print-entries
+ entries sorter update entry-id)))
+ (when update
+ (delete-region (point) (point-max)))
+ (set-buffer-modified-p nil)
+ ;; If REMEMBER-POS was specified, move to the "old" location.
+ (if saved-pt
+ (progn (goto-char saved-pt)
+ (move-to-column saved-col))
+ (goto-char (point-min)))))
+
+(defun tabulated-list-print-entries (entries sorter update entry-id)
+ (let (saved-pt)
(while entries
(let* ((elt (car entries))
(tabulated-list--near-rows
@@ -495,14 +544,7 @@ tabulated-list-print
(forward-line 1)
(delete-region old (point))))))
(setq entries (cdr entries)))
- (when update
- (delete-region (point) (point-max)))
- (set-buffer-modified-p nil)
- ;; If REMEMBER-POS was specified, move to the "old" location.
- (if saved-pt
- (progn (goto-char saved-pt)
- (move-to-column saved-col))
- (goto-char (point-min)))))
+ saved-pt))
(defun tabulated-list-print-entry (id cols)
"Insert a Tabulated List entry at point.
diff --git a/test/lisp/emacs-lisp/tabulated-list-tests.el b/test/lisp/emacs-lisp/tabulated-list-tests.el
index 8be2be3139e..e53268b3f14 100644
--- a/test/lisp/emacs-lisp/tabulated-list-tests.el
+++ b/test/lisp/emacs-lisp/tabulated-list-tests.el
@@ -130,4 +130,45 @@ tabulated-list-sort
(should-error (tabulated-list-sort) :type 'user-error)
(should-error (tabulated-list-sort 4) :type 'user-error)))
+(ert-deftest tabulated-list-groups ()
+ (with-temp-buffer
+ (tabulated-list-mode)
+ (setq tabulated-list-groups
+ (reverse
+ (seq-group-by (lambda (b) (concat "* " (aref (cadr b) 3)))
+ tabulated-list--test-entries)))
+ (setq tabulated-list-format tabulated-list--test-format)
+ (setq tabulated-list-padding 7)
+ (tabulated-list-init-header)
+ (tabulated-list-print)
+ ;; Basic printing.
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "\
+* installed
+ zzzz-game zzzz-game 2113 installed play zzzz in Emacs
+ mode mode 1128 installed A simple mode for editing Actionscript 3 files
+* available
+ abc-mode abc-mode 944 available Major mode for editing abc music files
+* obsolete
+ 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
+"))
+ ;; Sort and preserve position.
+ (forward-line 2)
+ (let ((pos (thing-at-point 'line)))
+ (tabulated-list-next-column 2)
+ (tabulated-list-sort)
+ (should (equal (thing-at-point 'line) pos))
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "\
+* installed
+ mode mode 1128 installed A simple mode for editing Actionscript 3 files
+ zzzz-game zzzz-game 2113 installed play zzzz in Emacs
+* available
+ abc-mode abc-mode 944 available Major mode for editing abc music files
+* obsolete
+ 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
+")))))
+
;;; tabulated-list-tests.el ends here
^ permalink raw reply related [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-21 17:34 bug#69305: outline-minor-mode for tabulated-list-mode Juri Linkov
@ 2024-02-21 19:12 ` Eli Zaretskii
2024-02-22 7:44 ` Juri Linkov
0 siblings, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-21 19:12 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305
> From: Juri Linkov <juri@linkov.net>
> Date: Wed, 21 Feb 2024 19:34:17 +0200
>
> >> +(defcustom Buffer-menu-group-by nil
> >> + "If non-nil, buffers are grouped by function."
> >> + :type 'function
> >> + :group 'Buffer-menu
> >> + :version "30.1")
> >
> > Please consider letting users choose a symbol, not a function. Each
> > symbol can be mapped to a function, but having a user option whose
> > values are functions makes it harder for users to customize the
> > option.
>
> Ok, now the type is changed to 'symbol'. Here is the complete patch:
Thanks, but I wonder if we can be a tad more user-friendly? The user
option exists, and it can accept simple enough data structures for
customizations, but the default is nil, and there's no example or
pre-cooked list of ready-to-use values anywhere in sight, not even in
the doc string. Users will have to work hard to produce a grouping of
their liking. E.g., suppose I want to group buffers by mode -- how
would I go about it? Or what about grouping buffers by their leading
directories -- how can that be done? Etc. etc. -- this could be a
very powerful feature, but we should make its use easier. And, after
reading the documentation of tabulated-list-groups and that of
tabulated-list-entries several times, I have no idea how to specify
simple groupings such as those described above. Which makes examples
or pre-cooked values even more important, IMO.
What I had in mind when I said "choose a symbol" was that a symbol
will stand for a pre-cooked grouping. For example, 'mode would cause
buffers grouped by major-mode, 'directory will group by leading
directories, 'alphabet will group by the first letter of the name,
etc. What this patch provides is quite a far cry from that.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-21 19:12 ` Eli Zaretskii
@ 2024-02-22 7:44 ` Juri Linkov
2024-02-22 8:20 ` Eli Zaretskii
2024-02-24 18:06 ` Ihor Radchenko
0 siblings, 2 replies; 37+ messages in thread
From: Juri Linkov @ 2024-02-22 7:44 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 69305
[-- Attachment #1: Type: text/plain, Size: 1633 bytes --]
>> >> +(defcustom Buffer-menu-group-by nil
>> >> + "If non-nil, buffers are grouped by function."
>> >> + :type 'function
>> >> + :group 'Buffer-menu
>> >> + :version "30.1")
>> >
>> > Please consider letting users choose a symbol, not a function. Each
>> > symbol can be mapped to a function, but having a user option whose
>> > values are functions makes it harder for users to customize the
>> > option.
>>
>> Ok, now the type is changed to 'symbol'. Here is the complete patch:
>
> Thanks, but I wonder if we can be a tad more user-friendly? The user
> option exists, and it can accept simple enough data structures for
> customizations, but the default is nil, and there's no example or
> pre-cooked list of ready-to-use values anywhere in sight, not even in
> the doc string. Users will have to work hard to produce a grouping of
> their liking. E.g., suppose I want to group buffers by mode -- how
> would I go about it? Or what about grouping buffers by their leading
> directories -- how can that be done? Etc. etc. -- this could be a
> very powerful feature, but we should make its use easier. And, after
> reading the documentation of tabulated-list-groups and that of
> tabulated-list-entries several times, I have no idea how to specify
> simple groupings such as those described above. Which makes examples
> or pre-cooked values even more important, IMO.
Ok, then this patch adds two pre-cooked functions as a starting point
for users to understand the principle. Then users will propose
more functions and we will choose the most useful candidates
for including to the set of default functions later.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: tabulated-list-groups.patch --]
[-- Type: text/x-diff, Size: 11124 bytes --]
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 70d1a40f836..bb2100dbb4d 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -1239,6 +1239,21 @@ Tabulated List Mode
above form when called with no arguments.
@end defvar
+@defvar tabulated-list-groups
+This buffer-local variable specifies the groups of entries displayed in
+the Tabulated List buffer. Its value should be either a list, or a
+function.
+
+If the value is a list, each list element corresponds to one group, and
+should have the form @w{@code{(@var{group-name} @var{entries})}}, where
+@var{group-name} is a string inserted before all group entries, and
+@var{entries} have the same format as @code{tabulated-list-entries}
+(see above).
+
+Otherwise, the value should be a function which returns a list of the
+above form when called with no arguments.
+@end defvar
+
@defvar tabulated-list-revert-hook
This normal hook is run prior to reverting a Tabulated List buffer. A
derived mode can add a function to this hook to recompute
diff --git a/etc/NEWS b/etc/NEWS
index 7b248c3fe78..b549eab9f0b 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1332,6 +1332,11 @@ will return the URL for that bug.
This allows for rcirc logs to use a custom timestamp format, than the
chat buffers use by default.
+---
+*** New user option 'Buffer-menu-group-by'.
+It splits buffers by groups that are displayed with headings in
+Outline minor mode.
+
---
*** New command 'Buffer-menu-toggle-internal'.
This command toggles the display of internal buffers in Buffer Menu mode;
@@ -1997,6 +2002,10 @@ inside 'treesit-language-source-alist', so that calling
It may be useful, for example, for the purposes of bisecting a
treesitter grammar.
++++
+** New buffer-local variable 'tabulated-list-groups'.
+It prints and sorts the groups of entries separately.
+
\f
* Changes in Emacs 30.1 on Non-Free Operating Systems
diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el
index e13c3b56b4e..53bf66fdab1 100644
--- a/lisp/buff-menu.el
+++ b/lisp/buff-menu.el
@@ -95,6 +95,25 @@ Buffer-menu-use-frame-buffer-list
:group 'Buffer-menu
:version "22.1")
+(defcustom Buffer-menu-group-by nil
+ "If non-nil, buffers are grouped by function.
+This function takes one argument: a list of entries in the same format
+as in `tabulated-list-entries', and should return a list in the format
+suitable for `tabulated-list-groups'. Also when this variable is non-nil,
+then `outline-minor-mode' is enabled in the Buffer Menu. Then with the
+default value of `outline-regexp' you can use Outline minor mode commands
+to show/hide groups of buffers.
+The default options can group by a mode, and by a root directory of
+a project or just `default-directory'."
+ :type '(choice (const :tag "No grouping" nil)
+ (function-item :tag "Group by mode"
+ Buffer-menu-group-by-mode)
+ (function-item :tag "Group by root"
+ Buffer-menu-group-by-root)
+ (function :tag "Custom function"))
+ :group 'Buffer-menu
+ :version "30.1")
+
(defvar-local Buffer-menu-files-only nil
"Non-nil if the current Buffer Menu lists only file buffers.
This is set by the prefix argument to `buffer-menu' and related
@@ -674,7 +691,12 @@ list-buffers-noselect
(setq Buffer-menu-buffer-list buffer-list)
(setq Buffer-menu-filter-predicate filter-predicate)
(list-buffers--refresh buffer-list old-buffer)
- (tabulated-list-print))
+ (tabulated-list-print)
+ (when tabulated-list-groups
+ (setq-local outline-minor-mode-cycle t
+ outline-minor-mode-highlight t
+ outline-minor-mode-use-buttons 'in-margins)
+ (outline-minor-mode 1)))
buffer))
(defun Buffer-menu-mouse-select (event)
@@ -750,7 +772,11 @@ list-buffers--refresh
`("Mode" ,Buffer-menu-mode-width t)
'("File" 1 t)))
(setq tabulated-list-use-header-line Buffer-menu-use-header-line)
- (setq tabulated-list-entries (nreverse entries)))
+ (setq tabulated-list-entries (nreverse entries))
+ (when Buffer-menu-group-by
+ (setq tabulated-list-groups
+ (seq-group-by Buffer-menu-group-by
+ tabulated-list-entries))))
(tabulated-list-init-header))
(defun tabulated-list-entry-size-> (entry1 entry2)
@@ -769,4 +795,13 @@ Buffer-menu--pretty-file-name
(abbreviate-file-name list-buffers-directory))
(t "")))
+(defun Buffer-menu-group-by-mode (entry)
+ (concat "* " (aref (cadr entry) 5)))
+
+(defun Buffer-menu-group-by-root (entry)
+ (with-current-buffer (car entry)
+ (if-let ((project (project-current)))
+ (concat "* " (project-root project))
+ (concat "* " default-directory))))
+
;;; buff-menu.el ends here
diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el
index 9884a2fc24b..a78e1726c26 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -139,6 +139,21 @@ tabulated-list-entries
arguments and must return a list of the above form.")
(put 'tabulated-list-entries 'permanent-local t)
+(defvar-local tabulated-list-groups nil
+ "Groups displayed in the current Tabulated List buffer.
+This should be either a function, or a list.
+If a list, each element has the form (GROUP-NAME ENTRIES),
+where:
+
+ - GROUP-NAME is a group name as a string, which is displayed
+ at the top line of each group.
+
+ - ENTRIES is a list described in `tabulated-list-entries'.
+
+If `tabulated-list-groups' is a function, it is called with no
+arguments and must return a list of the above form.")
+(put 'tabulated-list-groups 'permanent-local t)
+
(defvar-local tabulated-list-padding 0
"Number of characters preceding each Tabulated List mode entry.
By default, lines are padded with spaces, but you can use the
@@ -427,6 +444,9 @@ tabulated-list-print
specified by `tabulated-list-sort-key'. It then erases the
buffer and inserts the entries with `tabulated-list-printer'.
+If `tabulated-list-groups' is non-nil, each group of entries
+is sorted separately after printing the group header line.
+
Optional argument REMEMBER-POS, if non-nil, means to move point
to the entry with the same ID element as the current line.
@@ -437,6 +457,9 @@ tabulated-list-print
`tabulated-list-put-tag'). Don't use this immediately after
changing `tabulated-list-sort-key'."
(let ((inhibit-read-only t)
+ (groups (if (functionp tabulated-list-groups)
+ (funcall tabulated-list-groups)
+ tabulated-list-groups))
(entries (if (functionp tabulated-list-entries)
(funcall tabulated-list-entries)
tabulated-list-entries))
@@ -447,7 +470,14 @@ tabulated-list-print
(setq saved-col (current-column)))
;; Sort the entries, if necessary.
(when sorter
- (setq entries (sort entries sorter)))
+ (if groups
+ (setq groups
+ (mapcar (lambda (group)
+ (cons (car group) (sort (cdr group) sorter)))
+ groups))
+ (setq entries (sort entries sorter))))
+ (unless (functionp tabulated-list-groups)
+ (setq tabulated-list-groups groups))
(unless (functionp tabulated-list-entries)
(setq tabulated-list-entries entries))
;; Without a sorter, we have no way to just update.
@@ -459,6 +489,25 @@ tabulated-list-print
(unless tabulated-list-use-header-line
(tabulated-list-print-fake-header)))
;; Finally, print the resulting list.
+ (if groups
+ (dolist (group groups)
+ (insert (car group) ?\n)
+ (when-let ((saved-pt-new (tabulated-list-print-entries
+ (cdr group) sorter update entry-id)))
+ (setq saved-pt saved-pt-new)))
+ (setq saved-pt (tabulated-list-print-entries
+ entries sorter update entry-id)))
+ (when update
+ (delete-region (point) (point-max)))
+ (set-buffer-modified-p nil)
+ ;; If REMEMBER-POS was specified, move to the "old" location.
+ (if saved-pt
+ (progn (goto-char saved-pt)
+ (move-to-column saved-col))
+ (goto-char (point-min)))))
+
+(defun tabulated-list-print-entries (entries sorter update entry-id)
+ (let (saved-pt)
(while entries
(let* ((elt (car entries))
(tabulated-list--near-rows
@@ -495,14 +544,7 @@ tabulated-list-print
(forward-line 1)
(delete-region old (point))))))
(setq entries (cdr entries)))
- (when update
- (delete-region (point) (point-max)))
- (set-buffer-modified-p nil)
- ;; If REMEMBER-POS was specified, move to the "old" location.
- (if saved-pt
- (progn (goto-char saved-pt)
- (move-to-column saved-col))
- (goto-char (point-min)))))
+ saved-pt))
(defun tabulated-list-print-entry (id cols)
"Insert a Tabulated List entry at point.
diff --git a/test/lisp/emacs-lisp/tabulated-list-tests.el b/test/lisp/emacs-lisp/tabulated-list-tests.el
index 8be2be3139e..e53268b3f14 100644
--- a/test/lisp/emacs-lisp/tabulated-list-tests.el
+++ b/test/lisp/emacs-lisp/tabulated-list-tests.el
@@ -130,4 +130,45 @@ tabulated-list-sort
(should-error (tabulated-list-sort) :type 'user-error)
(should-error (tabulated-list-sort 4) :type 'user-error)))
+(ert-deftest tabulated-list-groups ()
+ (with-temp-buffer
+ (tabulated-list-mode)
+ (setq tabulated-list-groups
+ (reverse
+ (seq-group-by (lambda (b) (concat "* " (aref (cadr b) 3)))
+ tabulated-list--test-entries)))
+ (setq tabulated-list-format tabulated-list--test-format)
+ (setq tabulated-list-padding 7)
+ (tabulated-list-init-header)
+ (tabulated-list-print)
+ ;; Basic printing.
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "\
+* installed
+ zzzz-game zzzz-game 2113 installed play zzzz in Emacs
+ mode mode 1128 installed A simple mode for editing Actionscript 3 files
+* available
+ abc-mode abc-mode 944 available Major mode for editing abc music files
+* obsolete
+ 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
+"))
+ ;; Sort and preserve position.
+ (forward-line 2)
+ (let ((pos (thing-at-point 'line)))
+ (tabulated-list-next-column 2)
+ (tabulated-list-sort)
+ (should (equal (thing-at-point 'line) pos))
+ (should (string-equal
+ (buffer-substring-no-properties (point-min) (point-max))
+ "\
+* installed
+ mode mode 1128 installed A simple mode for editing Actionscript 3 files
+ zzzz-game zzzz-game 2113 installed play zzzz in Emacs
+* available
+ abc-mode abc-mode 944 available Major mode for editing abc music files
+* obsolete
+ 4clojure 4clojure 1507 obsolete Open and evaluate 4clojure.com questions
+")))))
+
;;; tabulated-list-tests.el ends here
^ permalink raw reply related [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-22 7:44 ` Juri Linkov
@ 2024-02-22 8:20 ` Eli Zaretskii
2024-02-22 17:30 ` Juri Linkov
2024-02-24 18:06 ` Ihor Radchenko
1 sibling, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-22 8:20 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305
> From: Juri Linkov <juri@linkov.net>
> Cc: 69305@debbugs.gnu.org
> Date: Thu, 22 Feb 2024 09:44:40 +0200
>
> > Thanks, but I wonder if we can be a tad more user-friendly? The user
> > option exists, and it can accept simple enough data structures for
> > customizations, but the default is nil, and there's no example or
> > pre-cooked list of ready-to-use values anywhere in sight, not even in
> > the doc string. Users will have to work hard to produce a grouping of
> > their liking. E.g., suppose I want to group buffers by mode -- how
> > would I go about it? Or what about grouping buffers by their leading
> > directories -- how can that be done? Etc. etc. -- this could be a
> > very powerful feature, but we should make its use easier. And, after
> > reading the documentation of tabulated-list-groups and that of
> > tabulated-list-entries several times, I have no idea how to specify
> > simple groupings such as those described above. Which makes examples
> > or pre-cooked values even more important, IMO.
>
> Ok, then this patch adds two pre-cooked functions as a starting point
> for users to understand the principle. Then users will propose
> more functions and we will choose the most useful candidates
> for including to the set of default functions later.
Thanks.
> +@defvar tabulated-list-groups
> +This buffer-local variable specifies the groups of entries displayed in
> +the Tabulated List buffer. Its value should be either a list, or a
> +function.
> +
> +If the value is a list, each list element corresponds to one group, and
> +should have the form @w{@code{(@var{group-name} @var{entries})}}, where
> +@var{group-name} is a string inserted before all group entries, and
> +@var{entries} have the same format as @code{tabulated-list-entries}
> +(see above).
> +
> +Otherwise, the value should be a function which returns a list of the
> +above form when called with no arguments.
> +@end defvar
I think the way to specify ENTRIES for this customization should be
described in more detail. Reading the above description, even the
idea of using ENTRIES for specifying grouping is unclear, since
tabulated-list-entries is basically just a list of column descriptors.
> +(defcustom Buffer-menu-group-by nil
> + "If non-nil, buffers are grouped by function.
> +This function takes one argument: a list of entries in the same format
> +as in `tabulated-list-entries', and should return a list in the format
> +suitable for `tabulated-list-groups'. Also when this variable is non-nil,
> +then `outline-minor-mode' is enabled in the Buffer Menu. Then with the
> +default value of `outline-regexp' you can use Outline minor mode commands
> +to show/hide groups of buffers.
> +The default options can group by a mode, and by a root directory of
> +a project or just `default-directory'."
> + :type '(choice (const :tag "No grouping" nil)
> + (function-item :tag "Group by mode"
> + Buffer-menu-group-by-mode)
> + (function-item :tag "Group by root"
> + Buffer-menu-group-by-root)
I think the description text should be "Group by project" or "Group by
project root directory" or maybe "Group by project or directory".
Just "by root" is too vague.
> +If `tabulated-list-groups' is non-nil, each group of entries
> +is sorted separately after printing the group header line.
The part following "after printing" is IMO more confusing than
helpful. What will be lost if you remove it?
> +(ert-deftest tabulated-list-groups ()
> + (with-temp-buffer
> + (tabulated-list-mode)
> + (setq tabulated-list-groups
> + (reverse
> + (seq-group-by (lambda (b) (concat "* " (aref (cadr b) 3)))
> + tabulated-list--test-entries)))
> + (setq tabulated-list-format tabulated-list--test-format)
> + (setq tabulated-list-padding 7)
> + (tabulated-list-init-header)
> + (tabulated-list-print)
This seems to test only the function value of tabulated-list-groups?
What about the other form of the value?
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-22 8:20 ` Eli Zaretskii
@ 2024-02-22 17:30 ` Juri Linkov
2024-02-22 19:10 ` Eli Zaretskii
0 siblings, 1 reply; 37+ messages in thread
From: Juri Linkov @ 2024-02-22 17:30 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 69305
>> +@defvar tabulated-list-groups
>> +This buffer-local variable specifies the groups of entries displayed in
>> +the Tabulated List buffer. Its value should be either a list, or a
>> +function.
>> +
>> +If the value is a list, each list element corresponds to one group, and
>> +should have the form @w{@code{(@var{group-name} @var{entries})}}, where
>> +@var{group-name} is a string inserted before all group entries, and
>> +@var{entries} have the same format as @code{tabulated-list-entries}
>> +(see above).
>> +
>> +Otherwise, the value should be a function which returns a list of the
>> +above form when called with no arguments.
>> +@end defvar
>
> I think the way to specify ENTRIES for this customization should be
> described in more detail. Reading the above description, even the
> idea of using ENTRIES for specifying grouping is unclear, since
> tabulated-list-entries is basically just a list of column descriptors.
But ENTRIES are described in 'tabulated-list-entries'. Here ENTRIES
are no different from 'tabulated-list-entries' that are just
column descriptors.
>> +(defcustom Buffer-menu-group-by nil
>> + "If non-nil, buffers are grouped by function.
>> +This function takes one argument: a list of entries in the same format
>> +as in `tabulated-list-entries', and should return a list in the format
>> +suitable for `tabulated-list-groups'. Also when this variable is non-nil,
>> +then `outline-minor-mode' is enabled in the Buffer Menu. Then with the
>> +default value of `outline-regexp' you can use Outline minor mode commands
>> +to show/hide groups of buffers.
>> +The default options can group by a mode, and by a root directory of
>> +a project or just `default-directory'."
>> + :type '(choice (const :tag "No grouping" nil)
>> + (function-item :tag "Group by mode"
>> + Buffer-menu-group-by-mode)
>> + (function-item :tag "Group by root"
>> + Buffer-menu-group-by-root)
>
> I think the description text should be "Group by project" or "Group by
> project root directory" or maybe "Group by project or directory".
> Just "by root" is too vague.
Ok, then will use "Group by project root or directory".
>> +If `tabulated-list-groups' is non-nil, each group of entries
>> +is sorted separately after printing the group header line.
>
> The part following "after printing" is IMO more confusing than
> helpful. What will be lost if you remove it?
Oops, this was too ugly, will remove this part.
>> +(ert-deftest tabulated-list-groups ()
>> + (with-temp-buffer
>> + (tabulated-list-mode)
>> + (setq tabulated-list-groups
>> + (reverse
>> + (seq-group-by (lambda (b) (concat "* " (aref (cadr b) 3)))
>> + tabulated-list--test-entries)))
>> + (setq tabulated-list-format tabulated-list--test-format)
>> + (setq tabulated-list-padding 7)
>> + (tabulated-list-init-header)
>> + (tabulated-list-print)
>
> This seems to test only the function value of tabulated-list-groups?
> What about the other form of the value?
The other forms have no functional difference.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-22 17:30 ` Juri Linkov
@ 2024-02-22 19:10 ` Eli Zaretskii
2024-02-23 7:09 ` Juri Linkov
0 siblings, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-22 19:10 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305
> From: Juri Linkov <juri@linkov.net>
> Cc: 69305@debbugs.gnu.org
> Date: Thu, 22 Feb 2024 19:30:20 +0200
>
> >> +@defvar tabulated-list-groups
> >> +This buffer-local variable specifies the groups of entries displayed in
> >> +the Tabulated List buffer. Its value should be either a list, or a
> >> +function.
> >> +
> >> +If the value is a list, each list element corresponds to one group, and
> >> +should have the form @w{@code{(@var{group-name} @var{entries})}}, where
> >> +@var{group-name} is a string inserted before all group entries, and
> >> +@var{entries} have the same format as @code{tabulated-list-entries}
> >> +(see above).
> >> +
> >> +Otherwise, the value should be a function which returns a list of the
> >> +above form when called with no arguments.
> >> +@end defvar
> >
> > I think the way to specify ENTRIES for this customization should be
> > described in more detail. Reading the above description, even the
> > idea of using ENTRIES for specifying grouping is unclear, since
> > tabulated-list-entries is basically just a list of column descriptors.
>
> But ENTRIES are described in 'tabulated-list-entries'. Here ENTRIES
> are no different from 'tabulated-list-entries' that are just
> column descriptors.
My point is that it isn't obvious how to describe grouping in terms of
column descriptors. I think the manual should tell in more detail how
to use column descriptors to specify how entries should be grouped.
Maybe an example or two is all that it takes to do that.
> >> +(ert-deftest tabulated-list-groups ()
> >> + (with-temp-buffer
> >> + (tabulated-list-mode)
> >> + (setq tabulated-list-groups
> >> + (reverse
> >> + (seq-group-by (lambda (b) (concat "* " (aref (cadr b) 3)))
> >> + tabulated-list--test-entries)))
> >> + (setq tabulated-list-format tabulated-list--test-format)
> >> + (setq tabulated-list-padding 7)
> >> + (tabulated-list-init-header)
> >> + (tabulated-list-print)
> >
> > This seems to test only the function value of tabulated-list-groups?
> > What about the other form of the value?
>
> The other forms have no functional difference.
Sorry, I don't follow. Shouldn't we test the capability of specifying
grouping by the method other than by providing a function?
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-22 19:10 ` Eli Zaretskii
@ 2024-02-23 7:09 ` Juri Linkov
2024-02-23 8:13 ` Eli Zaretskii
0 siblings, 1 reply; 37+ messages in thread
From: Juri Linkov @ 2024-02-23 7:09 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 69305
>> >> +@defvar tabulated-list-groups
>> >> +This buffer-local variable specifies the groups of entries displayed in
>> >> +the Tabulated List buffer. Its value should be either a list, or a
>> >> +function.
>> >> +
>> >> +If the value is a list, each list element corresponds to one group, and
>> >> +should have the form @w{@code{(@var{group-name} @var{entries})}}, where
>> >> +@var{group-name} is a string inserted before all group entries, and
>> >> +@var{entries} have the same format as @code{tabulated-list-entries}
>> >> +(see above).
>> >> +
>> >> +Otherwise, the value should be a function which returns a list of the
>> >> +above form when called with no arguments.
>> >> +@end defvar
>> >
>> > I think the way to specify ENTRIES for this customization should be
>> > described in more detail. Reading the above description, even the
>> > idea of using ENTRIES for specifying grouping is unclear, since
>> > tabulated-list-entries is basically just a list of column descriptors.
>>
>> But ENTRIES are described in 'tabulated-list-entries'. Here ENTRIES
>> are no different from 'tabulated-list-entries' that are just
>> column descriptors.
>
> My point is that it isn't obvious how to describe grouping in terms of
> column descriptors. I think the manual should tell in more detail how
> to use column descriptors to specify how entries should be grouped.
> Maybe an example or two is all that it takes to do that.
Sorry, I don't understand what is unclear here:
If the value is a list, each list element corresponds to one group, and
should have the form @w{@code{(@var{group-name} @var{entries})}}, where
@var{group-name} is a string inserted before all group entries, and
@var{entries} have the same format as @code{tabulated-list-entries}
(see above).
Basically this says that the format is (group-name entries) where
entries are described in tabulated-list-entries as having the format
(id contents). There is no need to duplicate the description of entries.
>> >> +(ert-deftest tabulated-list-groups ()
>> >> + (with-temp-buffer
>> >> + (tabulated-list-mode)
>> >> + (setq tabulated-list-groups
>> >> + (reverse
>> >> + (seq-group-by (lambda (b) (concat "* " (aref (cadr b) 3)))
>> >> + tabulated-list--test-entries)))
>> >> + (setq tabulated-list-format tabulated-list--test-format)
>> >> + (setq tabulated-list-padding 7)
>> >> + (tabulated-list-init-header)
>> >> + (tabulated-list-print)
>> >
>> > This seems to test only the function value of tabulated-list-groups?
>> > What about the other form of the value?
>>
>> The other forms have no functional difference.
>
> Sorry, I don't follow. Shouldn't we test the capability of specifying
> grouping by the method other than by providing a function?
Actually there are no other methods.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-23 7:09 ` Juri Linkov
@ 2024-02-23 8:13 ` Eli Zaretskii
2024-02-24 17:43 ` Juri Linkov
0 siblings, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-23 8:13 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305
> From: Juri Linkov <juri@linkov.net>
> Cc: 69305@debbugs.gnu.org
> Date: Fri, 23 Feb 2024 09:09:03 +0200
>
> >> >> +@defvar tabulated-list-groups
> >> >> +This buffer-local variable specifies the groups of entries displayed in
> >> >> +the Tabulated List buffer. Its value should be either a list, or a
> >> >> +function.
> >> >> +
> >> >> +If the value is a list, each list element corresponds to one group, and
> >> >> +should have the form @w{@code{(@var{group-name} @var{entries})}}, where
> >> >> +@var{group-name} is a string inserted before all group entries, and
> >> >> +@var{entries} have the same format as @code{tabulated-list-entries}
> >> >> +(see above).
> >> >> +
> >> >> +Otherwise, the value should be a function which returns a list of the
> >> >> +above form when called with no arguments.
> >> >> +@end defvar
> >> >
> >> > I think the way to specify ENTRIES for this customization should be
> >> > described in more detail. Reading the above description, even the
> >> > idea of using ENTRIES for specifying grouping is unclear, since
> >> > tabulated-list-entries is basically just a list of column descriptors.
> >>
> >> But ENTRIES are described in 'tabulated-list-entries'. Here ENTRIES
> >> are no different from 'tabulated-list-entries' that are just
> >> column descriptors.
> >
> > My point is that it isn't obvious how to describe grouping in terms of
> > column descriptors. I think the manual should tell in more detail how
> > to use column descriptors to specify how entries should be grouped.
> > Maybe an example or two is all that it takes to do that.
>
> Sorry, I don't understand what is unclear here:
>
> If the value is a list, each list element corresponds to one group, and
> should have the form @w{@code{(@var{group-name} @var{entries})}}, where
> @var{group-name} is a string inserted before all group entries, and
> @var{entries} have the same format as @code{tabulated-list-entries}
> (see above).
>
> Basically this says that the format is (group-name entries) where
> entries are described in tabulated-list-entries as having the format
> (id contents). There is no need to duplicate the description of entries.
Maybe I'm missing something here. To put it more concretely, can you
show a value of tabulated-list-groups that will cause the buffers in
buffer list grouped by major mode using the above form?
> >> >> +(ert-deftest tabulated-list-groups ()
> >> >> + (with-temp-buffer
> >> >> + (tabulated-list-mode)
> >> >> + (setq tabulated-list-groups
> >> >> + (reverse
> >> >> + (seq-group-by (lambda (b) (concat "* " (aref (cadr b) 3)))
> >> >> + tabulated-list--test-entries)))
> >> >> + (setq tabulated-list-format tabulated-list--test-format)
> >> >> + (setq tabulated-list-padding 7)
> >> >> + (tabulated-list-init-header)
> >> >> + (tabulated-list-print)
> >> >
> >> > This seems to test only the function value of tabulated-list-groups?
> >> > What about the other form of the value?
> >>
> >> The other forms have no functional difference.
> >
> > Sorry, I don't follow. Shouldn't we test the capability of specifying
> > grouping by the method other than by providing a function?
>
> Actually there are no other methods.
The doc string says the "value can be either a list or a function". I
see only one value here, so I'm asking what about a value of the other
form. Or what am I missing here?
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-23 8:13 ` Eli Zaretskii
@ 2024-02-24 17:43 ` Juri Linkov
2024-02-24 18:09 ` Eli Zaretskii
2024-02-24 18:13 ` Eli Zaretskii
0 siblings, 2 replies; 37+ messages in thread
From: Juri Linkov @ 2024-02-24 17:43 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 69305
>> >> >> +@defvar tabulated-list-groups
>> >> >> +This buffer-local variable specifies the groups of entries displayed in
>> >> >> +the Tabulated List buffer. Its value should be either a list, or a
>> >> >> +function.
>> >> >> +
>> >> >> +If the value is a list, each list element corresponds to one group, and
>> >> >> +should have the form @w{@code{(@var{group-name} @var{entries})}}, where
>> >> >> +@var{group-name} is a string inserted before all group entries, and
>> >> >> +@var{entries} have the same format as @code{tabulated-list-entries}
>> >> >> +(see above).
>> >> >> +
>> >> >> +Otherwise, the value should be a function which returns a list of the
>> >> >> +above form when called with no arguments.
>> >> >> +@end defvar
>> >> >
>> >> > I think the way to specify ENTRIES for this customization should be
>> >> > described in more detail. Reading the above description, even the
>> >> > idea of using ENTRIES for specifying grouping is unclear, since
>> >> > tabulated-list-entries is basically just a list of column descriptors.
>> >>
>> >> But ENTRIES are described in 'tabulated-list-entries'. Here ENTRIES
>> >> are no different from 'tabulated-list-entries' that are just
>> >> column descriptors.
>> >
>> > My point is that it isn't obvious how to describe grouping in terms of
>> > column descriptors. I think the manual should tell in more detail how
>> > to use column descriptors to specify how entries should be grouped.
>> > Maybe an example or two is all that it takes to do that.
>>
>> Sorry, I don't understand what is unclear here:
>>
>> If the value is a list, each list element corresponds to one group, and
>> should have the form @w{@code{(@var{group-name} @var{entries})}}, where
>> @var{group-name} is a string inserted before all group entries, and
>> @var{entries} have the same format as @code{tabulated-list-entries}
>> (see above).
>>
>> Basically this says that the format is (group-name entries) where
>> entries are described in tabulated-list-entries as having the format
>> (id contents). There is no need to duplicate the description of entries.
>
> Maybe I'm missing something here. To put it more concretely, can you
> show a value of tabulated-list-groups that will cause the buffers in
> buffer list grouped by major mode using the above form?
Data structure for `tabulated-list-groups' is a list of elements,
each element should of the form
(GROUP-NAME (ID . CONTENTS) (ID . CONTENTS) ...)
where GROUP-NAME is the name of the group, ID is a Lisp object that
identifies the entry and CONTENTS is a vector with the same number of
elements as `tabulated-list-format'. When buffers grouped by major mode:
(("* Lisp Interaction" (#<buffer *scratch*> ["." " " "*" #("*scratch*" 0 9 ...) "225" "Lisp Interaction" ""]) ...))
>> >> >> +(ert-deftest tabulated-list-groups ()
>> >> >> + (with-temp-buffer
>> >> >> + (tabulated-list-mode)
>> >> >> + (setq tabulated-list-groups
>> >> >> + (reverse
>> >> >> + (seq-group-by (lambda (b) (concat "* " (aref (cadr b) 3)))
>> >> >> + tabulated-list--test-entries)))
>> >> >> + (setq tabulated-list-format tabulated-list--test-format)
>> >> >> + (setq tabulated-list-padding 7)
>> >> >> + (tabulated-list-init-header)
>> >> >> + (tabulated-list-print)
>> >> >
>> >> > This seems to test only the function value of tabulated-list-groups?
>> >> > What about the other form of the value?
>> >>
>> >> The other forms have no functional difference.
>> >
>> > Sorry, I don't follow. Shouldn't we test the capability of specifying
>> > grouping by the method other than by providing a function?
>>
>> Actually there are no other methods.
>
> The doc string says the "value can be either a list or a function". I
> see only one value here, so I'm asking what about a value of the other
> form. Or what am I missing here?
Another form is a function. But there is no need to test this.
It's just a copy from tabulated-list-entries that is unused.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-22 7:44 ` Juri Linkov
2024-02-22 8:20 ` Eli Zaretskii
@ 2024-02-24 18:06 ` Ihor Radchenko
2024-02-24 18:16 ` Eli Zaretskii
2024-02-25 17:20 ` Juri Linkov
1 sibling, 2 replies; 37+ messages in thread
From: Ihor Radchenko @ 2024-02-24 18:06 UTC (permalink / raw)
To: Juri Linkov, Adam Porter; +Cc: 69305, Eli Zaretskii
Juri Linkov <juri@linkov.net> writes:
> +@defvar tabulated-list-groups
> +This buffer-local variable specifies the groups of entries displayed in
> +the Tabulated List buffer. Its value should be either a list, or a
> +function.
> +
> +If the value is a list, each list element corresponds to one group, and
> +should have the form @w{@code{(@var{group-name} @var{entries})}}, where
> +@var{group-name} is a string inserted before all group entries, and
> +@var{entries} have the same format as @code{tabulated-list-entries}
> +(see above).
> +
> +Otherwise, the value should be a function which returns a list of the
> +above form when called with no arguments.
> +@end defvar
I am wondering if flexible grouping system from Adam's org-super-agenda
package may provide some inspiration.
Check out
https://github.com/alphapapa/org-super-agenda/?tab=readme-ov-file#usage
--
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-24 17:43 ` Juri Linkov
@ 2024-02-24 18:09 ` Eli Zaretskii
2024-02-24 18:13 ` Eli Zaretskii
1 sibling, 0 replies; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-24 18:09 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-24 17:43 ` Juri Linkov
2024-02-24 18:09 ` Eli Zaretskii
@ 2024-02-24 18:13 ` Eli Zaretskii
2024-02-25 8:00 ` Adam Porter
2024-02-25 17:25 ` Juri Linkov
1 sibling, 2 replies; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-24 18:13 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305
> From: Juri Linkov <juri@linkov.net>
> Cc: 69305@debbugs.gnu.org
> Date: Sat, 24 Feb 2024 19:43:25 +0200
>
> >> Sorry, I don't understand what is unclear here:
> >>
> >> If the value is a list, each list element corresponds to one group, and
> >> should have the form @w{@code{(@var{group-name} @var{entries})}}, where
> >> @var{group-name} is a string inserted before all group entries, and
> >> @var{entries} have the same format as @code{tabulated-list-entries}
> >> (see above).
> >>
> >> Basically this says that the format is (group-name entries) where
> >> entries are described in tabulated-list-entries as having the format
> >> (id contents). There is no need to duplicate the description of entries.
> >
> > Maybe I'm missing something here. To put it more concretely, can you
> > show a value of tabulated-list-groups that will cause the buffers in
> > buffer list grouped by major mode using the above form?
>
> Data structure for `tabulated-list-groups' is a list of elements,
> each element should of the form
>
> (GROUP-NAME (ID . CONTENTS) (ID . CONTENTS) ...)
>
> where GROUP-NAME is the name of the group, ID is a Lisp object that
> identifies the entry and CONTENTS is a vector with the same number of
> elements as `tabulated-list-format'. When buffers grouped by major mode:
>
> (("* Lisp Interaction" (#<buffer *scratch*> ["." " " "*" #("*scratch*" 0 9 ...) "225" "Lisp Interaction" ""]) ...))
This is the value that the user is supposed to supply for the
defcustom? That is, the user must specify all the buffers explicitly?
What happens when there's one more buffer in some mode? does the user
have then to modify the value of the defcustom?
> >> >> >> +(ert-deftest tabulated-list-groups ()
> >> >> >> + (with-temp-buffer
> >> >> >> + (tabulated-list-mode)
> >> >> >> + (setq tabulated-list-groups
> >> >> >> + (reverse
> >> >> >> + (seq-group-by (lambda (b) (concat "* " (aref (cadr b) 3)))
> >> >> >> + tabulated-list--test-entries)))
> >> >> >> + (setq tabulated-list-format tabulated-list--test-format)
> >> >> >> + (setq tabulated-list-padding 7)
> >> >> >> + (tabulated-list-init-header)
> >> >> >> + (tabulated-list-print)
> >> >> >
> >> >> > This seems to test only the function value of tabulated-list-groups?
> >> >> > What about the other form of the value?
> >> >>
> >> >> The other forms have no functional difference.
> >> >
> >> > Sorry, I don't follow. Shouldn't we test the capability of specifying
> >> > grouping by the method other than by providing a function?
> >>
> >> Actually there are no other methods.
> >
> > The doc string says the "value can be either a list or a function". I
> > see only one value here, so I'm asking what about a value of the other
> > form. Or what am I missing here?
>
> Another form is a function. But there is no need to test this.
> It's just a copy from tabulated-list-entries that is unused.
I give up.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-24 18:06 ` Ihor Radchenko
@ 2024-02-24 18:16 ` Eli Zaretskii
2024-02-24 18:36 ` Ihor Radchenko
2024-02-25 17:20 ` Juri Linkov
1 sibling, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-24 18:16 UTC (permalink / raw)
To: Ihor Radchenko; +Cc: adam, 69305, juri
> From: Ihor Radchenko <yantar92@posteo.net>
> Cc: Eli Zaretskii <eliz@gnu.org>, 69305@debbugs.gnu.org
> Date: Sat, 24 Feb 2024 18:06:46 +0000
>
> I am wondering if flexible grouping system from Adam's org-super-agenda
> package may provide some inspiration.
> Check out
> https://github.com/alphapapa/org-super-agenda/?tab=readme-ov-file#usage
What I had in mind was much simpler to use. But I guess I'm the only
one who wants to let users set up grouping in some easy way, because
I'm being shown more and more complicated customizations, claiming
they are suitable.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-24 18:16 ` Eli Zaretskii
@ 2024-02-24 18:36 ` Ihor Radchenko
2024-02-24 18:49 ` Eli Zaretskii
0 siblings, 1 reply; 37+ messages in thread
From: Ihor Radchenko @ 2024-02-24 18:36 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: adam, 69305, juri
Eli Zaretskii <eliz@gnu.org> writes:
>> I am wondering if flexible grouping system from Adam's org-super-agenda
>> package may provide some inspiration.
>> Check out
>> https://github.com/alphapapa/org-super-agenda/?tab=readme-ov-file#usage
>
> What I had in mind was much simpler to use. But I guess I'm the only
> one who wants to let users set up grouping in some easy way, because
> I'm being shown more and more complicated customizations, claiming
> they are suitable.
Don't be deceived by the length of org-super-agenda readme.
Most of the keywords listed there are an equivalent to column names in
tabulated-list-mode.
What might be relevant are the following group customizations:
:face
A face to apply to items in the group. If face is a plist containing
:append t, it will be appended. See function add-face-text-property.
:transformer
Used to transform item strings before display. Either a function
called with one argument, the item string, or a sexp, in which case
the item string is bound to it.
and the following options to provide automatic grouping without a need
to write dedicated function:
:and
Group ITEMS that match all selectors in GROUP.
:anything
Select every item, no matter what. This is probably most useful with
:discard, because it doesn’t actually test anything, so it’s faster
than, e.g. ~:regexp “.”~, which has to get the entry text for every
item.
:discard
Discard items that match selectors. Any groups processed after this one
will not see discarded items. You might use this at the beginning or end
of a list of groups, either to narrow down the list of items (used in
combination with :not), or to exclude items you’re not interested in.
:not
Group ITEMS that match no selectors in GROUP.
Note that the :not group selector creates a group with items it does not
match; it can be combined with :discard to discard items that don’t
match. For example, (:discard (:not (:priority "A"))) as the first
selector would mean that only priority A items would appear in the
agenda, while (:discard (:priority "C")) would mean that any priority C
items would not appear in the agenda.
:order
A number setting the order sections will be displayed in the agenda,
lowest number first. Defaults to 0.
:order-multi
Set the order of multiple groups at once, like (:order-multi (2 (groupA)
(groupB) ...)) to set the order of these groups to 2.
:take
Take the first N items in GROUP. If N is negative, take the last N
items. For example, (:take (-3 group)) will take the last 3 items from
the group. The remainder of items are discarded. Note: The order of
entries from GROUP is not guaranteed to be preserved, so :take may not
always show expected entries.
--
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-24 18:36 ` Ihor Radchenko
@ 2024-02-24 18:49 ` Eli Zaretskii
2024-02-25 7:45 ` Adam Porter
2024-02-25 7:53 ` Adam Porter
0 siblings, 2 replies; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-24 18:49 UTC (permalink / raw)
To: Ihor Radchenko; +Cc: adam, 69305, juri
> From: Ihor Radchenko <yantar92@posteo.net>
> Cc: juri@linkov.net, adam@alphapapa.net, 69305@debbugs.gnu.org
> Date: Sat, 24 Feb 2024 18:36:23 +0000
>
> Eli Zaretskii <eliz@gnu.org> writes:
>
> >> I am wondering if flexible grouping system from Adam's org-super-agenda
> >> package may provide some inspiration.
> >> Check out
> >> https://github.com/alphapapa/org-super-agenda/?tab=readme-ov-file#usage
> >
> > What I had in mind was much simpler to use. But I guess I'm the only
> > one who wants to let users set up grouping in some easy way, because
> > I'm being shown more and more complicated customizations, claiming
> > they are suitable.
>
> Don't be deceived by the length of org-super-agenda readme.
> Most of the keywords listed there are an equivalent to column names in
> tabulated-list-mode.
Did you read what I suggested as the preferred way of specifying the
grouping? It's way simpler than what org-super-agenda expects.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-24 18:49 ` Eli Zaretskii
@ 2024-02-25 7:45 ` Adam Porter
2024-02-25 17:36 ` Juri Linkov
2024-02-25 7:53 ` Adam Porter
1 sibling, 1 reply; 37+ messages in thread
From: Adam Porter @ 2024-02-25 7:45 UTC (permalink / raw)
To: Eli Zaretskii, Ihor Radchenko; +Cc: 69305, juri
Hi,
On 2/24/24 12:49, Eli Zaretskii wrote:
>> From: Ihor Radchenko <yantar92@posteo.net>
>> Cc: juri@linkov.net, adam@alphapapa.net, 69305@debbugs.gnu.org
>> Date: Sat, 24 Feb 2024 18:36:23 +0000
>>
>> Eli Zaretskii <eliz@gnu.org> writes:
>>
>>>> I am wondering if flexible grouping system from Adam's org-super-agenda
>>>> package may provide some inspiration.
>>>> Check out
>>>> https://github.com/alphapapa/org-super-agenda/?tab=readme-ov-file#usage
>>>
>>> What I had in mind was much simpler to use. But I guess I'm the only
>>> one who wants to let users set up grouping in some easy way, because
>>> I'm being shown more and more complicated customizations, claiming
>>> they are suitable.
>>
>> Don't be deceived by the length of org-super-agenda readme.
>> Most of the keywords listed there are an equivalent to column names in
>> tabulated-list-mode.
>
> Did you read what I suggested as the preferred way of specifying the
> grouping? It's way simpler than what org-super-agenda expects.
I appreciate Ihor's mentioning my org-super-agenda library. But while
it is indeed a useful tool, please note that since I wrote it, I learned
a lot about the topic, and I wrote a new library purposefully designed
to facilitate grouping arbitrary data in arbitrary ways with a simple
API: taxy.el, which is on GNU ELPA. It supports both statically defined
grouping, as well as user-customizeable grouping using a concise DSL
defined with top-level forms.
So if you were to use one of these as inspiration (or as a library
directly), I'd strongly recommend using `taxy', as that's what it's
designed for.
The documentation is fairly thorough; please see the installed Info
manual, or the readme at:
https://github.com/alphapapa/taxy.el#usage
Let me know if I can help facilitate a solution using it, or help anyone
work with the API.
Thanks,
Adam
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-24 18:49 ` Eli Zaretskii
2024-02-25 7:45 ` Adam Porter
@ 2024-02-25 7:53 ` Adam Porter
2024-02-25 8:26 ` Eli Zaretskii
1 sibling, 1 reply; 37+ messages in thread
From: Adam Porter @ 2024-02-25 7:53 UTC (permalink / raw)
To: Eli Zaretskii, Ihor Radchenko; +Cc: 69305, juri
By the way, with regard to grouping buffers specifically, this is what
my Bufler package does, again in an extensible, user-programmable way:
https://github.com/alphapapa/bufler.el
I wrote it after putting significant effort into using Ibuffer's
grouping features, which didn't meet my needs.
Bufler supports grouping buffers by many different attributes, such as
directory, filename, mode, project, parent-project, TRAMP status, etc.
And, significantly, it does such grouping dynamically at multiple
levels. For example, within a "~/src/emacs" directory, subgroups for
git projects within that directory can be created dynamically, providing
a grouping like:
+ Dir: ~/src/emacs
|-+ Project: ~/src/emacs/bufler.el
| |- *magit-status: bufler.el*
|-+ Project: ~/src/emacs/activities.el
|- README.org
If org-super-agenda was my exploration of the topic, Bufler served as
the prototype of a better API, which I then factored out into Taxy.
Eventually I'll rebase Bufler on top of Taxy.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-24 18:13 ` Eli Zaretskii
@ 2024-02-25 8:00 ` Adam Porter
2024-02-25 17:25 ` Juri Linkov
1 sibling, 0 replies; 37+ messages in thread
From: Adam Porter @ 2024-02-25 8:00 UTC (permalink / raw)
To: eliz; +Cc: 69305, juri
>> Data structure for `tabulated-list-groups' is a list of elements,
>> each element should of the form
>>
>> (GROUP-NAME (ID . CONTENTS) (ID . CONTENTS) ...)
>>
>> where GROUP-NAME is the name of the group, ID is a Lisp object that
>> identifies the entry and CONTENTS is a vector with the same number of
>> elements as `tabulated-list-format'. When buffers grouped by major mode:
>>
>> (("* Lisp Interaction" (#<buffer *scratch*> ["." " " "*" #("*scratch*" 0 9 ...) "225" "Lisp Interaction" ""]) ...))
>
> This is the value that the user is supposed to supply for the
> defcustom? That is, the user must specify all the buffers explicitly?
> What happens when there's one more buffer in some mode? does the user
> have then to modify the value of the defcustom?
FWIW, using, e.g. Bufler/Taxy to group buffers, the user would define a
set of group key functions like so:
(setf buffer-keys '((project) (special mode) mode))
That in effect says, "If a buffer is part of a project, group it by that
project's directory; otherwise if a buffer is special, group it with
other special buffers, and create subgroups by mode; otherwise group it
by mode."
Then the groups are created dynamically at runtime when the buffer list
buffer is refreshed.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-25 7:53 ` Adam Porter
@ 2024-02-25 8:26 ` Eli Zaretskii
0 siblings, 0 replies; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-25 8:26 UTC (permalink / raw)
To: Adam Porter; +Cc: 69305, yantar92, juri
> Date: Sun, 25 Feb 2024 01:53:55 -0600
> Cc: juri@linkov.net, 69305@debbugs.gnu.org
> From: Adam Porter <adam@alphapapa.net>
>
> By the way, with regard to grouping buffers specifically, this is what
> my Bufler package does, again in an extensible, user-programmable way:
>
> https://github.com/alphapapa/bufler.el
>
> I wrote it after putting significant effort into using Ibuffer's
> grouping features, which didn't meet my needs.
>
> Bufler supports grouping buffers by many different attributes, such as
> directory, filename, mode, project, parent-project, TRAMP status, etc.
> And, significantly, it does such grouping dynamically at multiple
> levels. For example, within a "~/src/emacs" directory, subgroups for
> git projects within that directory can be created dynamically, providing
> a grouping like:
>
> + Dir: ~/src/emacs
> |-+ Project: ~/src/emacs/bufler.el
> | |- *magit-status: bufler.el*
> |-+ Project: ~/src/emacs/activities.el
> |- README.org
Thanks. Once again, my proposal (and frankly, an expectation) was
that we provide a much simpler customization facility for grouping
entries in a tabulated-list-mode buffer. I won't mind that the
current fancy customization is extended to use something like what
bufler.el does (although it needs to be generalize to support more
than buffer lists), but that will not fill the gap that I feel exists
in what we offer now.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-24 18:06 ` Ihor Radchenko
2024-02-24 18:16 ` Eli Zaretskii
@ 2024-02-25 17:20 ` Juri Linkov
1 sibling, 0 replies; 37+ messages in thread
From: Juri Linkov @ 2024-02-25 17:20 UTC (permalink / raw)
To: Ihor Radchenko; +Cc: Adam Porter, 69305, Eli Zaretskii
> I am wondering if flexible grouping system from Adam's org-super-agenda
> package may provide some inspiration.
> Check out
> https://github.com/alphapapa/org-super-agenda/?tab=readme-ov-file#usage
The designed feature of enabling outline-minor-mode in tabulated-list-mode
is intended to be as simple as possible while keeping flexibility
for user's customization.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-24 18:13 ` Eli Zaretskii
2024-02-25 8:00 ` Adam Porter
@ 2024-02-25 17:25 ` Juri Linkov
2024-02-25 19:17 ` Eli Zaretskii
1 sibling, 1 reply; 37+ messages in thread
From: Juri Linkov @ 2024-02-25 17:25 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 69305
>> >> Sorry, I don't understand what is unclear here:
>> >>
>> >> If the value is a list, each list element corresponds to one group, and
>> >> should have the form @w{@code{(@var{group-name} @var{entries})}}, where
>> >> @var{group-name} is a string inserted before all group entries, and
>> >> @var{entries} have the same format as @code{tabulated-list-entries}
>> >> (see above).
>> >>
>> >> Basically this says that the format is (group-name entries) where
>> >> entries are described in tabulated-list-entries as having the format
>> >> (id contents). There is no need to duplicate the description of entries.
>> >
>> > Maybe I'm missing something here. To put it more concretely, can you
>> > show a value of tabulated-list-groups that will cause the buffers in
>> > buffer list grouped by major mode using the above form?
>>
>> Data structure for `tabulated-list-groups' is a list of elements,
>> each element should of the form
>>
>> (GROUP-NAME (ID . CONTENTS) (ID . CONTENTS) ...)
>>
>> where GROUP-NAME is the name of the group, ID is a Lisp object that
>> identifies the entry and CONTENTS is a vector with the same number of
>> elements as `tabulated-list-format'. When buffers grouped by major mode:
>>
>> (("* Lisp Interaction" (#<buffer *scratch*> ["." " " "*" #("*scratch*" 0 9 ...) "225" "Lisp Interaction" ""]) ...))
>
> This is the value that the user is supposed to supply for the
> defcustom? That is, the user must specify all the buffers explicitly?
> What happens when there's one more buffer in some mode? does the user
> have then to modify the value of the defcustom?
This describes the internal data structure, not a defcustom.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-25 7:45 ` Adam Porter
@ 2024-02-25 17:36 ` Juri Linkov
2024-02-26 3:31 ` Adam Porter
0 siblings, 1 reply; 37+ messages in thread
From: Juri Linkov @ 2024-02-25 17:36 UTC (permalink / raw)
To: Adam Porter; +Cc: 69305, Eli Zaretskii, Ihor Radchenko
> So if you were to use one of these as inspiration (or as a library
> directly), I'd strongly recommend using `taxy', as that's what it's
> designed for.
> [...]
> Let me know if I can help facilitate a solution using it, or help anyone
> work with the API.
Thanks for proposing help, but for inspiration I'm using
my own package https://github.com/link0ff/emacs-ee
It's much more powerful than anything I have seen so far.
But on the other hand, it became so unmanageable
that I semi-abandoned it due to its overly complexity.
Is your package more light-weight than mine? I doubt it ;-)
This is why I proposed to do the same with minimal changes relying on
existing core packages tabulated-list-mode and outline-minor-mode that
already handle 95% of required functionality.
What remains to do is just to fill the rest 5%. In addition to the
first patch, there will be 2-3 equally small patches that will
complete functionality equivalent to the said packages.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-25 17:25 ` Juri Linkov
@ 2024-02-25 19:17 ` Eli Zaretskii
2024-02-27 7:30 ` Juri Linkov
0 siblings, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-25 19:17 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305
> From: Juri Linkov <juri@linkov.net>
> Cc: 69305@debbugs.gnu.org
> Date: Sun, 25 Feb 2024 19:25:10 +0200
>
> >> >> Sorry, I don't understand what is unclear here:
> >> >>
> >> >> If the value is a list, each list element corresponds to one group, and
> >> >> should have the form @w{@code{(@var{group-name} @var{entries})}}, where
> >> >> @var{group-name} is a string inserted before all group entries, and
> >> >> @var{entries} have the same format as @code{tabulated-list-entries}
> >> >> (see above).
> >> >>
> >> >> Basically this says that the format is (group-name entries) where
> >> >> entries are described in tabulated-list-entries as having the format
> >> >> (id contents). There is no need to duplicate the description of entries.
> >> >
> >> > Maybe I'm missing something here. To put it more concretely, can you
> >> > show a value of tabulated-list-groups that will cause the buffers in
> >> > buffer list grouped by major mode using the above form?
> >>
> >> Data structure for `tabulated-list-groups' is a list of elements,
> >> each element should of the form
> >>
> >> (GROUP-NAME (ID . CONTENTS) (ID . CONTENTS) ...)
> >>
> >> where GROUP-NAME is the name of the group, ID is a Lisp object that
> >> identifies the entry and CONTENTS is a vector with the same number of
> >> elements as `tabulated-list-format'. When buffers grouped by major mode:
> >>
> >> (("* Lisp Interaction" (#<buffer *scratch*> ["." " " "*" #("*scratch*" 0 9 ...) "225" "Lisp Interaction" ""]) ...))
> >
> > This is the value that the user is supposed to supply for the
> > defcustom? That is, the user must specify all the buffers explicitly?
> > What happens when there's one more buffer in some mode? does the user
> > have then to modify the value of the defcustom?
>
> This describes the internal data structure, not a defcustom.
Well, my question above, viz.:
>> > Maybe I'm missing something here. To put it more concretely, can you
>> > show a value of tabulated-list-groups that will cause the buffers in
>> > buffer list grouped by major mode using the above form?
was about the value of this defcustom. I hoped that by having such a
value as part of this discussion, we will be able to clear any
misunderstandings that could be getting in the way.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-25 17:36 ` Juri Linkov
@ 2024-02-26 3:31 ` Adam Porter
2024-03-06 17:37 ` Juri Linkov
0 siblings, 1 reply; 37+ messages in thread
From: Adam Porter @ 2024-02-26 3:31 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305, Eli Zaretskii, Ihor Radchenko
[-- Attachment #1: Type: text/plain, Size: 2010 bytes --]
Hi Juri,
On 2/25/24 11:36, Juri Linkov wrote:
>> So if you were to use one of these as inspiration (or as a library
>> directly), I'd strongly recommend using `taxy', as that's what it's
>> designed for.
>> [...]
>> Let me know if I can help facilitate a solution using it, or help anyone
>> work with the API.
>
> Thanks for proposing help, but for inspiration I'm using
> my own package https://github.com/link0ff/emacs-ee
> It's much more powerful than anything I have seen so far.
> But on the other hand, it became so unmanageable
> that I semi-abandoned it due to its overly complexity.
Taxy might be able to help with that, because it's designed to simply
abstract the matter of classifying data into hierarchies. It's only 381
lines of code, which includes macros that allow applications to define
their own, user-extensible grouping languages with top-level forms.
UI frontends to render the data structures are separated from the
concern of grouping. A simple "pretty print" one is provided, but the
main implementation so far is the associated library, taxy-magit-section.
> Is your package more light-weight than mine? I doubt it ;-)
Well, judge for yourself. :) Attached is a file that provides a simple
buffer-grouping command based on Taxy. It's what I would call a "level
one" implementation, without defining a DSL or user-customizeable
grouping. Adding those features would only take a few more lines of
code, but I'm keeping this example as simple as possible. This only
takes 41 lines of code. It produces a view as seen in the attached
screenshot. And it only took about 5 minutes to write by modifying a
similar example that works on another kind of object.
Anyway, I'm not necessarily pushing a solution here, only trying to
share what's available. I did spend a lot of time on this project, and
IMHO it solves the problem elegantly and powerfully, so I would like to
see it applied more widely, but things included with Emacs itself are
another matter.
[-- Attachment #2: buffery.el --]
[-- Type: text/x-emacs-lisp, Size: 2305 bytes --]
;;; buffery.el --- Buffer view with Taxy grouping -*- lexical-binding: t; -*-
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'cl-lib)
(require 'project)
(require 'taxy)
(require 'taxy-magit-section)
(defvar buffery-taxy
(cl-labels ((directory (buffer)
(buffer-local-value 'default-directory buffer))
(mode (buffer)
(prin1-to-string (buffer-local-value 'major-mode buffer)))
(project (buffer)
(with-current-buffer buffer
(when-let ((project (project-current)))
(project-root project))))
(specialp (buffer)
(when (not (buffer-file-name buffer))
"*special*"))
(make-fn (&rest args)
(apply #'make-taxy-magit-section
:make #'make-fn
:format-fn #'buffer-name
args)))
(make-fn
:name "Buffers"
:take (apply-partially #'taxy-take-keyed
(list (list #'project)
(list #'specialp)
#'directory #'mode)))))
(defun buffery ()
(interactive)
(let* ((buffers (buffer-list))
(buffer (get-buffer-create "*Buffery*"))
(inhibit-read-only t))
(with-current-buffer buffer
(erase-buffer)
(thread-last buffery-taxy
taxy-emptied
(taxy-fill buffers)
(taxy-sort* #'string< #'taxy-name)
taxy-magit-section-insert))
(pop-to-buffer buffer)))
(provide 'buffery)
;;; buffery.el ends here
[-- Attachment #3: example.png --]
[-- Type: image/png, Size: 63425 bytes --]
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-25 19:17 ` Eli Zaretskii
@ 2024-02-27 7:30 ` Juri Linkov
2024-02-27 8:31 ` Eli Zaretskii
0 siblings, 1 reply; 37+ messages in thread
From: Juri Linkov @ 2024-02-27 7:30 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 69305
>> >> >> Sorry, I don't understand what is unclear here:
>> >> >>
>> >> >> If the value is a list, each list element corresponds to one group, and
>> >> >> should have the form @w{@code{(@var{group-name} @var{entries})}}, where
>> >> >> @var{group-name} is a string inserted before all group entries, and
>> >> >> @var{entries} have the same format as @code{tabulated-list-entries}
>> >> >> (see above).
>> >> >>
>> >> >> Basically this says that the format is (group-name entries) where
>> >> >> entries are described in tabulated-list-entries as having the format
>> >> >> (id contents). There is no need to duplicate the description of entries.
>> >> >
>> >> > Maybe I'm missing something here. To put it more concretely, can you
>> >> > show a value of tabulated-list-groups that will cause the buffers in
>> >> > buffer list grouped by major mode using the above form?
>> >>
>> >> Data structure for `tabulated-list-groups' is a list of elements,
>> >> each element should of the form
>> >>
>> >> (GROUP-NAME (ID . CONTENTS) (ID . CONTENTS) ...)
>> >>
>> >> where GROUP-NAME is the name of the group, ID is a Lisp object that
>> >> identifies the entry and CONTENTS is a vector with the same number of
>> >> elements as `tabulated-list-format'. When buffers grouped by major mode:
>> >>
>> >> (("* Lisp Interaction" (#<buffer *scratch*> ["." " " "*" #("*scratch*" 0 9 ...) "225" "Lisp Interaction" ""]) ...))
>> >
>> > This is the value that the user is supposed to supply for the
>> > defcustom? That is, the user must specify all the buffers explicitly?
>> > What happens when there's one more buffer in some mode? does the user
>> > have then to modify the value of the defcustom?
>>
>> This describes the internal data structure, not a defcustom.
>
> Well, my question above, viz.:
>
>>> > Maybe I'm missing something here. To put it more concretely, can you
>>> > show a value of tabulated-list-groups that will cause the buffers in
>>> > buffer list grouped by major mode using the above form?
>
> was about the value of this defcustom. I hoped that by having such a
> value as part of this discussion, we will be able to clear any
> misunderstandings that could be getting in the way.
But tabulated-list-groups is not a defcustom.
There are no defcustoms here.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-27 7:30 ` Juri Linkov
@ 2024-02-27 8:31 ` Eli Zaretskii
2024-02-27 17:40 ` Juri Linkov
0 siblings, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-27 8:31 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305
> From: Juri Linkov <juri@linkov.net>
> Cc: 69305@debbugs.gnu.org
> Date: Tue, 27 Feb 2024 09:30:10 +0200
>
> >> >> >> Sorry, I don't understand what is unclear here:
> >> >> >>
> >> >> >> If the value is a list, each list element corresponds to one group, and
> >> >> >> should have the form @w{@code{(@var{group-name} @var{entries})}}, where
> >> >> >> @var{group-name} is a string inserted before all group entries, and
> >> >> >> @var{entries} have the same format as @code{tabulated-list-entries}
> >> >> >> (see above).
> >> >> >>
> >> >> >> Basically this says that the format is (group-name entries) where
> >> >> >> entries are described in tabulated-list-entries as having the format
> >> >> >> (id contents). There is no need to duplicate the description of entries.
> >> >> >
> >> >> > Maybe I'm missing something here. To put it more concretely, can you
> >> >> > show a value of tabulated-list-groups that will cause the buffers in
> >> >> > buffer list grouped by major mode using the above form?
> >> >>
> >> >> Data structure for `tabulated-list-groups' is a list of elements,
> >> >> each element should of the form
> >> >>
> >> >> (GROUP-NAME (ID . CONTENTS) (ID . CONTENTS) ...)
> >> >>
> >> >> where GROUP-NAME is the name of the group, ID is a Lisp object that
> >> >> identifies the entry and CONTENTS is a vector with the same number of
> >> >> elements as `tabulated-list-format'. When buffers grouped by major mode:
> >> >>
> >> >> (("* Lisp Interaction" (#<buffer *scratch*> ["." " " "*" #("*scratch*" 0 9 ...) "225" "Lisp Interaction" ""]) ...))
> >> >
> >> > This is the value that the user is supposed to supply for the
> >> > defcustom? That is, the user must specify all the buffers explicitly?
> >> > What happens when there's one more buffer in some mode? does the user
> >> > have then to modify the value of the defcustom?
> >>
> >> This describes the internal data structure, not a defcustom.
> >
> > Well, my question above, viz.:
> >
> >>> > Maybe I'm missing something here. To put it more concretely, can you
> >>> > show a value of tabulated-list-groups that will cause the buffers in
> >>> > buffer list grouped by major mode using the above form?
> >
> > was about the value of this defcustom. I hoped that by having such a
> > value as part of this discussion, we will be able to clear any
> > misunderstandings that could be getting in the way.
>
> But tabulated-list-groups is not a defcustom.
> There are no defcustoms here.
Buffer-menu-group-by _is_ a defcustom, and it is documented thusly:
+ "If non-nil, buffers are grouped by function.
+This function takes one argument: a list of entries in the same format
+as in `tabulated-list-entries', and should return a list in the format
+suitable for `tabulated-list-groups'.
So you are inviting users to write functions that return values of a
certain format, but the format's documentation IMO doesn't make it
clear how to specify a grouping, and for its important part alludes to
another variable (tabulated-list-entries), whose documentation is
suitable for different kind of uses, not for grouping of entries.
Since tabulated-list-groups is such an important part of the
documentation of Buffer-menu-group-by, the doc string of
tabulated-list-groups is in effect part of the doc string of
Buffer-menu-group-by, and should IMO be worded as appropriate for user
options.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-27 8:31 ` Eli Zaretskii
@ 2024-02-27 17:40 ` Juri Linkov
2024-02-27 18:44 ` Eli Zaretskii
0 siblings, 1 reply; 37+ messages in thread
From: Juri Linkov @ 2024-02-27 17:40 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 69305
>> >> >> >> Sorry, I don't understand what is unclear here:
>> >> >> >>
>> >> >> >> If the value is a list, each list element corresponds to one group, and
>> >> >> >> should have the form @w{@code{(@var{group-name} @var{entries})}}, where
>> >> >> >> @var{group-name} is a string inserted before all group entries, and
>> >> >> >> @var{entries} have the same format as @code{tabulated-list-entries}
>> >> >> >> (see above).
>> >> >> >>
>> >> >> >> Basically this says that the format is (group-name entries) where
>> >> >> >> entries are described in tabulated-list-entries as having the format
>> >> >> >> (id contents). There is no need to duplicate the description of entries.
>> >> >> >
>> >> >> > Maybe I'm missing something here. To put it more concretely, can you
>> >> >> > show a value of tabulated-list-groups that will cause the buffers in
>> >> >> > buffer list grouped by major mode using the above form?
>> >> >>
>> >> >> Data structure for `tabulated-list-groups' is a list of elements,
>> >> >> each element should of the form
>> >> >>
>> >> >> (GROUP-NAME (ID . CONTENTS) (ID . CONTENTS) ...)
>> >> >>
>> >> >> where GROUP-NAME is the name of the group, ID is a Lisp object that
>> >> >> identifies the entry and CONTENTS is a vector with the same number of
>> >> >> elements as `tabulated-list-format'. When buffers grouped by major mode:
>> >> >>
>> >> >> (("* Lisp Interaction" (#<buffer *scratch*> ["." " " "*" #("*scratch*" 0 9 ...) "225" "Lisp Interaction" ""]) ...))
>> >> >
>> >> > This is the value that the user is supposed to supply for the
>> >> > defcustom? That is, the user must specify all the buffers explicitly?
>> >> > What happens when there's one more buffer in some mode? does the user
>> >> > have then to modify the value of the defcustom?
>> >>
>> >> This describes the internal data structure, not a defcustom.
>> >
>> > Well, my question above, viz.:
>> >
>> >>> > Maybe I'm missing something here. To put it more concretely, can you
>> >>> > show a value of tabulated-list-groups that will cause the buffers in
>> >>> > buffer list grouped by major mode using the above form?
>> >
>> > was about the value of this defcustom. I hoped that by having such a
>> > value as part of this discussion, we will be able to clear any
>> > misunderstandings that could be getting in the way.
>>
>> But tabulated-list-groups is not a defcustom.
>> There are no defcustoms here.
>
> Buffer-menu-group-by _is_ a defcustom, and it is documented thusly:
>
> + "If non-nil, buffers are grouped by function.
> +This function takes one argument: a list of entries in the same format
> +as in `tabulated-list-entries', and should return a list in the format
> +suitable for `tabulated-list-groups'.
>
> So you are inviting users to write functions that return values of a
> certain format, but the format's documentation IMO doesn't make it
> clear how to specify a grouping, and for its important part alludes to
> another variable (tabulated-list-entries), whose documentation is
> suitable for different kind of uses, not for grouping of entries.
The format 'tabulated-list-entries' is input.
The format 'tabulated-list-groups' is output.
> Since tabulated-list-groups is such an important part of the
> documentation of Buffer-menu-group-by, the doc string of
> tabulated-list-groups is in effect part of the doc string of
> Buffer-menu-group-by, and should IMO be worded as appropriate for user
> options.
The docstring of 'tabulated-list-groups' already
sufficiently documents the format:
(defvar-local tabulated-list-groups nil
"Groups displayed in the current Tabulated List buffer.
This should be either a function, or a list.
If a list, each element has the form (GROUP-NAME ENTRIES),
where:
- GROUP-NAME is a group name as a string, which is displayed
at the top line of each group.
- ENTRIES is a list described in `tabulated-list-entries'.
There is no need to duplicate the description of linked
'tabulated-list-entries'. And here it's clear that the function
should add GROUP-NAME to groups from 'tabulated-list-entries'.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-27 17:40 ` Juri Linkov
@ 2024-02-27 18:44 ` Eli Zaretskii
2024-02-28 7:36 ` Juri Linkov
0 siblings, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-27 18:44 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305
> From: Juri Linkov <juri@linkov.net>
> Cc: 69305@debbugs.gnu.org
> Date: Tue, 27 Feb 2024 19:40:10 +0200
>
> >> But tabulated-list-groups is not a defcustom.
> >> There are no defcustoms here.
> >
> > Buffer-menu-group-by _is_ a defcustom, and it is documented thusly:
> >
> > + "If non-nil, buffers are grouped by function.
> > +This function takes one argument: a list of entries in the same format
> > +as in `tabulated-list-entries', and should return a list in the format
> > +suitable for `tabulated-list-groups'.
> >
> > So you are inviting users to write functions that return values of a
> > certain format, but the format's documentation IMO doesn't make it
> > clear how to specify a grouping, and for its important part alludes to
> > another variable (tabulated-list-entries), whose documentation is
> > suitable for different kind of uses, not for grouping of entries.
>
> The format 'tabulated-list-entries' is input.
> The format 'tabulated-list-groups' is output.
Yes, I'm well aware of that.
> > Since tabulated-list-groups is such an important part of the
> > documentation of Buffer-menu-group-by, the doc string of
> > tabulated-list-groups is in effect part of the doc string of
> > Buffer-menu-group-by, and should IMO be worded as appropriate for user
> > options.
>
> The docstring of 'tabulated-list-groups' already
> sufficiently documents the format:
No, it doesn't document it sufficiently. As I already said several
times.
> (defvar-local tabulated-list-groups nil
> "Groups displayed in the current Tabulated List buffer.
> This should be either a function, or a list.
> If a list, each element has the form (GROUP-NAME ENTRIES),
> where:
>
> - GROUP-NAME is a group name as a string, which is displayed
> at the top line of each group.
>
> - ENTRIES is a list described in `tabulated-list-entries'.
>
> There is no need to duplicate the description of linked
> 'tabulated-list-entries'.
This is not about duplication. This is about adding information that
currently isn't there.
> And here it's clear that the function should add GROUP-NAME to
> groups from 'tabulated-list-entries'.
Which doesn't clarify the issue at hand even a single bit.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-27 18:44 ` Eli Zaretskii
@ 2024-02-28 7:36 ` Juri Linkov
2024-02-28 12:16 ` Eli Zaretskii
0 siblings, 1 reply; 37+ messages in thread
From: Juri Linkov @ 2024-02-28 7:36 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 69305
>> >> But tabulated-list-groups is not a defcustom.
>> >> There are no defcustoms here.
>> >
>> > Buffer-menu-group-by _is_ a defcustom, and it is documented thusly:
>> >
>> > + "If non-nil, buffers are grouped by function.
>> > +This function takes one argument: a list of entries in the same format
>> > +as in `tabulated-list-entries', and should return a list in the format
>> > +suitable for `tabulated-list-groups'.
>> >
>> > So you are inviting users to write functions that return values of a
>> > certain format, but the format's documentation IMO doesn't make it
>> > clear how to specify a grouping, and for its important part alludes to
>> > another variable (tabulated-list-entries), whose documentation is
>> > suitable for different kind of uses, not for grouping of entries.
>>
>> The format 'tabulated-list-entries' is input.
>> The format 'tabulated-list-groups' is output.
>
> Yes, I'm well aware of that.
>
>> > Since tabulated-list-groups is such an important part of the
>> > documentation of Buffer-menu-group-by, the doc string of
>> > tabulated-list-groups is in effect part of the doc string of
>> > Buffer-menu-group-by, and should IMO be worded as appropriate for user
>> > options.
>>
>> The docstring of 'tabulated-list-groups' already
>> sufficiently documents the format:
>
> No, it doesn't document it sufficiently. As I already said several
> times.
>
>> (defvar-local tabulated-list-groups nil
>> "Groups displayed in the current Tabulated List buffer.
>> This should be either a function, or a list.
>> If a list, each element has the form (GROUP-NAME ENTRIES),
>> where:
>>
>> - GROUP-NAME is a group name as a string, which is displayed
>> at the top line of each group.
>>
>> - ENTRIES is a list described in `tabulated-list-entries'.
>>
>> There is no need to duplicate the description of linked
>> 'tabulated-list-entries'.
>
> This is not about duplication. This is about adding information that
> currently isn't there.
>
>> And here it's clear that the function should add GROUP-NAME to
>> groups from 'tabulated-list-entries'.
>
> Which doesn't clarify the issue at hand even a single bit.
Sorry, I don't understand what is missing here.
Please show an example of changes that you want.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-28 7:36 ` Juri Linkov
@ 2024-02-28 12:16 ` Eli Zaretskii
2024-02-29 7:45 ` Juri Linkov
0 siblings, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-28 12:16 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305
> From: Juri Linkov <juri@linkov.net>
> Cc: 69305@debbugs.gnu.org
> Date: Wed, 28 Feb 2024 09:36:30 +0200
>
> >> >> But tabulated-list-groups is not a defcustom.
> >> >> There are no defcustoms here.
> >> >
> >> > Buffer-menu-group-by _is_ a defcustom, and it is documented thusly:
> >> >
> >> > + "If non-nil, buffers are grouped by function.
> >> > +This function takes one argument: a list of entries in the same format
> >> > +as in `tabulated-list-entries', and should return a list in the format
> >> > +suitable for `tabulated-list-groups'.
> >> >
> >> > So you are inviting users to write functions that return values of a
> >> > certain format, but the format's documentation IMO doesn't make it
> >> > clear how to specify a grouping, and for its important part alludes to
> >> > another variable (tabulated-list-entries), whose documentation is
> >> > suitable for different kind of uses, not for grouping of entries.
> >>
> >> The format 'tabulated-list-entries' is input.
> >> The format 'tabulated-list-groups' is output.
> >
> > Yes, I'm well aware of that.
> >
> >> > Since tabulated-list-groups is such an important part of the
> >> > documentation of Buffer-menu-group-by, the doc string of
> >> > tabulated-list-groups is in effect part of the doc string of
> >> > Buffer-menu-group-by, and should IMO be worded as appropriate for user
> >> > options.
> >>
> >> The docstring of 'tabulated-list-groups' already
> >> sufficiently documents the format:
> >
> > No, it doesn't document it sufficiently. As I already said several
> > times.
> >
> >> (defvar-local tabulated-list-groups nil
> >> "Groups displayed in the current Tabulated List buffer.
> >> This should be either a function, or a list.
> >> If a list, each element has the form (GROUP-NAME ENTRIES),
> >> where:
> >>
> >> - GROUP-NAME is a group name as a string, which is displayed
> >> at the top line of each group.
> >>
> >> - ENTRIES is a list described in `tabulated-list-entries'.
> >>
> >> There is no need to duplicate the description of linked
> >> 'tabulated-list-entries'.
> >
> > This is not about duplication. This is about adding information that
> > currently isn't there.
> >
> >> And here it's clear that the function should add GROUP-NAME to
> >> groups from 'tabulated-list-entries'.
> >
> > Which doesn't clarify the issue at hand even a single bit.
>
> Sorry, I don't understand what is missing here.
> Please show an example of changes that you want.
Sorry, I cannot show an example of something whose use I don't
understand. Which is why I asked _you_ to show an example: how to set
up Buffer-menu-group-by to group buffers by major-mode.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-28 12:16 ` Eli Zaretskii
@ 2024-02-29 7:45 ` Juri Linkov
2024-02-29 16:33 ` Eli Zaretskii
0 siblings, 1 reply; 37+ messages in thread
From: Juri Linkov @ 2024-02-29 7:45 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 69305
>> >> >> But tabulated-list-groups is not a defcustom.
>> >> >> There are no defcustoms here.
>> >> >
>> >> > Buffer-menu-group-by _is_ a defcustom, and it is documented thusly:
>> >> >
>> >> > + "If non-nil, buffers are grouped by function.
>> >> > +This function takes one argument: a list of entries in the same format
>> >> > +as in `tabulated-list-entries', and should return a list in the format
>> >> > +suitable for `tabulated-list-groups'.
>> >> >
>> >> > So you are inviting users to write functions that return values of a
>> >> > certain format, but the format's documentation IMO doesn't make it
>> >> > clear how to specify a grouping, and for its important part alludes to
>> >> > another variable (tabulated-list-entries), whose documentation is
>> >> > suitable for different kind of uses, not for grouping of entries.
>> >>
>> >> The format 'tabulated-list-entries' is input.
>> >> The format 'tabulated-list-groups' is output.
>> >
>> > Yes, I'm well aware of that.
>> >
>> >> > Since tabulated-list-groups is such an important part of the
>> >> > documentation of Buffer-menu-group-by, the doc string of
>> >> > tabulated-list-groups is in effect part of the doc string of
>> >> > Buffer-menu-group-by, and should IMO be worded as appropriate for user
>> >> > options.
>> >>
>> >> The docstring of 'tabulated-list-groups' already
>> >> sufficiently documents the format:
>> >
>> > No, it doesn't document it sufficiently. As I already said several
>> > times.
>> >
>> >> (defvar-local tabulated-list-groups nil
>> >> "Groups displayed in the current Tabulated List buffer.
>> >> This should be either a function, or a list.
>> >> If a list, each element has the form (GROUP-NAME ENTRIES),
>> >> where:
>> >>
>> >> - GROUP-NAME is a group name as a string, which is displayed
>> >> at the top line of each group.
>> >>
>> >> - ENTRIES is a list described in `tabulated-list-entries'.
>> >>
>> >> There is no need to duplicate the description of linked
>> >> 'tabulated-list-entries'.
>> >
>> > This is not about duplication. This is about adding information that
>> > currently isn't there.
>> >
>> >> And here it's clear that the function should add GROUP-NAME to
>> >> groups from 'tabulated-list-entries'.
>> >
>> > Which doesn't clarify the issue at hand even a single bit.
>>
>> Sorry, I don't understand what is missing here.
>> Please show an example of changes that you want.
>
> Sorry, I cannot show an example of something whose use I don't
> understand. Which is why I asked _you_ to show an example: how to set
> up Buffer-menu-group-by to group buffers by major-mode.
Ah, you wanted to include a buffer example in "Tabulated List Mode".
Ok, here it is:
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 630e42e6878..e79b73eb081 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -1246,6 +1246,41 @@ Tabulated List Mode
above form when called with no arguments.
@end defvar
+@defvar tabulated-list-groups
+This buffer-local variable specifies the groups of entries displayed in
+the Tabulated List buffer. Its value should be either a list, or a
+function.
+
+If the value is a list, each list element corresponds to one group, and
+should have the form @w{@code{(@var{group-name} @var{entries})}}, where
+@var{group-name} is a string inserted before all group entries, and
+@var{entries} have the same format as @code{tabulated-list-entries}
+(see above).
+
+Otherwise, the value should be a function which returns a list of the
+above form when called with no arguments.
+@end defvar
+
+You can use @code{seq-group-by} to create @code{tabulated-list-groups}
+from @code{tabulated-list-entries}. For example:
+
+@smallexample
+@group
+ (setq tabulated-list-groups
+ (seq-group-by 'Buffer-menu-group-by-mode
+ tabulated-list-entries))
+@end group
+@end smallexample
+
+where you can define @code{Buffer-menu-group-by-mode} like this:
+
+@smallexample
+@group
+(defun Buffer-menu-group-by-mode (entry)
+ (concat "* " (aref (cadr entry) 5)))
+@end group
+@end smallexample
+
@defvar tabulated-list-revert-hook
This normal hook is run prior to reverting a Tabulated List buffer. A
derived mode can add a function to this hook to recompute
^ permalink raw reply related [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-29 7:45 ` Juri Linkov
@ 2024-02-29 16:33 ` Eli Zaretskii
2024-02-29 17:50 ` Juri Linkov
0 siblings, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2024-02-29 16:33 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305
> From: Juri Linkov <juri@linkov.net>
> Cc: 69305@debbugs.gnu.org
> Date: Thu, 29 Feb 2024 09:45:00 +0200
>
> > Sorry, I cannot show an example of something whose use I don't
> > understand. Which is why I asked _you_ to show an example: how to set
> > up Buffer-menu-group-by to group buffers by major-mode.
>
> Ah, you wanted to include a buffer example in "Tabulated List Mode".
> Ok, here it is:
Thanks!
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-29 16:33 ` Eli Zaretskii
@ 2024-02-29 17:50 ` Juri Linkov
2024-03-03 6:53 ` Jean Louis
0 siblings, 1 reply; 37+ messages in thread
From: Juri Linkov @ 2024-02-29 17:50 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 69305
close 69305 30.0.50
thanks
>> Ok, here it is:
>
> Thanks!
So now pushed to master.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-29 17:50 ` Juri Linkov
@ 2024-03-03 6:53 ` Jean Louis
2024-03-03 7:52 ` Juri Linkov
0 siblings, 1 reply; 37+ messages in thread
From: Jean Louis @ 2024-03-03 6:53 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305, Eli Zaretskii
* Juri Linkov <juri@linkov.net> [2024-02-29 20:54]:
> close 69305 30.0.50
> thanks
>
> >> Ok, here it is:
> >
> > Thanks!
>
> So now pushed to master.
I hope that the new change will not affect the standard functionality of tabulated-list-mode which I use heavily.
Major grouping of tabulated-list-mode is by columns, not by rows, so I really wonder what will happen in the new outline-minor-mode for tabulated-list-mode when it is active and then user sort it by column
In my opinion tabulated shall remain tabulated, but I wish to see what is benefit of outline-minor-mode as I cannot understand it yet.
Jean
Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns
In support of Richard M. Stallman
https://stallmansupport.org/
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-03-03 6:53 ` Jean Louis
@ 2024-03-03 7:52 ` Juri Linkov
0 siblings, 0 replies; 37+ messages in thread
From: Juri Linkov @ 2024-03-03 7:52 UTC (permalink / raw)
To: Jean Louis; +Cc: 69305, Eli Zaretskii
> I hope that the new change will not affect the standard functionality
> of tabulated-list-mode which I use heavily.
Indeed, it should not affect the default behavior.
> Major grouping of tabulated-list-mode is by columns, not by rows, so
> I really wonder what will happen in the new outline-minor-mode for
> tabulated-list-mode when it is active and then user sort it by column
When sorted by column then rows in all groups will be sorted
by the same column.
> In my opinion tabulated shall remain tabulated, but I wish to see what
> is benefit of outline-minor-mode as I cannot understand it yet.
Rest assured, tabulated will remain tabulated, just outline heading lines
are added between groups.
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-02-26 3:31 ` Adam Porter
@ 2024-03-06 17:37 ` Juri Linkov
2024-03-08 23:13 ` Adam Porter
0 siblings, 1 reply; 37+ messages in thread
From: Juri Linkov @ 2024-03-06 17:37 UTC (permalink / raw)
To: Adam Porter; +Cc: 69305, Eli Zaretskii, Ihor Radchenko
> (defvar buffery-taxy
> (cl-labels ((directory (buffer)
> (buffer-local-value 'default-directory buffer))
> (mode (buffer)
> (prin1-to-string (buffer-local-value 'major-mode buffer)))
> (project (buffer)
> (with-current-buffer buffer
> (when-let ((project (project-current)))
> (project-root project))))
> (specialp (buffer)
> (when (not (buffer-file-name buffer))
> "*special*"))
> (make-fn (&rest args)
> (apply #'make-taxy-magit-section
> :make #'make-fn
> :format-fn #'buffer-name
> args)))
> (make-fn
> :name "Buffers"
> :take (apply-partially #'taxy-take-keyed
> (list (list #'project)
> (list #'specialp)
> #'directory #'mode)))))
Thanks for the good example. This is how the same
is achieved with 'Buffer-menu-group-by':
#+begin_src emacs-lisp
(setq Buffer-menu-group-by
(lambda (b)
(concat "* "
(or
(with-current-buffer (car b)
(when-let ((project (project-current)))
(project-root project)))
(when (not (buffer-file-name (car b)))
"*special*")
(buffer-local-value 'default-directory (car b))
(aref (cadr b) 5)))))
#+end_src
^ permalink raw reply [flat|nested] 37+ messages in thread
* bug#69305: outline-minor-mode for tabulated-list-mode
2024-03-06 17:37 ` Juri Linkov
@ 2024-03-08 23:13 ` Adam Porter
0 siblings, 0 replies; 37+ messages in thread
From: Adam Porter @ 2024-03-08 23:13 UTC (permalink / raw)
To: Juri Linkov; +Cc: 69305, Eli Zaretskii, Ihor Radchenko
Hi Juri,
On 3/6/24 11:37, Juri Linkov wrote:
>> (defvar buffery-taxy
>> (cl-labels ((directory (buffer)
>> (buffer-local-value 'default-directory buffer))
>> (mode (buffer)
>> (prin1-to-string (buffer-local-value 'major-mode buffer)))
>> (project (buffer)
>> (with-current-buffer buffer
>> (when-let ((project (project-current)))
>> (project-root project))))
>> (specialp (buffer)
>> (when (not (buffer-file-name buffer))
>> "*special*"))
>> (make-fn (&rest args)
>> (apply #'make-taxy-magit-section
>> :make #'make-fn
>> :format-fn #'buffer-name
>> args)))
>> (make-fn
>> :name "Buffers"
>> :take (apply-partially #'taxy-take-keyed
>> (list (list #'project)
>> (list #'specialp)
>> #'directory #'mode)))))
>
> Thanks for the good example. This is how the same
> is achieved with 'Buffer-menu-group-by':
>
> #+begin_src emacs-lisp
> (setq Buffer-menu-group-by
> (lambda (b)
> (concat "* "
> (or
> (with-current-buffer (car b)
> (when-let ((project (project-current)))
> (project-root project)))
> (when (not (buffer-file-name (car b)))
> "*special*")
> (buffer-local-value 'default-directory (car b))
> (aref (cadr b) 5)))))
> #+end_src
Please note that that does not produce the same result. Your example
produces one level of grouping. Taxy, when used with `taxy-take-keyed',
produces dynamically nested groups according to the list of key
functions and their nesting.
The Taxy documentation describes these features extensively, with examples:
https://github.com/alphapapa/taxy.el#dynamic-taxys
^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2024-03-08 23:13 UTC | newest]
Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-21 17:34 bug#69305: outline-minor-mode for tabulated-list-mode Juri Linkov
2024-02-21 19:12 ` Eli Zaretskii
2024-02-22 7:44 ` Juri Linkov
2024-02-22 8:20 ` Eli Zaretskii
2024-02-22 17:30 ` Juri Linkov
2024-02-22 19:10 ` Eli Zaretskii
2024-02-23 7:09 ` Juri Linkov
2024-02-23 8:13 ` Eli Zaretskii
2024-02-24 17:43 ` Juri Linkov
2024-02-24 18:09 ` Eli Zaretskii
2024-02-24 18:13 ` Eli Zaretskii
2024-02-25 8:00 ` Adam Porter
2024-02-25 17:25 ` Juri Linkov
2024-02-25 19:17 ` Eli Zaretskii
2024-02-27 7:30 ` Juri Linkov
2024-02-27 8:31 ` Eli Zaretskii
2024-02-27 17:40 ` Juri Linkov
2024-02-27 18:44 ` Eli Zaretskii
2024-02-28 7:36 ` Juri Linkov
2024-02-28 12:16 ` Eli Zaretskii
2024-02-29 7:45 ` Juri Linkov
2024-02-29 16:33 ` Eli Zaretskii
2024-02-29 17:50 ` Juri Linkov
2024-03-03 6:53 ` Jean Louis
2024-03-03 7:52 ` Juri Linkov
2024-02-24 18:06 ` Ihor Radchenko
2024-02-24 18:16 ` Eli Zaretskii
2024-02-24 18:36 ` Ihor Radchenko
2024-02-24 18:49 ` Eli Zaretskii
2024-02-25 7:45 ` Adam Porter
2024-02-25 17:36 ` Juri Linkov
2024-02-26 3:31 ` Adam Porter
2024-03-06 17:37 ` Juri Linkov
2024-03-08 23:13 ` Adam Porter
2024-02-25 7:53 ` Adam Porter
2024-02-25 8:26 ` Eli Zaretskii
2024-02-25 17:20 ` Juri Linkov
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.