unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#45361: 28.0.50; tabulated-list-mode: should be sorting by specified sort function
@ 2020-12-22  7:13 Jean Louis
  2020-12-22  9:31 ` Stephen Berman
  0 siblings, 1 reply; 3+ messages in thread
From: Jean Louis @ 2020-12-22  7:13 UTC (permalink / raw)
  To: 45361



PROBLEM:

The variable `tabulated-list-format' provides for programmer
option to sort columns and I would like to sort number as
strings "12" as numbers, not as strings. I do not know how to
properly provide the sorting function to `tabulated-list-format' so
that it works when actually sorting.

DATA:

The tabulated list mode works as this:

(let ((buffer "*tabulated*"))
  (switch-to-buffer-other-window buffer)
  (setq tabulated-list-format [("Count" 10 t :right-align t) ("Name" 60 t)])
  (setq tabulated-list-entries '((6 ["6" "Mercury"])
				 (7 ["7" "GNU Emacs"])
				 (8 ["8" "YouTube Videos"])
				 (9 ["9" "Speedy worker cleaning tables in a restaurant"])
				 (71 ["71" "Trenching"])
				 (82 ["82" "Easier trenching idea"])))
  (tabulated-list-mode)
  (tabulated-list-init-header)
  (hl-line-mode)
  (tabulated-list-print))

When evaluated I would get the list such as:

         6 Mercury
         7 GNU Emacs
        71 Trenching
         8 YouTube Videos
        82 Easier trenching idea
         9 Speedy worker cleaning tables in a restaurant

and my goal would be to be able to sort the column "Count" so
that I get a result sorted by the number (which is string):

         6 Mercury
         7 GNU Emacs
         8 YouTube Videos
         9 Speedy worker cleaning tables in a restaurant
        71 Trenching
        82 Easier trenching idea


The description of `tabulated-list-format' says:

The format of the current Tabulated List mode buffer.
This should be a vector of elements (NAME WIDTH SORT . PROPS),
where:
 - NAME is a string describing the column.
   This is the label for the column in the header line.
   Different columns must have non-‘equal’ names.
 - WIDTH is the width to reserve for the column.
   For the final element, its numerical value is ignored.
 - SORT specifies how to sort entries by this column.
   If nil, this column cannot be used for sorting.
   If t, sort by comparing the string value printed in the column.
   Otherwise, it should be a predicate function suitable for
   ‘sort’, accepting arguments with the same form as the elements
   of ‘tabulated-list-entries’.

I could make a function to list what elements are accepted on click:

(defun my-sort (&rest args)
  (message "%s" args))

and include it here:

(let ((buffer "*tabulated*"))
  (switch-to-buffer-other-window buffer)
  (setq tabulated-list-format [("Count" 10 my-sort :right-align t) ("Name" 60 t)])
  (setq tabulated-list-entries '((1 ["6" "Mercury"])
				 (2 ["7" "GNU Emacs"])
				 (3 ["8" "YouTube Videos"])
				 (4 ["9" "Speedy worker cleaning tables in a restaurant"])
				 (5 ["71" "Trenching"])
				 (6 ["82" "Easier trenching idea"])))
  (tabulated-list-mode)
  (tabulated-list-init-header)
  (hl-line-mode)
  (tabulated-list-print))

Then I can see something like this in `*Messages*' buffer:

((6 [82 Easier trenching idea]) (5 [71 Trenching]))
((6 [82 Easier trenching idea]) (4 [9 Speedy worker cleaning tables in a restaurant]))
((5 [71 Trenching]) (4 [9 Speedy worker cleaning tables in a restaurant]))
((3 [8 YouTube Videos]) (2 [7 GNU Emacs]))
((3 [8 YouTube Videos]) (1 [6 Mercury]))
((2 [7 GNU Emacs]) (1 [6 Mercury]))
((6 [82 Easier trenching idea]) (3 [8 YouTube Videos]))
((5 [71 Trenching]) (3 [8 YouTube Videos]))
((4 [9 Speedy worker cleaning tables in a restaurant]) (3 [8 YouTube Videos]))

Then I would like to use the function `string-collate-lessp' as that
seem to understand how numbers should be compared.

For example this is giving me correct result:

(sort '("121" "117" "1") 'string-collate-lessp) => ("1" "117" "121")

Then I am attempting to make the sorting function:

(defun my-sort (s1 s2)
  (let* ((s1-number (elt (cadr s1) 0))
	 (s2-number (elt (cadr s2) 0)))
    (string-collate-lessp s1-number s2-number)))

(my-sort '(2 ["7" "GNU Emacs"]) '(1 ["6" "Mercury"]))

Now this works well first time as when the list is displayed it is
already sorted by "Count":

