0

The following code is an excerpt from the elisp tutorial, section 14.6.

(while (re-search-forward "^(defun" nil t)
    (setq lengths-list (cons (count-words-in-defun) lengths-list)))

Placing the cursor just before the code and executing (forward-sexp) will fail, because of the ( symbol imbedded in the regexp "^(defun". My ugly remedy is below:

(setq my-regexp (concat "^" (char-to-string 40) "defun"))
(while (re-search-forward my-regexp nil t)
    (setq lengths-list (cons (count-words-in-defun) lengths-list)))

Is there a less ugly approach? Alternatively, is there a wrapper for (forward-sexp) that provides optional arguments to ignore imbedded quotes and ignore imbedded comments (e.g. ;...)?

If not, I will reference this posting as a feature request for both forward-sexp and backward-sexp.

4
  • WFM in 27.0.50 and probably earlier too. What is your emacs-version?
    – sds
    Commented Oct 22, 2018 at 16:24
  • 3
    forward-sexp does the right thing, but only if you're using the right major-mode. since how to skip strings and comments is something that depends on the language.
    – Stefan
    Commented Oct 22, 2018 at 16:35
  • @sds I just confirmed Stefan's comment. I am using emacs 25.3.1, and the problem exists in text mode but is resolved okay in lisp mode.
    – zugzwang
    Commented Oct 22, 2018 at 16:52
  • see also my comment to the answer from sds.
    – zugzwang
    Commented Oct 22, 2018 at 17:02

1 Answer 1

2

While forward-sexp works just fine for me on the code in question (in Emacs 27.0.50), the standard workaround is to add a single backslash, e.g., "^\(defun ".

One place where it actually is needed is when doc string contains code. Emacs uses a simple heuristic ("line starting with a paren starts a function") for beginning-of-defun and code like this:

(defun foo (...)
  "Blah blah...
Sample code:
(foo 1 2 3)
Blah"
  (actual code))

breaks the heuristic.

The standard workaround is to add a backslash:

(defun foo (...)
  "Blah blah...
Sample code:
\(foo 1 2 3)
Blah"
  (actual code))
2
  • Just discovered that the problem is mode specific; I keep my elisp tutorial notes in elisp_notes_todo.txt. Per my comment above (reply to Stefan), I can resolve my problem via M-x lisp-mode, then forward-sexp, then M-x text-mode. Assuming that your answer works, it will be helpful for an unbalanced parenthesis in the doc string. Thanks
    – zugzwang
    Commented Oct 22, 2018 at 16:58
  • my bad. actually, applying forward-sexp on the first section of code in sds' answer works okay, in lisp mode. Experimenting, I just discovered that forward-sexp also works okay in lisp mode when the doc string has an unbalanced parenthesis, so my previous comment is flawed. So, since temporarily changing to lisp-mode seems to resolve all forward-sexp problems, sds' approach can apparently be restricted to beginning-of-defun problems.
    – zugzwang
    Commented Oct 22, 2018 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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