(dun-climb): Handle unknown object name.
[bpt/emacs.git] / lisp / sort.el
index c013591..392ea93 100644 (file)
@@ -1,6 +1,6 @@
 ;;; sort.el --- commands to sort text in an Emacs buffer.
 
-;; Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 1987, 1994, 1995 Free Software Foundation, Inc.
 
 ;; Author: Howie Kaye
 ;; Maintainer: FSF
@@ -32,6 +32,7 @@
 (defvar sort-fold-case nil
   "*Non-nil if the buffer sort functions should ignore case.")
 
+;;;###autoload
 (defun sort-subr (reverse nextrecfun endrecfun &optional startkeyfun endkeyfun)
   "General text sorting routine to divide buffer into records and sort them.
 Arguments are REVERSE NEXTRECFUN ENDRECFUN &optional STARTKEYFUN ENDKEYFUN.
@@ -94,9 +95,7 @@ same as ENDRECFUN."
                                    'string<)))
                  (sort sort-lists
                        (cond ((numberp (car (car sort-lists)))
-                              (function
-                               (lambda (a b)
-                                 (< (car a) (car b)))))
+                              'car-less-than-car)
                              ((consp (car (car sort-lists)))
                               (function
                                (lambda (a b)
@@ -211,7 +210,10 @@ REVERSE (non-nil means reverse order), BEG and END (region to sort)."
       (narrow-to-region beg end)
       (goto-char (point-min))
       (sort-subr reverse
-                (function (lambda () (skip-chars-forward "\n \t\f")))
+                (function
+                 (lambda ()
+                   (while (and (not (eobp)) (looking-at paragraph-separate))
+                     (forward-line 1))))
                 'forward-paragraph))))
 
 ;;;###autoload
@@ -248,12 +250,11 @@ Fields are separated by whitespace and numbered from 1 up.
 Specified field must contain a number in each line of the region.
 With a negative arg, sorts by the ARGth field counted from the right.
 Called from a program, there are three arguments:
-FIELD, BEG and END.  BEG and END specify region to sort.
-If you want to sort floating-point numbers, try `sort-float-fields'."
+FIELD, BEG and END.  BEG and END specify region to sort."
   (interactive "p\nr")
   (sort-fields-1 field beg end
                 (function (lambda ()
-                            (sort-skip-fields (1- field))
+                            (sort-skip-fields field)
                             (string-to-number
                              (buffer-substring
                                (point)
@@ -264,26 +265,26 @@ If you want to sort floating-point numbers, try `sort-float-fields'."
                                  (point))))))
                 nil))
 
-;;;###autoload
-(defun sort-float-fields (field beg end)
-  "Sort lines in region numerically by the ARGth field of each line.
-Fields are separated by whitespace and numbered from 1 up.  Specified field
-must contain a floating point number in each line of the region.  With a
-negative arg, sorts by the ARGth field counted from the right.  Called from a
-program, there are three arguments: FIELD, BEG and END.  BEG and END specify
-region to sort."
-  (interactive "p\nr")
-  (sort-fields-1 field beg end
-                (function (lambda ()
-                            (sort-skip-fields (1- field))
-                            (string-to-number
-                             (buffer-substring
-                              (point)
-                              (save-excursion
-                                (re-search-forward
-                                 "[+-]?[0-9]*\.?[0-9]*\\([eE][+-]?[0-9]+\\)?")
-                                (point))))))
-                nil))
+;;;;;###autoload
+;;(defun sort-float-fields (field beg end)
+;;  "Sort lines in region numerically by the ARGth field of each line.
+;;Fields are separated by whitespace and numbered from 1 up.  Specified field
+;;must contain a floating point number in each line of the region.  With a
+;;negative arg, sorts by the ARGth field counted from the right.  Called from a
+;;program, there are three arguments: FIELD, BEG and END.  BEG and END specify
+;;region to sort."
+;;  (interactive "p\nr")
+;;  (sort-fields-1 field beg end
+;;              (function (lambda ()
+;;                          (sort-skip-fields field)
+;;                          (string-to-number
+;;                           (buffer-substring
+;;                            (point)
+;;                            (save-excursion
+;;                              (re-search-forward
+;;                               "[+-]?[0-9]*\.?[0-9]*\\([eE][+-]?[0-9]+\\)?")
+;;                              (point))))))
+;;              nil))
 
 ;;;###autoload
 (defun sort-fields (field beg end)
@@ -295,7 +296,7 @@ FIELD, BEG and END.  BEG and END specify region to sort."
   (interactive "p\nr")
   (sort-fields-1 field beg end
                 (function (lambda ()
-                            (sort-skip-fields (1- field))
+                            (sort-skip-fields field)
                             nil))
                 (function (lambda () (skip-chars-forward "^ \t\n")))))
 
