-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvih.hs
74 lines (65 loc) · 2.48 KB
/
vih.hs
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
import EditBuffer
import Rendering
import Input
import Char
import Control.Exception
data EditMode = Command | Insert deriving (Eq,Show)
vih :: IO ()
vih =
do initInput
mainLoop Command emptyBuffer
mainLoop :: EditMode -> EditBuffer -> IO ()
mainLoop mode previousBuffer =
do cls
buffer <- return (frame previousBuffer)
render buffer
-- writeAt commandHome (showRepresentation buffer)
ch <- getInputChar
if mode == Insert
then
case ch of
'\ESC' -> mainLoop Command (enterCommandMode buffer)
_ -> if isInputChar ch
then mainLoop mode (insertChar ch buffer)
else mainLoop mode buffer
else
case ch of
':' -> handleCommandLine buffer
'i' -> mainLoop Insert buffer
'h' -> mainLoop mode (moveLeft buffer)
'j' -> mainLoop mode (moveDown buffer)
'k' -> mainLoop mode (moveUp buffer)
'l' -> mainLoop mode (moveRight buffer)
'd' -> do nextCh <- getInputChar
if nextCh == 'd'
then mainLoop mode (deleteLine buffer)
else mainLoop mode buffer
'g' -> do nextCh <- getInputChar
if nextCh == 'g'
then mainLoop mode (moveToHome buffer)
else mainLoop mode buffer
'G' -> mainLoop mode (moveToEnd buffer)
'0' -> mainLoop mode (moveToLineStart buffer)
'$' -> mainLoop mode (moveToLineEnd buffer)
'o' -> mainLoop Insert (insertLineAfter buffer)
'r' -> do nextCh <- getInputChar
if isInputChar nextCh
then mainLoop mode (replaceChar nextCh buffer)
else mainLoop mode buffer
'w' -> mainLoop mode (wordForward buffer)
'b' -> mainLoop mode (wordBackward buffer)
'x' -> mainLoop mode (deleteChar buffer)
_ -> mainLoop mode buffer
-- aborts when line command is not parseable. Fix with exception catch
handleCommandLine :: EditBuffer -> IO ()
handleCommandLine buffer =
do goto commandHome
putStr ":"
command <- getLine
if head command == 'q'
then return ()
else if isDigit (head command)
then mainLoop Command (moveToLine (read command :: Int) buffer)
else mainLoop Command buffer
isInputChar :: Char -> Bool
isInputChar ch = (not (isControl ch)) || (ch == '\n')