I'm trying to make an expression that would match the text foo if it's not on a commented out line.

;; foo ; <= not this
bar    ; <= not this
foo    ; <= this

Now rx.el can exclude character syntax classes, like:

 (not (syntax comment-start))
 (not (syntax comment-end)))

But this will only skip the comment character itself, not the whole line. How can I make it to completely skip the commented out line?

  • 2
    Can you please give an example of the code using this regular expression? Different uses require different regular expressions or approaches.
    – Basil
    Aug 8 '17 at 9:12
  • 1
    Please explain how you want to use this regular expression. What you want to do can't be done with a regular expression, but it can probably be done in two lines of code. These two lines depend on what you want to do, so if you want help, you need to tell us what you want to do (and not just the way you tried which doesn't do what you need). Also, your explanation needs to be in your question. Your question must stand on its own. A link to a large, changing code file doesn't help. Aug 9 '17 at 0:34

How can I make it to completely skip the commented out line?

"Skipping lines" is not an inherent capability of regular expressions. Regexps either do or do not match whatever input they are given. The line skipping logic merely can be (and in Emacs world, usually is) built around regular expressions. Without further examples of your code or intent I cannot give a complete or accurate answer.

Having said that, here is some sample code which accumulates a list of all non-empty lines in a buffer which do not begin with a comment:

  (goto-char (point-min))
  (let (lines)
    (while (< (point) (point-max))
      (when (re-search-forward (rx bol (not (syntax comment-start)))
        (push (buffer-substring-no-properties
    (nreverse lines)))

The rx form above which determines such lines expands to the regexp "^\\S<". The lines are guaranteed to be non-empty by bounding the re-search-forward to (line-end-position). An unbounded search would include empty lines.

Evaluating the code above in a buffer with the following contents


;; bar
alice ; bob

results in the list of strings

("foo" "baz" "alice ; bob")

Here is another example which accumulates a list of all non-empty strings between the beginning of each line and either the start of a comment or the end of the line, whichever appears first:

  (goto-char (point-min))
  (let (lines)
    (while (< (point) (point-max))
      (when (re-search-forward (rx bol (group (+ (not (syntax comment-start)))))
        (push (match-string-no-properties 1) lines))
    (nreverse lines)))

The rx form used in this case expands to "^\\(\\S<+\\)" and evaluating the code in the same buffer as before gives

("foo" "baz" "alice ")

OK, back up. I was doing my tests in the scratch buffer, but I found out that the rx.el (syntax comment-start) abstract form does not work at least in my prog-mode derived mode. And yet, the comment-start local variable is correctly set, go figure.

The only condition I found to skip comment lines (not part of it) in another mode than Elisp is this:

(when (eq 'comment (syntax-ppss-context (syntax-ppss)))
  (message "This line contains a comment"))

I found it in python.el that also uses rx too but not to detect comments.

Also relevant is

(with-syntax-table my-mode-syntax-table
    (forward-comment (point-max)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.