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:
@@ -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 *)
|
||||
|
||||
Reference in New Issue
Block a user