diff --git a/src/cg/01-stdlib.cg b/src/cg/01-stdlib.cg index 6ae0253..cfb63bf 100644 --- a/src/cg/01-stdlib.cg +++ b/src/cg/01-stdlib.cg @@ -32,6 +32,18 @@ filter = f list \ list | True \ [x, ...filter f xs] | False \ filter f xs); +# insertAt : Int \ a \ List a +insertAt = idx el list \ list + | [] \ [el] + | [x, ...xs] \ (idx + | 0 \ [el, x, ...xs] + | n \ [x, ...insertAt (n - 1) el xs]); + +insertCharAt = text pos char \ + before = slice text 0 pos; + after = slice text pos (len text); + before & char & after; + # updateAt updateAt = i f list \ mapWithIndex (x j \ (i == j | True \ f x | False \ x) diff --git a/src/cg/06-textEditor.cg b/src/cg/06-textEditor.cg index b466f72..737d70f 100644 --- a/src/cg/06-textEditor.cg +++ b/src/cg/06-textEditor.cg @@ -1,20 +1,46 @@ textEditor = name \ # defaults = {}; - # c = { ...defaults, ...config }; source = getSource name; lines = split "\n" source; - # clampCursor : State -> State + insertChar = char state \ + newLines = updateAt state.cursorRow (line \ + insertCharAt line state.cursorCol char + ) state.lines; + + { state = state.{ lines = newLines, cursorCol = state.cursorCol + 1 }, emit = [] }; + + backspace = state \ + state.cursorCol == 0 + | True \ { state = state, emit = [] } # todo, join line, if not at row 0 + | False \ ( + newLines = updateAt state.cursorRow (line \ + before = slice line 0 (state.cursorCol - 1); + after = slice line state.cursorCol (len line); + before & after) state.lines; + + { state = state.{ lines = newLines, cursorCol = state.cursorCol - 1 }, emit = [] }); + + enter = state \ + line = nth state.cursorRow state.lines ~ unwrapOr ""; + before = slice line 0 state.cursorCol; + after = slice line state.cursorCol (len line); + + newLines = updateAt state.cursorRow (_ \ before) state.lines; + newLines2 = insertAt (state.cursorRow + 1) after newLines; + + { state = state.{ lines = newLines2, cursorCol = 0, cursorRow = state.cursorRow + 1 }, emit = [] }; + clampCursor = state \ - line = nth state.cursorRow lines ~ unwrapOr ""; + line = nth state.cursorRow state.lines ~ unwrapOr ""; newRow = max 0 state.cursorRow; - newRow2 = min (len state.lines - 1) (state.cursorRow); + newRow2 = min (len state.lines - 1) newRow; newCol = max 0 (state.cursorCol); - newCol2 = min (len line - 1) (state.cursorCol); + newCol2 = min (len line - 1) newCol; state.{ cursorRow = newRow2, cursorCol = newCol2 }; @@ -51,17 +77,44 @@ textEditor = name \ }, update = state event \ event - # | Key { key = " " } \ toggleFocused state - # | Key { key = "Enter" } \ toggleFocused state - | Key { key = "ArrowDown" } \ downArrow state - | Key { key = "j" } \ downArrow state + | Key { key = "j" } \ (state.mode + | Insert \ insertChar "j" state + | Normal \ downArrow state) + | Key { key = "ArrowUp" } \ upArrow state - | Key { key = "k" } \ upArrow state + | Key { key = "k" } \ (state.mode + | Insert \ insertChar "k" state + | Normal \ upArrow state) + | Key { key = "ArrowLeft" } \ leftArrow state - | Key { key = "h" } \ leftArrow state + | Key { key = "h" } \ (state.mode + | Insert \ insertChar "h" state + | Normal \ leftArrow state) + | Key { key = "ArrowRight" } \ rightArrow state - | Key { key = "l" } \ rightArrow state + | Key { key = "l" } \ (state.mode + | Insert \ insertChar "l" state + | Normal \ rightArrow state) + + | Key { key = "i" } \ (state.mode + | Insert \ insertChar "i" state + | Normal \ { state = state.{ mode = state.mode | Normal \ Insert | _ \ Insert } }) + + | Key { key = "Escape" } \ { state = state.{ mode = state.mode | Insert \ Normal | _ \ Normal } } + + | Key { key = "Backspace" } \ (state.mode + | Insert \ backspace state + | _ \ { state = state, emit = [] }) + + | Key { key = "Enter" } \ (state.mode + | Insert \ enter state + | _ \ { state = state, emit = [] }) + + # any other key + | Key { key = key, printable = True } \ (state.mode + | Insert \ insertChar key state + | _ \ { state = state, emit = [] }) | _ \ { state = state, emit = [] },