Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong highlighting when multi-line string is closed just before an escaped quote #119

Closed
ronisbr opened this issue Apr 21, 2020 · 4 comments · Fixed by #133
Closed

Wrong highlighting when multi-line string is closed just before an escaped quote #119

ronisbr opened this issue Apr 21, 2020 · 4 comments · Fixed by #133

Comments

@ronisbr
Copy link
Contributor

ronisbr commented Apr 21, 2020

Hi!

The highlighting engine does not understand that a multi-line comment section (""") was ended if it ends just after an escaped quote:

Captura de Tela 2020-04-21 às 17 42 23

If I add a space between \" and """, then everything works.

@non-Jedi
Copy link
Contributor

This is the same problem as #15 which I tried to solve with #114. Unfortunately, that PR has strange transient behavior. Fontifying a buffer from scratch works fine but if you edit a triple-quoted string all text after the triple-quoted string is fontified a string until you reopen the buffer. Any help on fixing it would be appreciated. :)

@ronisbr
Copy link
Contributor Author

ronisbr commented Apr 22, 2020

Hi @non-Jedi

Unfortunately, I have close to zero experience in elisp to help you :( However, python has a similar syntax. They solved it by defining the following expression for the delimiters:

      (string-delimiter . ,(rx (and
                                ;; Match even number of backslashes.
                                (or (not (any ?\\ ?\' ?\")) point
                                    ;; Quotes might be preceded by a escaped quote.
                                    (and (or (not (any ?\\)) point) ?\\
                                         (* ?\\ ?\\) (any ?\' ?\")))
                                (* ?\\ ?\\)
                                ;; Match single or triple quotes of any kind.
                                (group (or  "\"" "\"\"\"" "'" "'''"))))))

@ronisbr
Copy link
Contributor Author

ronisbr commented Apr 22, 2020

Actually, using this delimiter instead of the group in Julia mode seems to work:

(defconst julia-syntax-propertize-function
  (syntax-propertize-rules
   ;; triple-quoted strings are a single string rather than 3
   ((rx 
     (and
      ;; Match even number of backslashes.
      (or (not (any ?\\ ?\' ?\")) point
       ;; Quotes might be preceded by a escaped quote.
       (and (or (not (any ?\\)) point) ?\\
	(* ?\\ ?\\) (any ?\' ?\")))
      (* ?\\ ?\\)
      ;; Match single or triple quotes of any kind.
      (group (or  "\"" "\"\"\"" "'")))
     (and
      ;; Match even number of backslashes.
      (or (not (any ?\\ ?\' ?\")) point
       ;; Quotes might be preceded by a escaped quote.
       (and (or (not (any ?\\)) point) ?\\
	(* ?\\ ?\\) (any ?\' ?\")))
      (* ?\\ ?\\)
      ;; Match single or triple quotes of any kind.
      (group (or  "\"" "\"\"\"" "'")))
     (and
      ;; Match even number of backslashes.
      (or (not (any ?\\ ?\' ?\")) point
       ;; Quotes might be preceded by a escaped quote.
       (and (or (not (any ?\\)) point) ?\\
	(* ?\\ ?\\) (any ?\' ?\")))
      (* ?\\ ?\\)
      ;; Match single or triple quotes of any kind.
      (group (or  "\"" "\"\"\"" "'"))))
	;; First " starts a string if not already inside a string (or comment)
    (1 (let ((ppss (save-excursion (syntax-ppss (match-beginning 0)))))
         (unless (or (nth 3 ppss) (nth 4 ppss))
           (string-to-syntax "|"))))
    ;; Last " ends a string if already inside a string
    (2 (and (nth 3 (save-excursion (syntax-ppss (match-beginning 0))))
            (string-to-syntax "|"))))
   ;; backslash acts as an operator if it's not inside a string
   ("\\\\"
    (0 (unless (nth 3 (save-excursion (syntax-ppss (match-beginning 0))))
         (string-to-syntax "."))))
   (julia-char-regex
    (1 "\"")                    ; Treat ' as a string delimiter.
    (2 ".")                     ; Don't highlight anything between.
    (3 "\"")))) ; Treat the last " in """ as a string delimiter.

Captura de Tela 2020-04-22 às 10 25 14

However, I will not dare to submit a PR because I know you guys can write a much more cleaner code than I did :D Up to now, I have found no regressions so far and this does not have the transient behavior mentioned by @non-Jedi .

EDIT: Julia does not use ''' as in Python.

@ronisbr
Copy link
Contributor Author

ronisbr commented May 5, 2020

There is a problem with my regex. It does fix \"""". However, in Julia, the following string is valid:

"""
""
"""

Thus, we must have something that, if the string is started by """, then it must end by """. Question: should I submit a PR to fix the reported problem? Notice that this behavior also exists in current version. So there is not a regression.

Nerver mind, there will be a regression.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants