Skip to content
This repository was archived by the owner on Nov 26, 2025. It is now read-only.

Commit d78231a

Browse files
committed
fix multiline string literals
1 parent 53d4939 commit d78231a

File tree

2 files changed

+32
-51
lines changed

2 files changed

+32
-51
lines changed

test/zig-tests.el

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const string =
4040
;"
4141
'(("const" font-lock-keyword-face)
4242
("string" font-lock-variable-name-face)
43-
("\\\\ This newline is NOT escaped \\\n" zig-multiline-string-face))))
43+
("\\\\ This newline is NOT escaped \\" zig-multiline-string-face))))
4444

4545
(ert-deftest test-font-lock-backslash-in-str-literal ()
4646
(zig-test-font-lock
@@ -100,8 +100,8 @@ const python =
100100
;"
101101
'(("const" font-lock-keyword-face)
102102
("python" font-lock-variable-name-face)
103-
("\\\\def main():\n" zig-multiline-string-face)
104-
("\\\\ print(\"Hello, world!\")\n" zig-multiline-string-face))))
103+
("\\\\def main():" zig-multiline-string-face)
104+
("\\\\ print(\"Hello, world!\")" zig-multiline-string-face))))
105105

106106
(ert-deftest test-font-lock-parameters-pointers-and-arrays ()
107107
(zig-test-font-lock
@@ -175,6 +175,16 @@ const python =
175175
("i123" font-lock-type-face)
176176
("u55555" font-lock-type-face))))
177177

178+
(ert-deftest test-font-lock-escaped-backslash ()
179+
(zig-test-font-lock
180+
"const a = foo('\\\\', \"C:\\\\\", \\\\
181+
);"
182+
'(("const" font-lock-keyword-face)
183+
("a" font-lock-variable-name-face)
184+
("'\\\\'" font-lock-string-face)
185+
("\"C:\\\\\"" font-lock-string-face)
186+
("\\\\" zig-multiline-string-face))))
187+
178188
;;===========================================================================;;
179189
;; Indentation tests
180190

zig-mode.el

Lines changed: 19 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -361,18 +361,19 @@ This is written mainly to be used as `end-of-defun-function' for Zig."
361361
(and (not (looking-at " *\\(//[^\n]*\\)?\n"))
362362
(current-column)))
363363
(+ prev-block-indent-col zig-indent-offset))))
364-
;; is-expr-continutation: True if this line continues an
364+
;; is-expr-continuation: True if this line continues an
365365
;; expression from the previous line, false otherwise.
366-
(is-expr-continutation
366+
(is-expr-continuation
367367
(and
368368
(not (looking-at "[]});]\\|else"))
369369
(save-excursion
370370
(zig-skip-backwards-past-whitespace-and-comments)
371371
(when (> (point) 1)
372372
(backward-char)
373-
(not (looking-at "[,;([{}]")))))))
373+
(or (zig-currently-in-str)
374+
(not (looking-at "[,;([{}]"))))))))
374375
;; Now we can calculate indent-col:
375-
(if is-expr-continutation
376+
(if is-expr-continuation
376377
(+ base-indent-col zig-indent-offset)
377378
base-indent-col)))))
378379
;; If point is within the indentation whitespace, move it to the end of the
@@ -383,53 +384,23 @@ This is written mainly to be used as `end-of-defun-function' for Zig."
383384
(indent-line-to indent-col)
384385
(save-excursion (indent-line-to indent-col)))))
385386

386-
(defun zig-syntax-propertize-to-newline-if-in-multiline-str (end)
387-
;; First, we need to check if we're in a multiline string literal; if we're
388-
;; not, do nothing.
389-
(when (zig-currently-in-str)
390-
(let ((start (zig-start-of-current-str-or-comment)))
391-
(when (save-excursion
392-
(goto-char start)
393-
(looking-at "\\\\\\\\"))
394-
;; At this point, we've determined that we're within a multiline string
395-
;; literal. Let `stop' be the position of the closing newline, or
396-
;; `end', whichever comes first.
397-
(let ((stop (if (save-excursion
398-
(goto-char start)
399-
(re-search-forward "\n" end t))
400-
(prog1 (match-end 0)
401-
;; We found the closing newline, so mark it as the
402-
;; end of this string literal.
403-
(put-text-property (match-beginning 0)
404-
(match-end 0)
405-
'syntax-table
406-
(string-to-syntax "|")))
407-
end)))
408-
;; Zig multiline string literals don't support escapes, so mark all
409-
;; backslashes (up to `stop') as punctation instead of escapes.
410-
(save-excursion
411-
(goto-char (1+ start))
412-
(while (re-search-forward "\\\\" stop t)
413-
(put-text-property (match-beginning 0) (match-end 0)
414-
'syntax-table (string-to-syntax "."))
415-
(goto-char (match-end 0))))
416-
;; Move to the end of the string (or `end'), so that
417-
;; zig-syntax-propertize can pick up from there.
418-
(goto-char stop))))))
387+
(defun zig-syntax-propertize-multiline-string (end)
388+
(let* ((eol (save-excursion (search-forward "\n" end t)))
389+
(stop (or eol end)))
390+
(while (search-forward "\\" stop t)
391+
(put-text-property (match-beginning 0) (match-end 0) 'syntax-table (string-to-syntax ".")))
392+
(when eol (put-text-property (- eol 2) (1- eol) 'syntax-table (string-to-syntax "|")))
393+
(goto-char stop)))
419394

420395
(defun zig-syntax-propertize (start end)
421396
(goto-char start)
422-
(zig-syntax-propertize-to-newline-if-in-multiline-str end)
423-
(funcall
424-
(syntax-propertize-rules
425-
;; Multiline strings
426-
;; Do not match backslashes that are preceded by single or
427-
;; double-quotes.
428-
("[^\\'\"]c?\\(\\\\\\)\\\\"
429-
(1 (prog1 "|"
430-
(goto-char (match-end 0))
431-
(zig-syntax-propertize-to-newline-if-in-multiline-str end)))))
432-
(point) end))
397+
(when (eq t (zig-currently-in-str))
398+
(zig-syntax-propertize-multiline-string end))
399+
(while (search-forward "\\\\" end t)
400+
(when (null (save-excursion (backward-char 2) (zig-currently-in-str)))
401+
(backward-char)
402+
(put-text-property (match-beginning 0) (point) 'syntax-table (string-to-syntax "|"))
403+
(zig-syntax-propertize-multiline-string end))))
433404

434405
(defun zig-mode-syntactic-face-function (state)
435406
(save-excursion

0 commit comments

Comments
 (0)