new task: rewrite basic cursor.sml functions (h, j, k, l) to look for 'is line break preceded by non-line break?' rather than 'is there a double line break?' because the second question which is already implemented has buggy behaviour on triple line breaks, where cursor does not go to the place user expects. Currently, on Cursor.viL has been rewritten to match the first question.

This commit is contained in:
2024-11-05 13:14:52 +00:00
parent 9df6f92a33
commit b0a37c5c56
2 changed files with 38 additions and 50 deletions

View File

@@ -126,6 +126,30 @@ struct
cursorIdx cursorIdx
end end
fun helpViL (strIdx, hd, cursorIdx, tl) =
if String.sub (hd, strIdx) = #"\n" then
(* if line break, go to next idx, no matter what chr is there *)
cursorIdx + 1
else
if strIdx + 1 < String.size hd then
(* next chr is in hd *)
if String.sub (hd, strIdx + 1) = #"\n" then
(* if non-line break followed by line break, go to chr + 2 *)
cursorIdx + 2
else
cursorIdx + 1
else
(case tl of
tlhd :: _ =>
if String.sub (tlhd, 0) = #"\n" then
(* non-line break followed by line break *)
cursorIdx + 2
else
(* non-line break followed by non-line break *)
cursorIdx
| [] =>
cursorIdx)
(* Prerequisite: lineGap is moved to requested idx first (* Prerequisite: lineGap is moved to requested idx first
* todo: check if we are in a \r\n pair, but this is not a priority *) * todo: check if we are in a \r\n pair, but this is not a priority *)
fun viL (lineGap: LineGap.t, cursorIdx) = fun viL (lineGap: LineGap.t, cursorIdx) =
@@ -138,57 +162,19 @@ struct
(* convert absolute cursorIdx to idx relative to hd string *) (* convert absolute cursorIdx to idx relative to hd string *)
val strIdx = cursorIdx - bufferIdx val strIdx = cursorIdx - bufferIdx
in in
if strIdx + 1 < String.size hd then if strIdx < String.size hd then
(* if there is at least one character after this idx *) (* strIdx is in hd *)
let helpViL (strIdx, hd, cursorIdx, tl)
val nextChr = String.sub (hd, strIdx + 1)
in
(case nextChr of
#"\n" =>
if strIdx + 2 < String.size hd then
(* if there are at least two chars after strIdx *)
cursorIdx + 2
else else
(* only one char after strIdx which is \n (* strIdx is in tl *)
* if there is a string at the tl, can increment by 2 *)
(case tl of
_ :: _ => cursorIdx + 2
| [] => cursorIdx + 1)
| _ => cursorIdx + 1)
end
else
(* no chars after this idx; have to check tl *)
(case tl of (case tl of
tlhd :: tltl => tlhd :: tltl =>
(* if there is another string after current head, we can increment cursorIdx
* however, first we need to check if next char is \n. *)
let let
val nextChr = String.sub (tlhd, 0) val strIdx = strIdx - String.size hd
in in
(case nextChr of helpViL (strIdx, tlhd, cursorIdx, tltl)
#"\n" =>
if String.size tlhd > 2 then
(* if there is at least one character after \n
* then increment 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 tltl of
_ :: _ => cursorIdx + 2
| [] => cursorIdx + 1)
| _ =>
(* next char is not newline,
* so we can just increment by 1 *)
cursorIdx + 1)
end end
| [] => | [] =>
(* if there is no string after current head, return original cursorIdx *)
cursorIdx) cursorIdx)
end end
| [] => | [] =>

View File

@@ -5,6 +5,8 @@ sig
-> MailboxType.t list -> MailboxType.t list
end end
structure TextBuilder :> TEXT_BUILDER = structure TextBuilder :> TEXT_BUILDER =
struct struct
val xSpace = 13 val xSpace = 13