* org-table.el (org-table-sort-lines): Fix case sensitive sorting, improve docstring. * test-org-table.el (test-org-table/sort-lines): Enforce C locale when testing alphabetic sorting.
‘sort-subr’ ignores ‘sort-fold-case’ when a predicate is provided. To correctly handle case-sensitivity, we now bake it into the predicate. Since we are now sorting according to the user’s locale, WITH-CASE will not make a difference in most instances, since most locales always sort case-insensitively (cf. how GNU sort ignores the ‘-f’ switch). We now mention this in the function docstring. In order to meaningfully test case-sensitive sorting, we now enforce the C locale in the respective unit test. --- lisp/org-table.el | 9 ++++---- testing/lisp/test-org-table.el | 49 +++++++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/lisp/org-table.el b/lisp/org-table.el index 316533172..5ebca54fd 100644 --- a/lisp/org-table.el +++ b/lisp/org-table.el @@ -1714,7 +1714,8 @@ (defun org-table-sort-lines in the field, or as a HH:MM value). Sorting in reverse order is also possible. -With prefix argument WITH-CASE, alphabetic sorting will be case-sensitive. +With prefix argument WITH-CASE, alphabetic sorting will be case-sensitive +if the locale allows for it. If SORTING-TYPE is specified when this function is called from a Lisp program, no prompting will take place. SORTING-TYPE must be a character, @@ -1766,8 +1767,7 @@ (defun org-table-sort-lines ;; Determine arguments for `sort-subr'. Also record original ;; position. `org-table-save-field' cannot help here since ;; sorting is too much destructive. - (let* ((sort-fold-case (not with-case)) - (coordinates + (let* ((coordinates (cons (count-lines (point-min) (line-beginning-position)) (current-column))) (extract-key-from-field @@ -1794,7 +1794,8 @@ (defun org-table-sort-lines (predicate (cl-case sorting-type ((?n ?N ?t ?T) #'<) - ((?a ?A) #'org-string-collate-lessp) + ((?a ?A) (if with-case #'org-string-collate-lessp + (lambda (s1 s2) (org-string-collate-lessp s1 s2 nil t)))) ((?f ?F) (or compare-func (and interactive? diff --git a/testing/lisp/test-org-table.el b/testing/lisp/test-org-table.el index d90caa8e9..873e79abb 100644 --- a/testing/lisp/test-org-table.el +++ b/testing/lisp/test-org-table.el @@ -1689,28 +1689,33 @@ (org-test-with-temp-text "| <point>1 | 2 |\n| 5 | 3 |\n| 2 | 4 |\n" (org-table-sort-lines nil ?N) (buffer-string)))) - ;; Sort alphabetically. - (should - (equal "| a | x |\n| B | 4 |\n| c | 3 |\n" - (org-test-with-temp-text "| <point>a | x |\n| c | 3 |\n| B | 4 |\n" - (org-table-sort-lines nil ?a) - (buffer-string)))) - (should - (equal "| c | 3 |\n| B | 4 |\n| a | x |\n" - (org-test-with-temp-text "| <point>a | x |\n| c | 3 |\n| B | 4 |\n" - (org-table-sort-lines nil ?A) - (buffer-string)))) - ;; Sort alphabetically with case. - (should - (equal "| C |\n| a |\n| b |\n" - (org-test-with-temp-text "| <point>a |\n| C |\n| b |\n" - (org-table-sort-lines t ?a) - (buffer-string)))) - (should - (equal "| C |\n| b |\n| a |\n" - (org-test-with-temp-text "| <point>a |\n| C |\n| b |\n" - (org-table-sort-lines nil ?A) - (buffer-string)))) + ;; Sort alphabetically. Enforce the C locale for consistent results. + (let ((original-string-collate-lessp (symbol-function 'string-collate-lessp))) + (cl-letf (((symbol-function 'string-collate-lessp) + (lambda (s1 s2 &optional locale ignore-case) + (funcall original-string-collate-lessp + s1 s2 "C" ignore-case)))) + (should + (equal "| a | x |\n| B | 4 |\n| c | 3 |\n" + (org-test-with-temp-text "| <point>a | x |\n| c | 3 |\n| B | 4 |\n" + (org-table-sort-lines nil ?a) + (buffer-string)))) + (should + (equal "| c | 3 |\n| B | 4 |\n| a | x |\n" + (org-test-with-temp-text "| <point>a | x |\n| c | 3 |\n| B | 4 |\n" + (org-table-sort-lines nil ?A) + (buffer-string)))) + ;; Sort alphabetically with case. + (should + (equal "| C |\n| a |\n| b |\n" + (org-test-with-temp-text "| <point>a |\n| C |\n| b |\n" + (org-table-sort-lines t ?a) + (buffer-string)))) + (should + (equal "| C |\n| b |\n| a |\n" + (org-test-with-temp-text "| <point>a |\n| C |\n| b |\n" + (org-table-sort-lines nil ?A) + (buffer-string)))))) ;; Sort by time (timestamps) (should (equal -- 2.16.2