@@ -92,6 +92,27 @@ This is the case if the \".\" is part of a \"forall <tvar> . <type>\"."
9292 (string= " " (string (char-after start)))
9393 (string= " " (string (char-before start))))))))
9494
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+
95116;;;### autoload
96117(defface haskell-keyword-face
97118 '((t :inherit font-lock-keyword-face ))
@@ -420,10 +441,54 @@ that should be commented under LaTeX-style literate scripts."
420441 (" ^\\ (\\\\\\ )end{code}$" 1 " !" ))
421442 haskell-basic-syntactic-keywords))
422443
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+
423468(defun haskell-syntactic-face-function (state )
424469 " `font-lock-syntactic-face-function' for Haskell."
425470 (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 ))
427492 ; ; Else comment. If it's from syntax table, use default face.
428493 ((or (eq 'syntax-table (nth 7 state))
429494 (and (eq haskell-literate 'bird )
0 commit comments