• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..15-Sep-2021-

src/H15-Sep-2021-7,2564,987

test/H15-Sep-2021-3,0681,943

COMMANDS.mdH A D15-Sep-20218.1 KiB650388

LICENSEH A D15-Sep-202111.1 KiB202169

README.mdH A D15-Sep-20215.4 KiB163111

hls-tactics-plugin.cabalH A D15-Sep-20214 KiB176165

README.md

1<p align="center">
2<img src="https://haskellwingman.dev/wingman.png" height="256" alt="Wingman for Haskell" title="Wingman for Haskell">
3</p>
4
5<p>&nbsp;</p>
6
7# Wingman for Haskell
8
9[![Hackage](https://img.shields.io/hackage/v/hls-tactics-plugin.svg?logo=haskell&label=hls-tactics-plugin)](https://hackage.haskell.org/package/hls-tactics-plugin)
10
11"Focus on the important stuff; delegate the rest"
12
13
14## Dedication
15
16> There's a lot of automation that can happen that isn't a replacement of
17> humans, but of mind-numbing behavior.
18>
19> --Stewart Butterfield
20
21
22## Overview
23
24Wingman writes the boring, auxiliary code, so you don't have to. Generate
25functions from type signatures, and intelligently complete holes.
26
27
28## Getting Started
29
30Wingman for Haskell is enabled by default in all [official release of Haskell
31Language Server.][hls] Just hover over a typed hole, run the "Attempt to
32fill hole" code action, *et voila!*
33
34[hls]: https://github.com/haskell/haskell-language-server/releases
35
36
37## Usage
38
39When enabled, Wingman for Haskell will remove HLS support for hole-fit code
40actions. These code actions are provided by GHC and make typechecking extremely
41slow in the presence of typed holes. Because Wingman relies so heavily on typed
42holes, these features are in great tension.
43
44The solution: we just remove the hole-fit actions. If you'd prefer to use these
45actions, you can get them back by compiling HLS without the Wingman plugin.
46
47
48## Editor Configuration
49
50### Enabling Jump to Hole
51
52Set the `haskell.plugin.tactics.config.hole_severity` config option to `4`, or
53`hint` if your editor uses a GUI for its configuration. This has the potential
54to negatively impact performance --- please holler if you notice any appreciable
55slowdown by enabling this option.
56
57
58### coc.nvim
59
60The following vimscript maps Wingman code-actions to your leader key:
61
62```viml
63" use [h and ]h to navigate between holes
64nnoremap <silent> [h :<C-U>call CocActionAsync('diagnosticPrevious', 'hint')<CR>
65nnoremap <silent> ]h :<C-U>call <SID>JumpToNextHole()<CR>
66
67" <leader>d to perform a pattern match, <leader>n to fill a hole
68nnoremap <silent> <leader>d  :<C-u>set operatorfunc=<SID>WingmanDestruct<CR>g@l
69nnoremap <silent> <leader>n  :<C-u>set operatorfunc=<SID>WingmanFillHole<CR>g@l
70nnoremap <silent> <leader>r  :<C-u>set operatorfunc=<SID>WingmanRefine<CR>g@l
71nnoremap <silent> <leader>c  :<C-u>set operatorfunc=<SID>WingmanUseCtor<CR>g@l
72nnoremap <silent> <leader>a  :<C-u>set operatorfunc=<SID>WingmanDestructAll<CR>g@l
73
74
75function! s:JumpToNextHole()
76  call CocActionAsync('diagnosticNext', 'hint')
77endfunction
78
79function! s:GotoNextHole()
80  " wait for the hole diagnostics to reload
81  sleep 500m
82  " and then jump to the next hole
83  normal 0
84  call <SID>JumpToNextHole()
85endfunction
86
87function! s:WingmanRefine(type)
88  call CocAction('codeAction', a:type, ['refactor.wingman.refine'])
89  call <SID>GotoNextHole()
90endfunction
91
92function! s:WingmanDestruct(type)
93  call CocAction('codeAction', a:type, ['refactor.wingman.caseSplit'])
94  call <SID>GotoNextHole()
95endfunction
96
97function! s:WingmanDestructAll(type)
98  call CocAction('codeAction', a:type, ['refactor.wingman.splitFuncArgs'])
99  call <SID>GotoNextHole()
100endfunction
101
102function! s:WingmanFillHole(type)
103  call CocAction('codeAction', a:type, ['refactor.wingman.fillHole'])
104  call <SID>GotoNextHole()
105endfunction
106
107function! s:WingmanUseCtor(type)
108  call CocAction('codeAction', a:type, ['refactor.wingman.useConstructor'])
109  call <SID>GotoNextHole()
110endfunction
111```
112
113### Emacs
114
115When using Emacs, wingman actions should be available out-of-the-box and
116show up e.g. when using `M-x helm-lsp-code-actions RET` provided by
117[helm-lsp](https://github.com/emacs-lsp/helm-lsp) or as popups via
118[lsp-ui-sideline](https://emacs-lsp.github.io/lsp-ui/#lsp-ui-sideline).
119
120Additionally, if you want to bind wingman actions directly to specific
121keybindings or use them from Emacs Lisp, you can do so like this:
122
123``` emacs-lisp
124;; will define elisp functions for the given lsp code actions, prefixing the
125;; given function names with "lsp"
126(lsp-make-interactive-code-action wingman-fill-hole "refactor.wingman.fillHole")
127(lsp-make-interactive-code-action wingman-case-split "refactor.wingman.caseSplit")
128(lsp-make-interactive-code-action wingman-refine "refactor.wingman.refine")
129(lsp-make-interactive-code-action wingman-split-func-args "refactor.wingman.spltFuncArgs")
130(lsp-make-interactive-code-action wingman-use-constructor "refactor.wingman.useConstructor")
131
132;; example key bindings
133(define-key haskell-mode-map (kbd "C-c d") #'lsp-wingman-case-split)
134(define-key haskell-mode-map (kbd "C-c n") #'lsp-wingman-fill-hole)
135(define-key haskell-mode-map (kbd "C-c r") #'lsp-wingman-refine)
136(define-key haskell-mode-map (kbd "C-c c") #'lsp-wingman-use-constructor)
137(define-key haskell-mode-map (kbd "C-c a") #'lsp-wingman-split-func-args)
138```
139
140### Other Editors
141
142Please open a PR if you have a working configuration!
143
144
145## Features
146
147* [Type-directed code synthesis][auto], including pattern matching and recursion
148* [Automatic case-splitting][case] --- just run the "Case split on <x>" code action
149* [Smart next actions][next], for those times it can't read your mind
150
151[auto]: https://haskellwingman.dev/foldr.gif
152[case]: https://haskellwingman.dev/case-split.gif
153[next]: https://haskellwingman.dev/intros.gif
154
155
156## Support
157
158Please consider [pledging on Patreon][patreon] to support the project and get
159access to cutting-edge features.
160
161[patreon]: https://www.patreon.com/wingman_for_haskell
162
163