Merge pull request #870 from ttuegel/nix-mode
nix-mode: set syntax and font properties for multiline strings
This commit is contained in:
		
						commit
						33dc8c5e87
					
				
					 1 changed files with 84 additions and 2 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue