Skip to content

Commit e54b254

Browse files
committed
Merge pull request #1159 from gracjan/pr-font-lock-improve
Improve font-lock
2 parents 0e4694e + 403d6c9 commit e54b254

File tree

4 files changed

+48
-47
lines changed

4 files changed

+48
-47
lines changed

haskell-font-lock.el

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -217,24 +217,15 @@ Regexp match data 0 points to the chars."
217217
(varid "\\b[[:lower:]_][[:alnum:]'_]*\\b")
218218
;; We allow ' preceding conids because of DataKinds/PolyKinds
219219
(conid "\\b'?[[:upper:]][[:alnum:]'_]*\\b")
220-
(modid (concat "\\b" conid "\\(\\." conid "\\)*\\b"))
221-
(qvarid (concat modid "\\." varid))
222-
(qconid (concat modid "\\." conid))
223220
(sym "\\s.+")
224-
225-
;; Reserved identifiers
226-
(reservedid
227-
(concat "\\<"
228-
;; `as', `hiding', and `qualified' are part of the import
229-
;; spec syntax, but they are not reserved.
230-
;; `_' can go in here since it has temporary word syntax.
231-
;; (regexp-opt
232-
;; '("case" "class" "data" "default" "deriving" "do"
233-
;; "else" "if" "import" "in" "infix" "infixl"
234-
;; "infixr" "instance" "let" "module" "newtype" "of"
235-
;; "then" "type" "where" "_") t)
236-
"\\(_\\|c\\(ase\\|lass\\)\\|d\\(ata\\|e\\(fault\\|riving\\)\\|o\\)\\|else\\|i\\(mport\\|n\\(fix[lr]?\\|stance\\)\\|[fn]\\)\\|let\\|module\\|mdo\\|newtype\\|of\\|rec\\|proc\\|t\\(hen\\|ype\\)\\|where\\)"
237-
"\\>"))
221+
(reservedids
222+
;; `as', `hiding', and `qualified' are part of the import
223+
;; spec syntax, but they are not reserved.
224+
;; `_' can go in here since it has temporary word syntax.
225+
'("case" "class" "data" "default" "deriving" "do"
226+
"else" "if" "import" "in" "infix" "infixl"
227+
"infixr" "instance" "let" "module" "mdo" "newtype" "of"
228+
"rec" "proc" "then" "type" "where" "_"))
238229

