From 493647044e9ae25060595c881ef3dafc4a06a61b Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Sun, 23 Feb 2025 02:49:52 +0300 Subject: [PATCH 1/8] Extend string tests to cover comment constructions --- tests/purescript-font-lock-tests.el | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/purescript-font-lock-tests.el b/tests/purescript-font-lock-tests.el index e9d3865..d10fa52 100644 --- a/tests/purescript-font-lock-tests.el +++ b/tests/purescript-font-lock-tests.el @@ -80,11 +80,14 @@ hello "foo = \"\"\" # a string with hashtag # another # one +-- not a comment -- +-- | not a comment +{- not a comment -} \"\"\" " '((1 3 font-lock-function-name-face) (5 5 font-lock-variable-name-face) - (7 55 font-lock-string-face)))) + (7 114 font-lock-string-face)))) (ert-deftest multiline-string-with-embedded-strings () :expected-result :failed From e0e33fd3b18d1515050fdb84f630e9a97ba46efb Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Sat, 22 Feb 2025 11:16:55 +0300 Subject: [PATCH 2/8] Test comments highlighting --- tests/purescript-font-lock-tests.el | 55 +++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/purescript-font-lock-tests.el b/tests/purescript-font-lock-tests.el index d10fa52..798f7ad 100644 --- a/tests/purescript-font-lock-tests.el +++ b/tests/purescript-font-lock-tests.el @@ -99,3 +99,58 @@ this = \"still a string\" '((1 3 font-lock-function-name-face) (5 5 font-lock-variable-name-face) (7 37 font-lock-string-face)))) + +(ert-deftest docs-bar-comment-different-spacings () + (purescript-test-ranges + "-- | Docs comment space +-- | Docs comment many spaces +" + '((1 57 font-lock-doc-face)))) + +(ert-deftest docs-bar-comment-continuation () + "Acc. to +https://github.com/purescript/documentation/blob/master/language/Syntax.md +PureScript explicitly doesn't support Haskell-style docs continuation +where vertical bar is omitted" + :expected-result :failed + (purescript-test-ranges + "-- | Docs start +-- continue +" + '((1 16 font-lock-doc-face) + (17 19 font-lock-comment-delimiter-face) + (20 28 font-lock-comment-face)))) + +(ert-deftest docs-cap-comment-different-spacings () + (purescript-test-ranges + "-- ^ Docs comment space +-- ^ Docs comment many spaces +" + '((1 57 font-lock-doc-face)))) + +(ert-deftest multiline-comment () + (purescript-test-ranges + "{- +multiline comment +-- | not a doc +--| not a doc +still comment +-} +noncomment +{--} +noncomment +" + '((1 64 font-lock-comment-face) + (65 66 font-lock-comment-delimiter-face) + (67 78 nil) + (79 80 font-lock-comment-face) + (81 82 font-lock-comment-delimiter-face) + (83 93 nil)))) + +(ert-deftest multiline-comment-w-delimiter-inside () + :expected-result :failed + (purescript-test-ranges + "{- {-{- -} noncomment" + '((1 6 font-lock-comment-face) + (7 10 font-lock-comment-delimiter-face) + (11 21 nil)))) From bd3f3c6799df20106403d1b7c36758fe87a724b2 Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Sun, 23 Feb 2025 02:38:31 +0300 Subject: [PATCH 3/8] Don't consider a comment after docs-comment a documentation As described in the test and the commentary, PureScript doesn't consider a "no-bar" comment that follows documentation part of the documentation. It is an explicitly documented behavior that is different from Haskell. --- purescript-font-lock.el | 32 +++++++---------------------- tests/purescript-font-lock-tests.el | 3 +-- 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/purescript-font-lock.el b/purescript-font-lock.el index a9f93ea..2b21ae7 100644 --- a/purescript-font-lock.el +++ b/purescript-font-lock.el @@ -363,9 +363,6 @@ that should be commented under LaTeX-style literate scripts." :type 'boolean :group 'purescript) -(defvar purescript-font-lock-seen-docstring nil) -(make-variable-buffer-local 'purescript-font-lock-seen-docstring) - (defvar purescript-literate) (defun purescript-syntactic-face-function (state) @@ -383,31 +380,16 @@ that should be commented under LaTeX-style literate scripts." ;; b) {-^ ... -} ;; c) -- | ... ;; d) -- ^ ... - ;; e) -- ... - ;; Where `e' is the tricky one: it is only a docstring comment if it - ;; follows immediately another docstring comment. Even an empty line - ;; breaks such a sequence of docstring comments. It is not clear if `e' - ;; can follow any other case, so I interpreted it as following only cases - ;; c,d,e (not a or b). In any case, this `e' is expensive since it - ;; requires extra work for each and every non-docstring comment, so I only - ;; go through the more expensive check if we've already seen a docstring - ;; comment in the buffer. + + ;; Worth pointing out purescript opted out of ability to continue + ;; docs-comment by omitting an empty line like in Haskell, see: + ;; https://github.com/purescript/documentation/blob/master/language/Syntax.md + ;; IOW, given a `-- | foo' line followed by `-- bar' line, the latter is a + ;; plain comment. ((and purescript-font-lock-docstrings (save-excursion (goto-char (nth 8 state)) - (or (looking-at "\\(-- \\|{-\\)[ \\t]*[|^]") - (and purescript-font-lock-seen-docstring - (looking-at "-- ") - (let ((doc nil) - pos) - (while (and (not doc) - (setq pos (line-beginning-position)) - (forward-comment -1) - (eq (line-beginning-position 2) pos) - (looking-at "--\\( [|^]\\)?")) - (setq doc (match-beginning 1))) - doc))))) - (set (make-local-variable 'purescript-font-lock-seen-docstring) t) + (looking-at "\\(-- \\|{-\\)[ \\t]*[|^]"))) 'font-lock-doc-face) (t 'font-lock-comment-face))) diff --git a/tests/purescript-font-lock-tests.el b/tests/purescript-font-lock-tests.el index 798f7ad..b9ea38d 100644 --- a/tests/purescript-font-lock-tests.el +++ b/tests/purescript-font-lock-tests.el @@ -102,7 +102,7 @@ this = \"still a string\" (ert-deftest docs-bar-comment-different-spacings () (purescript-test-ranges - "-- | Docs comment space + "-- | Docs comment 1 space -- | Docs comment many spaces " '((1 57 font-lock-doc-face)))) @@ -112,7 +112,6 @@ this = \"still a string\" https://github.com/purescript/documentation/blob/master/language/Syntax.md PureScript explicitly doesn't support Haskell-style docs continuation where vertical bar is omitted" - :expected-result :failed (purescript-test-ranges "-- | Docs start -- continue From 31568404643e253041d717c3dcb395a32328bf79 Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Sun, 23 Feb 2025 02:57:20 +0300 Subject: [PATCH 4/8] Remove code that depended on lack of font-lock-syntactic-keywords The variable exists since Emacs 21 at least, so this check serves no purpose. --- purescript-font-lock.el | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/purescript-font-lock.el b/purescript-font-lock.el index 2b21ae7..f93d05e 100644 --- a/purescript-font-lock.el +++ b/purescript-font-lock.el @@ -262,17 +262,6 @@ Returns keywords suitable for `font-lock-keywords'." (,sym 0 (if (eq (char-after (match-beginning 0)) ?:) purescript-constructor-face purescript-operator-face)))) - (unless (boundp 'font-lock-syntactic-keywords) - (cl-case literate - (bird - (setq keywords - `(("^[^>\n].*$" 0 purescript-comment-face t) - ,@keywords - ("^>" 0 purescript-default-face t)))) - ((latex tex) - (setq keywords - `((purescript-fl-latex-comments 0 'font-lock-comment-face t) - ,@keywords))))) keywords)) ;; The next three aren't used in Emacs 21. From 58fce7c4b3d1cc9f6469b555fd126ee792e2f8f5 Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Sun, 23 Feb 2025 05:10:29 +0300 Subject: [PATCH 5/8] Add `type` highlight test --- tests/purescript-font-lock-tests.el | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/purescript-font-lock-tests.el b/tests/purescript-font-lock-tests.el index b9ea38d..5dbf422 100644 --- a/tests/purescript-font-lock-tests.el +++ b/tests/purescript-font-lock-tests.el @@ -153,3 +153,19 @@ noncomment '((1 6 font-lock-comment-face) (7 10 font-lock-comment-delimiter-face) (11 21 nil)))) + +(ert-deftest type-with-typenames-and--> () + (purescript-test-ranges + "type Component props = Effect (props -> JSX)" + '((1 4 font-lock-keyword-face) + (5 5 nil) + (6 14 font-lock-type-face) + (15 21 nil) + (22 22 font-lock-variable-name-face) + (23 23 nil) + (24 29 font-lock-type-face) + (30 37 nil) + (38 39 font-lock-variable-name-face) + (40 40 nil) + (41 43 font-lock-type-face) + (44 45 nil)))) From 413f56a58ae71f09f924fd963685c2af5f15a19a Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Sun, 23 Feb 2025 13:28:38 +0300 Subject: [PATCH 6/8] Factor out `(purescript-font-lock-defaults-create)` block --- purescript-mode.el | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/purescript-mode.el b/purescript-mode.el index 416a510..dd18942 100644 --- a/purescript-mode.el +++ b/purescript-mode.el @@ -322,16 +322,7 @@ see documentation for that variable for more details." (set (make-local-variable 'comment-end-skip) "[ \t]*\\(-}\\|\\s>\\)") (set (make-local-variable 'parse-sexp-ignore-comments) nil) (set (make-local-variable 'indent-line-function) 'purescript-mode-suggest-indent-choice) - ;; Set things up for font-lock. - (set (make-local-variable 'font-lock-defaults) - '(purescript-font-lock-choose-keywords - nil nil ((?\' . "w") (?_ . "w")) nil - (font-lock-syntactic-keywords - . purescript-font-lock-choose-syntactic-keywords) - (font-lock-syntactic-face-function - . purescript-syntactic-face-function) - ;; Get help from font-lock-syntactic-keywords. - (parse-sexp-lookup-properties . t))) + (purescript-font-lock-defaults-create) ; set things up for font-lock. ;; PureScript's layout rules mean that TABs have to be handled with extra care. ;; The safer option is to avoid TABs. The second best is to make sure ;; TABs stops are 8 chars apart, as mandated by the PureScript Report. --Stef From f51a214c28999723fd295935ce84a789cfc21261 Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Sun, 23 Feb 2025 14:41:03 +0300 Subject: [PATCH 7/8] Restore `module` in non-toplevel and test that --- purescript-font-lock.el | 4 ++-- tests/purescript-font-lock-tests.el | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/purescript-font-lock.el b/purescript-font-lock.el index f93d05e..2757a09 100644 --- a/purescript-font-lock.el +++ b/purescript-font-lock.el @@ -177,7 +177,7 @@ Returns keywords suitable for `font-lock-keywords'." ;; record fields or other identifiers. (toplevel-keywords (rx line-start (zero-or-more whitespace) - (group (or "type" "module" "import" "data" "class" "newtype" + (group (or "type" "import" "data" "class" "newtype" "instance" "derive") word-end))) ;; Reserved identifiers @@ -186,7 +186,7 @@ Returns keywords suitable for `font-lock-keywords'." ;; spec syntax, but they are not reserved. ;; `_' can go in here since it has temporary word syntax. (regexp-opt - '("ado" "case" "do" "else" "if" "in" "infix" + '("ado" "case" "do" "else" "if" "in" "infix" "module" "infixl" "infixr" "let" "of" "then" "where" "_") 'words)) ;; Top-level declarations diff --git a/tests/purescript-font-lock-tests.el b/tests/purescript-font-lock-tests.el index 5dbf422..76cfa08 100644 --- a/tests/purescript-font-lock-tests.el +++ b/tests/purescript-font-lock-tests.el @@ -169,3 +169,25 @@ noncomment (40 40 nil) (41 43 font-lock-type-face) (44 45 nil)))) + +(ert-deftest module-in-different-locations () + (purescript-test-ranges + "module React.Basic.Hooks ( Component, module React.Basic + , module Data.Tuple.Nested ) where +" + '((1 6 font-lock-keyword-face) + (7 7 nil) + (8 24 font-lock-type-face) + (25 27 nil) + (28 36 font-lock-type-face) + (37 38 nil) + (39 44 font-lock-keyword-face) + (45 45 nil) + (46 56 font-lock-type-face) + (57 84 nil) + (85 90 font-lock-keyword-face) + (91 91 nil) + (92 108 font-lock-type-face) + (109 111 nil) + (112 116 font-lock-keyword-face) + (117 117 nil)))) From 81d0cbc1b2548d0f9885ea5ee91574bc2476b261 Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Sun, 23 Feb 2025 14:54:37 +0300 Subject: [PATCH 8/8] Add test for do + qualified do --- tests/purescript-font-lock-tests.el | 56 +++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/purescript-font-lock-tests.el b/tests/purescript-font-lock-tests.el index 76cfa08..8cbe9d9 100644 --- a/tests/purescript-font-lock-tests.el +++ b/tests/purescript-font-lock-tests.el @@ -191,3 +191,59 @@ noncomment (109 111 nil) (112 116 font-lock-keyword-face) (117 117 nil)))) + +(ert-deftest func-decl-w-do-and-qualified-do () + (purescript-test-ranges + "mkMyComponent :: Component {} +mkMyComponent = do + modalComp :: (NodeRef -> JSX) <- mkModal + component \"mkMyComponent\" \\_ -> React.do + dialogRef :: NodeRef <- newNodeRef + pure $ R.label_ [] +" + '((1 13 font-lock-function-name-face) + (14 14 nil) + (15 16 font-lock-variable-name-face) + (17 17 nil) + (18 26 font-lock-type-face) + (27 30 nil) + (31 43 font-lock-function-name-face) + (44 44 nil) + (45 45 font-lock-variable-name-face) + (46 46 nil) + (47 48 font-lock-keyword-face) + (49 61 nil) + (62 63 font-lock-variable-name-face) + (64 65 nil) + (66 72 font-lock-type-face) + (73 73 nil) + (74 75 font-lock-variable-name-face) + (76 76 nil) + (77 79 font-lock-type-face) + (80 81 nil) + (82 83 font-lock-variable-name-face) + (84 104 nil) + (105 119 font-lock-string-face) + (120 120 nil) + (121 121 font-lock-variable-name-face) + (122 122 font-lock-keyword-face) + (123 123 nil) + (124 125 font-lock-variable-name-face) + (126 126 nil) + (127 131 font-lock-type-face) + (132 132 font-lock-variable-name-face) + (133 134 font-lock-keyword-face) + (135 149 nil) + (150 151 font-lock-variable-name-face) + (152 152 nil) + (153 159 font-lock-type-face) + (160 160 nil) + (161 162 font-lock-variable-name-face) + (163 181 nil) + (182 182 font-lock-variable-name-face) + (183 183 nil) + (184 184 font-lock-type-face) + (185 185 font-lock-variable-name-face) + (186 192 nil) + (193 194 font-lock-type-face) + (195 195 nil))))