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
|
module Buffer.Motion where
import Data.List (dropWhileEnd)
import Buffer.Class
--data Motion = Motion Int LeftRightMotion
-- TODO factor Count
-- TODO various Vim gX
data LeftRightMotion
= GotoLeft Int
| GotoRight Int
| GotoFirstChar
-- | GotoFirstNonBlankChar
| GotoEndOfLine -- XXX in Vi this can go downwards
| GotoColumn Int
| GotoFindLeft Int Char
| GotoFindRight Int Char
| GotillFindLeft Int Char
| GotillFindRight Int Char
-- | RepeatLastFind Int
-- | RepeatLastFindReverse Int
-- TODO fail if cannot splitAt properly OR if we didn't modify the buffer
gotoLeft i (ls, rs) =
let (lls, rls) = splitAt (length ls - i) ls in (lls, rls ++ rs)
-- TODO fail if cannot splitAt properly OR if we didn't modify the buffer
gotoRight i (ls, rs) =
let (lrs, rrs) = splitAt i rs in (ls ++ lrs, rrs)
gotoFirstChar (ls, rs) = ("", ls ++ rs)
gotoEndOfLine (ls, rs) = (ls ++ rs, "")
-- TODO fail if i <= 0 or i > length
gotoColumn i (ls, rs) = splitAt (i - 1) $ ls ++ rs
-- TODO is this definition correct?
spanEnd :: (a -> Bool) -> [a] -> ([a], [a])
spanEnd p xs = let ls = dropWhileEnd p xs in (ls, drop (length ls) xs)
-- TODO don't allow i == 0 in go{to,till}Find{Left,Right}
gotoFindLeft i c b@(ls, rs)
| i == 0 = b
| i > 0 =
let (lls, rls) = spanEnd (/= c) ls
in gotoFindLeft (i - 1) c (init lls, last lls : rls ++ rs)
gotoFindRight i c b@(ls, rs)
| i == 0 = b
| i > 0 =
let (lrs, rrs) = span (/= c) rs
in gotoFindRight (i - 1) c (ls ++ lrs ++ [head rrs], tail rrs)
-- TODO this has to fail it there aren't enought c's
gotillFindLeft i c b@(ls, rs) =
let (lls, rls) = spanEnd (/= c) ls
in
if i > 1
then gotillFindLeft (i - 1) c (init lls, last lls : rls ++ rs)
else (lls, rls ++ rs)
--gotillFindRight i c b@(ls, rs)
-- | i == 0 = b
-- | i > 0 =
-- let (lrs, rrs) = span (/= c) rs
-- in gotoFindRight (i - 1) c (ls ++ lrs, rrs)
gotillFindRight i c b@(ls, rs) =
let (lrs, rrs) = span (/= c) rs
in
if i > 1
then gotillFindRight (i - 1) c (ls ++ lrs ++ [head rrs], tail rrs)
else (ls ++ lrs, rrs)
move :: LeftRightMotion -> Buffer -> Buffer
move (GotoLeft i) = gotoLeft i
move (GotoRight i) = gotoRight i
move GotoFirstChar = gotoFirstChar
move GotoEndOfLine = gotoEndOfLine
move (GotoColumn i) = gotoColumn i
move (GotoFindLeft i c) = gotoFindLeft i c
move (GotoFindRight i c) = gotoFindRight i c
move (GotillFindLeft i c) = gotillFindLeft i c
move (GotillFindRight i c) = gotillFindRight i c
|