@@ -92,6 +92,27 @@ This is the case if the \".\" is part of a \"forall <tvar> . <type>\"."
92
92
(string= " " (string (char-after start)))
93
93
(string= " " (string (char-before start))))))))
94
94
95
+ ;;;### autoload
96
+ (defcustom haskell-font-lock-quasi-quote-modes
97
+ `((" hsx" . xml-mode)
98
+ (" hamlet" . xml-mode)
99
+ (" shamlet" . xml-mode)
100
+ (" xmlQQ" . xml-mode)
101
+ (" xml" . xml-mode)
102
+ (" cmd" . shell-mode)
103
+ (" sh_" . shell-mode)
104
+ (" jmacro" . javascript-mode)
105
+ (" jmacroE" . javascript-mode)
106
+ (" r" . ess-mode)
107
+ (" rChan" . ess-mode)
108
+ (" sql" . sql-mode))
109
+ " Mapping from quasi quoter token to fontification mode.
110
+
111
+ If a quasi quote is seen in Haskell code its contents will have
112
+ font faces assigned as if respective mode was enabled."
113
+ :group 'haskell
114
+ :type '(repeat (cons string symbol)))
115
+
95
116
;;;### autoload
96
117
(defface haskell-keyword-face
97
118
'((t :inherit font-lock-keyword-face ))
@@ -420,10 +441,54 @@ that should be commented under LaTeX-style literate scripts."
420
441
(" ^\\ (\\\\\\ )end{code}$" 1 " !" ))
421
442
haskell-basic-syntactic-keywords))
422
443
444
+ (defun haskell-font-lock-fontify-block (lang-mode start end )
445
+ " Fontify a block as LANG-MODE."
446
+ (let ((string (buffer-substring-no-properties start end))
447
+ (modified (buffer-modified-p ))
448
+ (org-buffer (current-buffer )) pos next)
449
+ (remove-text-properties start end '(face nil ))
450
+ (with-current-buffer
451
+ (get-buffer-create
452
+ (concat " haskell-font-lock-fontify-block:" (symbol-name lang-mode)))
453
+ (delete-region (point-min ) (point-max ))
454
+ (insert string " " ) ; ; so there's a final property change
455
+ (unless (eq major-mode lang-mode) (funcall lang-mode))
456
+ (font-lock-ensure )
457
+ (setq pos (point-min ))
458
+ (while (setq next (next-single-property-change pos 'face ))
459
+ (put-text-property
460
+ (+ start (1- pos)) (1- (+ start next)) 'face
461
+ (get-text-property pos 'face ) org-buffer)
462
+ (setq pos next)))
463
+ (add-text-properties
464
+ start end
465
+ '(font-lock-fontified t fontified t font-lock-multiline t ))
466
+ (set-buffer-modified-p modified)))
467
+
423
468
(defun haskell-syntactic-face-function (state )
424
469
" `font-lock-syntactic-face-function' for Haskell."
425
470
(cond
426
- ((nth 3 state) 'font-lock-string-face ) ; as normal
471
+ ((nth 3 state)
472
+ (if (equal ?| (nth 3 state))
473
+ ; ; find out what kind of QuasiQuote is this
474
+ (let* ((qqname (save-excursion
475
+ (goto-char (nth 8 state))
476
+ (skip-syntax-backward " w._" )
477
+ (buffer-substring-no-properties (point ) (nth 8 state))))
478
+ (lang-mode (cdr (assoc qqname haskell-font-lock-quasi-quote-modes))))
479
+
480
+ (if (and lang-mode
481
+ (fboundp lang-mode))
482
+ (save-excursion
483
+ ; ; find the end of the QuasiQuote
484
+ (parse-partial-sexp (point ) (point-max ) nil nil state
485
+ 'syntax-table )
486
+ (haskell-font-lock-fontify-block lang-mode (nth 8 state) (point ))
487
+ ; ; must return nil here so that it is not fontified again as string
488
+ nil )
489
+ ; ; fontify normally as string because lang-mode is not present
490
+ 'font-lock-string-face ))
491
+ 'font-lock-string-face ))
427
492
; ; Else comment. If it's from syntax table, use default face.
428
493
((or (eq 'syntax-table (nth 7 state))
429
494
(and (eq haskell-literate 'bird )
0 commit comments