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."