From 66f1fb0b5ea767b83a3ef6844145ac776ea3bfd3 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Tue, 13 Jan 2026 23:54:48 +0000 Subject: [PATCH] implement 'yk' motion (next: add tests for it) --- fcore/normal-mode/normal-mode.sml | 1 + fcore/normal-mode/normal-yank.sml | 55 +++++++++++++++++++++++++++++++ temp.txt | 2 ++ todo.md | 4 +-- 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/fcore/normal-mode/normal-mode.sml b/fcore/normal-mode/normal-mode.sml index f2f6a75..7d6df17 100644 --- a/fcore/normal-mode/normal-mode.sml +++ b/fcore/normal-mode/normal-mode.sml @@ -462,6 +462,7 @@ struct fun parseYankTerminal (str, count, app, chrCmd, time) = case chrCmd of #"h" => NormalYank.yankLeft (app, count) + | #"k" => NormalYank.yankLineUp (app, count) | #"l" => NormalYank.yankRight (app, count) | #"y" => NormalYank.yankLine (app, count) | #"0" => NormalYank.yankToStartOfLine app diff --git a/fcore/normal-mode/normal-yank.sml b/fcore/normal-mode/normal-yank.sml index fd58e26..93815b4 100644 --- a/fcore/normal-mode/normal-yank.sml +++ b/fcore/normal-mode/normal-yank.sml @@ -44,6 +44,61 @@ struct finish (app, buffer, str) end + fun yankLineUp (app: app_type, count) = + let + val {buffer, cursorIdx, ...} = app + val buffer = LineGap.goToIdx (cursorIdx, buffer) + + val cursorLineNumber = + if Cursor.isNextChrEndOfLine (buffer, cursorIdx) then + LineGap.idxToLineNumber (cursorIdx + 1, buffer) + else + LineGap.idxToLineNumber (cursorIdx, buffer) + val newCursorLineNumber = Int.max (cursorLineNumber - count, 0) + in + if cursorLineNumber = 0 then + NormalFinish.clearMode app + else if newCursorLineNumber = 0 then + let + val endOfLine = Cursor.viDlr (buffer, cursorIdx, 1) + val buffer = LineGap.goToIdx (endOfLine, buffer) + + val endOfLine = + if Cursor.isCursorAtStartOfLine (buffer, endOfLine) then + endOfLine + 1 + else + endOfLine + 2 + + val buffer = LineGap.goToIdx (endOfLine, buffer) + val str = LineGap.substring (0, endOfLine, buffer) + in + finish (app, buffer, str) + end + else + let + val endOfLine = Cursor.viDlr (buffer, cursorIdx, 1) + val buffer = LineGap.goToIdx (endOfLine, buffer) + val endsOnNewline = Cursor.isCursorAtStartOfLine (buffer, endOfLine) + + val endOfLine = if endsOnNewline then endOfLine else endOfLine + 1 + + val newCursorLineNumber = + if endsOnNewline andalso endOfLine = #textLength buffer - 1 then + newCursorLineNumber - 1 + else + newCursorLineNumber + val buffer = LineGap.goToLine (newCursorLineNumber, buffer) + + val lineIdx = LineGap.lineNumberToIdx (newCursorLineNumber, buffer) + val length = endOfLine - lineIdx + + val buffer = LineGap.goToIdx (endOfLine, buffer) + val str = LineGap.substring (lineIdx, length, buffer) + in + finish (app, buffer, str) + end + end + fun yankLine (app: app_type, count) = let val {buffer, cursorIdx, ...} = app diff --git a/temp.txt b/temp.txt index 3b18e51..bc52a2b 100644 --- a/temp.txt +++ b/temp.txt @@ -1 +1,3 @@ hello world +test line +zzz diff --git a/todo.md b/todo.md index 92c3079..48fdb18 100644 --- a/todo.md +++ b/todo.md @@ -1,3 +1,3 @@ # To-do list - -- Implement 'yj' and 'yk' and add tests for them +- Add tests for 'yk' motion +- Implement 'yj' motion and add tests for it