(remove-hook): Doc fix.
[bpt/emacs.git] / lisp / sort.el
index f1131ef..7e200b4 100644 (file)
 ;; along with GNU Emacs; see the file COPYING.  If not, write to
 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
+;;; Commentary:
+
+;;; This package provides the sorting facilities documented in the Emacs
+;;; user's manual.
+
 ;;; Code:
 
+(defvar sort-fold-case nil
+  "*Non-nil if the buffer sort functions should ignore case.")
+
 (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.
@@ -64,7 +72,8 @@ same as ENDRECFUN."
       (if messages (message "Finding sort keys..."))
       (let* ((sort-lists (sort-build-lists nextrecfun endrecfun
                                           startkeyfun endkeyfun))
-            (old (reverse sort-lists)))
+            (old (reverse sort-lists))
+            (case-fold-search sort-fold-case))
        (if (null sort-lists)
            ()
          (or reverse (setq sort-lists (nreverse sort-lists)))
@@ -239,12 +248,13 @@ 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."
+FIELD, BEG and END.  BEG and END specify region to sort.
+If you want to sort floating-point numbers, try `sort-float-fields'."
   (interactive "p\nr")
   (sort-fields-1 field beg end
                 (function (lambda ()
-                            (sort-skip-fields (1- field))
-                            (string-to-int
+                            (sort-skip-fields field)
+                            (string-to-number
                              (buffer-substring
                                (point)
                                (save-excursion
@@ -254,6 +264,7 @@ FIELD, BEG and END.  BEG and END specify region to sort."
                                  (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
@@ -264,8 +275,8 @@ region to sort."
   (interactive "p\nr")
   (sort-fields-1 field beg end
                 (function (lambda ()
-                            (sort-skip-fields (1- field))
-                            (string-to-float
+                            (sort-skip-fields field)
+                            (string-to-number
                              (buffer-substring
                               (point)
                               (save-excursion
@@ -284,7 +295,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")))))
 
@@ -302,25 +313,42 @@ 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
 ;;;###autoload
 (defun sort-regexp-fields (reverse record-regexp key-regexp beg end)
-  "Sort the region lexicographically as specifed by RECORD-REGEXP and KEY.
+  "Sort the region lexicographically as specified by RECORD-REGEXP and KEY.
 RECORD-REGEXP specifies the textual units which should be sorted.
   For example, to sort lines RECORD-REGEXP would be \"^.*$\"
 KEY specifies the part of each record (ie each match for RECORD-REGEXP)