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
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
* todo: check if we are in a \r\n pair, but this is not a priority *)
fun viL (lineGap: LineGap.t, cursorIdx) =
@@ -138,58 +162,20 @@ struct
(* convert absolute cursorIdx to idx relative to hd string *)
val strIdx = cursorIdx - bufferIdx
in
if strIdx + 1 < String.size hd then
(* if there is at least one character after this idx *)
let
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
(* only one char after strIdx which is \n
* if there is a string at the tl, can increment by 2 *)
(case tl of
_ :: _ => cursorIdx + 2
| [] => cursorIdx + 1)
| _ => cursorIdx + 1)
end
if strIdx < String.size hd then
(* strIdx is in hd *)
helpViL (strIdx, hd, cursorIdx, tl)
else
(* no chars after this idx; have to check tl *)
(* strIdx is in tl *)
(case tl of
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
val nextChr = String.sub (tlhd, 0)
in
(case nextChr of
#"\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
| [] =>
(* if there is no string after current head, return original cursorIdx *)
cursorIdx)
tlhd :: tltl =>
let
val strIdx = strIdx - String.size hd
in
helpViL (strIdx, tlhd, cursorIdx, tltl)
end
| [] =>
cursorIdx)
end
| [] =>
(* return original cursorIdx if there is nothing to the right *)

View File

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