Skip to content

Commit

Permalink
fix multiline string literals
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobly0 committed Apr 14, 2024
1 parent c914dce commit 6ec406c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 51 deletions.
16 changes: 13 additions & 3 deletions test/zig-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const string =
;"
'(("const" font-lock-keyword-face)
("string" font-lock-variable-name-face)
("\\\\ This newline is NOT escaped \\\n" zig-multiline-string-face))))
("\\\\ This newline is NOT escaped \\" zig-multiline-string-face))))

(ert-deftest test-font-lock-backslash-in-str-literal ()
(zig-test-font-lock
Expand Down Expand Up @@ -100,8 +100,8 @@ const python =
;"
'(("const" font-lock-keyword-face)
("python" font-lock-variable-name-face)
("\\\\def main():\n" zig-multiline-string-face)
("\\\\ print(\"Hello, world!\")\n" zig-multiline-string-face))))
("\\\\def main():" zig-multiline-string-face)
("\\\\ print(\"Hello, world!\")" zig-multiline-string-face))))

(ert-deftest test-font-lock-parameters-pointers-and-arrays ()
(zig-test-font-lock
Expand Down Expand Up @@ -177,6 +177,16 @@ const python =
("u123" font-lock-type-face)
("i55555" font-lock-type-face))))

(ert-deftest test-font-lock-escaped-backslash ()
(zig-test-font-lock
"const a = foo('\\\\', \"C:\\\\\", \\\\
);"
'(("const" font-lock-keyword-face)
("a" font-lock-variable-name-face)
("'\\\\'" font-lock-string-face)
("\"C:\\\\\"" font-lock-string-face)
("\\\\" zig-multiline-string-face))))

;;===========================================================================;;
;; Indentation tests

Expand Down
67 changes: 19 additions & 48 deletions zig-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -361,18 +361,19 @@ This is written mainly to be used as `end-of-defun-function' for Zig."
(and (not (looking-at " *\\(//[^\n]*\\)?\n"))
(current-column)))
(+ prev-block-indent-col zig-indent-offset))))
;; is-expr-continutation: True if this line continues an
;; is-expr-continuation: True if this line continues an
;; expression from the previous line, false otherwise.
(is-expr-continutation
(is-expr-continuation
(and
(not (looking-at "[]});]\\|else"))
(save-excursion
(zig-skip-backwards-past-whitespace-and-comments)
(when (> (point) 1)
(backward-char)
(not (looking-at "[,;([{}]")))))))
(or (zig-currently-in-str)
(not (looking-at "[,;([{}]"))))))))
;; Now we can calculate indent-col:
(if is-expr-continutation
(if is-expr-continuation
(+ base-indent-col zig-indent-offset)
base-indent-col)))))
;; If point is within the indentation whitespace, move it to the end of the
Expand All @@ -383,53 +384,23 @@ This is written mainly to be used as `end-of-defun-function' for Zig."
(indent-line-to indent-col)
(save-excursion (indent-line-to indent-col)))))

(defun zig-syntax-propertize-to-newline-if-in-multiline-str (end)
;; First, we need to check if we're in a multiline string literal; if we're
;; not, do nothing.
(when (zig-currently-in-str)
(let ((start (zig-start-of-current-str-or-comment)))
(when (save-excursion
(goto-char start)
(looking-at "\\\\\\\\"))
;; At this point, we've determined that we're within a multiline string
;; literal. Let `stop' be the position of the closing newline, or
;; `end', whichever comes first.
(let ((stop (if (save-excursion
(goto-char start)
(re-search-forward "\n" end t))
(prog1 (match-end 0)
;; We found the closing newline, so mark it as the
;; end of this string literal.
(put-text-property (match-beginning 0)
(match-end 0)
'syntax-table
(string-to-syntax "|")))
end)))
;; Zig multiline string literals don't support escapes, so mark all
;; backslashes (up to `stop') as punctation instead of escapes.
(save-excursion
(goto-char (1+ start))
(while (re-search-forward "\\\\" stop t)
(put-text-property (match-beginning 0) (match-end 0)
'syntax-table (string-to-syntax "."))
(goto-char (match-end 0))))
;; Move to the end of the string (or `end'), so that
;; zig-syntax-propertize can pick up from there.
(goto-char stop))))))
(defun zig-syntax-propertize-multiline-string (end)
(let* ((eol (save-excursion (search-forward "\n" end t)))
(stop (or eol end)))
(while (search-forward "\\" stop t)
(put-text-property (match-beginning 0) (match-end 0) 'syntax-table (string-to-syntax ".")))
(when eol (put-text-property (- eol 2) (1- eol) 'syntax-table (string-to-syntax "|")))
(goto-char stop)))

(defun zig-syntax-propertize (start end)
(goto-char start)
(zig-syntax-propertize-to-newline-if-in-multiline-str end)
(funcall
(syntax-propertize-rules
;; Multiline strings
;; Do not match backslashes that are preceded by single or
;; double-quotes.
("[^\\'\"]c?\\(\\\\\\)\\\\"
(1 (prog1 "|"
(goto-char (match-end 0))
(zig-syntax-propertize-to-newline-if-in-multiline-str end)))))
(point) end))
(when (eq t (zig-currently-in-str))
(zig-syntax-propertize-multiline-string end))
(while (search-forward "\\\\" end t)
(when (null (save-excursion (backward-char 2) (zig-currently-in-str)))
(backward-char)
(put-text-property (match-beginning 0) (point) 'syntax-table (string-to-syntax "|"))
(zig-syntax-propertize-multiline-string end))))

(defun zig-mode-syntactic-face-function (state)
(save-excursion
Expand Down

0 comments on commit 6ec406c

Please sign in to comment.