comparison lisp/replace.el @ 1069:13daf40fb997

[xemacs-hg @ 2002-10-24 14:59:22 by youngs] 2002-10-25 Scott Evans <gse@antisleep.com> * replace.el (operate-on-non-matching-lines) (operate-on-non-matching-lines): Generalized from delete-non-matching-lines and delete-matching-lines. The "operate" versions work with regions, can copy to the kill ring, and return the number of lines copied/deleted. (delete-non-matching-lines): Use operate-on-non-matching-lines. (delete-matching-lines): Use operate-on-matching-lines. (kill-non-matching-lines): New. (copy-non-matching-lines): New. (kill-matching-lines): New. (copy-matching-lines): New.
author youngs
date Thu, 24 Oct 2002 14:59:27 +0000
parents e7ef97881643
children 1b0339b048ce
comparison
equal deleted inserted replaced
1068:9d75b4fe084c 1069:13daf40fb997
210 which will run faster and will not set the mark or print anything." 210 which will run faster and will not set the mark or print anything."
211 (interactive (query-replace-read-args "Replace regexp" t)) 211 (interactive (query-replace-read-args "Replace regexp" t))
212 (perform-replace regexp to-string nil t delimited)) 212 (perform-replace regexp to-string nil t delimited))
213 213
214 214
215
216 ;; gse wonders: Is there a better place for this to go? Might other packages
217 ;; want to use it?
215 (defvar regexp-history nil 218 (defvar regexp-history nil
216 "History list for some commands that read regular expressions.") 219 "History list for some commands that read regular expressions.")
217 220
221 (defun operate-on-non-matching-lines (regexp delete kill &optional beg end)
222 "Internal function used by delete-non-matching-lines,
223 kill-non-matching-lines, and copy-matching-lines.
224
225 REGEXP is a regular expression to *not* match when performing
226 operations.
227
228 If DELETE is non-nil, the lines of text are deleted. It doesn't make
229 sense to set this to nil if KILL is nil -- nothing will happen.
230
231 If KILL is non-nil, the lines of text are stored in the kill ring (as
232 one block of text).
233
234 BEG and END, if non-nil, specify the start and end locations to work
235 within. If these are nil, point and point-max are used.
236
237 A match split across lines preserves all the lines it lies in.
238 Applies to all lines after point.
239
240 Returns the number of lines matched."
241 (with-search-caps-disable-folding regexp t
242 (save-excursion
243 ;; Move to a beginning point if specified.
244 (when beg (goto-char beg))
245 ;; Always start on the beginning of a line.
246 (or (bolp) (forward-line 1))
247
248 (let ((matched-text nil)
249 (curmatch-start (point))
250 (limit (copy-marker (point-max))))
251 ;; Limit search if limits were specified.
252 (when end (setq limit (copy-marker end)))
253
254 ;; Search. Stop if we are at end of buffer or outside the
255 ;; limit.
256 (while (not (or
257 (eobp)
258 (and limit (>= (point) limit))))
259 ;; curmatch-start is first char not preserved by previous match.
260 (if (not (re-search-forward regexp limit 'move))
261 (let ((curmatch-end limit))
262 (setq matched-text (concat matched-text (buffer-substring curmatch-start curmatch-end)))
263 (if delete (delete-region curmatch-start curmatch-end)))
264 (let ((curmatch-end (save-excursion (goto-char (match-beginning 0))
265 (beginning-of-line)
266 (point))))
267 ;; Now curmatch-end is first char preserved by the new match.
268 (if (< curmatch-start curmatch-end)
269 (progn
270 (setq matched-text (concat matched-text (buffer-substring curmatch-start curmatch-end)))
271 (if delete (delete-region curmatch-start curmatch-end))))))
272 (setq curmatch-start (save-excursion (forward-line 1)
273 (point)))
274 ;; If the match was empty, avoid matching again at same place.
275 (and (not (eobp)) (= (match-beginning 0) (match-end 0))
276 (forward-char 1)))
277
278 ;; If any lines were matched and KILL is non-nil, insert the
279 ;; matched lines into the kill ring.
280 (if (and matched-text kill) (kill-new matched-text))
281
282 ;; Return the number of matched lines.
283 (with-temp-buffer
284 ;; Use concat to make a string even if matched-text is nil.
285 (insert (concat matched-text))
286 (count-lines (point-min) (point-max)))
287 ))))
288
218 (define-function 'keep-lines 'delete-non-matching-lines) 289 (define-function 'keep-lines 'delete-non-matching-lines)
219 (defun delete-non-matching-lines (regexp) 290 (defun delete-non-matching-lines (regexp)
220 "Delete all lines except those containing matches for REGEXP. 291 "Delete lines that do not match REGEXP, from point to the end of the
221 A match split across lines preserves all the lines it lies in. 292 buffer (or within the region, if it is active)."
222 Applies to all lines after point."
223 (interactive (list (read-from-minibuffer 293 (interactive (list (read-from-minibuffer
224 "Keep lines (containing match for regexp): " 294 "Keep lines (containing match for regexp): "
225 nil nil nil 'regexp-history))) 295 nil nil nil 'regexp-history)))
226 (with-interactive-search-caps-disable-folding regexp t 296 (let ((beg nil)
297 (end nil)
298 (count nil))
299 (when (region-active-p)
300 (setq beg (region-beginning))
301 (setq end (region-end)))
302 (setq count (operate-on-non-matching-lines regexp t nil beg end))
303 (message "%i lines deleted" count)))
304
305 (defun kill-non-matching-lines (regexp)
306 "Delete the lines that do not match REGEXP, from point to the end of
307 the buffer (or within the region, if it is active). The deleted lines
308 are placed in the kill ring as one block of text."
309 (interactive (list (read-from-minibuffer
310 "Kill non-matching lines (regexp): "
311 nil nil nil 'regexp-history)))
312 (let ((beg nil)
313 (end nil)
314 (count nil))
315 (when (region-active-p)
316 (setq beg (region-beginning))
317 (setq end (region-end)))
318 (setq count (operate-on-non-matching-lines regexp t t beg end))
319 (message "%i lines killed" count)))
320
321 (defun copy-non-matching-lines (regexp)
322 "Find all lines that do not match REGEXP from point to the end of the
323 buffer (or within the region, if it is active), and place them in the
324 kill ring as one block of text."
325 (interactive (list (read-from-minibuffer
326 "Copy non-matching lines (regexp): "
327 nil nil nil 'regexp-history)))
328 (let ((beg nil)
329 (end nil)
330 (count nil))
331 (when (region-active-p)
332 (setq beg (region-beginning))
333 (setq end (region-end)))
334 (setq count (operate-on-non-matching-lines regexp nil t beg end))
335 (message "%i lines copied" count)))
336
337 (defun operate-on-matching-lines (regexp delete kill &optional beg end)
338 "Internal function used by delete-matching-lines, kill-matching-lines,
339 and copy-matching-lines.
340
341 If DELETE is non-nil, the lines of text are deleted. It doesn't make
342 sense to set this to nil if KILL is nil -- nothing will happen.
343
344 If KILL is non-nil, the lines of text are stored in the kill ring (as
345 one block of text).
346
347 BEG and END, if non-nil, specify the start and end locations to work
348 within. If these are nil, point and point-max are used.
349
350 If a match is split across lines, all the lines it lies in are deleted.
351 Applies to lines after point.
352 Returns the number of lines matched."
353 (with-search-caps-disable-folding regexp t
227 (save-excursion 354 (save-excursion
228 (or (bolp) (forward-line 1)) 355 (let ((matched-text nil)
229 (let ((start (point))) 356 (curmatch-start nil)
230 (while (not (eobp)) 357 (curmatch-end nil)
231 ;; Start is first char not preserved by previous match. 358 (limit nil))
232 (if (not (re-search-forward regexp nil 'move)) 359
233 (delete-region start (point-max)) 360 ;; Limit search if limits were specified.
234 (let ((end (save-excursion (goto-char (match-beginning 0)) 361 (when beg (goto-char beg))
235 (beginning-of-line) 362 (when end (setq limit (copy-marker end)))
236 (point)))) 363
237 ;; Now end is first char preserved by the new match. 364 (while (and (not (eobp))
238 (if (< start end) 365 (re-search-forward regexp limit t))
239 (delete-region start end)))) 366 (setq curmatch-start (save-excursion (goto-char (match-beginning 0))
240 (setq start (save-excursion (forward-line 1) 367 (beginning-of-line)
241 (point))) 368 (point)))
242 ;; If the match was empty, avoid matching again at same place. 369 (setq curmatch-end (progn (forward-line 1) (point)))
243 (and (not (eobp)) (= (match-beginning 0) (match-end 0)) 370 (setq matched-text (concat matched-text (buffer-substring curmatch-start curmatch-end)))
244 (forward-char 1))))))) 371 (if delete (delete-region curmatch-start curmatch-end)))
372
373 (if (and matched-text kill) (kill-new matched-text))
374
375 ;; Return the number of matched lines.
376 (with-temp-buffer
377 ;; Use concat to make a string even if matched-text is nil.
378 (insert (concat matched-text))
379 (count-lines (point-min) (point-max)))
380 ))))
245 381
246 (define-function 'flush-lines 'delete-matching-lines) 382 (define-function 'flush-lines 'delete-matching-lines)
247 (defun delete-matching-lines (regexp) 383 (defun delete-matching-lines (regexp)
248 "Delete lines containing matches for REGEXP. 384 "Delete the lines that match REGEXP, from point to the end of the
249 If a match is split across lines, all the lines it lies in are deleted. 385 buffer (or within the region, if it is active)."
250 Applies to lines after point."
251 (interactive (list (read-from-minibuffer 386 (interactive (list (read-from-minibuffer
252 "Flush lines (containing match for regexp): " 387 "Flush lines (containing match for regexp): "
253 nil nil nil 'regexp-history))) 388 nil nil nil 'regexp-history)))
254 (with-interactive-search-caps-disable-folding regexp t 389 (let ((beg nil)
255 (save-excursion 390 (end nil)
256 (while (and (not (eobp)) 391 (count nil))
257 (re-search-forward regexp nil t)) 392 (when (region-active-p)
258 (delete-region (save-excursion (goto-char (match-beginning 0)) 393 (setq beg (region-beginning))
259 (beginning-of-line) 394 (setq end (region-end)))
260 (point)) 395 (setq count (operate-on-matching-lines regexp t nil beg end))
261 (progn (forward-line 1) (point))))))) 396 (message "%i lines deleted" count)))
397
398 (defun kill-matching-lines (regexp)
399 "Delete the lines that match REGEXP, from point to the end of the
400 buffer (or within the region, if it is active). The deleted lines are
401 placed in the kill ring as one block of text."
402 (interactive (list (read-from-minibuffer
403 "Kill lines (containing match for regexp): "
404 nil nil nil 'regexp-history)))
405 (let ((beg nil)
406 (end nil)
407 (count nil))
408 (when (region-active-p)
409 (setq beg (region-beginning))
410 (setq end (region-end)))
411 (setq count (operate-on-matching-lines regexp t t beg end))
412 (message "%i lines killed" count)))
413
414 (defun copy-matching-lines (regexp)
415 "Find all lines that match REGEXP from point to the end of the
416 buffer (or within the region, if it is active), and place them in the
417 kill ring as one block of text."
418 (interactive (list (read-from-minibuffer
419 "Copy lines (containing match for regexp): "
420 nil nil nil 'regexp-history)))
421 (let ((beg nil)
422 (end nil)
423 (count nil))
424 (when (region-active-p)
425 (setq beg (region-beginning))
426 (setq end (region-end)))
427 (setq count (operate-on-matching-lines regexp nil t beg end))
428 (message "%i lines copied" count)))
262 429
263 (define-function 'how-many 'count-matches) 430 (define-function 'how-many 'count-matches)
264 (defun count-matches (regexp) 431 (defun count-matches (regexp)
265 "Print number of matches for REGEXP following point." 432 "Print number of matches for REGEXP following point."
266 (interactive (list (read-from-minibuffer 433 (interactive (list (read-from-minibuffer