Skip to content

Commit 92c4a48

Browse files
committed
markdown: Support multiline HTML blocks
This is needed by “Demystifying MonadBaseControl”.
1 parent 28206e3 commit 92c4a48

File tree

5 files changed

+31
-23
lines changed

5 files changed

+31
-23
lines changed

blog/build.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
"2018-09-13-custom-core-forms-in-racket-part-ii-generalizing-to-arbitrary-expressions-and-internal-definitions.md"
7171
"2018-10-06-macroexpand-anywhere-with-local-apply-transformer.md"
7272
"2019-04-21-defeating-racket-s-separate-compilation-guarantee.md"
73-
#;"2019-09-07-demystifying-monadbasecontrol.md" ; html tables
73+
"2019-09-07-demystifying-monadbasecontrol.md"
7474
"2019-10-19-empathy-and-subjective-experience-in-programming-languages.md"
7575
"2019-11-05-parse-don-t-validate.md"
7676
"2020-01-19-no-dynamic-type-systems-are-not-inherently-more-open.md"

blog/markdown/parse.rkt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
racket/function
99
racket/list
1010
racket/match
11+
racket/string
1112
threading
1213
xml
1314
"parse/content.rkt"
@@ -313,7 +314,7 @@ As it parses the indentation for each block, it transfers it from the
313314
; html blocks
314315
(do (lookahead/p (or/p (try/p (string/p "<div"))
315316
(try/p (string/p "<h2"))))
316-
[html-str <- rest-of-line/p]
317+
[html-str <- (map/p string-append* (many-till/p rest-of-line/p newline/p))]
317318
(scan-line-start (reverse (cons (add-blocks inner-block (list (html-block (string->xexpr html-str)))) in-blocks))))
318319

319320
; free-form content (new paragraph)

blog/markdown/parse/content.rkt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,25 @@
5555

5656
;; -----------------------------------------------------------------------------
5757

58-
(define special-chars "*`[]<!\\\r\n")
58+
(define special-chars "_*`[]<!\\ \r\n")
5959

6060
(define content/p
6161
(label/p "content"
62-
(or/p (map/p list->string ((pure cons) (char-not-in/p (string-append "_" special-chars))
63-
; allow _ to appear inside words
64-
(many/p (char-not-in/p special-chars))))
62+
(or/p (map/p string-append*
63+
(many+/p (or/p
64+
; allow _ to appear inside words
65+
(try/p ((pure string) (char-not-in/p special-chars)
66+
(char/p #\_)
67+
(char-not-in/p special-chars)))
68+
(map/p string (char-not-in/p special-chars)))))
69+
; spaces
70+
(map/p list->string (many+/p (char/p #\space)))
6571
; escaped char
6672
(do (char/p #\\) (map/p string any-char/p))
6773
; bold / italic
6874
(map/p (λ~> simplify-content bold) (around/p (try/p (string/p "**")) (lazy/p content/p)))
6975
(map/p (λ~> simplify-content italic) (around/p (char/p #\*) (lazy/p content/p)))
76+
(map/p (λ~> simplify-content italic) (around/p (char/p #\_) (lazy/p content/p)))
7077
; code
7178
(do [backticks <- (many+/p (char/p #\`))]
7279
[chars <- (many-till/p any-char/p (try/p (string/p (list->string backticks))))]

blog/markdown/to-scribble.rkt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,10 @@
128128

129129
(define (xexpr->block xexpr)
130130
(match xexpr
131-
[(list (? symbol? tag) (list (list (? symbol? attr-name) (? string? attr-val)) ...) xexpr ...)
131+
[(list (? symbol? tag) (list (list (? symbol? attr-name) (? string? attr-val)) ...) xexprs ...)
132132
(paragraph (style #f (list (alt-tag (symbol->string tag))
133133
(attributes (map cons attr-name attr-val))))
134-
(map xexpr->content xexpr))]))
134+
(map xexpr->content xexprs))]))
135135

136136
(define (xexpr->content xexpr)
137137
(match xexpr

blog/posts/2019-09-07-demystifying-monadbasecontrol.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -182,30 +182,30 @@ instance MonadBaseControl b m => MonadBaseControl b (StateT s m) where
182182

183183
1. Start by examining the definitions of `InputState` and `OutputState`. Are they what you expected? You’d be forgiven for expecting the following:
184184

185-
```haskell
186-
type InputState (StateT s m) = s
187-
type OutputState (StateT s m) = s
188-
```
185+
```haskell
186+
type InputState (StateT s m) = s
187+
type OutputState (StateT s m) = s
188+
```
189189

190-
After all, thats what we wrote in the table, isnt it?
190+
After all, thats what we wrote in the table, isnt it?
191191

192-
However, if you give it a try, youll find it doesnt work. `InputState` and `OutputState` must capture the state of the *entire* monad, not just a single transformer layer, so we have to combine the `StateT s` state with the state of the underlying monad. In the simplest case we get
192+
However, if you give it a try, youll find it doesnt work. `InputState` and `OutputState` must capture the state of the *entire* monad, not just a single transformer layer, so we have to combine the `StateT s` state with the state of the underlying monad. In the simplest case we get
193193

194-
```haskell
195-
InputState (StateT s IO) = (s, ())
196-
```
194+
```haskell
195+
InputState (StateT s IO) = (s, ())
196+
```
197197

198-
which is boring, but in a more complex case, we need to get something like this:
198+
which is boring, but in a more complex case, we need to get something like this:
199199

200-
```haskell
201-
InputState (StateT s (ReaderT IO)) = (s, (r, ()))
202-
```
200+
```haskell
201+
InputState (StateT s (ReaderT IO)) = (s, (r, ()))
202+
```
203203

204-
Therefore, `InputState (StateT s m)` combines `s` with `InputState m` in a tuple, and `OutputState` does the same.
204+
Therefore, `InputState (StateT s m)` combines `s` with `InputState m` in a tuple, and `OutputState` does the same.
205205

206206
2. Moving on, take a look at `captureInputState` and `closeOverInputState`. Just as `InputState` and `OutputState` capture the state of the entire monad, these functions need to be inductive in the same way.
207207

208-
`captureInputState` acquires the current state using `get`, and it combines it with the remaining monadic state using `lift captureInputState`. `closeOverInputState` uses the captured state to peel off the outermost `StateT` layer, then calls `closeOverInputState` recursively to peel off the rest of them.
208+
`captureInputState` acquires the current state using `get`, and it combines it with the remaining monadic state using `lift captureInputState`. `closeOverInputState` uses the captured state to peel off the outermost `StateT` layer, then calls `closeOverInputState` recursively to peel off the rest of them.
209209

210210
3. Finally, `restoreOutputState` restores the state of the underlying monad stack, then restores the `StateT` state, ensuring everything ends up back the way its supposed to be.
211211

0 commit comments

Comments
 (0)