Skip to content

Fix quotes with syntax properties #2

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions rust-mode-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,8 @@ fn bar() { }" 14 67))
"/**
*
*/"
8
"This is a very very very very very very very long string"
7
" This is a very very very very very very very long string"
"/**
* This is a very very very very
* very very very long string
Expand Down Expand Up @@ -317,8 +317,7 @@ fn foo() {
/*!
* this is a nested doc comment
*/

//! And so is this
\n //! And so is this
}"))

(ert-deftest indent-inside-braces ()
Expand Down Expand Up @@ -527,6 +526,18 @@ fn foo() {
"
))

;; Closing braces in single char literals and strings should not confuse the indentation
(ert-deftest indent-closing-braces-in-char-literals ()
(test-indent
"
fn foo() {
{ bar('}'); }
{ bar(']'); }
{ bar(')'); }
}
"
))

(setq rust-test-motion-string
"
fn fn1(arg: int) -> bool {
Expand Down Expand Up @@ -894,3 +905,17 @@ list of substrings of `STR' each followed by its face."
"/* #[foo] */"
'("/* " font-lock-comment-delimiter-face
"#[foo] */" font-lock-comment-face)))

(ert-deftest font-lock-double-quote-character-literal ()
(rust-test-font-lock
"'\"'; let"
'("'\"'" font-lock-string-face
"let" font-lock-keyword-face)))

(ert-deftest font-lock-single-quote-character-literal ()
(rust-test-font-lock
"fn main() { let ch = '\\''; }"
'("fn" font-lock-keyword-face
"main" font-lock-function-name-face
"let" font-lock-keyword-face
"'\\''" font-lock-string-face)))
61 changes: 47 additions & 14 deletions rust-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@

table))

(defvar rust-mode-character-literal-syntax-table
(let ((table (make-syntax-table rust-mode-syntax-table)))
(modify-syntax-entry ?' "\"" table)
(modify-syntax-entry ?\" "_" table)

table))

(defgroup rust-mode nil
"Support for Rust code."
:link '(url-link "http://www.rust-lang.org/")
Expand Down Expand Up @@ -259,14 +266,6 @@
;; Lifetimes like `'foo`
(,(concat "'" (rust-re-grab rust-re-ident) "[^']") 1 font-lock-variable-name-face)

;; Character constants, since they're not treated as strings
;; in order to have sufficient leeway to parse 'lifetime above.
(,(rust-re-grab "'[^']'") 1 font-lock-string-face)
(,(rust-re-grab "'\\\\[nrt]'") 1 font-lock-string-face)
(,(rust-re-grab "'\\\\x[[:xdigit:]]\\{2\\}'") 1 font-lock-string-face)
(,(rust-re-grab "'\\\\u[[:xdigit:]]\\{4\\}'") 1 font-lock-string-face)
(,(rust-re-grab "'\\\\U[[:xdigit:]]\\{8\\}'") 1 font-lock-string-face)

;; CamelCase Means Type Or Constructor
(,(rust-re-grabword rust-re-CamelCase) 1 font-lock-type-face)
)
Expand Down Expand Up @@ -439,12 +438,19 @@ Assume that this is called after beginning-of-defun. So point is
at the beginning of the defun body.

This is written mainly to be used as `end-of-defun-function' for Rust."
(interactive "p")
(interactive)
;; Find the opening brace
(re-search-forward "[{]" nil t)
(goto-char (match-beginning 0))
;; Go to the closing brace
(forward-sexp))
(if (re-search-forward "[{]" nil t)
(progn
(goto-char (match-beginning 0))
;; Go to the closing brace
(condition-case err
(forward-sexp)
(scan-error
;; The parentheses are unbalanced; instead of being unable to fontify, just jump to the end of the buffer
(goto-char (point-max)))))
;; There is no opening brace, so consider the whole buffer to be one "defun"
(goto-char (point-max))))

;; For compatibility with Emacs < 24, derive conditionally
(defalias 'rust-parent-mode
Expand Down Expand Up @@ -481,7 +487,34 @@ This is written mainly to be used as `end-of-defun-function' for Rust."
(setq-local comment-line-break-function 'rust-comment-indent-new-line)
(setq-local imenu-generic-expression rust-imenu-generic-expression)
(setq-local beginning-of-defun-function 'rust-beginning-of-defun)
(setq-local end-of-defun-function 'rust-end-of-defun))
(setq-local end-of-defun-function 'rust-end-of-defun)
(setq-local parse-sexp-lookup-properties t)
(add-hook 'syntax-propertize-extend-region-functions 'rust-syntax-propertize-extend-region)
(setq-local syntax-propertize-function 'rust-syntax-propertize))

(defun rust-syntax-propertize-extend-region (start end)
(save-excursion
(goto-char start)
(beginning-of-defun)
(cons
(point)
(progn
(goto-char end)
(end-of-defun)
(point)))))

(defun rust-syntax-propertize (start end)
;; Find character literals and make the syntax table recognize the single quote as the string delimiter
(dolist (char-lit-re
'("'[^']'"
"'\\\\['nrt]'"
"'\\\\x[[:xdigit:]]\\{2\\}'"
"'\\\\u[[:xdigit:]]\\{4\\}'"
"'\\\\U[[:xdigit:]]\\{8\\}'"))
(save-excursion
(goto-char start)
(while (re-search-forward char-lit-re end t)
(put-text-property (match-beginning 0) (match-end 0) 'syntax-table rust-mode-character-literal-syntax-table)))))

;;;###autoload
(add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-mode))
Expand Down