Files
sml-projects/fcore/cursor.sml

59 lines
2.2 KiB
Standard ML
Raw Normal View History

structure Cursor =
struct
(* todo: viL does not handle \r\n pair right now
* but this is not a priority so it's okay *)
local
fun helpVilLf (hd, strIdx, bufferIdx, cursorIdx, tl) =
(* if we are in \n,
* move cursor to character after newline
* if possible *)
if strIdx < String.size hd - 3 then
(* we know it is safe to move cursorIdx by 2
* if strIdx + 2 is before or at the end of the string. *)
cursorIdx + 2
else
(* we have to check the tl to see if it is not empty
* so we know it is safe to move. *)
case tl of
_ :: _ =>
(* not empty, so we can increment by 2 *)
cursorIdx + 2
| [] =>
(* empty, so return end of string which is \n *)
bufferIdx + String.size hd - 1
in
(* 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) =
let
val {rightStrings, idx = bufferIdx, ...} = lineGap
in
case rightStrings of
hd :: tl =>
let
(* convert absolute cursorIdx to idx relative to hd string *)
val strIdx = cursorIdx - bufferIdx
in
if strIdx < String.size hd - 2 then
(case String.sub (hd, strIdx + 1) of
#"\n" => helpVilLf (hd, strIdx, bufferIdx, cursorIdx, tl)
| _ => cursorIdx + 1)
2024-10-17 04:03:45 +01:00
else
(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. *)
(case String.sub (tlhd, 0) of
#"\n" => helpVilLf (tlhd, 0, bufferIdx, cursorIdx, tltl)
| _ => cursorIdx + 1)
| _ =>
(* if there is no string after current head, return original cursorIdx *)
cursorIdx)
end
| [] =>
(* return original cursorIdx if there is nothing to the right *)
cursorIdx
end
end
end