239230
;; Top-level declarations
240231
(topdecl-var
@@ -263,8 +254,6 @@ Regexp match data 0 points to the chars."
263254

264255
,@(haskell-font-lock-symbols-keywords)
265256

266-
(,reservedid 1 'haskell-keyword-face)
267-
268257
;; Special case for `as', `hiding', `safe' and `qualified', which are
269258
;; keywords in import statements but are not otherwise reserved.
270259
("\\<import[ \t]+\\(?:\\(safe\\>\\)[ \t]*\\)?\\(?:\\(qualified\\>\\)[ \t]*\\)?\\(?:\"[^\"]*\"[\t ]*\\)?[^ \t\n()]+[ \t]*\\(?:\\(\\<as\\>\\)[ \t]*[^ \t\n()]+[ \t]*\\)?\\(\\<hiding\\>\\)?"
@@ -302,9 +291,12 @@ Regexp match data 0 points to the chars."
302291

303292
;; Toplevel Declarations.
304293
;; Place them *before* generic id-and-op highlighting.
305-
(,topdecl-var (1 'haskell-definition-face))
306-
(,topdecl-var2 (2 'haskell-definition-face))
307-
(,topdecl-bangpat (1 'haskell-definition-face))
294+
(,topdecl-var (1 (unless (member (match-string 1) ',reservedids)
295+
'haskell-definition-face)))
296+
(,topdecl-var2 (2 (unless (member (match-string 2) ',reservedids)
297+
'haskell-definition-face)))
298+
(,topdecl-bangpat (1 (unless (member (match-string 1) ',reservedids)
299+
'haskell-definition-face)))
308300
(,topdecl-sym (2 (unless (member (match-string 2) '("\\" "=" "->" "" "<-" "" "::" "" "," ";" "`"))
309301
'haskell-definition-face)))
310302
(,topdecl-sym2 (1 (unless (member (match-string 1) '("\\" "=" "->" "" "<-" "" "::" "" "," ";" "`"))
@@ -314,19 +306,26 @@ Regexp match data 0 points to the chars."
314306
("(\\(,*\\|->\\))" 0 'haskell-constructor-face)
315307
("\\[\\]" 0 'haskell-constructor-face)
316308

317-
(,(concat "`" varid "`") 0 'haskell-operator-face)
318-
(,(concat "`" conid "`") 0 'haskell-operator-face)
319-
(,(concat "`" qvarid "`") 0 'haskell-operator-face)
320-
(,(concat "`" qconid "`") 0 'haskell-operator-face)
321-
322-
(,qconid 0 'haskell-constructor-face)
323-
324-
(,conid 0 'haskell-constructor-face)
325-
326-
(,sym 0 (if (and (eq (char-after (match-beginning 0)) ?:)
327-
(not (member (match-string 0) '("::" ""))))
328-
'haskell-constructor-face
329-
'haskell-operator-face))))
309+
(,(concat "`" haskell-lexeme-qid-or-qsym "`") 0 'haskell-operator-face)
310+
311+
(,haskell-lexeme-qid-or-qsym
312+
0 (cl-case (haskell-lexeme-classify-by-first-char (char-after (match-beginning 1)))
313+
(varid (when (member (match-string 0) ',reservedids)
314+
;; Note: keywords parse as keywords only when not qualified.
315+
;; GHC parses Control.let as a single but illegal lexeme.
316+
'haskell-keyword-face))
317+
(conid 'haskell-constructor-face)
318+
(varsym (when (and (not (member (match-string 0) '("-" "+" ".")))
319+
(not (save-excursion
320+
(goto-char (match-beginning 1))
321+
(looking-at-p "\\sw"))))
322+
;; We need to protect against the case of
323+
;; plus, minus or dot inside a floating
324+
;; point number.
325+
'haskell-operator-face))
326+
(consym (if (not (member (match-string 1) '("::" "")))
327+
'haskell-constructor-face
328+
'haskell-operator-face))))))
330329
keywords))
331330

332331

@@ -456,7 +455,8 @@ Regexp match data 0 points to the chars."
456455
(font-lock-syntactic-face-function
457456
. haskell-syntactic-face-function)
458457
;; Get help from font-lock-syntactic-keywords.
459-
(parse-sexp-lookup-properties . t))))
458+
(parse-sexp-lookup-properties . t)
459+
(font-lock-extra-managed-props . (composition)))))
460460

461461
(defun haskell-fontify-as-mode (text mode)
462462
"Fontify TEXT as MODE, returning the fontified text."

haskell-mode.el

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,8 @@ Minor modes that work well with `haskell-mode':
761761
(font-lock-syntactic-face-function
762762
. haskell-syntactic-face-function)
763763
;; Get help from font-lock-syntactic-keywords.
764-
(parse-sexp-lookup-properties . t)))
764+
(parse-sexp-lookup-properties . t)
765+
(font-lock-extra-managed-props . (composition))))
765766
;; Haskell's layout rules mean that TABs have to be handled with extra care.
766767
;; The safer option is to avoid TABs. The second best is to make sure
767768
;; TABs stops are 8 chars apart, as mandated by the Haskell Report. --Stef

tests/haskell-font-lock-tests.el

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -162,16 +162,16 @@ if all of its characters have syntax and face. See
162162
("." "." haskell-constructor-face)
163163
("C" "w" haskell-constructor-face)
164164

165-
("D" "w" haskell-constructor-face)
166-
("." "." haskell-constructor-face)
167-
("E" "w" haskell-constructor-face)
168-
("." "." haskell-operator-face)
165+
("D" "w" nil)
166+
("." "." nil)
167+
("E" "w" nil)
168+
("." "." nil)
169169
("f" "w" nil)
170170

171-
("G" "w" haskell-constructor-face)
172-
("." "." haskell-constructor-face)
173-
("H" "w" haskell-constructor-face)
174-
("." "." haskell-operator-face) ; this is wrong
171+
("G" "w" haskell-operator-face)
172+
("." "." haskell-operator-face)
173+
("H" "w" haskell-operator-face)
174+
("." "." haskell-operator-face)
175175
(">>=" "." haskell-operator-face)
176176

177177
("<=<" "." haskell-operator-face))))
@@ -452,7 +452,7 @@ if all of its characters have syntax and face. See
452452
"nope :: nope"
453453
"nope <- nope"
454454
"nope ` nope")
455-
'(("," t haskell-operator-face)
455+
'(("," t nil)
456456
("=" t haskell-operator-face)
457457
("->" t haskell-operator-face)
458458
("::" t haskell-operator-face)

tests/haskell-lexeme-tests.el

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ order."
9292

9393
(ert-deftest haskell-lexeme-unicode-ids-2 ()
9494
"Unicode ids, unicode as last character in line"
95-
:expected-result :failed
95+
;;:expected-result :failed
9696
(check-lexemes
9797
'("Żółw.head,Data.żółw,Артур.Артур")
9898
'("Żółw.head" "," "Data.żółw" "," "Артур.Артур")))

0 commit comments

Comments
 (0)