|
|
1.1 ! root 1: ;; Replace commands for Emacs. ! 2: ;; Copyright (C) 1985, 1986 Free Software Foundation, Inc. ! 3: ! 4: ;; This file is part of GNU Emacs. ! 5: ! 6: ;; GNU Emacs is distributed in the hope that it will be useful, ! 7: ;; but WITHOUT ANY WARRANTY. No author or distributor ! 8: ;; accepts responsibility to anyone for the consequences of using it ! 9: ;; or for whether it serves any particular purpose or works at all, ! 10: ;; unless he says so in writing. Refer to the GNU Emacs General Public ! 11: ;; License for full details. ! 12: ! 13: ;; Everyone is granted permission to copy, modify and redistribute ! 14: ;; GNU Emacs, but only under the conditions described in the ! 15: ;; GNU Emacs General Public License. A copy of this license is ! 16: ;; supposed to have been given to you along with GNU Emacs so you ! 17: ;; can know your rights and responsibilities. It should be in a ! 18: ;; file named COPYING. Among other things, the copyright notice ! 19: ;; and this notice must be preserved on all copies. ! 20: ! 21: ! 22: (fset 'delete-non-matching-lines 'keep-lines) ! 23: (defun keep-lines (regexp) ! 24: "Delete all lines except those containing matches for REGEXP. ! 25: A match split across lines preserves all the lines it lies in. ! 26: Applies to all lines after point." ! 27: (interactive "sKeep lines (containing match for regexp): ") ! 28: (save-excursion ! 29: (or (bolp) (forward-line 1)) ! 30: (let ((start (point))) ! 31: (while (not (eobp)) ! 32: ;; Start is first char not preserved by previous match. ! 33: (if (not (re-search-forward regexp nil 'move)) ! 34: (delete-region start (point-max)) ! 35: (let ((end (save-excursion (goto-char (match-beginning 0)) ! 36: (beginning-of-line) ! 37: (point)))) ! 38: ;; Now end is first char preserved by the new match. ! 39: (if (< start end) ! 40: (delete-region start end)))) ! 41: (setq start (save-excursion (forward-line 1) ! 42: (point))))))) ! 43: ! 44: (fset 'delete-matching-lines 'flush-lines) ! 45: (defun flush-lines (regexp) ! 46: "Delete lines containing matches for REGEXP. ! 47: If a match is split across lines, all the lines it lies in are deleted. ! 48: Applies to lines after point." ! 49: (interactive "sFlush lines (containing match for regexp): ") ! 50: (save-excursion ! 51: (while (and (not (eobp)) ! 52: (re-search-forward regexp nil t)) ! 53: (delete-region (save-excursion (goto-char (match-beginning 0)) ! 54: (beginning-of-line) ! 55: (point)) ! 56: (progn (forward-line 1) (point)))))) ! 57: ! 58: (fset 'count-matches 'how-many) ! 59: (defun how-many (regexp) ! 60: "Print number of matches for REGEXP following point." ! 61: (interactive "sHow many matches for (regexp): ") ! 62: (let ((count 0) opoint) ! 63: (save-excursion ! 64: (while (and (not (eobp)) ! 65: (progn (setq opoint (point)) ! 66: (re-search-forward regexp nil t))) ! 67: (if (= opoint (point)) ! 68: (forward-char 1) ! 69: (setq count (1+ count)))) ! 70: (message "%d occurrences" count)))) ! 71: ! 72: (defvar occur-mode-map ()) ! 73: (if occur-mode-map ! 74: () ! 75: (setq occur-mode-map (make-sparse-keymap)) ! 76: (define-key occur-mode-map "\C-c\C-c" 'occur-mode-goto-occurrence)) ! 77: ! 78: (defvar occur-buffer nil) ! 79: (defvar occur-nlines nil) ! 80: (defvar occur-pos-list nil) ! 81: ! 82: (defun occur-mode () ! 83: "Major mode for output from \\[occur]. ! 84: Move point to one of the occurrences in this buffer, ! 85: then use \\[occur-mode-goto-occurrence] to go to the same occurrence ! 86: in the buffer that the occurrences were found in. ! 87: \\{occur-mode-map}" ! 88: (kill-all-local-variables) ! 89: (use-local-map occur-mode-map) ! 90: (setq major-mode 'occur-mode) ! 91: (setq mode-name "Occur") ! 92: (make-local-variable 'occur-buffer) ! 93: (make-local-variable 'occur-nlines) ! 94: (make-local-variable 'occur-pos-list)) ! 95: ! 96: (defun occur-mode-goto-occurrence () ! 97: "Go to the line this occurrence was found in, in the buffer it was found in." ! 98: (interactive) ! 99: (if (or (null occur-buffer) ! 100: (null (buffer-name occur-buffer))) ! 101: (progn ! 102: (setq occur-buffer nil ! 103: occur-pos-list nil) ! 104: (error "Buffer in which occurences were found is deleted."))) ! 105: (let* ((occur-number (/ (1- (count-lines (point-min) (point))) ! 106: (cond ((< occur-nlines 0) ! 107: (- 2 occur-nlines)) ! 108: ((> occur-nlines 0) ! 109: (+ 2 (* 2 occur-nlines))) ! 110: (t 1)))) ! 111: (pos (nth occur-number occur-pos-list))) ! 112: (pop-to-buffer occur-buffer) ! 113: (goto-char (marker-position pos)))) ! 114: ! 115: (defvar list-matching-lines-default-context-lines 0 ! 116: "*Default number of context lines to include around a list-matching-lines ! 117: match. A negative number means to include that many lines before the match. ! 118: A positive number means to include that many lines both before and after.") ! 119: ! 120: (fset 'list-matching-lines 'occur) ! 121: (defun occur (regexp &optional nlines) ! 122: "Show all lines following point containing a match for REGEXP. ! 123: Display each line with NLINES lines before and after, ! 124: or -NLINES before if NLINES is negative. ! 125: NLINES defaults to list-matching-lines-default-context-lines. ! 126: Interactively it is the prefix arg. ! 127: ! 128: The lines are shown in a buffer named *Occur*. ! 129: It serves as a menu to find any of the occurrences in this buffer. ! 130: \\[describe-mode] in that buffer will explain how." ! 131: (interactive "sList lines matching regexp: \nP") ! 132: (setq nlines (if nlines (prefix-numeric-value nlines) ! 133: list-matching-lines-default-context-lines)) ! 134: (let ((first t) ! 135: (buffer (current-buffer)) ! 136: linenum prevpos) ! 137: (save-excursion ! 138: (beginning-of-line) ! 139: (setq linenum (1+ (count-lines (point-min) (point)))) ! 140: (setq prevpos (point))) ! 141: (with-output-to-temp-buffer "*Occur*" ! 142: (save-excursion ! 143: (set-buffer standard-output) ! 144: (insert "Lines matching ") ! 145: (prin1 regexp) ! 146: (insert " in buffer " (buffer-name buffer) ?. ?\n) ! 147: (occur-mode) ! 148: (setq occur-buffer buffer) ! 149: (setq occur-nlines nlines) ! 150: (setq occur-pos-list ())) ! 151: (if (eq buffer standard-output) ! 152: (goto-char (point-max))) ! 153: (save-excursion ! 154: (while (re-search-forward regexp nil t) ! 155: (beginning-of-line 1) ! 156: (save-excursion ! 157: (setq linenum (+ linenum (count-lines prevpos (point)))) ! 158: (setq prevpos (point))) ! 159: (let* ((start (save-excursion ! 160: (forward-line (if (< nlines 0) nlines (- nlines))) ! 161: (point))) ! 162: (end (save-excursion ! 163: (if (> nlines 0) ! 164: (forward-line (1+ nlines)) ! 165: (forward-line 1)) ! 166: (point))) ! 167: (tag (format "%3d" linenum)) ! 168: (empty (make-string (length tag) ?\ )) ! 169: tem) ! 170: (save-excursion ! 171: (setq tem (make-marker)) ! 172: (set-marker tem (point)) ! 173: (set-buffer standard-output) ! 174: (setq occur-pos-list (cons tem occur-pos-list)) ! 175: (or first (zerop nlines) ! 176: (insert "--------\n")) ! 177: (setq first nil) ! 178: (insert-buffer-substring buffer start end) ! 179: (backward-char (- end start)) ! 180: (setq tem (if (< nlines 0) (- nlines) nlines)) ! 181: (while (> tem 0) ! 182: (insert empty ?:) ! 183: (forward-line 1) ! 184: (setq tem (1- tem))) ! 185: (insert tag ?:) ! 186: (forward-line 1) ! 187: (while (< tem nlines) ! 188: (insert empty ?:) ! 189: (forward-line 1) ! 190: (setq tem (1+ tem)))) ! 191: (forward-line 1))) ! 192: (set-buffer standard-output) ! 193: ;; Put positions in increasing order to go with buffer. ! 194: (setq occur-pos-list (nreverse occur-pos-list)) ! 195: (if (interactive-p) ! 196: (message "%d matching lines." (length occur-pos-list))))))) ! 197: ! 198: (defconst query-replace-help ! 199: "Type Space or `y' to replace one match, Delete or `n' to skip to next, ! 200: ESC or `q' to exit, Period to replace one match and exit, ! 201: Comma to replace but not move point immediately, ! 202: C-r to enter recursive edit (\\[exit-recursive-edit] to get out again), ! 203: C-w to delete match and recursive edit, ! 204: C-l to clear the screen, redisplay, and offer same replacement again, ! 205: ! to replace all remaining matches with no more questions, ! 206: ^ to move point back to previous match." ! 207: "Help message while in query-replace") ! 208: ! 209: (defun perform-replace (from-string to-string ! 210: query-flag regexp-flag delimited-flag) ! 211: (let ((nocasify (not (and case-fold-search case-replace ! 212: (string-equal from-string ! 213: (downcase from-string))))) ! 214: (literal (not regexp-flag)) ! 215: (search-function (if regexp-flag 're-search-forward 'search-forward)) ! 216: (search-string from-string) ! 217: (keep-going t) ! 218: (lastrepl nil)) ;Position after last match considered. ! 219: (if delimited-flag ! 220: (setq search-function 're-search-forward ! 221: search-string (concat "\\b" ! 222: (if regexp-flag from-string ! 223: (regexp-quote from-string)) ! 224: "\\b"))) ! 225: (push-mark) ! 226: (push-mark) ! 227: (while (and keep-going ! 228: (not (eobp)) ! 229: (progn ! 230: (set-mark (point)) ! 231: (funcall search-function search-string nil t))) ! 232: ;; Don't replace the null string ! 233: ;; right after end of previous replacement. ! 234: (if (eq lastrepl (point)) ! 235: (forward-char 1) ! 236: (undo-boundary) ! 237: (if (not query-flag) ! 238: (replace-match to-string nocasify literal) ! 239: (let (done replaced) ! 240: (while (not done) ! 241: ;; Preserve the match data. Process filters and sentinels ! 242: ;; could run inside read-char.. ! 243: (let ((data (match-data)) ! 244: (help-form ! 245: '(concat "Query replacing " ! 246: (if regexp-flag "regexp " "") ! 247: from-string " with " to-string ".\n\n" ! 248: (substitute-command-keys query-replace-help)))) ! 249: (setq char help-char) ! 250: (while (= char help-char) ! 251: (message "Query replacing %s with %s: " from-string to-string) ! 252: (setq char (read-char)) ! 253: (if (= char ??) ! 254: (setq unread-command-char help-char char help-char))) ! 255: (store-match-data data)) ! 256: (cond ((or (= char ?\e) ! 257: (= char ?q)) ! 258: (setq keep-going nil) ! 259: (setq done t)) ! 260: ((= char ?^) ! 261: (goto-char (mark)) ! 262: (setq replaced t)) ! 263: ((or (= char ?\ ) ! 264: (= char ?y)) ! 265: (or replaced ! 266: (replace-match to-string nocasify literal)) ! 267: (setq done t)) ! 268: ((= char ?\.) ! 269: (or replaced ! 270: (replace-match to-string nocasify literal)) ! 271: (setq keep-going nil) ! 272: (setq done t)) ! 273: ((= char ?\,) ! 274: (if (not replaced) ! 275: (progn ! 276: (replace-match to-string nocasify literal) ! 277: (setq replaced t)))) ! 278: ((= char ?!) ! 279: (or replaced ! 280: (replace-match to-string nocasify literal)) ! 281: (setq done t query-flag nil)) ! 282: ((or (= char ?\177) ! 283: (= char ?n)) ! 284: (setq done t)) ! 285: ((= char ?\C-l) ! 286: (recenter nil)) ! 287: ((= char ?\C-r) ! 288: (store-match-data ! 289: (prog1 (match-data) ! 290: (save-excursion (recursive-edit))))) ! 291: ((= char ?\C-w) ! 292: (delete-region (match-beginning 0) (match-end 0)) ! 293: (store-match-data ! 294: (prog1 (match-data) ! 295: (save-excursion (recursive-edit)))) ! 296: (setq replaced t)) ! 297: (t ! 298: (setq keep-going nil) ! 299: (setq unread-command-char char) ! 300: (setq done t)))))) ! 301: (setq lastrepl (point)))) ! 302: (pop-mark) ! 303: keep-going)) ! 304:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.