nix-mode: set syntax and font properties for multiline strings
This commit is contained in:
parent
6e120b76ee
commit
a828fe5b46
|
@ -8,6 +8,20 @@
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
|
(defun nix-syntax-match-antiquote (limit)
|
||||||
|
(let ((pos (next-single-char-property-change (point) 'nix-syntax-antiquote
|
||||||
|
nil limit)))
|
||||||
|
(when (and pos (> pos (point)))
|
||||||
|
(goto-char pos)
|
||||||
|
(let ((char (char-after pos)))
|
||||||
|
(pcase char
|
||||||
|
(`?$
|
||||||
|
(forward-char 2))
|
||||||
|
(`?}
|
||||||
|
(forward-char 1)))
|
||||||
|
(set-match-data (list pos (point)))
|
||||||
|
t))))
|
||||||
|
|
||||||
(defconst nix-font-lock-keywords
|
(defconst nix-font-lock-keywords
|
||||||
'("\\_<if\\_>" "\\_<then\\_>" "\\_<else\\_>" "\\_<assert\\_>" "\\_<with\\_>"
|
'("\\_<if\\_>" "\\_<then\\_>" "\\_<else\\_>" "\\_<assert\\_>" "\\_<with\\_>"
|
||||||
"\\_<let\\_>" "\\_<in\\_>" "\\_<rec\\_>" "\\_<inherit\\_>" "\\_<or\\_>"
|
"\\_<let\\_>" "\\_<in\\_>" "\\_<rec\\_>" "\\_<inherit\\_>" "\\_<or\\_>"
|
||||||
|
@ -26,7 +40,8 @@
|
||||||
("<[a-zA-Z0-9._\\+-]+\\(/[a-zA-Z0-9._\\+-]+\\)*>"
|
("<[a-zA-Z0-9._\\+-]+\\(/[a-zA-Z0-9._\\+-]+\\)*>"
|
||||||
. font-lock-constant-face)
|
. font-lock-constant-face)
|
||||||
("[a-zA-Z0-9._\\+-]*\\(/[a-zA-Z0-9._\\+-]+\\)+"
|
("[a-zA-Z0-9._\\+-]*\\(/[a-zA-Z0-9._\\+-]+\\)+"
|
||||||
. font-lock-constant-face))
|
. font-lock-constant-face)
|
||||||
|
(nix-syntax-match-antiquote 0 font-lock-preprocessor-face t))
|
||||||
"Font lock keywords for nix.")
|
"Font lock keywords for nix.")
|
||||||
|
|
||||||
(defvar nix-mode-syntax-table
|
(defvar nix-mode-syntax-table
|
||||||
|
@ -38,6 +53,67 @@
|
||||||
table)
|
table)
|
||||||
"Syntax table for Nix mode.")
|
"Syntax table for Nix mode.")
|
||||||
|
|
||||||
|
(defun nix-syntax-propertize-escaped-antiquote ()
|
||||||
|
"Set syntax properies for escaped antiquote marks."
|
||||||
|
nil)
|
||||||
|
|
||||||
|
(defun nix-syntax-propertize-multiline-string ()
|
||||||
|
"Set syntax properies for multiline string delimiters."
|
||||||
|
(let* ((start (match-beginning 0))
|
||||||
|
(end (match-end 0))
|
||||||
|
(context (save-excursion (save-match-data (syntax-ppss start))))
|
||||||
|
(string-type (nth 3 context)))
|
||||||
|
(pcase string-type
|
||||||
|
(`t
|
||||||
|
;; inside a multiline string
|
||||||
|
;; ending multi-line string delimiter
|
||||||
|
(put-text-property (1- end) end
|
||||||
|
'syntax-table (string-to-syntax "|")))
|
||||||
|
(`nil
|
||||||
|
;; beginning multi-line string delimiter
|
||||||
|
(put-text-property start (1+ start)
|
||||||
|
'syntax-table (string-to-syntax "|"))))))
|
||||||
|
|
||||||
|
(defun nix-syntax-propertize-antiquote ()
|
||||||
|
"Set syntax properties for antiquote marks."
|
||||||
|
(let* ((start (match-beginning 0)))
|
||||||
|
(put-text-property start (1+ start)
|
||||||
|
'syntax-table (string-to-syntax "|"))
|
||||||
|
(put-text-property start (+ start 2)
|
||||||
|
'nix-syntax-antiquote t)))
|
||||||
|
|
||||||
|
(defun nix-syntax-propertize-close-brace ()
|
||||||
|
"Set syntax properties for close braces.
|
||||||
|
If a close brace `}' ends an antiquote, the next character begins a string."
|
||||||
|
(let* ((start (match-beginning 0))
|
||||||
|
(end (match-end 0))
|
||||||
|
(context (save-excursion (save-match-data (syntax-ppss start))))
|
||||||
|
(open (nth 1 context)))
|
||||||
|
(when open ;; a corresponding open-brace was found
|
||||||
|
(let* ((antiquote (get-text-property open 'nix-syntax-antiquote)))
|
||||||
|
(when antiquote
|
||||||
|
(put-text-property (+ start 1) (+ start 2)
|
||||||
|
'syntax-table (string-to-syntax "|"))
|
||||||
|
(put-text-property start (1+ start)
|
||||||
|
'nix-syntax-antiquote t))))))
|
||||||
|
|
||||||
|
(defun nix-syntax-propertize (start end)
|
||||||
|
"Special syntax properties for Nix."
|
||||||
|
;; search for multi-line string delimiters
|
||||||
|
(goto-char start)
|
||||||
|
(remove-text-properties start end '(syntax-table nil nix-syntax-antiquote nil))
|
||||||
|
(funcall
|
||||||
|
(syntax-propertize-rules
|
||||||
|
("''\\${"
|
||||||
|
(0 (ignore (nix-syntax-propertize-escaped-antiquote))))
|
||||||
|
("''"
|
||||||
|
(0 (ignore (nix-syntax-propertize-multiline-string))))
|
||||||
|
("\\${"
|
||||||
|
(0 (ignore (nix-syntax-propertize-antiquote))))
|
||||||
|
("}"
|
||||||
|
(0 (ignore (nix-syntax-propertize-close-brace)))))
|
||||||
|
start end))
|
||||||
|
|
||||||
(defun nix-indent-line ()
|
(defun nix-indent-line ()
|
||||||
"Indent current line in a Nix expression."
|
"Indent current line in a Nix expression."
|
||||||
(interactive)
|
(interactive)
|
||||||
|
@ -69,7 +145,13 @@ The hook `nix-mode-hook' is run when Nix mode is started.
|
||||||
(set-syntax-table nix-mode-syntax-table)
|
(set-syntax-table nix-mode-syntax-table)
|
||||||
|
|
||||||
;; Font lock support.
|
;; Font lock support.
|
||||||
(setq font-lock-defaults '(nix-font-lock-keywords nil nil nil nil))
|
(setq-local font-lock-defaults '(nix-font-lock-keywords nil nil nil nil))
|
||||||
|
|
||||||
|
;; Special syntax properties for Nix
|
||||||
|
(setq-local syntax-propertize-function 'nix-syntax-propertize)
|
||||||
|
|
||||||
|
;; Look at text properties when parsing
|
||||||
|
(setq-local parse-sexp-lookup-properties t)
|
||||||
|
|
||||||
;; Automatic indentation [C-j].
|
;; Automatic indentation [C-j].
|
||||||
(set (make-local-variable 'indent-line-function) 'nix-indent-line)
|
(set (make-local-variable 'indent-line-function) 'nix-indent-line)
|
||||||
|
|
Loading…
Reference in a new issue