This file is indexed.

/usr/share/doc/libghc-blogliterately-doc/html/src/Text-BlogLiterately-Ghci.html is in libghc-blogliterately-doc 0.8.1.5-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
<title>src/Text/BlogLiterately/Ghci.hs</title>
<link type='text/css' rel='stylesheet' href='hscolour.css' />
</head>
<body>
<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE PatternGuards #-}</span>
<a name="line-2"></a>
<a name="line-3"></a><span class='hs-comment'>-----------------------------------------------------------------------------</span>
<a name="line-4"></a><span class='hs-comment'>-- |</span>
<a name="line-5"></a><span class='hs-comment'>-- Module      :  Text.BlogLiterately.Ghci</span>
<a name="line-6"></a><span class='hs-comment'>-- Copyright   :  (c) 1997-2005 Ralf Hinze &lt;ralf.hinze@comlab.ox.ac.uk&gt;, Andres Loeh &lt;lhs2tex@andres-loeh.de&gt;, 2012 Brent Yorgey</span>
<a name="line-7"></a><span class='hs-comment'>-- License     :  GPL (see LICENSE)</span>
<a name="line-8"></a><span class='hs-comment'>-- Maintainer  :  Brent Yorgey &lt;byorgey@gmail.com&gt;</span>
<a name="line-9"></a><span class='hs-comment'>--</span>
<a name="line-10"></a><span class='hs-comment'>-- Format specially marked blocks as interactive ghci sessions.  Uses</span>
<a name="line-11"></a><span class='hs-comment'>-- some ugly but effective code for interacting with an external ghci</span>
<a name="line-12"></a><span class='hs-comment'>-- process taken from lhs2TeX.</span>
<a name="line-13"></a><span class='hs-comment'>--</span>
<a name="line-14"></a><span class='hs-comment'>-----------------------------------------------------------------------------</span>
<a name="line-15"></a>
<a name="line-16"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Text</span><span class='hs-varop'>.</span><span class='hs-conid'>BlogLiterately</span><span class='hs-varop'>.</span><span class='hs-conid'>Ghci</span>
<a name="line-17"></a>    <span class='hs-layout'>(</span>
<a name="line-18"></a>    <span class='hs-comment'>-- * Running ghci</span>
<a name="line-19"></a>      <span class='hs-conid'>ProcessInfo</span>
<a name="line-20"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>ghciEval</span>
<a name="line-21"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>withGhciProcess</span>
<a name="line-22"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>isLiterate</span>
<a name="line-23"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>stopGhci</span>
<a name="line-24"></a>
<a name="line-25"></a>    <span class='hs-comment'>-- * Extracting output</span>
<a name="line-26"></a>    <span class='hs-comment'>-- $extract</span>
<a name="line-27"></a>
<a name="line-28"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>magic</span>
<a name="line-29"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>extract'</span>
<a name="line-30"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>extract</span>
<a name="line-31"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>breaks</span>
<a name="line-32"></a>
<a name="line-33"></a>    <span class='hs-comment'>-- * Formatting</span>
<a name="line-34"></a>    <span class='hs-layout'>,</span> <span class='hs-varid'>formatInlineGhci</span>
<a name="line-35"></a>
<a name="line-36"></a>    <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-37"></a>
<a name="line-38"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Arrow</span>              <span class='hs-layout'>(</span><span class='hs-varid'>first</span><span class='hs-layout'>)</span>
<a name="line-39"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>Class</span>     <span class='hs-layout'>(</span><span class='hs-varid'>liftIO</span><span class='hs-layout'>)</span>
<a name="line-40"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span><span class='hs-varop'>.</span><span class='hs-conid'>Trans</span><span class='hs-varop'>.</span><span class='hs-conid'>Reader</span> <span class='hs-layout'>(</span><span class='hs-conid'>ReaderT</span><span class='hs-layout'>,</span> <span class='hs-varid'>ask</span><span class='hs-layout'>,</span> <span class='hs-varid'>runReaderT</span><span class='hs-layout'>)</span>
<a name="line-41"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Char</span>                  <span class='hs-layout'>(</span><span class='hs-varid'>isSpace</span><span class='hs-layout'>)</span>
<a name="line-42"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Functor</span>               <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-varop'>&lt;$&gt;</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-43"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>List</span>                  <span class='hs-layout'>(</span><span class='hs-varid'>intercalate</span><span class='hs-layout'>,</span> <span class='hs-varid'>isPrefixOf</span><span class='hs-layout'>)</span>
<a name="line-44"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>FilePath</span>            <span class='hs-layout'>(</span><span class='hs-varid'>takeFileName</span><span class='hs-layout'>)</span>
<a name="line-45"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span>
<a name="line-46"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>Strict</span>           <span class='hs-keyword'>as</span> <span class='hs-conid'>Strict</span>
<a name="line-47"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>Temp</span>
<a name="line-48"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>Process</span>             <span class='hs-layout'>(</span><span class='hs-conid'>ProcessHandle</span><span class='hs-layout'>,</span>
<a name="line-49"></a>                                             <span class='hs-varid'>runInteractiveCommand</span><span class='hs-layout'>,</span>
<a name="line-50"></a>                                             <span class='hs-varid'>waitForProcess</span><span class='hs-layout'>)</span>
<a name="line-51"></a>
<a name="line-52"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>List</span><span class='hs-varop'>.</span><span class='hs-conid'>Split</span>
<a name="line-53"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>Text</span><span class='hs-varop'>.</span><span class='hs-conid'>Pandoc</span>                <span class='hs-layout'>(</span><span class='hs-conid'>Block</span> <span class='hs-layout'>(</span><span class='hs-conid'>CodeBlock</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-conid'>Pandoc</span><span class='hs-layout'>,</span>
<a name="line-54"></a>                                             <span class='hs-varid'>bottomUpM</span><span class='hs-layout'>)</span>
<a name="line-55"></a>
<a name="line-56"></a><span class='hs-keyword'>import</span>           <span class='hs-conid'>Text</span><span class='hs-varop'>.</span><span class='hs-conid'>BlogLiterately</span><span class='hs-varop'>.</span><span class='hs-conid'>Block</span>  <span class='hs-layout'>(</span><span class='hs-varid'>onTag</span><span class='hs-layout'>)</span>
<a name="line-57"></a>
<a name="line-58"></a><a name="ProcessInfo"></a><span class='hs-comment'>-- | Information about a running process: stdin, stdout, stderr, and a</span>
<a name="line-59"></a><a name="ProcessInfo"></a><span class='hs-comment'>--   handle.</span>
<a name="line-60"></a><a name="ProcessInfo"></a><span class='hs-keyword'>type</span> <span class='hs-conid'>ProcessInfo</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-conid'>Handle</span><span class='hs-layout'>,</span> <span class='hs-conid'>Handle</span><span class='hs-layout'>,</span> <span class='hs-conid'>Handle</span><span class='hs-layout'>,</span> <span class='hs-conid'>ProcessHandle</span><span class='hs-layout'>)</span>
<a name="line-61"></a>
<a name="line-62"></a><a name="GhciInput"></a><span class='hs-comment'>-- | An input to ghci consists of an expression/command, possibly</span>
<a name="line-63"></a><a name="GhciInput"></a><span class='hs-comment'>--   paired with an expected output.</span>
<a name="line-64"></a><a name="GhciInput"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>GhciInput</span>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>GhciInput</span> <span class='hs-conid'>String</span> <span class='hs-layout'>(</span><span class='hs-conid'>Maybe</span> <span class='hs-conid'>String</span><span class='hs-layout'>)</span>
<a name="line-65"></a>  <span class='hs-keyword'>deriving</span> <span class='hs-conid'>Show</span>
<a name="line-66"></a>
<a name="line-67"></a><a name="GhciOutput"></a><span class='hs-comment'>-- | An output from ghci is either a correct output, or an incorrect</span>
<a name="line-68"></a><a name="GhciOutput"></a><span class='hs-comment'>--   (unexpected) output paired with the expected output.</span>
<a name="line-69"></a><a name="GhciOutput"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>GhciOutput</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>OK</span> <span class='hs-conid'>String</span>
<a name="line-70"></a>                <span class='hs-keyglyph'>|</span> <span class='hs-conid'>Unexpected</span> <span class='hs-conid'>String</span> <span class='hs-conid'>String</span>
<a name="line-71"></a>  <span class='hs-keyword'>deriving</span> <span class='hs-conid'>Show</span>
<a name="line-72"></a>
<a name="line-73"></a><a name="GhciLine"></a><span class='hs-comment'>-- | A @GhciLine@ is a @GhciInput@ paired with its corresponding @GhciOutput@.</span>
<a name="line-74"></a><a name="GhciLine"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>GhciLine</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>GhciLine</span> <span class='hs-conid'>GhciInput</span> <span class='hs-conid'>GhciOutput</span>
<a name="line-75"></a>  <span class='hs-keyword'>deriving</span> <span class='hs-conid'>Show</span>
<a name="line-76"></a>
<a name="line-77"></a><a name="ghciEval"></a><span class='hs-comment'>-- | Evaluate an expression using an external @ghci@ process.</span>
<a name="line-78"></a><span class='hs-definition'>ghciEval</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GhciInput</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ReaderT</span> <span class='hs-conid'>ProcessInfo</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>GhciOutput</span>
<a name="line-79"></a><span class='hs-definition'>ghciEval</span> <span class='hs-layout'>(</span><span class='hs-conid'>GhciInput</span> <span class='hs-varid'>expr</span> <span class='hs-varid'>expected</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>  <span class='hs-keyword'>do</span>
<a name="line-80"></a>  <span class='hs-layout'>(</span><span class='hs-varid'>pin</span><span class='hs-layout'>,</span> <span class='hs-varid'>pout</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>ask</span>
<a name="line-81"></a>  <span class='hs-keyword'>let</span> <span class='hs-varid'>script</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"putStrLn "</span> <span class='hs-varop'>++</span> <span class='hs-varid'>show</span> <span class='hs-varid'>magic</span> <span class='hs-varop'>++</span> <span class='hs-str'>"\n"</span>
<a name="line-82"></a>                 <span class='hs-varop'>++</span> <span class='hs-varid'>expr</span> <span class='hs-varop'>++</span> <span class='hs-str'>"\n"</span>
<a name="line-83"></a>                 <span class='hs-varop'>++</span> <span class='hs-str'>"putStrLn "</span> <span class='hs-varop'>++</span> <span class='hs-varid'>show</span> <span class='hs-varid'>magic</span> <span class='hs-varop'>++</span> <span class='hs-str'>"\n"</span>
<a name="line-84"></a>  <span class='hs-varid'>out</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>liftIO</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>do</span>
<a name="line-85"></a>    <span class='hs-varid'>hPutStr</span> <span class='hs-varid'>pin</span> <span class='hs-varid'>script</span>
<a name="line-86"></a>    <span class='hs-varid'>hFlush</span> <span class='hs-varid'>pin</span>
<a name="line-87"></a>    <span class='hs-varid'>extract'</span> <span class='hs-varid'>pout</span>
<a name="line-88"></a>  <span class='hs-keyword'>let</span> <span class='hs-varid'>out'</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>strip</span> <span class='hs-varid'>out</span>
<a name="line-89"></a>  <span class='hs-keyword'>case</span> <span class='hs-varid'>expected</span> <span class='hs-keyword'>of</span>
<a name="line-90"></a>    <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>OK</span> <span class='hs-varid'>out'</span>
<a name="line-91"></a>    <span class='hs-conid'>Just</span> <span class='hs-varid'>e</span>
<a name="line-92"></a>      <span class='hs-keyglyph'>|</span> <span class='hs-varid'>out'</span> <span class='hs-varop'>==</span> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>OK</span> <span class='hs-varid'>out'</span>
<a name="line-93"></a>      <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Unexpected</span> <span class='hs-varid'>out'</span> <span class='hs-varid'>e</span>
<a name="line-94"></a>
<a name="line-95"></a><a name="withGhciProcess"></a><span class='hs-comment'>-- | Start an external ghci process, run a computation with access to</span>
<a name="line-96"></a><span class='hs-comment'>--   it, and finally stop the process.</span>
<a name="line-97"></a><span class='hs-definition'>withGhciProcess</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FilePath</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ReaderT</span> <span class='hs-conid'>ProcessInfo</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span>
<a name="line-98"></a><span class='hs-definition'>withGhciProcess</span> <span class='hs-varid'>f</span> <span class='hs-varid'>m</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-99"></a>  <span class='hs-varid'>src</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-conid'>Strict</span><span class='hs-varop'>.</span><span class='hs-varid'>readFile</span> <span class='hs-varid'>f</span>
<a name="line-100"></a>  <span class='hs-keyword'>let</span> <span class='hs-varid'>isLit</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>isLiterate</span> <span class='hs-varid'>src</span>
<a name="line-101"></a>  <span class='hs-varid'>withLiterateHashWorkaround</span> <span class='hs-varid'>f</span> <span class='hs-varid'>src</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>f'</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
<a name="line-102"></a>    <span class='hs-varid'>h</span>     <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>runInteractiveCommand</span> <span class='hs-varop'>$</span> <span class='hs-str'>"ghci -v0 -ignore-dot-ghci "</span>
<a name="line-103"></a>                                     <span class='hs-varop'>++</span> <span class='hs-layout'>(</span><span class='hs-keyword'>if</span> <span class='hs-varid'>isLit</span> <span class='hs-keyword'>then</span> <span class='hs-varid'>f'</span> <span class='hs-keyword'>else</span> <span class='hs-str'>""</span><span class='hs-layout'>)</span>
<a name="line-104"></a>    <span class='hs-varid'>res</span>   <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>runReaderT</span> <span class='hs-varid'>m</span> <span class='hs-varid'>h</span>
<a name="line-105"></a>    <span class='hs-varid'>stopGhci</span> <span class='hs-varid'>h</span>
<a name="line-106"></a>    <span class='hs-varid'>return</span> <span class='hs-varid'>res</span>
<a name="line-107"></a>
<a name="line-108"></a><a name="withLiterateHashWorkaround"></a><span class='hs-comment'>-- | Workaround for https://ghc.haskell.org/trac/ghc/ticket/4836; see</span>
<a name="line-109"></a><span class='hs-comment'>--   also https://github.com/byorgey/BlogLiterately/issues/11.  If the</span>
<a name="line-110"></a><span class='hs-comment'>--   file contains any lines beginning with #, create a temporary file</span>
<a name="line-111"></a><span class='hs-comment'>--   with those lines filtered out, and pass that instead.[</span>
<a name="line-112"></a><span class='hs-definition'>withLiterateHashWorkaround</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FilePath</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>FilePath</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span>
<a name="line-113"></a><span class='hs-definition'>withLiterateHashWorkaround</span> <span class='hs-varid'>f</span> <span class='hs-varid'>src</span> <span class='hs-varid'>k</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-114"></a>  <span class='hs-keyword'>let</span> <span class='hs-varid'>bad</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-str'>"#"</span> <span class='hs-varop'>`isPrefixOf`</span><span class='hs-layout'>)</span>
<a name="line-115"></a>      <span class='hs-varid'>b</span>   <span class='hs-keyglyph'>=</span> <span class='hs-varid'>any</span> <span class='hs-varid'>bad</span> <span class='hs-varop'>.</span> <span class='hs-varid'>lines</span> <span class='hs-varop'>$</span> <span class='hs-varid'>src</span>
<a name="line-116"></a>  <span class='hs-keyword'>case</span> <span class='hs-varid'>b</span> <span class='hs-keyword'>of</span>
<a name="line-117"></a>    <span class='hs-conid'>False</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>k</span> <span class='hs-varid'>f</span>
<a name="line-118"></a>    <span class='hs-conid'>True</span>  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>withTempFile</span> <span class='hs-str'>""</span> <span class='hs-layout'>(</span><span class='hs-varid'>takeFileName</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>f'</span> <span class='hs-varid'>h</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>do</span>
<a name="line-119"></a>               <span class='hs-varid'>hPutStr</span> <span class='hs-varid'>h</span> <span class='hs-layout'>(</span><span class='hs-varid'>unlines</span> <span class='hs-varop'>.</span> <span class='hs-varid'>filter</span> <span class='hs-layout'>(</span><span class='hs-varid'>not</span> <span class='hs-varop'>.</span> <span class='hs-varid'>bad</span><span class='hs-layout'>)</span> <span class='hs-varop'>.</span> <span class='hs-varid'>lines</span> <span class='hs-varop'>$</span> <span class='hs-varid'>src</span><span class='hs-layout'>)</span>
<a name="line-120"></a>               <span class='hs-varid'>hClose</span> <span class='hs-varid'>h</span>
<a name="line-121"></a>               <span class='hs-varid'>k</span> <span class='hs-varid'>f'</span>
<a name="line-122"></a>
<a name="line-123"></a><a name="isLiterate"></a><span class='hs-comment'>-- | Poor man's check to see whether we have a literate Haskell file.</span>
<a name="line-124"></a><span class='hs-definition'>isLiterate</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span>
<a name="line-125"></a><span class='hs-definition'>isLiterate</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>any</span> <span class='hs-layout'>(</span><span class='hs-str'>"&gt; "</span> <span class='hs-varop'>`isPrefixOf`</span><span class='hs-layout'>)</span> <span class='hs-varop'>.</span> <span class='hs-varid'>lines</span>
<a name="line-126"></a>
<a name="line-127"></a><a name="stopGhci"></a><span class='hs-comment'>-- | Stop a ghci process by passing it @:q@ and waiting for it to exit.</span>
<a name="line-128"></a><span class='hs-definition'>stopGhci</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ProcessInfo</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-129"></a><span class='hs-definition'>stopGhci</span> <span class='hs-layout'>(</span><span class='hs-varid'>pin</span><span class='hs-layout'>,</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span><span class='hs-varid'>pid</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-130"></a>  <span class='hs-varid'>hPutStrLn</span> <span class='hs-varid'>pin</span> <span class='hs-str'>":q"</span>
<a name="line-131"></a>  <span class='hs-varid'>hFlush</span> <span class='hs-varid'>pin</span>
<a name="line-132"></a>  <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>waitForProcess</span> <span class='hs-varid'>pid</span>   <span class='hs-comment'>-- ignore exit code</span>
<a name="line-133"></a>  <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
<a name="line-134"></a>
<a name="line-135"></a><span class='hs-comment'>-- $extract</span>
<a name="line-136"></a><span class='hs-comment'>-- To extract the answer from @ghci@'s output we use a simple technique</span>
<a name="line-137"></a><span class='hs-comment'>-- which should work in most cases: we print the string @magic@ before</span>
<a name="line-138"></a><span class='hs-comment'>-- and after the expression we are interested in. We assume that</span>
<a name="line-139"></a><span class='hs-comment'>-- everything that appears before the first occurrence of @magic@ on the</span>
<a name="line-140"></a><span class='hs-comment'>-- same line is the prompt, and everything between the first @magic@ and</span>
<a name="line-141"></a><span class='hs-comment'>-- the second @magic@ plus prompt is the result we look for.</span>
<a name="line-142"></a>
<a name="line-143"></a><a name="magic"></a><span class='hs-comment'>-- | There is nothing magic about the magic string.</span>
<a name="line-144"></a><span class='hs-definition'>magic</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span>
<a name="line-145"></a><span class='hs-definition'>magic</span> <span class='hs-keyglyph'>=</span>  <span class='hs-str'>"!@#$^&amp;*"</span>
<a name="line-146"></a>
<a name="line-147"></a><a name="extract'"></a><span class='hs-definition'>extract'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Handle</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>String</span>
<a name="line-148"></a><span class='hs-definition'>extract'</span> <span class='hs-varid'>h</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fmap</span> <span class='hs-layout'>(</span><span class='hs-varid'>extract</span> <span class='hs-varop'>.</span> <span class='hs-varid'>unlines</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>readMagic</span> <span class='hs-num'>2</span><span class='hs-layout'>)</span>
<a name="line-149"></a>  <span class='hs-keyword'>where</span>
<a name="line-150"></a>    <span class='hs-varid'>readMagic</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>String</span><span class='hs-keyglyph'>]</span>
<a name="line-151"></a>    <span class='hs-varid'>readMagic</span> <span class='hs-num'>0</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>return</span> <span class='hs-conid'>[]</span>
<a name="line-152"></a>    <span class='hs-varid'>readMagic</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-153"></a>      <span class='hs-varid'>l</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>hGetLine</span> <span class='hs-varid'>h</span>
<a name="line-154"></a>      <span class='hs-keyword'>let</span> <span class='hs-varid'>n'</span> <span class='hs-keyglyph'>|</span> <span class='hs-layout'>(</span><span class='hs-varid'>null</span> <span class='hs-varop'>.</span> <span class='hs-varid'>snd</span> <span class='hs-varop'>.</span> <span class='hs-varid'>breaks</span> <span class='hs-layout'>(</span><span class='hs-varid'>isPrefixOf</span> <span class='hs-varid'>magic</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>l</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>n</span>
<a name="line-155"></a>             <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>                                  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>n</span> <span class='hs-comment'>-</span> <span class='hs-num'>1</span>
<a name="line-156"></a>      <span class='hs-varid'>fmap</span> <span class='hs-layout'>(</span><span class='hs-varid'>l</span><span class='hs-conop'>:</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>readMagic</span> <span class='hs-varid'>n'</span><span class='hs-layout'>)</span>
<a name="line-157"></a>
<a name="line-158"></a><a name="extract"></a><span class='hs-definition'>extract</span>                       <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span>
<a name="line-159"></a><span class='hs-definition'>extract</span> <span class='hs-varid'>s</span>                     <span class='hs-keyglyph'>=</span>  <span class='hs-varid'>v</span>
<a name="line-160"></a>    <span class='hs-keyword'>where</span> <span class='hs-layout'>(</span><span class='hs-varid'>t</span><span class='hs-layout'>,</span> <span class='hs-varid'>u</span><span class='hs-layout'>)</span>              <span class='hs-keyglyph'>=</span>  <span class='hs-varid'>breaks</span> <span class='hs-layout'>(</span><span class='hs-varid'>isPrefixOf</span> <span class='hs-varid'>magic</span><span class='hs-layout'>)</span> <span class='hs-varid'>s</span>
<a name="line-161"></a>          <span class='hs-comment'>-- t contains everything up to magic, u starts with magic</span>
<a name="line-162"></a>          <span class='hs-comment'>-- |u'                      =  tail (dropWhile (/='\n') u)|</span>
<a name="line-163"></a>          <span class='hs-varid'>pre</span>                 <span class='hs-keyglyph'>=</span>  <span class='hs-varid'>reverse</span> <span class='hs-varop'>.</span> <span class='hs-varid'>takeWhile</span> <span class='hs-layout'>(</span><span class='hs-varop'>/=</span><span class='hs-chr'>'\n'</span><span class='hs-layout'>)</span> <span class='hs-varop'>.</span> <span class='hs-varid'>reverse</span> <span class='hs-varop'>$</span> <span class='hs-varid'>t</span>
<a name="line-164"></a>          <span class='hs-varid'>prelength</span>           <span class='hs-keyglyph'>=</span>  <span class='hs-keyword'>if</span> <span class='hs-varid'>null</span> <span class='hs-varid'>pre</span> <span class='hs-keyword'>then</span> <span class='hs-num'>0</span> <span class='hs-keyword'>else</span> <span class='hs-varid'>length</span> <span class='hs-varid'>pre</span> <span class='hs-varop'>+</span> <span class='hs-num'>1</span>
<a name="line-165"></a>          <span class='hs-comment'>-- pre contains the prefix of magic on the same line</span>
<a name="line-166"></a>          <span class='hs-varid'>u'</span>                  <span class='hs-keyglyph'>=</span>  <span class='hs-varid'>drop</span> <span class='hs-layout'>(</span><span class='hs-varid'>length</span> <span class='hs-varid'>magic</span> <span class='hs-varop'>+</span> <span class='hs-varid'>prelength</span><span class='hs-layout'>)</span> <span class='hs-varid'>u</span>
<a name="line-167"></a>          <span class='hs-comment'>-- we drop the magic string, plus the newline, plus the prefix</span>
<a name="line-168"></a>          <span class='hs-layout'>(</span><span class='hs-varid'>v</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span>              <span class='hs-keyglyph'>=</span>  <span class='hs-varid'>breaks</span> <span class='hs-layout'>(</span><span class='hs-varid'>isPrefixOf</span> <span class='hs-layout'>(</span><span class='hs-varid'>pre</span> <span class='hs-varop'>++</span> <span class='hs-varid'>magic</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>u'</span>
<a name="line-169"></a>          <span class='hs-comment'>-- we look for the next occurrence of prefix plus magic</span>
<a name="line-170"></a>
<a name="line-171"></a><a name="breaks"></a><span class='hs-definition'>breaks</span>                        <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>,</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span>
<a name="line-172"></a><span class='hs-definition'>breaks</span> <span class='hs-keyword'>_</span> <span class='hs-conid'>[]</span>                   <span class='hs-keyglyph'>=</span>  <span class='hs-layout'>(</span><span class='hs-conid'>[]</span><span class='hs-layout'>,</span> <span class='hs-conid'>[]</span><span class='hs-layout'>)</span>
<a name="line-173"></a><span class='hs-definition'>breaks</span> <span class='hs-varid'>p</span> <span class='hs-keyword'>as</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:</span> <span class='hs-varid'>as'</span><span class='hs-layout'>)</span>
<a name="line-174"></a>    <span class='hs-keyglyph'>|</span> <span class='hs-varid'>p</span> <span class='hs-keyword'>as</span>                    <span class='hs-keyglyph'>=</span>  <span class='hs-layout'>(</span><span class='hs-conid'>[]</span><span class='hs-layout'>,</span> <span class='hs-keyword'>as</span><span class='hs-layout'>)</span>
<a name="line-175"></a>    <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>               <span class='hs-keyglyph'>=</span>  <span class='hs-varid'>first</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-conop'>:</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-varid'>breaks</span> <span class='hs-varid'>p</span> <span class='hs-varid'>as'</span>
<a name="line-176"></a>
<a name="line-177"></a><a name="formatInlineGhci"></a><span class='hs-comment'>-- | Given the path to the @.lhs@ source and its representation as a</span>
<a name="line-178"></a><span class='hs-comment'>--   @Pandoc@ document, @formatInlineGhci@ finds any @[ghci]@ blocks</span>
<a name="line-179"></a><span class='hs-comment'>--   in it, runs them through @ghci@, and formats the results as an</span>
<a name="line-180"></a><span class='hs-comment'>--   interactive @ghci@ session.</span>
<a name="line-181"></a><span class='hs-comment'>--</span>
<a name="line-182"></a><span class='hs-comment'>--   Lines beginning in the first column of the block are interpreted</span>
<a name="line-183"></a><span class='hs-comment'>--   as inputs.  Lines indented by one or more space are interpreted</span>
<a name="line-184"></a><span class='hs-comment'>--   as /expected outputs/.  Consecutive indented lines are</span>
<a name="line-185"></a><span class='hs-comment'>--   interpreted as one multi-line expected output, with a number of</span>
<a name="line-186"></a><span class='hs-comment'>--   spaces removed from the beginning of each line equal to the</span>
<a name="line-187"></a><span class='hs-comment'>--   number of spaces at the start of the first indented line.</span>
<a name="line-188"></a><span class='hs-comment'>--</span>
<a name="line-189"></a><span class='hs-comment'>--   If the output for a given input is the same as the expected</span>
<a name="line-190"></a><span class='hs-comment'>--   output (or if no expected output is given), the result is typeset</span>
<a name="line-191"></a><span class='hs-comment'>--   normally.  If the actual and expected outputs differ, the actual</span>
<a name="line-192"></a><span class='hs-comment'>--   output is typeset first in red, then the expected output in blue.</span>
<a name="line-193"></a><span class='hs-definition'>formatInlineGhci</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FilePath</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Pandoc</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>Pandoc</span>
<a name="line-194"></a><span class='hs-definition'>formatInlineGhci</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>withGhciProcess</span> <span class='hs-varid'>f</span> <span class='hs-varop'>.</span> <span class='hs-varid'>bottomUpM</span> <span class='hs-varid'>formatInlineGhci'</span>
<a name="line-195"></a>  <span class='hs-keyword'>where</span>
<a name="line-196"></a>    <span class='hs-varid'>formatInlineGhci'</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Block</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>ReaderT</span> <span class='hs-conid'>ProcessInfo</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>Block</span>
<a name="line-197"></a>    <span class='hs-varid'>formatInlineGhci'</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>onTag</span> <span class='hs-str'>"ghci"</span> <span class='hs-varid'>formatGhciBlock</span> <span class='hs-varid'>return</span>
<a name="line-198"></a>
<a name="line-199"></a>    <span class='hs-varid'>formatGhciBlock</span> <span class='hs-varid'>attr</span> <span class='hs-varid'>src</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-200"></a>      <span class='hs-keyword'>let</span> <span class='hs-varid'>inputs</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>parseGhciInputs</span> <span class='hs-varid'>src</span>
<a name="line-201"></a>      <span class='hs-varid'>results</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>zipWith</span> <span class='hs-conid'>GhciLine</span> <span class='hs-varid'>inputs</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>mapM</span> <span class='hs-varid'>ghciEval</span> <span class='hs-varid'>inputs</span>
<a name="line-202"></a>      <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>CodeBlock</span> <span class='hs-varid'>attr</span> <span class='hs-layout'>(</span><span class='hs-varid'>intercalate</span> <span class='hs-str'>"\n"</span> <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-varid'>formatGhciResult</span> <span class='hs-varid'>results</span><span class='hs-layout'>)</span>
<a name="line-203"></a>
<a name="line-204"></a><a name="parseGhciInputs"></a><span class='hs-definition'>parseGhciInputs</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>GhciInput</span><span class='hs-keyglyph'>]</span>
<a name="line-205"></a><span class='hs-definition'>parseGhciInputs</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-varid'>mkGhciInput</span>
<a name="line-206"></a>                <span class='hs-varop'>.</span> <span class='hs-varid'>split</span>
<a name="line-207"></a>                  <span class='hs-layout'>(</span> <span class='hs-varid'>dropInitBlank</span>
<a name="line-208"></a>                  <span class='hs-varop'>.</span> <span class='hs-varid'>dropFinalBlank</span>
<a name="line-209"></a>                  <span class='hs-varop'>.</span> <span class='hs-varid'>keepDelimsL</span>
<a name="line-210"></a>                  <span class='hs-varop'>$</span> <span class='hs-varid'>whenElt</span> <span class='hs-layout'>(</span><span class='hs-varid'>not</span> <span class='hs-varop'>.</span> <span class='hs-layout'>(</span><span class='hs-str'>" "</span> <span class='hs-varop'>`isPrefixOf`</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-211"></a>                  <span class='hs-layout'>)</span>
<a name="line-212"></a>                <span class='hs-varop'>.</span> <span class='hs-varid'>lines</span>
<a name="line-213"></a>
<a name="line-214"></a><a name="mkGhciInput"></a><span class='hs-definition'>mkGhciInput</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>String</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>GhciInput</span>
<a name="line-215"></a><span class='hs-definition'>mkGhciInput</span> <span class='hs-conid'>[]</span>       <span class='hs-keyglyph'>=</span> <span class='hs-conid'>GhciInput</span> <span class='hs-str'>""</span> <span class='hs-conid'>Nothing</span>
<a name="line-216"></a><span class='hs-definition'>mkGhciInput</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>i</span><span class='hs-keyglyph'>]</span>      <span class='hs-keyglyph'>=</span> <span class='hs-conid'>GhciInput</span> <span class='hs-varid'>i</span> <span class='hs-conid'>Nothing</span>
<a name="line-217"></a><span class='hs-definition'>mkGhciInput</span> <span class='hs-layout'>(</span><span class='hs-varid'>i</span><span class='hs-conop'>:</span><span class='hs-varid'>expr</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>GhciInput</span> <span class='hs-varid'>i</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varop'>.</span> <span class='hs-varid'>unlines'</span> <span class='hs-varop'>.</span> <span class='hs-varid'>unindent</span> <span class='hs-varop'>$</span> <span class='hs-varid'>expr</span><span class='hs-layout'>)</span>
<a name="line-218"></a>
<a name="line-219"></a><a name="unlines'"></a><span class='hs-definition'>unlines'</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>String</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span>
<a name="line-220"></a><span class='hs-definition'>unlines'</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>intercalate</span> <span class='hs-str'>"\n"</span>
<a name="line-221"></a>
<a name="line-222"></a><a name="strip"></a><span class='hs-definition'>strip</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span>
<a name="line-223"></a><span class='hs-definition'>strip</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>f</span> <span class='hs-varop'>.</span> <span class='hs-varid'>f</span>
<a name="line-224"></a>  <span class='hs-keyword'>where</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>dropWhile</span> <span class='hs-varid'>isSpace</span> <span class='hs-varop'>.</span> <span class='hs-varid'>reverse</span>
<a name="line-225"></a>
<a name="line-226"></a><a name="unindent"></a><span class='hs-definition'>unindent</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>String</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>String</span><span class='hs-keyglyph'>]</span>
<a name="line-227"></a><span class='hs-definition'>unindent</span> <span class='hs-conid'>[]</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>[]</span>
<a name="line-228"></a><span class='hs-definition'>unindent</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-conop'>:</span><span class='hs-varid'>xs</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span><span class='hs-varid'>drop</span> <span class='hs-varid'>indentAmt</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span><span class='hs-conop'>:</span><span class='hs-varid'>xs</span><span class='hs-layout'>)</span>
<a name="line-229"></a>  <span class='hs-keyword'>where</span> <span class='hs-varid'>indentAmt</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>length</span> <span class='hs-varop'>.</span> <span class='hs-varid'>takeWhile</span> <span class='hs-layout'>(</span><span class='hs-varop'>==</span><span class='hs-chr'>' '</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-varid'>x</span>
<a name="line-230"></a>
<a name="line-231"></a><a name="indent"></a><span class='hs-definition'>indent</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span>
<a name="line-232"></a><span class='hs-definition'>indent</span> <span class='hs-varid'>n</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>unlines'</span> <span class='hs-varop'>.</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span><span class='hs-varid'>replicate</span> <span class='hs-varid'>n</span> <span class='hs-chr'>' '</span><span class='hs-varop'>++</span><span class='hs-layout'>)</span> <span class='hs-varop'>.</span> <span class='hs-varid'>lines</span>
<a name="line-233"></a>
<a name="line-234"></a><a name="colored"></a><span class='hs-definition'>colored</span><span class='hs-layout'>,</span> <span class='hs-varid'>coloredBlock</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span>
<a name="line-235"></a><span class='hs-definition'>colored</span> <span class='hs-varid'>color</span> <span class='hs-varid'>txt</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"&lt;span style=\"color: "</span> <span class='hs-varop'>++</span> <span class='hs-varid'>color</span> <span class='hs-varop'>++</span> <span class='hs-str'>";\"&gt;"</span> <span class='hs-varop'>++</span> <span class='hs-varid'>txt</span> <span class='hs-varop'>++</span> <span class='hs-str'>"&lt;/span&gt;"</span>
<a name="line-236"></a><a name="coloredBlock"></a><span class='hs-definition'>coloredBlock</span> <span class='hs-varid'>color</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>unlines'</span> <span class='hs-varop'>.</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span><span class='hs-varid'>colored</span> <span class='hs-varid'>color</span><span class='hs-layout'>)</span> <span class='hs-varop'>.</span> <span class='hs-varid'>lines</span>
<a name="line-237"></a>
<a name="line-238"></a><a name="ghciPrompt"></a><span class='hs-definition'>ghciPrompt</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span>
<a name="line-239"></a><span class='hs-definition'>ghciPrompt</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>colored</span> <span class='hs-str'>"gray"</span> <span class='hs-str'>"ghci&amp;gt; "</span>
<a name="line-240"></a>
<a name="line-241"></a><a name="formatGhciResult"></a><span class='hs-definition'>formatGhciResult</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>GhciLine</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span>
<a name="line-242"></a><span class='hs-definition'>formatGhciResult</span> <span class='hs-layout'>(</span><span class='hs-conid'>GhciLine</span> <span class='hs-layout'>(</span><span class='hs-conid'>GhciInput</span> <span class='hs-varid'>input</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>OK</span> <span class='hs-varid'>output</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-243"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>all</span> <span class='hs-varid'>isSpace</span> <span class='hs-varid'>output</span>
<a name="line-244"></a>    <span class='hs-keyglyph'>=</span> <span class='hs-varid'>ghciPrompt</span> <span class='hs-varop'>++</span> <span class='hs-varid'>esc</span> <span class='hs-varid'>input</span>
<a name="line-245"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>
<a name="line-246"></a>    <span class='hs-keyglyph'>=</span> <span class='hs-varid'>ghciPrompt</span> <span class='hs-varop'>++</span> <span class='hs-varid'>esc</span> <span class='hs-varid'>input</span> <span class='hs-varop'>++</span> <span class='hs-str'>"\n"</span> <span class='hs-varop'>++</span> <span class='hs-varid'>indent</span> <span class='hs-num'>2</span> <span class='hs-layout'>(</span><span class='hs-varid'>esc</span> <span class='hs-varid'>output</span><span class='hs-layout'>)</span> <span class='hs-varop'>++</span> <span class='hs-str'>"\n"</span>
<a name="line-247"></a><span class='hs-definition'>formatGhciResult</span> <span class='hs-layout'>(</span><span class='hs-conid'>GhciLine</span> <span class='hs-layout'>(</span><span class='hs-conid'>GhciInput</span> <span class='hs-varid'>input</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>Unexpected</span> <span class='hs-varid'>output</span> <span class='hs-varid'>expr</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-248"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>ghciPrompt</span> <span class='hs-varop'>++</span> <span class='hs-varid'>esc</span> <span class='hs-varid'>input</span> <span class='hs-varop'>++</span> <span class='hs-str'>"\n"</span> <span class='hs-varop'>++</span> <span class='hs-varid'>indent</span> <span class='hs-num'>2</span> <span class='hs-layout'>(</span><span class='hs-varid'>coloredBlock</span> <span class='hs-str'>"red"</span> <span class='hs-layout'>(</span><span class='hs-varid'>esc</span> <span class='hs-varid'>output</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-249"></a>                            <span class='hs-varop'>++</span> <span class='hs-str'>"\n"</span> <span class='hs-varop'>++</span> <span class='hs-varid'>indent</span> <span class='hs-num'>2</span> <span class='hs-layout'>(</span><span class='hs-varid'>coloredBlock</span> <span class='hs-str'>"blue"</span> <span class='hs-layout'>(</span><span class='hs-varid'>esc</span> <span class='hs-varid'>expr</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-250"></a>                            <span class='hs-varop'>++</span> <span class='hs-str'>"\n"</span>
<a name="line-251"></a>
<a name="line-252"></a>    <span class='hs-comment'>-- XXX the styles above should be configurable...</span>
<a name="line-253"></a>
<a name="line-254"></a><a name="esc"></a><span class='hs-definition'>esc</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span>
<a name="line-255"></a><span class='hs-definition'>esc</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>concatMap</span> <span class='hs-varid'>escapeOne</span>
<a name="line-256"></a>  <span class='hs-keyword'>where</span>
<a name="line-257"></a>    <span class='hs-varid'>escapeOne</span> <span class='hs-chr'>'&lt;'</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"&amp;lt;"</span>
<a name="line-258"></a>    <span class='hs-varid'>escapeOne</span> <span class='hs-chr'>'&gt;'</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"&amp;gt;"</span>
<a name="line-259"></a>    <span class='hs-varid'>escapeOne</span>  <span class='hs-varid'>c</span>  <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>c</span><span class='hs-keyglyph'>]</span>
</pre></body>
</html>