diff options
| author | Juri Linkov | 2012-12-04 01:49:08 +0200 |
|---|---|---|
| committer | Juri Linkov | 2012-12-04 01:49:08 +0200 |
| commit | c38a186c2e06e0a351d166c5ef06d7307e145f45 (patch) | |
| tree | 21c24e9ae0de6c192f0b00e0386b3e14d4bc8eae | |
| parent | 9320b007d5518a4e1966e168286a3a3182e9e4d8 (diff) | |
| download | emacs-c38a186c2e06e0a351d166c5ef06d7307e145f45.tar.gz emacs-c38a186c2e06e0a351d166c5ef06d7307e145f45.zip | |
* lisp/sort.el (delete-duplicate-lines): New command.
Fixes: debbugs:13032
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | lisp/ChangeLog | 4 | ||||
| -rw-r--r-- | lisp/sort.el | 56 |
3 files changed, 65 insertions, 0 deletions
| @@ -69,6 +69,11 @@ New features include: | |||
| 69 | name and arguments. Useful to trace the value of (current-buffer) or | 69 | name and arguments. Useful to trace the value of (current-buffer) or |
| 70 | (point) when the function is invoked. | 70 | (point) when the function is invoked. |
| 71 | 71 | ||
| 72 | ** New command `delete-duplicate-lines' has two types of operation: | ||
| 73 | when its arg ADJACENT is non-nil (when called interactively with C-u C-u) | ||
| 74 | it works like the utility `uniq'. Otherwise by default it deletes | ||
| 75 | duplicate lines everywhere in the region without regard to adjacency. | ||
| 76 | |||
| 72 | ** Woman | 77 | ** Woman |
| 73 | 78 | ||
| 74 | *** The commands `woman-default-faces' and `woman-monochrome-faces' | 79 | *** The commands `woman-default-faces' and `woman-monochrome-faces' |
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 891e6771503..f4963a07a92 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | 2012-12-03 Juri Linkov <juri@jurta.org> | ||
| 2 | |||
| 3 | * sort.el (delete-duplicate-lines): New command. (Bug#13032) | ||
| 4 | |||
| 1 | 2012-12-03 Agustín Martín Domingo <agustin.martin@hispalinux.es> | 5 | 2012-12-03 Agustín Martín Domingo <agustin.martin@hispalinux.es> |
| 2 | 6 | ||
| 3 | * textmodes/ispell.el (ispell-init-process) | 7 | * textmodes/ispell.el (ispell-init-process) |
diff --git a/lisp/sort.el b/lisp/sort.el index 44f90fff379..cd0b4433ab3 100644 --- a/lisp/sort.el +++ b/lisp/sort.el | |||
| @@ -562,6 +562,62 @@ From a program takes two point or marker arguments, BEG and END." | |||
| 562 | (setq ll (cdr ll))) | 562 | (setq ll (cdr ll))) |
| 563 | (insert (car ll))))) | 563 | (insert (car ll))))) |
| 564 | 564 | ||
| 565 | ;;;###autoload | ||
| 566 | (defun delete-duplicate-lines (beg end &optional reverse adjacent interactive) | ||
| 567 | "Delete duplicate lines in the region between BEG and END. | ||
| 568 | |||
| 569 | If REVERSE is nil, search and delete duplicates forward keeping the first | ||
| 570 | occurrence of duplicate lines. If REVERSE is non-nil (when called | ||
| 571 | interactively with C-u prefix), search and delete duplicates backward | ||
| 572 | keeping the last occurrence of duplicate lines. | ||
| 573 | |||
| 574 | If ADJACENT is non-nil (when called interactively with two C-u prefixes), | ||
| 575 | delete repeated lines only if they are adjacent. It works like the utility | ||
| 576 | `uniq' and is useful when lines are already sorted in a large file since | ||
| 577 | this is more efficient in performance and memory usage than when ADJACENT | ||
| 578 | is nil that uses additional memory to remember previous lines. | ||
| 579 | |||
| 580 | When called from Lisp and INTERACTIVE is omitted or nil, return the number | ||
| 581 | of deleted duplicate lines, do not print it; if INTERACTIVE is t, the | ||
| 582 | function behaves in all respects as if it had been called interactively." | ||
| 583 | (interactive | ||
| 584 | (progn | ||
| 585 | (barf-if-buffer-read-only) | ||
| 586 | (list (region-beginning) (region-end) | ||
| 587 | (equal current-prefix-arg '(4)) | ||
| 588 | (equal current-prefix-arg '(16)) | ||
| 589 | t))) | ||
| 590 | (let ((lines (unless adjacent (make-hash-table :weakness 'key :test 'equal))) | ||
| 591 | line prev-line | ||
| 592 | (count 0) | ||
| 593 | (beg (copy-marker beg)) | ||
| 594 | (end (copy-marker end))) | ||
| 595 | (save-excursion | ||
| 596 | (goto-char (if reverse end beg)) | ||
| 597 | (if (and reverse (bolp)) (forward-char -1)) | ||
| 598 | (while (if reverse | ||
| 599 | (and (> (point) beg) (not (bobp))) | ||
| 600 | (and (< (point) end) (not (eobp)))) | ||
| 601 | (setq line (buffer-substring-no-properties | ||
| 602 | (line-beginning-position) (line-end-position))) | ||
| 603 | (if (if adjacent (equal line prev-line) (gethash line lines)) | ||
| 604 | (progn | ||
| 605 | (delete-region (progn (forward-line 0) (point)) | ||
| 606 | (progn (forward-line 1) (point))) | ||
| 607 | (if reverse (forward-line -1)) | ||
| 608 | (setq count (1+ count))) | ||
| 609 | (if adjacent (setq prev-line line) (puthash line t lines)) | ||
| 610 | (forward-line (if reverse -1 1))))) | ||
| 611 | (set-marker beg nil) | ||
| 612 | (set-marker end nil) | ||
| 613 | (when interactive | ||
| 614 | (message "Deleted %d %sduplicate line%s%s" | ||
| 615 | count | ||
| 616 | (if adjacent "adjacent " "") | ||
| 617 | (if (= count 1) "" "s") | ||
| 618 | (if reverse " backward" ""))) | ||
| 619 | count)) | ||
| 620 | |||
| 565 | (provide 'sort) | 621 | (provide 'sort) |
| 566 | 622 | ||
| 567 | ;;; sort.el ends here | 623 | ;;; sort.el ends here |