0
|
1 |
|
|
2 |
* haskell-ts-mode
|
|
3 |
|
|
4 |
A haskell mode that uses treesitter.
|
|
5 |
|
|
6 |
* Screenshot
|
|
7 |
|
|
8 |
[[./ss.png]]
|
|
9 |
|
|
10 |
The above screenshot is indented coloured using haskell-ts-mode, with
|
|
11 |
prettify-symbols-mode enabled.
|
|
12 |
|
|
13 |
* Usage
|
|
14 |
|
|
15 |
=C-c C-r= to open REPL
|
|
16 |
=C-c C-c= to send code to repl
|
|
17 |
=C-M-q= Indent paragraph
|
|
18 |
|
|
19 |
* Features
|
|
20 |
an overview of the features are:
|
|
21 |
- Syntax highliting
|
|
22 |
- Indentation
|
|
23 |
- Imenu support
|
|
24 |
- REPL (C-c r in the mode to run)
|
|
25 |
- Prettify symbols mode support
|
|
26 |
|
|
27 |
* Comparasion with haskell-mode
|
|
28 |
The more interesting features are:
|
|
29 |
- Logical syntax highlighting:
|
|
30 |
- Only arguments that can be used in functions are highlighted, eg
|
|
31 |
in `f (_:(a:[])) only 'a' is highlighted, as it is the only
|
|
32 |
variable that is captured that can be used in body of function
|
|
33 |
- The return type of a function is highlighted
|
|
34 |
- All new variabels are(or should be) highlighted, this includes
|
|
35 |
generators, lambda args.
|
|
36 |
- highlighting the '=' operaotr in guarded matches correctly, this
|
|
37 |
would be stupidly hard in regexp based syntax
|
|
38 |
- Unlike haskell-mode, quasi quotes are understood and do not confuse
|
|
39 |
the mode, thanks to treesitter
|
|
40 |
- Predictable (but less powerful) indentation: haskell-mode's
|
|
41 |
indentation works in a cyclical way, it cycles through where you
|
|
42 |
might want indentation. haskell-ts-mode, meanwhile relies on you to
|
|
43 |
set the concrete syntax tree changing whitespace.
|
|
44 |
- More perfomant, this is especially seen in longer files
|
|
45 |
- Much much less code, haskell mode has accumlated 30,000 lines of
|
|
46 |
features to do with all things haskell related, this mode just keeps
|
|
47 |
the scope to basic major mode stuff, and leaves other stuff for
|
|
48 |
external packages.
|
|
49 |
|
|
50 |
* Motivation
|
|
51 |
|
|
52 |
haskell-mode contains nearly 30k lines of code, and is
|
|
53 |
about 30 years old. Therefore, a lot of stuff emacs has gained the
|
|
54 |
ability to do in those years, haskell-mode already has implemented
|
|
55 |
them.
|
|
56 |
|
|
57 |
In 2018, a mode called haskell-tng-mode was made to solve some of
|
|
58 |
these problems. However because of haskell's syntax, it too became
|
|
59 |
very complex and required a web of dependencies.
|
|
60 |
|
|
61 |
Both these modes ended up practically parsing haskells syntax to
|
|
62 |
implement indentation, so I thought why not use tree sitter?
|
|
63 |
|
|
64 |
* Installation
|
|
65 |
|
|
66 |
The package is avaiable on elpa, you can install it using:
|
|
67 |
M-x package-install RET haskell-ts-mode RET
|
|
68 |
|
|
69 |
#+begin_src elisp
|
|
70 |
(add-to-list 'load-path "path/to/haskell-ts-mode")
|
|
71 |
(require 'haskell-ts-mode)
|
|
72 |
#+end_src
|
|
73 |
|
|
74 |
* Customization
|
|
75 |
|
|
76 |
If colour is too much or too less for you, adjust
|
|
77 |
treesit-font-lock-level accordingly.
|
|
78 |
|
|
79 |
If you want to highlight signature declarations (disabled by default),
|
|
80 |
add the following to your init file:
|
|
81 |
#+begin_src emacs-lisp
|
|
82 |
(setq haskell-ts-highlight-signature t)
|
|
83 |
#+end_src
|
|
84 |
|
|
85 |
** how to disable haskell-ts-mode indentation
|
|
86 |
|
|
87 |
#+begin_src emacs-lisp
|
|
88 |
(setq haskell-ts-use-indent nil)
|
|
89 |
#+end_src
|
|
90 |
|
|
91 |
** Pretify symbols mode
|
|
92 |
prettify symbols mode can be used to replace common symbols with
|
|
93 |
unicode alternatives.
|
|
94 |
|
|
95 |
#+begin_src emacs-lisp
|
|
96 |
(add-hook 'haskell-ts-mode 'prettify-symbols-mode)
|
|
97 |
#+end_src
|
|
98 |
|
|
99 |
** Adjusting font lock level
|
|
100 |
set haskell-ts-font-lock-level accordingly.
|
|
101 |
|
|
102 |
** Language server
|
|
103 |
|
|
104 |
haskell-ts-mode is compatiable with lsp-haskell.
|
|
105 |
|
|
106 |
To enable eglot support, use the following code in your init.el:
|
|
107 |
#+begin_src emacs-lisp
|
|
108 |
(with-eval-after-load 'eglot (haskell-ts-setup-eglot))
|
|
109 |
#+end_src
|
|
110 |
|
|
111 |
* TODO and limitations
|
|
112 |
- Imenu support for functions with multiple definitions
|
|
113 |
|
|
114 |
Limitations: _Proper indenting of multiline signatures_: the
|
|
115 |
treesitter grammer does not flatten the signautes, rather leaves them
|
|
116 |
to the standard infix interpretatoin. This makes indentation hard, as
|
|
117 |
it will mean the only way to check if the the signature node is an
|
|
118 |
ancestor of node at point is to perfom a recursive ascent, which is
|
|
119 |
horrible for perfomance.
|