branch: elpa/haskell-tng-mode
commit 6f8258c2e626731d0e996f5698b9074f0bd1e549
Author: Tseen She <ts33n....@gmail.com>
Commit: Tseen She <ts33n....@gmail.com>

    thinking about multiline
---
 README.md                |  4 ++--
 haskell-tng-font-lock.el | 58 +++++++++++++++++++++++++++++++++++++++++-------
 haskell-tng-mode.el      |  9 ++++++--
 3 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md
index b9e636e..7a96e7c 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ This is an exploratory alternative to 
[`haskell-mode`](https://github.com/haskel
 
 `haskell-mode` is almost 30 years old and has accumulated more than 25,000 
lines of code. It's too much to handle.
 
-Meanwhile, the GNU Emacs ecosystem has evolved to provide many features that 
`haskell-mode` independently implemented, such as 
[`projectile`](https://github.com/bbatsov/projectile), 
[`comint-mode`](https://masteringemacs.org/article/comint-writing-command-interpreter),
 [`highlight-symbol`](https://melpa.org/##/highlight-symbol), 
[`pretty-symbols`](https://github.com/drothlis/pretty-symbols), 
[`company-mode`](http://company-mode.github.io), 
[`yasnippet`](http://joaotavora.github.io/yasnip [...]
+Meanwhile, the GNU Emacs ecosystem has evolved to provide many features that 
`haskell-mode` independently implemented, such as 
[`projectile`](https://github.com/bbatsov/projectile), 
[`comint`](https://masteringemacs.org/article/comint-writing-command-interpreter),
 [`highlight-symbol`](https://melpa.org/##/highlight-symbol), 
[`pretty-symbols`](https://github.com/drothlis/pretty-symbols), 
[`company`](http://company-mode.github.io), 
[`yasnippet`](http://joaotavora.github.io/yasnippet/), [`p [...]
 
 ## Approach
 
@@ -22,7 +22,7 @@ If it is possible to implement a feature using another minor 
mode, or command li
 
 Bug reports and feature requests are a source of anxiety for maintainers, and 
encourage an unhealthy customer / supplier relationship between users and 
contributors.
 
-Instead, and following the [anarchical spirit of 
Haskell](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/history.pdf),
 we encourage discussions and debate around code contributions. Merge requests 
can be raised by anybody and discussed by anybody. If the maintainers are 
convinced by the technical merit and quality of a proposal, they may accept it.
+Instead, and following the [anarchical spirit of 
Haskell](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/history.pdf),
 we encourage discussions and debate around code contributions. Merge requests 
can be raised by anybody and discussed by anybody, and do not need to be 
complete. A failing automated test is the only way to report a bug. If the 
maintainers are convinced by the technical merit and quality of a proposal, 
they may accept it.
 
 ## Install
 
diff --git a/haskell-tng-font-lock.el b/haskell-tng-font-lock.el
index fef023e..bb8f897 100644
--- a/haskell-tng-font-lock.el
+++ b/haskell-tng-font-lock.el
@@ -47,6 +47,10 @@
   "Haskell top level declarations."
   :group 'haskell-tng:faces)
 
+;; TODO: a macro to call rx-to-string at runtime that doesn't need (: )
+;;
+;; TODO: regression tests https://github.com/Lindydancer/faceup
+;;
 ;; TODO: pragmas
 ;;
 ;; TODO: numeric / char primitives?
@@ -59,14 +63,24 @@
 ;;
 ;; TODO: consider ; in the "until the end of the line" searches.
 
+(defconst haskell-tng:conid '(: upper (* wordchar)))
+(defconst haskell-tng:consym '(: ":" (+ (syntax symbol))))
+(defconst haskell-tng:toplevel
+  `(: line-start (group (| (: (any lower ?_) (* wordchar))
+                           (: "(" (+? (syntax symbol)) ")")))
+      symbol-end))
+
+;; TODO a macro that wraps these consts with short-form names
+
 (setq
  haskell-tng:keywords
  ;; These regexps use the `rx' library so we can reuse common subpatterns. It
  ;; also increases the readability of the code and, in many cases, allows us to
  ;; do more work in a single regexp instead of multiple passes.
- (let* ((conid '(: upper (* wordchar)))
-        (qual `(: (+ (: ,conid (char ?.)))))
-        (consym '(: ":" (+ (syntax symbol)))))
+ (let ((conid haskell-tng:conid)
+       (qual `(: (+ (: ,haskell-tng:conid (char ?.)))))
+       (consym haskell-tng:consym)
+       (toplevel haskell-tng:toplevel))
    `(;; reservedid / reservedop
      (,(rx-to-string
         '(|
@@ -107,6 +121,8 @@
      (,(rx-to-string `(: symbol-start "module" symbol-end (+ space)
                          symbol-start (group (opt ,qual) ,conid) symbol-end))
       1 'haskell-tng:module)
+     ;; TODO types vs constructor highlighting.
+     ;; needs a multi-line anchor.
 
      ;; imports (multi-line support would improve this)
      (,(rx-to-string '(: word-start "import" word-end)) ;; anchor matcher
@@ -127,11 +143,7 @@
        nil nil (1 'haskell-tng:type)))
 
      ;; top-level
-     (,(rx-to-string `(: line-start
-                         (group (|
-                                 (: (any lower ?_) (* wordchar))
-                                 (: "(" (+? (syntax symbol)) ")")))
-                         symbol-end))
+     (,(rx-to-string toplevel)
       . 'haskell-tng:toplevel)
 
      ;; uses of F.Q.N.s
@@ -144,5 +156,35 @@
 
      )))
 
+;; TODO: consider previous/next symbol instead of whole line detection in
+;; font-lock-extend-region-functions for super duper hyper perf.
+
+(defun haskell-tng:multiline-faces ()
+  "For use in `font-lock-extend-region-functions'.
+
+Detects multiline patterns, such as multiline `module', `import'
+and type signatures, setting `font-lock-beg' / `font-lock-end'
+appropriately, returning nil."
+  (defvar font-lock-beg)
+  (defvar font-log-end)
+  (save-excursion
+    (goto-char font-lock-beg)
+
+    ;; TODO: detect :: and extend forwards as necessary
+    ;; TODO: detect -> and check if it's a type, then extend both ways
+    ;; TODO: detect module / import and check if its multiline
+    )
+  nil)
+
+(defun haskell-tng:mark-block ()
+  ;; TODO: this is kinda obscure, replace with mark-defun when it is defined
+  "For use as `font-lock-mark-block-function'."
+  (let ((toplevel (rx-to-string haskell-tng:toplevel)))
+    (right-char)
+    (re-search-forward toplevel (point-max) 'max)
+    (move-beginning-of-line nil)
+    (set-mark (point))
+    (re-search-forward toplevel (point-min) 'min -1)))
+
 (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 1887637..2ce02411 100644
--- a/haskell-tng-mode.el
+++ b/haskell-tng-mode.el
@@ -47,10 +47,15 @@
    syntax-propertize-function #'haskell-tng:syntax-propertize
    parse-sexp-lookup-properties t
 
-   font-lock-defaults '(haskell-tng:keywords nil nil nil)
+   font-lock-defaults '(haskell-tng:keywords
+                        nil nil nil nil
+                        (font-lock-mark-block-function . 
haskell-tng:mark-block))
+   font-lock-extend-region-functions '(font-lock-extend-region-wholelines
+                                       haskell-tng:multiline-faces)
 
    ;; whitespace is meaningful, no electric indentation
-   electric-indent-inhibit t))
+   electric-indent-inhibit t)
+  )
 
 (defcustom haskell-tng-mode-hook nil
   "List of functions to run after `haskell-tng-mode' is enabled."

Reply via email to