diff --git a/elixir-mode.el b/elixir-mode.el index 0f0e59b5..1008bdaf 100644 --- a/elixir-mode.el +++ b/elixir-mode.el @@ -260,12 +260,30 @@ is used to limit the scan." (put-text-property beg (1+ beg) 'elixir-interpolation (cons (nth 3 context) (match-data))))) -(defconst elixir-syntax-propertize-function - (syntax-propertize-rules - ((elixir-rx string-delimiter) - (0 (ignore (elixir-syntax-stringify)))) - ((rx (group "#{" (0+ (not (any "}"))) "}")) - (0 (ignore (elixir-syntax-propertize-interpolation)))))) +(defconst elixir-sigil-delimiter-pair + '((?\( . ")") + (?\{ . "}") + (?\< . ">") + (?\[ . "]"))) + +(defun elixir-syntax-replace-property-in-sigil () + (let ((heredoc-p (save-excursion + (goto-char (match-beginning 0)) + (looking-at-p "~s\"\"\"")))) + (unless heredoc-p + (forward-char 1) + (let* ((start-delim (char-after (1- (point)))) + (end-delim (or (assoc-default start-delim elixir-sigil-delimiter-pair) + (char-to-string start-delim))) + (end (save-excursion + (skip-chars-forward (concat "^" end-delim)) + (point))) + (word-syntax (string-to-syntax "w"))) + (when (memq start-delim '(?' ?\")) + (setq end (1+ end)) + (forward-char -1)) + (while (re-search-forward "[\"']" end t) + (put-text-property (1- (point)) (point) 'syntax-table word-syntax)))))) (defun elixir-syntax-propertize-function (start end) (let ((case-fold-search nil)) @@ -274,6 +292,8 @@ is used to limit the scan." (syntax-propertize-rules ((elixir-rx string-delimiter) (0 (ignore (elixir-syntax-stringify)))) + ((elixir-rx sigils) + (0 (ignore (elixir-syntax-replace-property-in-sigil)))) ((rx (group "#{" (0+ (not (any "}"))) "}")) (0 (ignore (elixir-syntax-propertize-interpolation))))) start end))) diff --git a/test/elixir-mode-font-test.el b/test/elixir-mode-font-test.el index c95dfa5b..88159995 100644 --- a/test/elixir-mode-font-test.el +++ b/test/elixir-mode-font-test.el @@ -299,6 +299,55 @@ when" (should-not (eq (elixir-test-face-at 17) 'font-lock-comment-face)) (should-not (eq (elixir-test-face-at 25) 'font-lock-comment-face)))) +(ert-deftest elixir-mode-syntax-table/quotes-in-sigils () + "https://github.com/elixir-lang/emacs-elixir/issues/265" + :tags '(fontification syntax-table) + (elixir-test-with-temp-buffer + "~s/\"/ +~r|'| +~c\"'\" +~w'\"' +~s(\") +~r[\"] +~c{\"} +~w<\"> +~s\"\"\" +foo +\"\"\"" + (should-not (eq (elixir-test-face-at 5) 'font-lock-string-face)) ; ~s// + + (should-not (eq (elixir-test-face-at 7) 'font-lock-string-face)) ; ~r|| + (should (eq (elixir-test-face-at 7) 'font-lock-builtin-face)) + (should-not (eq (elixir-test-face-at 11) 'font-lock-string-face)) + + (should-not (eq (elixir-test-face-at 13) 'font-lock-string-face)) ; ~c"" + (should (eq (elixir-test-face-at 13) 'font-lock-builtin-face)) + (should-not (eq (elixir-test-face-at 17) 'font-lock-string-face)) + + (should-not (eq (elixir-test-face-at 19) 'font-lock-string-face)) ; ~w'' + (should (eq (elixir-test-face-at 19) 'font-lock-builtin-face)) + (should-not (eq (elixir-test-face-at 23) 'font-lock-string-face)) + + (should-not (eq (elixir-test-face-at 25) 'font-lock-string-face)) ; ~s() + (should-not (eq (elixir-test-face-at 29) 'font-lock-string-face)) + + (should-not (eq (elixir-test-face-at 31) 'font-lock-string-face)) ; ~r[] + (should (eq (elixir-test-face-at 31) 'font-lock-builtin-face)) + (should-not (eq (elixir-test-face-at 35) 'font-lock-string-face)) + + (should-not (eq (elixir-test-face-at 37) 'font-lock-string-face)) ; ~c{} + (should (eq (elixir-test-face-at 37) 'font-lock-builtin-face)) + (should-not (eq (elixir-test-face-at 41) 'font-lock-string-face)) + + (should-not (eq (elixir-test-face-at 43) 'font-lock-string-face)) ; ~w<> + (should (eq (elixir-test-face-at 43) 'font-lock-builtin-face)) + (should-not (eq (elixir-test-face-at 47) 'font-lock-string-face)) + + (should (eq (elixir-test-face-at 51) 'font-lock-string-face)) ; ~s""" """ + (should (eq (elixir-test-face-at 52) 'font-lock-string-face)) + (should (eq (elixir-test-face-at 53) 'font-lock-string-face)) + (should (eq (elixir-test-face-at 55) 'font-lock-string-face)))) + (provide 'elixir-mode-font-test) ;;; elixir-mode-font-test.el ends here