Function: keep-lines

keep-lines is an interactive and byte-compiled function defined in replace.el.gz.

Signature

(keep-lines REGEXP &optional RSTART REND INTERACTIVE)

Documentation

Delete all lines except those containing matches for REGEXP.

A match split across lines preserves all the lines it lies in. When called from Lisp (and usually interactively as well, see below) applies to all lines starting after point.

If REGEXP contains upper case characters (excluding those preceded by \) and search-upper-case is non-nil, the matching is case-sensitive.

Second and third arg RSTART and REND specify the region to operate on. This command operates on (the accessible part of) all lines whose accessible part is entirely contained in the region determined by RSTART
and REND. (A newline ending a line counts as part of that line.) If RSTART
is non-nil, REND also has to be given.

Interactively, in Transient Mark mode when the mark is active, operate on all lines whose accessible part is entirely contained in the region. Otherwise, the command applies to all lines starting after point. When calling this function from Lisp, you can pretend that it was called interactively by passing a non-nil INTERACTIVE argument.

This function starts looking for the next match from the end of the previous match. Hence, it ignores matches that overlap a previously found match.

View in manual

Probably introduced at or before Emacs version 18.

Key Bindings

Aliases

delete-non-matching-lines

Source Code

;; Defined in /usr/src/emacs/lisp/replace.el.gz
(defun keep-lines (regexp &optional rstart rend interactive)
  "Delete all lines except those containing matches for REGEXP.
A match split across lines preserves all the lines it lies in.
When called from Lisp (and usually interactively as well, see below)
applies to all lines starting after point.

If REGEXP contains upper case characters (excluding those preceded by `\\')
and `search-upper-case' is non-nil, the matching is case-sensitive.

Second and third arg RSTART and REND specify the region to operate on.
This command operates on (the accessible part of) all lines whose
accessible part is entirely contained in the region determined by RSTART
and REND.  (A newline ending a line counts as part of that line.)  If RSTART
is non-nil, REND also has to be given.

Interactively, in Transient Mark mode when the mark is active, operate
on all lines whose accessible part is entirely contained in the region.
Otherwise, the command applies to all lines starting after point.
When calling this function from Lisp, you can pretend that it was
called interactively by passing a non-nil INTERACTIVE argument.

This function starts looking for the next match from the end of
the previous match.  Hence, it ignores matches that overlap
a previously found match."
  (interactive
   (progn
     (barf-if-buffer-read-only)
     (keep-lines-read-args "Keep lines containing match for regexp")))
  (if rstart
      (progn
	(goto-char (min rstart rend))
	(setq rend
	      (progn
		(save-excursion
		  (goto-char (max rstart rend))
		  (unless (or (bolp) (eobp))
		    (forward-line 0))
		  (point-marker)))))
    (if (and interactive (use-region-p))
	(setq rstart (region-beginning)
	      rend (progn
		     (goto-char (region-end))
		     (unless (or (bolp) (eobp))
		       (forward-line 0))
		     (point-marker)))
      (setq rstart (point)
	    rend (point-max-marker)))
    (goto-char rstart))
  (save-excursion
    (or (bolp) (forward-line 1))
    (let ((start (point))
	  (case-fold-search
	   (if (and case-fold-search search-upper-case)
	       (isearch-no-upper-case-p regexp t)
	     case-fold-search)))
      (while (< (point) rend)
	;; Start is first char not preserved by previous match.
	(if (not (re-search-forward regexp rend 'move))
	    (delete-region start rend)
	  (let ((end (save-excursion (goto-char (match-beginning 0))
				     (forward-line 0)
				     (point))))
	    ;; Now end is first char preserved by the new match.
	    (if (< start end)
		(delete-region start end))))

	(setq start (save-excursion (forward-line 1) (point)))
	;; If the match was empty, avoid matching again at same place.
	(and (< (point) rend)
	     (= (match-beginning 0) (match-end 0))
	     (forward-char 1)))))
  (set-marker rend nil)
  nil)