Backwards motions and deletions

This commit is contained in:
Dustin Swan 2026-03-18 20:04:25 -06:00
parent a3b815b449
commit 717ec2048b
No known key found for this signature in database
GPG key ID: 30D46587E2100467

View file

@ -53,10 +53,46 @@ textEditor = name \
pos = skipWhile (ch \ charKind ch == kind) lines row col;
skipWhile (ch \ ch == " ") lines pos.row pos.col;
skipBack = pred line row col lines \
col < 0
| True \ (row > 0
| True \ (
prevLine = nth (row - 1) lines ~ unwrapOr "";
skipBack pred prevLine (row - 1) (len prevLine - 1) lines)
| False \ { row = 0, col = 0 - 1 })
| False \ (pred (nth col line ~ unwrapOr "")
| True \ skipBack pred line row (col - 1) lines
| False \ { row = row, col = col });
prevWordStart = lines row col \
# step back 1
c = col - 1;
r = row;
r2 = c < 0
| True \ r - 1
| False \ r;
c2 = c < 0
| True \ (max 0 (len (nth (r - 1) lines ~ unwrapOr "") - 1))
| False \ c;
# no prev line
r2 < 0
| True \ { row = 0, col = 0 }
| False \ (
line = nth r2 lines ~ unwrapOr "";
# skip spaces backward
pos = skipBack (ch \ ch == " ") line r2 c2 lines;
# skip same kind backward
kind = charKind (nth pos.col (nth pos.row lines ~ unwrapOr "") ~ unwrapOr " ");
pos2 = skipBack (ch \ charKind ch == kind) (nth pos.row lines ~ unwrapOr "") pos.row (pos.col - 1) lines;
# go 1 ahead
{ row = pos2.row, col = pos2.col + 1 }
);
resolveMotion = motion state \
from = { row = state.cursorRow, col = state.cursorCol };
to = motion
| Word \ nextWordStart state.lines from.row from.col
| BackWord \ prevWordStart state.lines from.row from.col
| WholeLine \ from;
{ from = from, to = to };
@ -66,11 +102,10 @@ textEditor = name \
deleteRange = state from to \
line = nth from.row state.lines ~ unwrapOr "";
toCol = to.row > from.row
| True \ len line
| False \ to.col;
newLine = (slice line 0 from.col) & (slice line toCol (len line));
state.{ lines = updateAt from.row (_ \ newLine) state.lines, cursorCol = from.col };
startCol = min from.col to.col;
endCol = max from.col to.col;
newLine = (slice line 0 startCol) & (slice line endCol (len line));
state.{ lines = updateAt from.row (_ \ newLine) state.lines, cursorCol = startCol };
applyOperator = operator motion state \
target = resolveMotion motion state;
@ -277,6 +312,9 @@ textEditor = name \
| Key { key = "d" } \ (state.pending
| Some Delete \ applyOperator Delete WholeLine state
| _ \ { state = state.{ pending = Some Delete }, emit = [] })
| Key { key = "b" } \ (state.pending
| None \ withScroll { state = moveCursor (resolveMotion BackWord state) state, emit = [] }
| Some Delete \ withScroll (applyOperator Delete BackWord state))
| Key { key = "w" } \ (state.pending
| None \ withScroll { state = moveCursor (resolveMotion Word state) state, emit = [] }
| Some Delete \ withScroll (applyOperator Delete Word state))