(let ((buffer "*tabulated*"))
  (switch-to-buffer-other-window buffer)
  (setq tabulated-list-format [("Count" 10 my-sort :right-align t) ("Name" 60 nil)])
  (setq tabulated-list-entries '((1 ["6" "Mercury"])
				 (2 ["7" "GNU Emacs"])
				 (3 ["8" "YouTube Videos"])
				 (4 ["9" "Speedy worker cleaning tables in a restaurant"])
				 (5 ["71" "Trenching"])
				 (6 ["82" "Easier trenching idea"])))
  (tabulated-list-mode)
  (tabulated-list-init-header)
  (hl-line-mode)
  (tabulated-list-print))

But when I click on "Count" column or press S then it again gets
sorted rather alphabetic, not by using my function.

That is where I would need help to understand what is happening.

Because when I press S in the column "Count" when cursor is on the number, it invokes this function:

(defun tabulated-list-sort (&optional n)
  "Sort Tabulated List entries by the column at point.
With a numeric prefix argument N, sort the Nth column."
  (interactive "P")
  (let ((name (if n
		  (car (aref tabulated-list-format n))
		(get-text-property (point)
				   'tabulated-list-column-name))))
    (if (nth 2 (assoc name (append tabulated-list-format nil)))
        (tabulated-list--sort-by-column-name name)
      (user-error "Cannot sort by %s" name))))

Then this one:

(defun tabulated-list--sort-by-column-name (name)
  (when (and name (derived-mode-p 'tabulated-list-mode))
    ;; Flip the sort order on a second click.
    (if (equal name (car tabulated-list-sort-key))
	(setcdr tabulated-list-sort-key
		(not (cdr tabulated-list-sort-key)))
      (setq tabulated-list-sort-key (cons name nil)))
    (tabulated-list-init-header)
    (tabulated-list-print t)))

And if I read well those functions do not search for my function and
invoke `my-sort', but they should. Am I right there?

Jean



In GNU Emacs 28.0.50 (build 2, x86_64-pc-linux-gnu, X toolkit, cairo version 1.14.8, Xaw3d scroll bars)
 of 2020-11-25 built on protected.rcdrun.com
Repository revision: 30c437752df0a3a9410f1249fa0f237110811af2
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.11907000
System Description: Hyperbola GNU/Linux-libre

Configured using:
 'configure --prefix=/package/text/emacs --with-modules
 --with-x-toolkit=lucid'

Configured features:
XAW3D XPM JPEG TIFF GIF PNG RSVG CAIRO SOUND GPM DBUS GSETTINGS GLIB
NOTIFY INOTIFY ACL GNUTLS LIBXML2 FREETYPE HARFBUZZ M17N_FLT LIBOTF
ZLIB TOOLKIT_SCROLL_BARS LUCID X11 XDBE XIM MODULES THREADS JSON
PDUMPER LCMS2

Important settings:
  value of $LC_ALL: en_US.UTF-8
  value of $LANG: de_DE.UTF-8
  value of $XMODIFIERS: @im=exwm-xim
  locale-coding-system: utf-8-unix


-- 
Thanks,
Jean Louis
⎔ λ 🄯 𝍄 𝌡 𝌚





^ permalink raw reply	[flat|nested] 3+ messages in thread

* bug#45361: 28.0.50; tabulated-list-mode: should be sorting by specified sort function
  2020-12-22  7:13 bug#45361: 28.0.50; tabulated-list-mode: should be sorting by specified sort function Jean Louis
@ 2020-12-22  9:31 ` Stephen Berman
  2020-12-22  9:43   ` Jean Louis
  0 siblings, 1 reply; 3+ messages in thread
From: Stephen Berman @ 2020-12-22  9:31 UTC (permalink / raw)
  To: Jean Louis; +Cc: 45361

On Tue, 22 Dec 2020 08:13:50 +0100 Jean Louis <bugs@gnu.support> wrote:

> PROBLEM:
>
> The variable `tabulated-list-format' provides for programmer
> option to sort columns and I would like to sort number as
> strings "12" as numbers, not as strings. I do not know how to
> properly provide the sorting function to `tabulated-list-format' so
> that it works when actually sorting.
[...]
> Then I would like to use the function `string-collate-lessp' as that
> seem to understand how numbers should be compared.
>
> For example this is giving me correct result:
>
> (sort '("121" "117" "1") 'string-collate-lessp) => ("1" "117" "121")

But:

(sort '("21" "117" "1") 'string-collate-lessp) => ("1" "117" "21")

So string-collate-lessp doesn't do what it seems you want.

[...]
> But when I click on "Count" column or press S then it again gets
> sorted rather alphabetic, not by using my function.
>
> That is where I would need help to understand what is happening.
>
> Because when I press S in the column "Count" when cursor is on the number, it invokes this function:
>
> (defun tabulated-list-sort (&optional n)
>   "Sort Tabulated List entries by the column at point.
> With a numeric prefix argument N, sort the Nth column."
>   (interactive "P")
>   (let ((name (if n
> 		  (car (aref tabulated-list-format n))
> 		(get-text-property (point)
> 				   'tabulated-list-column-name))))
>     (if (nth 2 (assoc name (append tabulated-list-format nil)))
>         (tabulated-list--sort-by-column-name name)
>       (user-error "Cannot sort by %s" name))))
>
> Then this one:
>
> (defun tabulated-list--sort-by-column-name (name)
>   (when (and name (derived-mode-p 'tabulated-list-mode))
>     ;; Flip the sort order on a second click.
>     (if (equal name (car tabulated-list-sort-key))
> 	(setcdr tabulated-list-sort-key
> 		(not (cdr tabulated-list-sort-key)))
>       (setq tabulated-list-sort-key (cons name nil)))
>     (tabulated-list-init-header)
>     (tabulated-list-print t)))
>
> And if I read well those functions do not search for my function and
> invoke `my-sort', but they should. Am I right there?

Actually, tabulated-list-print does call my-sort via
tabulated-list--get-sorter.  Anyway, buffer-menu.el has the function
`tabulated-list-entry-size->', which with a small adjustment does what
you seem to want.  Try this:

(defun my-tabulated-list-entry-size-> (entry1 entry2)
  (> (string-to-number (aref (cadr entry1) 0))
     (string-to-number (aref (cadr entry2) 0))))

(let ((buffer "*tabulated*"))
  (switch-to-buffer-other-window buffer)
  (setq tabulated-list-format
	[("Count" 10 my-tabulated-list-entry-size-> :right-align t)
	 ("Name" 60 t)])
  (setq tabulated-list-entries '((6 ["6" "Mercury"])
				 (7 ["7" "GNU Emacs"])
				 (8 ["8" "YouTube Videos"])
				 (9 ["9" "Speedy worker cleaning tables in a restaurant"])
				 (71 ["71" "Trenching"])
				 (82 ["82" "Easier trenching idea"])))
  (tabulated-list-mode)
  (tabulated-list-init-header)
  (hl-line-mode)
  (tabulated-list-print))

Steve Berman





^ permalink raw reply	[flat|nested] 3+ messages in thread

* bug#45361: 28.0.50; tabulated-list-mode: should be sorting by specified sort function
  2020-12-22  9:31 ` Stephen Berman
@ 2020-12-22  9:43   ` Jean Louis
  0 siblings, 0 replies; 3+ messages in thread
From: Jean Louis @ 2020-12-22  9:43 UTC (permalink / raw)
  To: Stephen Berman; +Cc: 45361, 45361-done

* Stephen Berman <stephen.berman@gmx.net> [2020-12-22 12:32]:
> On Tue, 22 Dec 2020 08:13:50 +0100 Jean Louis <bugs@gnu.support> wrote:
> 
> > PROBLEM:
> >
> > The variable `tabulated-list-format' provides for programmer
> > option to sort columns and I would like to sort number as
> > strings "12" as numbers, not as strings. I do not know how to
> > properly provide the sorting function to `tabulated-list-format' so
> > that it works when actually sorting.
> [...]
> > Then I would like to use the function `string-collate-lessp' as that
> > seem to understand how numbers should be compared.
> >
> > For example this is giving me correct result:
> >
> > (sort '("121" "117" "1") 'string-collate-lessp) => ("1" "117" "121")
> 
> But:
> 
> (sort '("21" "117" "1") 'string-collate-lessp) => ("1" "117" "21")
> 
> So string-collate-lessp doesn't do what it seems you want.

Oh, I missed to see that. That is the problem.

> Actually, tabulated-list-print does call my-sort via
> tabulated-list--get-sorter.  Anyway, buffer-menu.el has the function
> `tabulated-list-entry-size->', which with a small adjustment does what
> you seem to want.  Try this:
> 
> (defun my-tabulated-list-entry-size-> (entry1 entry2)
>   (> (string-to-number (aref (cadr entry1) 0))
>      (string-to-number (aref (cadr entry2) 0))))

That is what I missed to see, thank you for references and your
help. Now it works well. 

Jean

P.S. Closing it as it is not a bug.








^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-12-22  9:43 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-22  7:13 bug#45361: 28.0.50; tabulated-list-mode: should be sorting by specified sort function Jean Louis
2020-12-22  9:31 ` Stephen Berman
2020-12-22  9:43   ` Jean Louis

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).