;;; sort.el --- commands to sort text in an Emacs buffer
-;; Copyright (C) 1986-1987, 1994-1995, 2001-2012
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1986-1987, 1994-1995, 2001-2014 Free Software
+;; Foundation, Inc.
;; Author: Howie Kaye
-;; Maintainer: FSF
+;; Maintainer: emacs-devel@gnu.org
;; Keywords: unix
;; This file is part of GNU Emacs.
(insert (car ll)))))
;;;###autoload
-(defun delete-duplicate-lines (beg end &optional reverse adjacent interactive)
- "Delete duplicate lines in the region between BEG and END.
-
-If REVERSE is nil, search and delete duplicates forward keeping the first
-occurrence of duplicate lines. If REVERSE is non-nil (when called
-interactively with C-u prefix), search and delete duplicates backward
-keeping the last occurrence of duplicate lines.
-
-If ADJACENT is non-nil (when called interactively with two C-u prefixes),
-delete repeated lines only if they are adjacent. It works like the utility
-`uniq' and is useful when lines are already sorted in a large file since
-this is more efficient in performance and memory usage than when ADJACENT
-is nil that uses additional memory to remember previous lines.
-
-When called from Lisp and INTERACTIVE is omitted or nil, return the number
-of deleted duplicate lines, do not print it; if INTERACTIVE is t, the
-function behaves in all respects as if it had been called interactively."
+(defun delete-duplicate-lines (beg end &optional reverse adjacent keep-blanks
+ interactive)
+ "Delete all but one copy of any identical lines in the region.
+Non-interactively, arguments BEG and END delimit the region.
+Normally it searches forwards, keeping the first instance of
+each identical line. If REVERSE is non-nil (interactively, with
+a C-u prefix), it searches backwards and keeps the last instance of
+each repeated line.
+
+Identical lines need not be adjacent, unless the argument
+ADJACENT is non-nil (interactively, with a C-u C-u prefix).
+This is a more efficient mode of operation, and may be useful
+on large regions that have already been sorted.
+
+If the argument KEEP-BLANKS is non-nil (interactively, with a
+C-u C-u C-u prefix), it retains repeated blank lines.
+
+Returns the number of deleted lines. Interactively, or if INTERACTIVE
+is non-nil, it also prints a message describing the number of deletions."
(interactive
(progn
(barf-if-buffer-read-only)
(list (region-beginning) (region-end)
(equal current-prefix-arg '(4))
(equal current-prefix-arg '(16))
+ (equal current-prefix-arg '(64))
t)))
- (let ((lines (unless adjacent (make-hash-table :weakness 'key :test 'equal)))
+ (let ((lines (unless adjacent (make-hash-table :test 'equal)))
line prev-line
(count 0)
(beg (copy-marker beg))
(and (< (point) end) (not (eobp))))
(setq line (buffer-substring-no-properties
(line-beginning-position) (line-end-position)))
- (if (if adjacent (equal line prev-line) (gethash line lines))
- (progn
- (delete-region (progn (forward-line 0) (point))
- (progn (forward-line 1) (point)))
- (if reverse (forward-line -1))
- (setq count (1+ count)))
- (if adjacent (setq prev-line line) (puthash line t lines))
- (forward-line (if reverse -1 1)))))
+ (if (and keep-blanks (string= "" line))
+ (forward-line 1)
+ (if (if adjacent (equal line prev-line) (gethash line lines))
+ (progn
+ (delete-region (progn (forward-line 0) (point))
+ (progn (forward-line 1) (point)))
+ (if reverse (forward-line -1))
+ (setq count (1+ count)))
+ (if adjacent (setq prev-line line) (puthash line t lines))
+ (forward-line (if reverse -1 1))))))
(set-marker beg nil)
(set-marker end nil)
(when interactive