[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/haskell-tng-mode 77d6ec5 019/385: cleaned up multiline exp
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/haskell-tng-mode 77d6ec5 019/385: cleaned up multiline explicit types |
Date: |
Tue, 5 Oct 2021 23:58:53 -0400 (EDT) |
branch: elpa/haskell-tng-mode
commit 77d6ec54c9669c142be5beb5ac48926d48a46506
Author: Tseen She <ts33n.sh3@gmail.com>
Commit: Tseen She <ts33n.sh3@gmail.com>
cleaned up multiline explicit types
---
haskell-tng-font-lock.el | 252 +++++++++++++++++++----------------------------
haskell-tng-mode.el | 11 +--
2 files changed, 103 insertions(+), 160 deletions(-)
diff --git a/haskell-tng-font-lock.el b/haskell-tng-font-lock.el
index 600059c..a7e2ba7 100644
--- a/haskell-tng-font-lock.el
+++ b/haskell-tng-font-lock.el
@@ -18,6 +18,16 @@
;;
;;; Code:
+;; TODO: regression tests https://github.com/Lindydancer/faceup
+;;
+;; TODO: pragmas
+;;
+;; TODO: numeric / char primitives?
+;;
+;; TODO: haddock, different face vs line comments, and some markup.
+;;
+;; TODO use levels so users can turn off type fontification
+
(require 'subr-x)
(defgroup haskell-tng:faces nil
@@ -49,14 +59,8 @@
"Haskell top level declarations."
:group 'haskell-tng:faces)
-;; TODO: regression tests https://github.com/Lindydancer/faceup
-;;
-;; TODO: pragmas
-;;
-;; TODO: numeric / char primitives?
-;;
-;; TODO: haddock, different face vs line comments, and some markup.
-
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Here are `rx' patterns that are reused as a very simple form of BNF grammar
(defconst haskell-tng:conid '(: upper (* wordchar)))
(defconst haskell-tng:qual `(: (+ (: ,haskell-tng:conid (char ?.)))))
(defconst haskell-tng:consym '(: ":" (+ (syntax symbol)))) ;; TODO exclude ::,
limited symbol set
@@ -72,19 +76,9 @@
(+ (not (syntax comment-end)))
(+ (syntax comment-end))))
"Newline or line comment.")
-(defconst haskell-tng:type
- ;; TODO literal types and generic lists ... eek!
- (let ((typepart `(| (+ (any ?\( ?\) ?\[ ?\]))
- (+ (any lower ?_))
- (: (opt ,haskell-tng:qual)
- (| "::" ,haskell-tng:conid ,haskell-tng:consym)))))
- `(: (opt ,haskell-tng:newline) (+ (| space ,typepart))
- (* (opt ,haskell-tng:newline (+ space)) "->" (+ (| space ,typepart)))))
- "An explicit type")
-
-;; TODO a macro that wraps these consts with short-form names
-;; TODO use the levels support so users can turn off type fontification
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Here is the `font-lock-keywords' table of matchers and highlighters.
(setq
haskell-tng:keywords
;; These regexps use the `rx' library so we can reuse common subpatterns. It
@@ -110,46 +104,46 @@
. 'haskell-tng:keyword)
;; types
- (haskell-tng:explicit-type-paint
+ (haskell-tng:explicit-type
(0 'haskell-tng:type keep))
- ;; TODO multiline data/newtype/class/instance types
- (,(rx-to-string `(: line-start "data" (+ space)
- (group (| ,conid ,consym))))
- (1 'haskell-tng:type))
- (,(rx-to-string `(: line-start (| "class" "instance") (+ space)
- (group (+? anything))
- (+ space) "where"))
- (1 'haskell-tng:type keep))
- ;; TypeApplications
- (,(rx-to-string `(: symbol-start "@" (* space)
- ;; TODO: more liberal type application
- (group (opt ,qual) (| ,conid ,consym))))
- (1 'haskell-tng:type))
+ ;; ;; TODO multiline data/newtype/class/instance types
+ ;; (,(rx-to-string `(: line-start "data" (+ space)
+ ;; (group (| ,conid ,consym))))
+ ;; (1 'haskell-tng:type))
+ ;; (,(rx-to-string `(: line-start (| "class" "instance") (+ space)
+ ;; (group (+? anything))
+ ;; (+ space) "where"))
+ ;; (1 'haskell-tng:type keep))
+ ;; ;; TypeApplications
+ ;; (,(rx-to-string `(: symbol-start "@" (* space)
+ ;; ;; TODO: more liberal type application
+ ;; (group (opt ,qual) (| ,conid ,consym))))
+ ;; (1 'haskell-tng:type))
;; TODO: multiline module / import sections
;; modules
- (,(rx-to-string `(: symbol-start "module" symbol-end (+ space)
- symbol-start (group (opt ,qual) ,conid) symbol-end))
- 1 'haskell-tng:module)
+ ;; (,(rx-to-string `(: symbol-start "module" symbol-end (+ space)
+ ;; symbol-start (group (opt ,qual) ,conid)
symbol-end))
+ ;; 1 'haskell-tng:module)
;; imports
- (,(rx-to-string '(: word-start "import" word-end)) ;; anchor matcher
- (,(rx-to-string `(: point (+ space) (group word-start "qualified"
word-end)))
- nil nil (1 'haskell-tng:keyword))
- (,(rx-to-string `(: point
- (opt (+ space) word-start "qualified" word-end)
- (+ space) word-start (group (opt ,qual) ,conid)
word-end))
- nil nil (1 'haskell-tng:module))
- (,(rx-to-string `(: point (+? (not (any ?\()))
- word-start (group (| "hiding" "as")) word-end
- (opt (+ space) word-start (group ,conid) word-end)))
- nil nil (1 'haskell-tng:keyword) (2 'haskell-tng:module nil t))
- (,(rx-to-string `(: symbol-start (group (| ,conid ,consym)) symbol-end
- (* space) "(..)"))
- nil nil (1 'haskell-tng:constructor))
- (,(rx-to-string `(: symbol-start (group (| ,conid ,consym)) symbol-end))
- nil nil (1 'haskell-tng:type)))
+ ;; (,(rx-to-string '(: word-start "import" word-end)) ;; anchor matcher
+ ;; (,(rx-to-string `(: point (+ space) (group word-start "qualified"
word-end)))
+ ;; nil nil (1 'haskell-tng:keyword))
+ ;; (,(rx-to-string `(: point
+ ;; (opt (+ space) word-start "qualified" word-end)
+ ;; (+ space) word-start (group (opt ,qual) ,conid)
word-end))
+ ;; nil nil (1 'haskell-tng:module))
+ ;; (,(rx-to-string `(: point (+? (not (any ?\()))
+ ;; word-start (group (| "hiding" "as")) word-end
+ ;; (opt (+ space) word-start (group ,conid)
word-end)))
+ ;; nil nil (1 'haskell-tng:keyword) (2 'haskell-tng:module nil t))
+ ;; (,(rx-to-string `(: symbol-start (group (| ,conid ,consym)) symbol-end
+ ;; (* space) "(..)"))
+ ;; nil nil (1 'haskell-tng:constructor))
+ ;; (,(rx-to-string `(: symbol-start (group (| ,conid ,consym))
symbol-end))
+ ;; nil nil (1 'haskell-tng:type)))
;; top-level
(,(rx-to-string toplevel)
@@ -165,135 +159,73 @@
)))
-(defvar haskell-tng:explicit-type-regex
- (rx-to-string `(: point "::" (* space) ,haskell-tng:type))
- "Cache of a regex internal to `haskell-tng:explicit-type'")
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Here are `function' matchers for use in `font-lock-keywords', and reusable
in
+;; the `font-lock-extend-region-functions' below. These set the match region
and
+;; return nil if there is not match in the limited search.
+;;
+;; Avoid compiling any regexes (i.e. `rx-to-string'), prefer `defconst' caches.
+(defconst haskell-tng:explicit-type-regex
+ ;; TODO literal types and generic lists ... eek!
+ (let ((newline haskell-tng:newline)
+ (typepart `(| (+ (any ?\( ?\) ?\[ ?\]))
+ (+ (any lower ?_))
+ (: (opt ,haskell-tng:qual)
+ (| "::" ,haskell-tng:conid ,haskell-tng:consym)))))
+ (rx-to-string
+ `(: symbol-start "::" (* space) (opt ,newline) (+ (| space ,typepart))
+ (* (opt ,newline (+ space)) "->" (+ (| space ,typepart)))))))
(defun haskell-tng:explicit-type (limit)
- "Matches an explicit type at point, bounded by a closing paren."
- (let ((end (min limit (or (haskell-tng:paren-close) limit))))
- (re-search-forward haskell-tng:explicit-type-regex end t)))
-(defun haskell-tng:explicit-type-paint (limit)
- ;; ideally we would use an anchored `haskell-tng:explicit-type' with a `::'
- ;; trigger, but there is a bug in GNU Emacs where anchored functions receive
a
- ;; much smaller `limit' than `font-lock-end' requested
- ;; https://lists.gnu.org/archive/html/emacs-devel/2018-11/msg00136.html
- "Matches an explicit type at point, bounded by a closing paren."
+ "Matches an explicit type, bounded by a closing paren."
(when (re-search-forward (rx symbol-start "::" symbol-end) limit t)
(goto-char (match-beginning 0))
- (haskell-tng:explicit-type limit)))
+ (when-let (bounded (haskell-tng:paren-close))
+ (setq limit (min limit (+ 1 bounded))))
+ (re-search-forward haskell-tng:explicit-type-regex limit t)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Below are `font-lock-extend-region-functions' procedures for extending the
+;; Here are `font-lock-extend-region-functions' procedures for extending the
;; region. Note that because we are using `font-lock-multiline' then multiline
;; patterns will always be rehighlighted as a group.
+;;
+;; Avoid compiling any regexes (i.e. `rx-to-string'), prefer `defconst' caches.
(eval-when-compile
;; NOTE: font-lock-end is non-inclusive.
(defvar font-lock-beg)
(defvar font-lock-end))
-(defconst haskell-tng:non-import
- ;; TODO: exclude more non-import/export characters. ideas: dots that aren't
- ;; (..) or part of a symbolic import, symbolic operators that are not
- ;; surrounded by parens.
- (rx (| ?\" ?\\))
- "Matches that should never exist in the parens of an import or export")
-(defun haskell-tng:extend-parens-open ()
- "For use in `font-lock-extend-region-functions'.
-Expand the region to include the opening parenthesis.
-The caller loops until everything is opened."
- (goto-char font-lock-beg)
- ;; TODO: exit early if in comment
- (when-let (open (nth 1 (syntax-ppss)))
- (goto-char open)
- (when (looking-at "(")
- (unless (re-search-forward haskell-tng:non-import font-lock-beg t)
- ;;(haskell-tng:debug-extend open)
- (setq font-lock-beg open)))))
-
-(defun haskell-tng:extend-parens-close ()
- "For use in `font-lock-extend-region-functions'.
-Expand the region to include a closing parenthesis.
-The caller loops until everything is closed."
- (goto-char font-lock-end)
- ;; TODO: exit early if in comment
- (when-let (close (haskell-tng:paren-close))
- (let ((end (+ 1 close)))
- (goto-char end)
- (unless (re-search-backward haskell-tng:non-import font-lock-end t)
- ;;(haskell-tng:debug-extend end)
- (setq font-lock-end end)))))
-
-(defun haskell-tng:paren-close ()
- "Return the position of the next `)', if it closes the current paren depth."
- (interactive) ;; TODO for manual testing
- (save-excursion
- (when-let (close (ignore-errors (scan-lists (point) 1 1)))
- (goto-char (- close 1))
- (when (looking-at ")")
- (point)))))
-
-(setq
- haskell-tng:beg-type
- ;; TODO: more restrictive search, add more like \ and =
- (rx symbol-start "::" symbol-end (* (not (any ?\\ ?=)))))
-(defun haskell-tng:extend-type-open ()
- "For use in `font-lock-extend-region-functions'.
-Ensures that multiline type signatures are opened."
- (goto-char font-lock-beg)
- ;; TODO: exit early if in comment
- ;; TODO: maximum lookback for a type
- (when (re-search-backward haskell-tng:beg-type (point-min) t)
- (let ((beg (match-beginning 0)))
- (when (< beg font-lock-beg)
- (goto-char beg)
- ;; validate that it's actually a type
- (haskell-tng:explicit-type (point-max)) ;; would not be needed if
backscan was more reliable
- (when (<= font-lock-beg (match-end 0))
- ;;(haskell-tng:debug-extend beg)
- (setq font-lock-beg beg)
- nil)))))
-
-(defun haskell-tng:extend-type-close ()
- "For use in `font-lock-extend-region-functions'.
-Ensures that multiline type signatures are closed."
+(defun haskell-tng:extend-explicit-type ()
+ "Multiline explicit type signatures are considered."
(goto-char font-lock-end)
- ;; TODO: exit early if in comment
- (when (re-search-backward haskell-tng:beg-type font-lock-beg t)
+ (when (re-search-backward
+ ;; TODO: more restrictive back scan
+ (rx symbol-start "::" symbol-end (*? (not (any ?\\ ?=))))
+ font-lock-beg t)
(let ((beg (match-beginning 0)))
(goto-char beg)
(haskell-tng:explicit-type (point-max))
- (let ((end (match-end 0)))
- (when (< font-lock-end end)
- ;;(haskell-tng:debug-extend end)
- (setq font-lock-beg end)
- nil)))))
+ (when (< font-lock-end (point))
+ (haskell-tng:debug-extend (point))
+ (setq font-lock-end (point))
+ nil))))
(defun haskell-tng:extend-defns ()
- "Extends data, type, class and instance definitons to include their full
type part."
+ "Multiline data, type, newtype, class and instance definitions."
nil
)
-(defun haskell-tng:extend-module-open ()
+(defun haskell-tng:extend-module ()
"For use in `font-lock-extend-region-functions'.
Ensures that multiline `module' definitions are opened."
nil)
-(defun haskell-tng:extend-module-close ()
- "For use in `font-lock-extend-region-functions'.
-Ensures that multiline `module' definitions are closed."
- nil)
-
-(defun haskell-tng:extend-import-open ()
+(defun haskell-tng:extend-import ()
"For use in `font-lock-extend-region-functions'.
Ensures that multiline `import' definitions are opened."
nil)
-(defun haskell-tng:extend-import-close ()
- "For use in `font-lock-extend-region-functions'.
-Ensures that multiline `import' definitions are closed."
- nil)
-
;; TODO multiline data / newtype / type definitions
+;; TODO delete the paren and type extender and rely on growing from a seed
(defun haskell-tng:debug-extend (to)
(message "extending `%s' to include `%s'!"
@@ -304,5 +236,21 @@ Ensures that multiline `import' definitions are closed."
(buffer-substring-no-properties font-lock-end to)
"BADNESS! Reduced the region"))))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Helpers
+(defun haskell-tng:paren-close ()
+ "Return the position of the next `)', if it closes the current paren depth."
+ (save-excursion
+ (when-let (close (ignore-errors (scan-lists (point) 1 1)))
+ (goto-char (- close 1))
+ (when (looking-at ")")
+ (point)))))
+
+;; FIXME
+(defun debug-goto-close ()
+ (interactive)
+ (when-let (p (haskell-tng:paren-close))
+ (goto-char p)))
+
(provide 'haskell-tng-font-lock)
;;; haskell-tng-font-lock.el ends here
diff --git a/haskell-tng-mode.el b/haskell-tng-mode.el
index d162cc9..5577d39 100644
--- a/haskell-tng-mode.el
+++ b/haskell-tng-mode.el
@@ -50,15 +50,10 @@
font-lock-defaults '(haskell-tng:keywords)
font-lock-multiline t
font-lock-extend-region-functions '(font-lock-extend-region-wholelines
- haskell-tng:extend-parens-open
- haskell-tng:extend-parens-close
- haskell-tng:extend-type-open
- haskell-tng:extend-type-close
+ haskell-tng:extend-explicit-type
haskell-tng:extend-defns
- haskell-tng:extend-module-open
- haskell-tng:extend-module-close
- haskell-tng:extend-import-open
- haskell-tng:extend-import-close)
+ haskell-tng:extend-module
+ haskell-tng:extend-import)
;; whitespace is meaningful, no electric indentation
electric-indent-inhibit t)
- [nongnu] elpa/haskell-tng-mode 700524b 008/385: typo in keywords, (continued)
- [nongnu] elpa/haskell-tng-mode 700524b 008/385: typo in keywords, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 6ce5efb 007/385: moar type fontification, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 7bc3218 010/385: extend types in parens, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 52f0cb9 011/385: expand parens, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode f99ca77 012/385: fixup! expand parens, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode bd8f905 016/385: almost there, regions not being expanded, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode db064be 024/385: dank macro for font-lock extends/keyword, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 639fc6c 018/385: multiline types and font-lock-multiline, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode cc739ad 020/385: multiline topdecl type sections, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 595bd44 034/385: type families, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 77d6ec5 019/385: cleaned up multiline explicit types,
ELPA Syncer <=
- [nongnu] elpa/haskell-tng-mode fa32b46 037/385: finally caught the bug in anchor pre/post resetting, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode f2ce737 038/385: neutral, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 95ab59c 014/385: multiline type matching seems to work, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 85272cb 029/385: fixup! fixup! improve the multiline font macro, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 00f7d84 002/385: simplify names, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 111396f 004/385: converted many font-face rules to the rx DSL, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 6f8258c 009/385: thinking about multiline, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 5536d23 025/385: all font locks use the new macro, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode a7a90ea 028/385: fixup! improve the multiline font macro, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode b9bc414 027/385: improve the multiline font macro, ELPA Syncer, 2021/10/05