1module FillInTheGaps where
6import Data.Maybe (fromMaybe)
7import Data.String (Pattern(..), split)
8import Data.Tuple.Nested ((/\))
10import Justifill (justifill)
11import Partial.Unsafe (unsafeCrashWith)
12import React.Basic (JSX, ReactComponent, element)
13import React.Basic.DOM as R
14import React.Basic.Hooks (component, useState)
15import React.Basic.Hooks as React
16import Yoga.Helpers (intersperse)
17import Yoga.InlineCode.Component as InlineCode
19data Segment = Filler String | Hole String
21renderSegments :: ReactComponent InlineCode.Props -> ((Array (Array Segment) -> Array (Array Segment)) -> Effect Unit) -> Array (Array Segment) -> JSX
22renderSegments ic update arrs = R.div_ (arrs `flip A.mapWithIndex` renderLine)
24 renderLine i l = R.div_ (l `flip A.mapWithIndex` renderSegment i)
25 renderSegment i j = case _ of
26 Filler s -> R.span_ [R.text s]
27 Hole _ -> element ic $ justifill { onSubmit: \s -> update (updateSegments i j s) }
29updateSegments :: Int -> Int -> String -> Array (Array Segment) -> Array (Array Segment)
30updateSegments i j v arrs = fromMaybe [] (A.modifyAt i (updateLine j v) arrs)
32updateLine :: Int -> String -> Array Segment -> Array Segment
33updateLine idx v arr = fromMaybe [] (A.modifyAt idx f arr)
36 Filler s -> unsafeCrashWith "Updated a filler"
39mkFillInTheGaps :: Effect (ReactComponent { code :: String })
41 ic <- InlineCode.makeComponent
42 component "FillInTheGaps" \{ code } -> React.do
45 lines = split (Pattern "\n") code
46 rawSegments = split (Pattern separator) >>> intersperse separator
48 x | x == separator -> Hole ""
50 initialSegments = lines <#> \line -> rawSegments line <#> toSegment
51 segments /\ modifySegments <- useState initialSegments
52 pure $ renderSegments ic (modifySegments) segments
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list