-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathTextBuffer.elm
103 lines (83 loc) · 2.99 KB
/
TextBuffer.elm
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
module TextBuffer where
import TextBufferStyles exposing (..)
import LineStyles exposing (LineStyle)
import Buffer exposing (..)
import Char exposing (isUpper, toUpper, toLower)
import Signal exposing (..)
import Html exposing (..)
import Html.Attributes exposing (class, style)
import Graphics.Element exposing (Element, show, flow, down)
import Time exposing (fpsWhen, since, Time, millisecond)
import List exposing (reverse, foldl, append)
import String exposing (cons, fromList)
-- MODEL
type alias Model = Buffer Char
oneLiner : Model
oneLiner = insertLine emptyLine emptyBuffer
-- UPDATE
type Action = Up | Down | Left | Right
| Insert Char | Delete | EOL | BOL
| InsertLine | SwapCase
{--
arrToAction : { x : Int, y : Int } -> Action
arrToAction {x, y} = if
| x == -1 -> Left
| x == 1 -> Right
| y == -1 -> Down
| y == 1 -> Up
| otherwise -> Noop
--}
update : Action -> Model -> Model
update action model = case action of
Up -> goUp model
Down -> goDown model
Left -> goLeft model
Right -> goRight model
Insert c -> insertAtCursor c model
Delete -> removeAtCursor model
EOL -> endOfLine model
BOL -> beginningOfLine model
InsertLine -> insertLine emptyLine model
SwapCase -> modifyUnderCursor swapCase model
applyActions : List Action -> Model -> Model
applyActions = foldl update |> flip
firstNonEmpty : Line Char -> Int
firstNonEmpty l = let
trimmedLength = String.length << String.trimLeft << fromList << asList <| l
in (length l) - trimmedLength
beginningOfLine : Model -> Model
beginningOfLine = atCurrentLine (\l -> moveCursorTo (firstNonEmpty l) l)
endOfLine : Model -> Model
endOfLine = atCurrentLine (\l -> moveCursorTo (length l) l)
swapCase : Char -> Char
swapCase c = if isUpper c then toLower c else toUpper c
-- VIEW
view : Model -> Html
view = viewWith LineStyles.default
viewWith : LineStyle -> Model -> Html
viewWith sty m = div [bufferStyle] (List.map (showLineWith sty) (asTaggedList m))
showLineWith : LineStyle -> (LineData, Line Char) -> Html
showLineWith sty ({num, current}, line) = let
(xs, bs) = getLists line
left = text << fromList <| reverse bs
rest = if
| not current -> [text (fromList xs)]
| otherwise -> case xs of
[] -> [span [sty.cursor] [text " "]]
(y::ys) ->
[ span [sty.cursor] [text << String.fromChar <| y]
, text << fromList <| ys
]
in div [sty.line] <| (span [sty.lineNum] [text (toString num)])::left::rest
-- CONTROL
{--
repeatAfterIf : Time -> number -> (a -> Bool) -> Signal a -> Signal a
repeatAfterIf time fps predicate s =
let repeatable = predicate <~ s
delayedRep = repeatable |> filter identity False |> since time |> Signal.map not
resetDelay = merge (always False <~ s) delayedRep
repeats = fpsWhen fps <| (&&) <~ repeatable ~ (dropRepeats resetDelay)
in sampleOn repeats s
repeatAfterMs : Int -> Signal a -> Signal a
repeatAfterMs n s = repeatAfterIf (toFloat n * millisecond) 30 (always True) s
--}