1

I made a function to filter unimportant lines from a CSS file I copied. I only want lines with the words "color" and "background" to remain in my buffer after the point the function is run. When I run the function it moves point to the next valid match but doesn't kill any lines. I want to kill all lines forward of point that don't match. I would run the command until the end of the buffer is reached if there is no convenient test to determine when the end of the buffer is reached. I'm new to Emacs LISP. How can I fix the function to kill the non-matching lines?

(defun my-color-filter ()
  (interactive)
  (while (not (re-search-forward "^.*\\(?:color\\|background\\).*$" nil t)) (beginning-of-line) (kill-line))
  )
haleonj
  • 125
  • 5

2 Answers2

3

Please take a look at keep-lines and friends1:

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.

Thus you would do M-x keep-lines RET ^.\(?:color\|background\).$ RET,


1 or type C-hig (emacs)Other Repeating Search RET

phils
  • 48,657
  • 3
  • 76
  • 115
sds
  • 5,928
  • 20
  • 39
  • Can you add examples how to use these functions? It might also make sense to add quotes from the documentation so this answer is meaningful even if documentation from your link is down. –  Jun 07 '19 at 17:03
  • @DoMiNeLa10: this is the official link, for it to go down you would need a pretty dramatic disaster. – sds Jun 07 '19 at 17:12
  • Even if the documentation stays up, this link could break when it's updated. Not to mention, when you quote a part of a page, you can be more precise rather than pointing to an entire section of the manual. –  Jun 07 '19 at 17:48
  • That whole page, ever single word of it, is eminently relevant to this specific question. And, no, the link will _not_ break when the page is updated. Emacs maintainers are pretty careful about these these things. – sds Jun 07 '19 at 17:50
  • https://emacs.stackexchange.com/a/40598/105 – Drew Jun 07 '19 at 19:42
  • The question seems to be "How can I fix the function to kill the non-matching lines", not "How can I delete non-matching lines." This answer doesn't address the question (except by suggesting to use `keep-lines` in OP's function body). – Drew Jun 07 '19 at 19:44
  • @Drew: is the question were about _code_, it would have been on SO, not here ;-) – sds Jun 07 '19 at 19:45
  • 1
    @sds: Why do you think that? – Drew Jun 07 '19 at 20:28
3

The suggestion by sds to use keep-lines is of course the way to go. If you are curious why your own function doesn't work, here is the reason: The while iteration terminates the first time you reach a line containing color or background. Instead, you should iterate over all lines and test each of them for color or background. Like this:

(defun my-color-filter ()
  (interactive)
  (while (re-search-forward (rx (group bol (* nonl) eol)) nil t nil)
    (if (not (string-match (rx (or "color" "background")) (match-string 1)))
        (progn (beginning-of-line) (kill-line)) 
        (forward-line))))
StarBug
  • 479
  • 4
  • 10