From 204f549c79fb1e4e993f300816e7a68077193786 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Sat, 13 Dec 2025 03:40:32 +0000 Subject: [PATCH] implement 'daw' motion --- fcore/cursor.sml | 172 ++++++++++++++++++++++- fcore/normal-mode/make-normal-delete.sml | 31 ++++ fcore/normal-mode/normal-mode.sml | 4 +- temp.txt | 3 + 4 files changed, 208 insertions(+), 2 deletions(-) diff --git a/fcore/cursor.sml b/fcore/cursor.sml index ce20cc4..fd1344b 100644 --- a/fcore/cursor.sml +++ b/fcore/cursor.sml @@ -619,7 +619,177 @@ struct fun lastContiguousNonSpace (lineGap, cursorIdx) = LastContiguousNonSpace.foldNext (lineGap, cursorIdx, ()) - (* Prerequisite: lineGap is moved to cursorIdx *) + structure AroundWordPrev = + MakeIfCharFolderPrev + (struct + type env = unit + + fun loopAlphaNum (strPos, shd, absIdx, stl) = + if strPos < 0 then + case stl of + shd :: stl => + loopAlphaNum (String.size shd - 1, shd, absIdx, stl) + | [] => 0 + else + let + val chr = String.sub (shd, strPos) + in + if Char.isAlphaNum chr orelse chr = #"_" then + loopAlphaNum (strPos - 1, shd, absIdx - 1, stl) + else + absIdx + 1 + end + + fun loopPunct (strPos, shd, absIdx, stl) = + if strPos < 0 then + case stl of + shd :: stl => loopPunct (String.size shd - 1, shd, absIdx, stl) + | [] => 0 + else + let + val chr = String.sub (shd, strPos) + in + if + Char.isAlphaNum chr orelse chr = #"_" orelse chr = #"\n" + orelse Char.isSpace chr + then absIdx + 1 + else (* is punct *) loopPunct (strPos - 1, shd, absIdx - 1, stl) + end + + fun loopSpace (strPos, shd, absIdx, stl) = + if strPos < 0 then + case stl of + shd :: stl => loopSpace (String.size shd - 1, shd, absIdx, stl) + | [] => 0 + else + let + val chr = String.sub (shd, strPos) + in + if chr = #"\n" then + absIdx + 1 + else if Char.isSpace chr then + loopSpace (strPos - 1, shd, absIdx - 1, stl) + else + absIdx + 1 + end + + fun fStart (strPos, shd, _, absIdx, stl, _, _) = + let + val chr = String.sub (shd, strPos) + in + if chr = #"\n" then + absIdx + else if Char.isAlphaNum chr orelse chr = #"_" then + loopAlphaNum (strPos - 1, shd, absIdx - 1, stl) + else if Char.isSpace chr then + loopSpace (strPos - 1, shd, absIdx - 1, stl) + else + loopPunct (strPos - 1, shd, absIdx - 1, stl) + end + end) + + fun aroundWordPrev (lineGap, cursorIdx) = + AroundWordPrev.foldPrev (lineGap, cursorIdx, ()) + + structure AroundWordNext = + MakeIfCharFolderNext + (struct + type env = unit + + fun stopAtFirstNonSpace (strPos, shd, absIdx, stl) = + if strPos = String.size shd then + case stl of + shd :: stl => stopAtFirstNonSpace (0, shd, absIdx, stl) + | [] => absIdx + else + let + val chr = String.sub (shd, strPos) + in + if chr = #"\n" then + absIdx - 1 + else if Char.isSpace chr then + stopAtFirstNonSpace (strPos + 1, shd, absIdx + 1, stl) + else + absIdx - 1 + end + + fun loopAlphaNum (strPos, shd, absIdx, stl) = + if strPos = String.size shd then + case stl of + shd :: stl => loopAlphaNum (0, shd, absIdx, stl) + | [] => absIdx + else + let + val chr = String.sub (shd, strPos) + in + if chr = #"\n" then + absIdx - 1 + else if Char.isAlphaNum chr orelse chr = #"_" then + loopAlphaNum (strPos + 1, shd, absIdx + 1, stl) + else if Char.isSpace chr then + stopAtFirstNonSpace (strPos + 1, shd, absIdx + 1, stl) + else + (* is punct *) + absIdx - 1 + end + + fun loopPunct (strPos, shd, absIdx, stl) = + if strPos = String.size shd then + case stl of + shd :: stl => loopPunct (0, shd, absIdx, stl) + | [] => absIdx + else + let + val chr = String.sub (shd, strPos) + in + if chr = #"\n" then + absIdx - 1 + else if Char.isAlphaNum chr orelse chr = #"_" then + absIdx - 1 + else if Char.isSpace chr then + stopAtFirstNonSpace (strPos + 1, shd, absIdx + 1, stl) + else + (* is punct *) + loopPunct (strPos + 1, shd, absIdx + 1, stl) + end + + fun loopSpace (strPos, shd, absIdx, stl) = + if strPos = String.size shd then + case stl of + shd :: stl => loopSpace (0, shd, absIdx, stl) + | [] => absIdx + else + let + val chr = String.sub (shd, strPos) + in + if chr = #"\n" then + absIdx - 1 + else if Char.isAlphaNum chr orelse chr = #"_" then + loopAlphaNum (strPos + 1, shd, absIdx + 1, stl) + else if Char.isSpace chr then + loopSpace (strPos + 1, shd, absIdx + 1, stl) + else + loopPunct (strPos + 1, shd, absIdx + 1, stl) + end + + fun fStart (strPos, shd, _, absIdx, stl, _, _) = + let + val chr = String.sub (shd, strPos) + in + if chr = #"\n" then + absIdx + else if Char.isAlphaNum chr orelse chr = #"_" then + loopAlphaNum (strPos + 1, shd, absIdx + 1, stl) + else if Char.isSpace chr then + loopSpace (strPos + 1, shd, absIdx + 1, stl) + else + loopPunct (strPos + 1, shd, absIdx + 1, stl) + end + end) + + fun aroundWordNext (lineGap, cursorIdx) = + AroundWordNext.foldNext (lineGap, cursorIdx, ()) + fun isCursorAtStartOfLine (lineGap: LineGap.t, cursorIdx) = let val {rightStrings, idx = bufferIdx, ...} = lineGap diff --git a/fcore/normal-mode/make-normal-delete.sml b/fcore/normal-mode/make-normal-delete.sml index 2b8cfc0..9882358 100644 --- a/fcore/normal-mode/make-normal-delete.sml +++ b/fcore/normal-mode/make-normal-delete.sml @@ -23,7 +23,14 @@ struct val initialMsg = Fn.initMsgs (low, length, buffer) val buffer = LineGap.delete (low, length, buffer) + val low = + if low >= #textLength buffer - 1 then + Int.max (#textLength buffer - 1, 0) + else + low + val buffer = LineGap.goToIdx (low, buffer) + val low = if Cursor.isOnNewlineAfterChr (buffer, low) then low - 1 else low in @@ -973,6 +980,30 @@ struct end end + fun deleteAroundWord (app: app_type, time) = + let + val {buffer, cursorIdx, dfa, ...} = app + val buffer = LineGap.goToIdx (cursorIdx, buffer) + + val low = Cursor.aroundWordPrev (buffer, cursorIdx) + val high = Cursor.aroundWordNext (buffer, cursorIdx) + 1 + + val length = high - low + in + deleteAndFinish (app, low, length, buffer, time) + end + + fun deleteAroundWORD (app: app_type, time) = + let + val {buffer, cursorIdx, dfa, ...} = app + val buffer = LineGap.goToIdx (cursorIdx, buffer) + val low = raise Fail "unimplemented" + val high = raise Fail "unimplemented" + val length = high - low + in + deleteAndFinish (app, low, length, buffer, time) + end + fun finishAfterDeleteInside (app: app_type, origLow, high, time) = if origLow = high then NormalFinish.clearMode app diff --git a/fcore/normal-mode/normal-mode.sml b/fcore/normal-mode/normal-mode.sml index e3e3863..7106b9f 100644 --- a/fcore/normal-mode/normal-mode.sml +++ b/fcore/normal-mode/normal-mode.sml @@ -234,7 +234,9 @@ struct fun parseDeleteAround (app, chr, time) = case chr of - #"(" => NormalDelete.deleteAroundChrOpen (app, chr, time) + #"w" => NormalDelete.deleteAroundWord (app, time) + | #"W" => NormalDelete.deleteAroundWORD (app, time) + | #"(" => NormalDelete.deleteAroundChrOpen (app, chr, time) | #"[" => NormalDelete.deleteAroundChrOpen (app, chr, time) | #"{" => NormalDelete.deleteAroundChrOpen (app, chr, time) | #"<" => NormalDelete.deleteAroundChrOpen (app, chr, time) diff --git a/temp.txt b/temp.txt index 9b48555..0424254 100644 --- a/temp.txt +++ b/temp.txt @@ -1 +1,4 @@ hello abc_123 world + +fun hello () = + print (##)lo"