[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/haskell-tng-mode b9bc414 027/385: improve the multiline fo
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/haskell-tng-mode b9bc414 027/385: improve the multiline font macro |
Date: |
Tue, 5 Oct 2021 23:58:55 -0400 (EDT) |
branch: elpa/haskell-tng-mode
commit b9bc414f7e9f6acab14b4df1a888df9b638a9c4e
Author: Tseen She <ts33n.sh3@gmail.com>
Commit: Tseen She <ts33n.sh3@gmail.com>
improve the multiline font macro
---
haskell-tng-font-lock.el | 119 +++++++++++++++++++++++++----------------------
haskell-tng-mode.el | 6 +--
2 files changed, 65 insertions(+), 60 deletions(-)
diff --git a/haskell-tng-font-lock.el b/haskell-tng-font-lock.el
index 47da66f..1707ffe 100644
--- a/haskell-tng-font-lock.el
+++ b/haskell-tng-font-lock.el
@@ -21,6 +21,7 @@
;; TODO: regression tests https://github.com/Lindydancer/faceup
;; TODO use levels so users can turn off type fontification
+(require 'dash)
(require 'haskell-tng-util)
(defgroup haskell-tng:faces nil
@@ -172,10 +173,13 @@
"Print debugging when the font-lock region is extended."
:type 'boolean)
-;; TODO (perf) don't call FIND or extend if there is a multiline property
-;; TODO simplify FIND to use paren-close / indent-close automatically?
-;; TODO option to avoid the initial regexp in -keyword if it overlaps
-(defmacro haskell-tng:font:multiline (name trigger find)
+(defconst haskell-tng:extend-region-functions
+ '(font-lock-extend-region-wholelines)
+ "Used in `font-lock-extend-region-functions'.
+Automatically populated by `haskell-tng:font:multiline'")
+
+;; TODO (perf) don't extend if the TRIGGER has a multiline prop
+(defmacro haskell-tng:font:multiline (name trigger find &rest limiters)
"Defines `font-lock-keywords' / `font-lock-extend-region-functions' entries.
TRIGGER is a referentially transparent form that produces a regexp.
@@ -184,76 +188,81 @@ FIND is a form that must behave the same as
`re-search-forward',
i.e. setting the match groups and placing point after the match.
The variable `limit' is dynamically bound within this form.
-Both TRIGGER and FIND should be optimised as they will be called
-repeatedly as the user is entering text and navigating the code.
-
-The generated `haskell-tng:PREFIX-extend' uses searches
-backwards from the end of the proposed region with TRIGGER. If a
-match is found, then FIND is evaluated with an unlimited limit to
-calculate the end position, which may extend the region.
+The generated `haskell-tng:PREFIX-extend' searches backwards from
+the end of the proposed region for TRIGGER. If a match is found,
+FIND is called with a limit until the end of the buffer, which
+may extend the region.
The generated `haskell-tng:PREFIX-keyword' searches forward for
TRIGGER within the fontification limit. The point is reset to the
-beginning of the TRIGGER's match and FIND is evaluated."
+beginning of the TRIGGER's match and FIND is evaluated.
+
+The LIMITERS are function names that will be called when the
+TRIGGER succeeds and may return a more restrictive limit than the
+defaults for FIND."
(declare (indent defun))
(let* ((sname (concat "haskell-tng:font:" (symbol-name name)))
(regexp (intern (concat sname ":trigger")))
(keyword (intern (concat sname ":keyword")))
(extend (intern (concat sname ":extend"))))
- `(progn
- (defconst ,regexp ,trigger)
- (defun ,keyword (limit)
- (when (re-search-forward ,regexp limit t)
- (goto-char (match-beginning 0))
- ,find))
- (defun ,extend ()
- (goto-char font-lock-end)
- (when (re-search-backward ,regexp font-lock-beg t)
- (let ((limit (point-max))) ,find)
- (when (< font-lock-end (point))
- (when haskell-tng:font:debug-extend
- (haskell-tng:font:debug-extend (point)))
- (setq font-lock-end (point))
- nil))))))
+ (cl-flet
+ ((finder (lim)
+ `(re-search-forward
+ ,find
+ (-min (cons ,lim (-non-nil (-map 'funcall ',limiters))))
+ t)))
+ `(progn
+ (defconst ,regexp ,trigger)
+ (defun ,extend ()
+ (goto-char font-lock-end)
+ (when (re-search-backward ,regexp font-lock-beg t)
+ ,(finder '(point-max))
+ (when (< font-lock-end (point))
+ (when haskell-tng:font:debug-extend
+ (haskell-tng:font:debug-extend (point)))
+ (setq font-lock-end (point))
+ nil)))
+ (defun ,keyword (limit)
+ (when (re-search-forward ,regexp limit t)
+ (goto-char (match-beginning 0))
+ ,(finder 'limit)))
+ (add-to-list 'haskell-tng:extend-region-functions ',extend t)))))
(haskell-tng:font:multiline explicit-type
(rx symbol-start "::" symbol-end)
- (let ((paren (haskell-tng:paren-close))
- (indent (haskell-tng:indent-close (- (point) 1))))
- (re-search-forward
- (rx symbol-start "::" symbol-end (group (+ anything)))
- (min limit (or paren limit) (or indent limit)) t)))
+ (rx symbol-start "::" symbol-end (group (+ anything)))
+ haskell-tng:paren-close
+ haskell-tng:font:explicit-type:indent)
+
+(defun haskell-tng:font:explicit-type:indent ()
+ "Indentation closing the previous symbol."
+ (save-excursion
+ (forward-symbol -1)
+ (haskell-tng:indent-close)))
(haskell-tng:font:multiline topdecl
(rx line-start (| "data" "newtype" "class" "instance") symbol-end)
- (re-search-forward
- (rx line-start (| "data" "newtype" "class" "instance") symbol-end
- (group (+? anything))
- (| (: line-start symbol-start)
- (: symbol-start (| "where" "=") symbol-end)))
- limit t))
+ (rx line-start (| "data" "newtype" "class" "instance") symbol-end
+ (group (+? anything))
+ (| (: line-start symbol-start)
+ (: symbol-start (| "where" "=") symbol-end))))
(haskell-tng:font:multiline type
(rx line-start "type" symbol-end)
- (let ((indent (haskell-tng:indent-close)))
- (re-search-forward
- (rx line-start "type" symbol-end (+ space) (group (+ anything)))
- (min limit (or indent limit)))))
-
+ (rx line-start "type" symbol-end (+ space) (group (+ anything)))
+ haskell-tng:indent-close)
+
+;; DeriveAnyClass
+;; DerivingStrategies
+;; GeneralizedNewtypeDeriving
+;; TODO DerivingVia
+;; TODO StandaloneDeriving
(haskell-tng:font:multiline deriving
(rx symbol-start "deriving" symbol-end)
- ;; DeriveAnyClass
- ;; DerivingStrategies
- ;; GeneralizedNewtypeDeriving
- ;; TODO DerivingVia
- ;; TODO StandaloneDeriving
- (let ((indent (haskell-tng:indent-close)))
- (re-search-forward
- (rx
- symbol-start "deriving" (+ space)
- (group (opt (| "anyclass" "stock" "newtype"))) (* space)
- ?\( (group (* anything)) ?\))
- (min limit (or indent limit)) t)))
+ (rx symbol-start "deriving" symbol-end
+ (+ space) (group (opt (| "anyclass" "stock" "newtype")))
+ (* space) ?\( (group (* anything)) ?\))
+ haskell-tng:indent-close)
;; TODO modules
;; TODO imports
diff --git a/haskell-tng-mode.el b/haskell-tng-mode.el
index 9fbdec8..bec845f 100644
--- a/haskell-tng-mode.el
+++ b/haskell-tng-mode.el
@@ -49,11 +49,7 @@
font-lock-defaults '(haskell-tng:keywords)
font-lock-multiline t
- font-lock-extend-region-functions '(font-lock-extend-region-wholelines
- haskell-tng:font:explicit-type:extend
- haskell-tng:font:topdecl:extend
- haskell-tng:font:type:extend
- haskell-tng:font:deriving:extend)
+ font-lock-extend-region-functions haskell-tng:extend-region-functions
;; whitespace is meaningful, no electric indentation
electric-indent-inhibit t)
- [nongnu] elpa/haskell-tng-mode 77d6ec5 019/385: cleaned up multiline explicit types, (continued)
- [nongnu] elpa/haskell-tng-mode 77d6ec5 019/385: cleaned up multiline explicit types, ELPA Syncer, 2021/10/05
- [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 <=
- [nongnu] elpa/haskell-tng-mode ea77bb2 017/385: fixup! almost there, regions not being expanded, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 2b82b2f 022/385: fixup! fixup! multiline topdecl type sections, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 46abfc4 035/385: getting closer to good types in imports, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode c3d4e70 031/385: don't reinvent standard tools, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 7c2dedb 043/385: use pyenv when running cask, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 2f04c01 051/385: starting work on semicolon inference, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode a4a664b 056/385: layout inference, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode d33d146 060/385: [ci skip] start to refactor layout out of lexer, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 12c7148 040/385: leave fontification in comments and strings, ELPA Syncer, 2021/10/05
- [nongnu] elpa/haskell-tng-mode 61f4c09 062/385: [ci skip] unify the testing approach, ELPA Syncer, 2021/10/05