***Abstract: To `sort-regexp-fields', add the ability to sort records by multi-part (non-contiguous) keys. ***Description: `sort-regexp-fields' can sort entire records, or a subset of each record specified by a secondary regexp or by a single backreference to the record as matched by the record-defining regexp. This fairly minor patch gives the user (or caller) the additional ability to sort by multiple backreferences; e.g., \3\1\4 It does this by storing a list of backreference numbers in the `key-regexp' parameter to `sort-regexp-fields'. Then in the `startkeyfun' function passed to `sort-subr', those backreference strings are concatenated (separated by a NUL character) to form the sort key. ***ChangeLog: 2014-03-04 Eric Roode * lisp/sort.el (sort-regexp-fields): add multi-key sorting * doc/lispref/text.texi (sort-regexp-fields): document multi-key sorting ***Patch 1 of 2 (lisp/sort.el): *** /c/usr/emacs-24.3/lisp/sort.el 2013-08-07 12:18:53.540292800 -0400 --- /ejr/dev/emacs/sort.el 2014-03-04 10:59:02.280611700 -0500 *************** KEY-REGEXP specifies the part of each re *** 417,422 **** --- 417,424 ---- RECORD-REGEXP) to be used for sorting. If it is \"\\\\digit\", use the digit'th \"\\\\(...\\\\)\" match field specified by RECORD-REGEXP. + If it is a sequence of such match fields: \"\\\\digit\\\\digit...\", + use a concatenation of those backreferences, in that order. If it is \"\\\\&\", use the whole record. Otherwise, KEY-REGEXP should be a regular expression with which to search within the record. If a match for KEY-REGEXP is not *************** sRegexp specifying key within record: \n *** 438,444 **** (cond ((or (equal key-regexp "") (equal key-regexp "\\&")) (setq key-regexp 0)) ((string-match "\\`\\\\[1-9]\\'" key-regexp) ! (setq key-regexp (- (aref key-regexp 1) ?0)))) (save-excursion (save-restriction (narrow-to-region beg end) --- 440,452 ---- (cond ((or (equal key-regexp "") (equal key-regexp "\\&")) (setq key-regexp 0)) ((string-match "\\`\\\\[1-9]\\'" key-regexp) ! (setq key-regexp (- (aref key-regexp 1) ?0))) ! ((string-match "\\`\\(\\\\[1-9]\\)+\\'" key-regexp) ! (let ((st 1) (en (length key-regexp)) mlist) ! (while (< st en) ! (push (- (aref key-regexp st) ?0) mlist) ! (setq st (+ 2 st))) ! (setq key-regexp (nreverse mlist))))) (save-excursion (save-restriction (narrow-to-region beg end) *************** sRegexp specifying key within record: \n *** 453,470 **** (function (lambda () (goto-char sort-regexp-record-end))) (function (lambda () ! (let ((n 0)) ! (cond ((numberp key-regexp) ! (setq n key-regexp)) ! ((re-search-forward ! key-regexp sort-regexp-record-end t) ! (setq n 0)) ! (t (throw 'key nil))) ! (condition-case () ! (cons (match-beginning n) ! (match-end n)) ! ;; if there was no such register ! (error (throw 'key nil))))))))))) (defvar sort-columns-subprocess t) --- 461,482 ---- (function (lambda () (goto-char sort-regexp-record-end))) (function (lambda () ! (if (listp key-regexp) ! (mapconcat ! (function (lambda (ix) (match-string ix))) ! key-regexp "\0") ! (let ((n 0)) ! (cond ((numberp key-regexp) ! (setq n key-regexp)) ! ((re-search-forward ! key-regexp sort-regexp-record-end t) ! (setq n 0)) ! (t (throw 'key nil))) ! (condition-case () ! (cons (match-beginning n) ! (match-end n)) ! ;; if there was no such register ! (error (throw 'key nil)))))))))))) (defvar sort-columns-subprocess t) ***Patch 2 of 2 (doc/lispref/text.texi): *** text.texi~ 2013-02-18 20:17:07.000000000 -0500 --- text.texi 2014-03-04 11:38:48.136225100 -0500 *************** on its own. *** 1988,1999 **** If @var{key-regexp} is: @table @asis @item @samp{\@var{digit}} then the text matched by the @var{digit}th @samp{\(...\)} parenthesis grouping in @var{record-regexp} is the sort key. ! @item @samp{\&} ! then the whole record is the sort key. @item a regular expression then @code{sort-regexp-fields} searches for a match for the regular --- 1988,2003 ---- If @var{key-regexp} is: @table @asis + @item @samp{\&} + then the whole record is the sort key. + @item @samp{\@var{digit}} then the text matched by the @var{digit}th @samp{\(...\)} parenthesis grouping in @var{record-regexp} is the sort key. ! @item a series of such backreferences: @samp{\@var{digit}\@var{digit}...} ! then the multiple subexpressions specified by the respective parenthesis ! groupings in @var{record-regexp} are combined to be the sort key. @item a regular expression then @code{sort-regexp-fields} searches for a match for the regular