|
1 #+title: haskell-ts-mode |
|
2 #+author: Pranshu Sharma |
1 |
3 |
2 * haskell-ts-mode |
4 * haskell-ts-mode |
3 |
5 |
4 A haskell mode that uses treesitter. |
6 A haskell mode that uses treesitter. |
5 |
7 |
6 * Screenshot |
8 * Screenshot |
7 |
9 |
8 [[./ss.png]] |
10 [[./ss.png]] |
9 |
11 |
10 The above screenshot is indented coloured using haskell-ts-mode, with |
12 The above screenshot is indented and coloured using haskell-ts-mode, |
11 prettify-symbols-mode enabled. |
13 with =prettify-symbols-mode= enabled. |
12 |
14 |
13 * Usage |
15 * Usage |
14 |
16 |
15 =C-c C-r= to open REPL |
17 =C-c C-r= to open REPL |
16 =C-c C-c= to send code to repl |
18 =C-c C-c= to send code to repl |
17 =C-M-q= Indent paragraph |
19 =C-M-q= Indent the function |
18 |
20 |
19 * Features |
21 * Features |
|
22 |
|
23 say it with me: indentation does not change the syntax-tree. This |
|
24 means that the indenation is a lot more predictable, but sometimes you |
|
25 must manually press M-i to indent. |
|
26 |
20 an overview of the features are: |
27 an overview of the features are: |
21 - Syntax highliting |
28 - Syntax highliting |
22 - Indentation |
29 - Indentation |
23 - Imenu support |
30 - Imenu support |
24 - REPL (C-c r in the mode to run) |
31 - REPL (C-c r in the mode to run) |
26 |
33 |
27 * Comparasion with haskell-mode |
34 * Comparasion with haskell-mode |
28 The more interesting features are: |
35 The more interesting features are: |
29 - Logical syntax highlighting: |
36 - Logical syntax highlighting: |
30 - Only arguments that can be used in functions are highlighted, eg |
37 - Only arguments that can be used in functions are highlighted, eg |
31 in `f (_:(a:[])) only 'a' is highlighted, as it is the only |
38 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 |
39 variable that is captured that can be used in body of function |
33 - The return type of a function is highlighted |
40 - The return type of a function is highlighted |
34 - All new variabels are(or should be) highlighted, this includes |
41 - All new variabels are(or should be) highlighted, this includes |
35 generators, lambda args. |
42 generators, lambda args. |
36 - highlighting the '=' operaotr in guarded matches correctly, this |
43 - highlighting the '=' operaotr in guarded matches correctly, this |
37 would be stupidly hard in regexp based syntax |
44 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 - More perfomant, this is especially seen in longer files |
45 - Much much less code, haskell mode has accumlated 30,000 lines of |
46 - 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 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 the scope to basic major mode stuff, and leaves other stuff for |
48 external packages. |
49 external packages. |
49 |
50 |
50 * Motivation |
51 * Motivation |
51 |
52 |
52 haskell-mode contains nearly 30k lines of code, and is |
53 =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 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 ability to do in those years, haskell-mode already has implemented |
55 them. |
56 them. |
56 |
57 |
57 In 2018, a mode called haskell-tng-mode was made to solve some of |
58 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 these problems. However because of haskell's syntax, it too became |
59 very complex and required a web of dependencies. |
60 very complex and required a web of dependencies. |
60 |
61 |
61 Both these modes ended up practically parsing haskells syntax to |
62 Both these modes ended up practically parsing haskells syntax to |
62 implement indentation, so I thought why not use tree sitter? |
63 implement indentation, so I thought why not use tree sitter? |
87 #+begin_src emacs-lisp |
88 #+begin_src emacs-lisp |
88 (setq haskell-ts-use-indent nil) |
89 (setq haskell-ts-use-indent nil) |
89 #+end_src |
90 #+end_src |
90 |
91 |
91 ** Pretify symbols mode |
92 ** Pretify symbols mode |
92 prettify symbols mode can be used to replace common symbols with |
93 =prettify-symbols-mode= can be used to replace common symbols with |
93 unicode alternatives. |
94 unicode alternatives. |
94 |
95 |
95 #+begin_src emacs-lisp |
96 #+begin_src emacs-lisp |
96 (add-hook 'haskell-ts-mode 'prettify-symbols-mode) |
97 (add-hook 'haskell-ts-mode 'prettify-symbols-mode) |
97 #+end_src |
98 #+end_src |
98 |
99 |
99 ** Adjusting font lock level |
100 ** Adjusting font lock level |
100 set haskell-ts-font-lock-level accordingly. |
101 set =haskell-ts-font-lock-level= accordingly. Default value is 4, so if |
|
102 you suffer from contagious dehydration, you can lower it. |
101 |
103 |
102 ** Language server |
104 ** Language server |
103 |
105 |
104 haskell-ts-mode is compatiable with lsp-haskell. |
106 =haskell-ts-mode= now works with =lsp-mode=, however =lsp-haskell= still requires on =haskell-mode=. |
105 |
107 |
106 To enable eglot support, use the following code in your init.el: |
108 To add =eglot= support, add the following code to you init.el: |
|
109 |
107 #+begin_src emacs-lisp |
110 #+begin_src emacs-lisp |
108 (with-eval-after-load 'eglot (haskell-ts-setup-eglot)) |
111 (with-eval-after-load 'eglot |
|
112 (defvar eglot-server-programs) |
|
113 (add-to-list 'eglot-server-programs |
|
114 '(haskell-ts-mode . ("haskell-language-server-wrapper" "--lsp")))) |
109 #+end_src |
115 #+end_src |
110 |
116 |
111 * TODO and limitations |
117 * TODO |
112 - Imenu support for functions with multiple definitions |
118 - Imenu support for functions with multiple definitions |
113 |
119 - _Proper indenting of multiline signatures_: the treesitter grammer |
114 Limitations: _Proper indenting of multiline signatures_: the |
120 does not flatten the signautes, rather leaves them to the standard |
115 treesitter grammer does not flatten the signautes, rather leaves them |
121 infix interpretatoin. This makes indentation hard, as it will mean |
116 to the standard infix interpretatoin. This makes indentation hard, as |
122 the only way to check if the the signature node is an ancestor of |
117 it will mean the only way to check if the the signature node is an |
123 node at point is to perfom a recursive ascent. |
118 ancestor of node at point is to perfom a recursive ascent, which is |
|
119 horrible for perfomance. |
|