-
Notifications
You must be signed in to change notification settings - Fork 19
/
HACKING
155 lines (113 loc) · 5.88 KB
/
HACKING
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# Contributing
At this early stage we're going a bit fast and loose. There are
currently no processes involving contributions. If in doubt, create an issue.
If you'd like to hack on purebred, either pick an issue from the backlog and
signal with a comment that you'd want to work on it. Most of the issues are very
high level and need clarification when it comes to implementation details. So
communication is the key here rather than hacking away.
## Hacking guidelines for purebred
- do not use hs-notmuch message methods that open file descriptors
- optics are your friend
- use `view`, `review`, `set`, `over` and so on instead of the
infix optic functions from lens
- use explicit import list or qualified imports
- no perf optimisations without measurements (preferably in the commit
message)
- use the weakest abstraction possible:
- traverse > mapM
- pure > return
- ``Data.Semigroup.<>`` > ``Data.Monoid.<>`` > ``Data.List.++``
- and so on...
- For executing subprocesses, use only the functions exported
from `Purebred.System.Process`. This is so that output is
tainted, indicating that it must be sanitised before use.
(The test suite is excepted from this policy.)
## How to profile
Profiling Purebred is perhaps not as obvious as profiling other
projects, because Purebred is compiling it's own configuration upon
startup.
First step is to enable profiling in cabal creating a `cabal.project` file:
$ cat cabal.project
packages: .
package *
profiling: True
Note: Currently the `--enable-profiling` does not install profiling
information in the cabal install directory. See
[#7297](https://github.com/haskell/cabal/issues/7297) for more
information.
Build purebred and install it:
$ cabal new-install -j --installdir=$HOME/.cabal/bin/ exe:purebred
Start `purebred` with additional `GHCOPTS` environment variable as
well as runtime parameters. The `GHCOPTS` environment variable tells
dyre to pass those parameters to `ghc` when recompiling the
config. The `RTS` options are used to enable profiling:
$ GHCOPTS="-prof -fprof-auto" ~/.cabal/bin/purebred +RTS -p
### Problems
If you run into compilation errors like:
Could not load module ‘Data.MIME’
It is a member of the hidden package ‘purebred-email-0.4.2’.
You can run ‘:set -package purebred-email’ to expose it.
(Note: this unloads all the modules in the current scope.)
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
33 | import Data.MIME (matchContentType)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
check your [GHC package
environment](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/packages.html?highlight=ghc%20pkg#package-environments). Most
likely, the package is not listed and needs to be added.
Also check whether files are present holding profiling
information. The file extension should be prefixed with a `p_`. For
example:
$ ls ~/.cabal/store/ghc-8.8.4/purebred-0.1.0.0-168d7c26ff515ebbea37fcb1e23cef711eef8e398f9fe910bec0900966231966/lib/
libHSpurebred-0.1.0.0-168d7c26ff515ebbea37fcb1e23cef711eef8e398f9fe910bec0900966231966.a
libHSpurebred-0.1.0.0-168d7c26ff515ebbea37fcb1e23cef711eef8e398f9fe910bec0900966231966-ghc8.8.4.so
libHSpurebred-0.1.0.0-168d7c26ff515ebbea37fcb1e23cef711eef8e398f9fe910bec0900966231966_p.a
Paths_purebred.dyn_hi
Paths_purebred.hi
Paths_purebred.p_hi
Purebred/
Purebred.dyn_hi
Purebred.hi
Purebred.p_hi
### User Acceptance Test Flakes
* Flakes can be caused by late running validations from input fields
(`To:`, `From:`) overwriting any status reports (see
https://github.com/purebred-mua/purebred/issues/429)
### Differences to Brick
We use Brick heavily, but there are slight differences in Purebred to
an application entirely written using Brick widgets only:
- Keybindings are customizable: Purebred has abstracted the
Keybindings from widget specific to application specific. When a new
keystroke is passed as a `VtyEvent`, Purebred checks if a handler is
registered otherwise it falls back to the default event handler for
the which in focus. For example, editors which handle input mostly
fallback to the widgets event handling, since we don't want to
create an event handler for every input character on your keyboard.
- Actions are composable: at least for the most. The `UI.Actions` tie
into the customizable keybindings and allow users to compose actions
for a widget in focus until the UI is repainted. One Keybinding can
perform one or more chained `Action`s. In order to work with moving
focus to other widgets, we use PhantomTypes to avoid registering
Keybindings for which no `Action` "matches".
### Style
- HLint is your friend. But not always. If you want to suppress a
hint (e.g. suppressing "Avoid lambda" for consistent and
refactoring-friendly lens definitoions), be sure to include an
explicit type annotation so that it will play nice with
``OverloadedStrings``.
{-# ANN module ("HLint: ignore Avoid lambda" :: String) #-}
## Using Nix as a development environment
The `nix develop .#shell-with-icu` command will give you a
development environment in which package dependencies for `purebred`
and `purebred-icu` are installed. From there a typical compile/run
session could look like this:
# clone purebred-icu as well into an adjacent directory to purebred
# and make cabal aware of purebred *and* purebred-icu necessary to build
echo "packages: .,../purebred-icu" > cabal.project.local
# install purebred and the purebred-icu plugin
$ cabal --enable-nix new-install --overwrite-policy=always exe:purebred lib:purebred-icu
# run purebred
$ ~/.cabal/bin/purebred
# run only acceptance tests containing 'user can abort'
PATH=~/.cabal/bin:$PATH cabal --enable-nix test --show-details=streaming --test-option='-p /user can abort/' uat
Legacy nix is also supported, check the `default.nix` file.