@@ -313,22 +314,58 @@ FIELD, BEG and END.  BEG and END specify region to sort."
                       startkeyfun endkeyfun)))
       (set-syntax-table tbl))))
 
+;; Position at the beginning of field N on the current line,
+;; assuming point is initially at the beginning of the line.
 (defun sort-skip-fields (n)
-  (let ((bol (point))
-       (eol (save-excursion (end-of-line 1) (point))))
-    (if (> n 0) (forward-word n)
-      (end-of-line)
-      (forward-word (1+ n)))
-    (if (or (and (>= (point) eol) (> n 0))
-           ;; this is marginally wrong; if the first line of the sort
-           ;; at bob has the wrong number of fields the error won't be
-           ;; reported until the next short line.
-           (and (< (point) bol) (< n 0)))
+  (if (> n 0)
+      ;; Skip across N - 1 fields.
+      (let ((i (1- n)))
+       (while (> i 0)
+         (skip-chars-forward " \t")
+         (skip-chars-forward "^ \t\n")
+         (setq i (1- i)))
+       (skip-chars-forward " \t")
+       (if (eolp)
+           (error "Line has too few fields: %s"
+                  (buffer-substring
+                   (save-excursion (beginning-of-line) (point))
+                   (save-excursion (end-of-line) (point))))))
+    (end-of-line)
+    ;; Skip back across - N - 1 fields.
+    (let ((i (1- (- n))))
+      (while (> i 0)
+       (skip-chars-backward " \t")
+       (skip-chars-backward "^ \t\n")
+       (setq i (1- i)))
+      (skip-chars-backward " \t"))
+    (if (bolp)
        (error "Line has too few fields: %s"
-              (buffer-substring bol eol)))
-    (skip-chars-forward " \t")))
-
+              (buffer-substring
+               (save-excursion (beginning-of-line) (point))
+               (save-excursion (end-of-line) (point)))))
+    ;; Position at the front of the field
+    ;; even if moving backwards.
+    (skip-chars-backward "^ \t\n")))
 \f
+(defvar sort-regexp-fields-regexp)
+(defvar sort-regexp-record-end)
+
+;; Move to the beginning of the next match for record-regexp,
+;; and set sort-regexp-record-end to the end of that match.
+;; If the next match is empty and does not advance point,
+;; skip one character and try again.
+(defun sort-regexp-fields-next-record ()
+  (let ((oldpos (point)))
+    (and (re-search-forward sort-regexp-fields-regexp nil 'move)
+        (setq sort-regexp-record-end (match-end 0))
+        (if (= sort-regexp-record-end oldpos)
+            (progn
+              (forward-char 1)
+              (re-search-forward sort-regexp-fields-regexp nil 'move)
+              (setq sort-regexp-record-end (match-end 0)))
+          t)
+        (goto-char (match-beginning 0)))))
+
 ;;;###autoload
 (defun sort-regexp-fields (reverse record-regexp key-regexp beg end)
   "Sort the region lexicographically as specified by RECORD-REGEXP and KEY.
@@ -360,15 +397,13 @@ sRegexp specifying key within record: \nr")
     (save-restriction
       (narrow-to-region beg end)
       (goto-char (point-min))
-      (let (sort-regexp-record-end) ;isn't dynamic scoping wonderful?
-       (re-search-forward record-regexp)
+      (let (sort-regexp-record-end
+           (sort-regexp-fields-regexp record-regexp))
+       (re-search-forward sort-regexp-fields-regexp)
        (setq sort-regexp-record-end (point))
        (goto-char (match-beginning 0))
        (sort-subr reverse
-                  (function (lambda ()
-                              (and (re-search-forward record-regexp nil 'move)
-                                   (setq sort-regexp-record-end (match-end 0))
-                                   (goto-char (match-beginning 0)))))
+                  'sort-regexp-fields-next-record
                   (function (lambda ()
                               (goto-char sort-regexp-record-end)))
                   (function (lambda ()