[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Scheme Mode and Regular Expression Literals
From: |
Stefan Monnier |
Subject: |
Re: Scheme Mode and Regular Expression Literals |
Date: |
Tue, 19 Mar 2024 09:36:40 -0400 |
User-agent: |
Gnus/5.13 (Gnus v5.13) |
> Now I put the logic to scan the beginning of sexp comments and regular
> expressions in syntax-propertize-rules macro. I use different functions
> to be invoked by them, because the beginning of regular expressions
> need to be canceled when they are already in normal strings or
> comments.
We usually don't bother doing that because it affects only navigation
*within* those strings/comments :-)
The code looks pretty good now. Can you turn it into a patch against
`scheme.el`?
In the mean time, see my comments below.
> (defun scheme-syntax-propertize-regexp-end (_ end)
> (let* ((state (syntax-ppss))
> (within-str (nth 3 state))
> (within-comm (nth 4 state))
> (start-delim-pos (nth 8 state)))
> (if (and (not within-comm)
> (and within-str
> (string=
> (buffer-substring-no-properties
> start-delim-pos
> (1+ start-delim-pos))
> "#")))
(eq ?# (char-after start-delim-pos)) would be simpler and more efficient.
Also, `within-str` and `within-comm` are mutually exclusive, so the
`(and (not within-comm)` is redundant.
> (let ((end-found nil))
> (while (and
> (not end-found)
> (re-search-forward "\\(/\\)" end t))
You don't need the \\( \\), you can just use (match-beginning 0)
instead, which will let Emacs use the simpler non-regexp
search algorithm.
> (progn
> (if
> (not (char-equal
> (char-before (match-beginning 1))
> ?\\ ))
This fails for #/foo\\/
In sh-script.el I used
(eq -1 (% (save-excursion (skip-chars-backward "\\\\")) 2))
At other places we let the regexp matcher skip those by using a hideous
regexp such as
"[^\\]\\(?:\\\\\\\\\\)*/"
(but this regexp fails to match the closing / if it's right at the
starting position, so you have to use a workaround such as doing
a (forward-char -1) before searching).
> (progn
> (put-text-property
> (match-beginning 1)
> (1+ (match-beginning 1))
Aka (match-end 1).
> 'syntax-table (string-to-syntax "|"))
> (setq end-found t)
> )))))
> )))
You can avoid the `end-found` thingy with
(while (and (re-search-forward "/" end 'move)
(eq -1 (% (save-excursion (skip-chars-backward "\\\\")) 2))))
(when (< (point) end) ;; Double check that `re-search-forward` succeeded.
(put-text-property ...))
> (defun scheme-syntax-propertize-regexp (_ end)
> (let* ((match-start-state (save-excursion
> (syntax-ppss (match-beginning 1))))
> (within-str (nth 3 match-start-state))
> (within-comm (nth 4 match-start-state)))
> (if (or within-str within-comm)
(nth 8 match-start-state) gives the same boolean answer as this `or`.
And instead of having `syntax-propertize-rules` add a | syntax and then
you replacing it with "@" you could also tell `syntax-propertize-rules`
when to do it with something like:
("\\(#\\)/" (1 (when (null (nth 8 (save-excursion
(syntax-ppss (match-beginning 0)))))
(prog1 "|"
(scheme-syntax-propertize-regexp-end
(point) end)))))
tho `syntax-propertize-rules` sadly doesn't currently handle this
combination of `when` and `prog1` :-(
("\\(#\\)/" (1 (when (null (nth 8 (save-excursion
(syntax-ppss (match-beginning 0)))))
(put-text-property ... "|" ..)
(scheme-syntax-propertize-regexp-end
(point) end)
nil)))
- Stefan