diff --git a/fcore/app-update.sml b/fcore/app-update.sml index 2f1a553..fa3f36d 100644 --- a/fcore/app-update.sml +++ b/fcore/app-update.sml @@ -37,9 +37,26 @@ struct (newApp, drawMsg) end + fun moveLeft (app: app_type) = + let + val {buffer, windowWidth, windowHeight, startLine, cursorIdx} = app + + val buffer = LineGap.goToIdx (cursorIdx, buffer) + val cursorIdx = Cursor.viH (buffer, cursorIdx) + + val buffer = LineGap.goToLine (startLine, buffer) + val drawMsg = TextBuilder.build + (startLine, cursorIdx, buffer, windowWidth, windowHeight) + + val newApp = AppWith.bufferAndCursorIdx (app, buffer, cursorIdx) + in + (newApp, drawMsg) + end + fun handleChr (app: app_type, chr) = case chr of - #"l" => moveRight app + #"h" => moveLeft app + | #"l" => moveRight app | _ => (app, []) fun update (app, msg) = diff --git a/fcore/cursor.sml b/fcore/cursor.sml index 7548497..f1745cf 100644 --- a/fcore/cursor.sml +++ b/fcore/cursor.sml @@ -54,7 +54,7 @@ struct * If not, increment cursorIdx by 1, * landing on newline. *) (case tltl of - tltlhd :: _ => cursorIdx + 2 + _ :: _ => cursorIdx + 2 | [] => cursorIdx + 1) | _ => (* next char is not newline, @@ -69,4 +69,76 @@ struct (* return original cursorIdx if there is nothing to the right *) cursorIdx end + + (* Prerequisite: lineGap is moved to requested idx first + * Implementation is mostly the same as the viL function, + * except we focus on decrementing instead, + * and we examing leftStrings list instead of tail of rightStrings + * if head of rightStrings is empty or does not have the idx we want. + * todo: check if we are in a \r\n pair, but this is not a priority *) + fun viH (lineGap: LineGap.t, cursorIdx) = + let + val {rightStrings, leftStrings, idx = bufferIdx, ...} = lineGap + in + case rightStrings of + hd :: _ => + let + (* convert absolute cursorIdx to idx relative to hd string *) + val strIdx = cursorIdx - bufferIdx + in + if strIdx > 0 then + (* if there is at least one char before this index *) + let + val prevChr = String.sub (hd, strIdx - 1) + in + (case prevChr of + #"\n" => + if strIdx > 1 then + (* if there are at least two chars before strIdx *) + cursorIdx - 2 + else + (* only one char before strIdx which is \n + * if there is a string at the leftStrings, can decrement by 2 *) + (case leftStrings of + _ :: _ => cursorIdx - 2 + | [] => cursorIdx - 1) + | _ => cursorIdx - 1) + end + else + (* no chars before this idx; have to check leftStrings *) + (case leftStrings of + lHd :: lTl => + (* if there is another string after current head, we can increment cursorIdx + * however, first we need to check if next char is \n. *) + let + val lastChr = String.sub (lHd, String.size lHd - 1) + in + (case lastChr of + #"\n" => + if String.size lHd > 2 then + (* if there is at least one character before \n + * then decrement cursorIdx by 2 *) + cursorIdx - 2 + else + (* this string only contains \n + * but there is a small possibility tltl + * contains another string. + * If it does, we can increment cursorIdx by 2, + * moving past newline. + * If not, increment cursorIdx by 1, + * landing on newline. *) + (case lTl of + _ :: _ => cursorIdx - 2 + | [] => cursorIdx - 1) + | _ => + (* next char is not newline, + * so we can just decrement by 1 *) + cursorIdx - 1) + end + | [] => + (* if there is no string after current head, return original cursorIdx *) + cursorIdx) + end + | [] => cursorIdx + end end diff --git a/shf b/shf index 14103cc..75e4bf3 100755 Binary files a/shf and b/shf differ