functorise some additional functions to reduce boilerplate

This commit is contained in:
2025-08-04 03:44:45 +01:00
parent cef8467ff6
commit aca8ba44b9

View File

@@ -153,6 +153,9 @@ struct
cursorIdx cursorIdx
end end
structure ViH =
MakeIfCharFolderPrev
(struct
fun helpViH (strIdx, hd, cursorIdx, leftStrings) = fun helpViH (strIdx, hd, cursorIdx, leftStrings) =
if strIdx > 0 then if strIdx > 0 then
(* bounds check: can access prev char in hd *) (* bounds check: can access prev char in hd *)
@@ -213,31 +216,11 @@ struct
cursorIdx - 1 cursorIdx - 1
| [] => 0) | [] => 0)
(* Prerequisite: lineGap is moved to requested idx first. *) fun fStart (strIdx, hd, _, cursorIdx, leftStrings, _) =
fun viH (lineGap: LineGap.t, cursorIdx) =
let
val {rightStrings, leftStrings, 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 then
(* strIdx in hd *)
helpViH (strIdx, hd, cursorIdx, leftStrings) helpViH (strIdx, hd, cursorIdx, leftStrings)
else end)
(* strIdx in tl *)
(case tl of val viH = ViH.foldPrev
tlhd :: tltl =>
let val strIdx = strIdx - String.size hd
in helpViH (strIdx, tlhd, cursorIdx, hd :: leftStrings)
end
| [] => cursorIdx)
end
| [] => cursorIdx
end
fun helpGetCursorColumn (distanceFromLine, strList, lineList) = fun helpGetCursorColumn (distanceFromLine, strList, lineList) =
case (strList, lineList) of case (strList, lineList) of
@@ -452,6 +435,9 @@ struct
| (_, _) => (* nowhere to go rightward, so return cursorIdx *) cursorIdx | (_, _) => (* nowhere to go rightward, so return cursorIdx *) cursorIdx
end end
structure ViK =
MakeIfCharFolderPrev
(struct
fun helpViK fun helpViK
( strPos ( strPos
, str , str
@@ -477,7 +463,8 @@ struct
, lhd , lhd
, ltl , ltl
) )
| (_, _) => (* empty, so return start of previous string *) absIdx + 1 | (_, _) => (* empty, so return start of previous string *)
absIdx + 1
else else
case String.sub (str, strPos) of case String.sub (str, strPos) of
#"\n" => #"\n" =>
@@ -530,7 +517,7 @@ struct
, lineTl , lineTl
) )
fun startViK (strIdx, shd, cursorIdx, leftStrings, lhd, leftLines) = fun fStart (strIdx, shd, lhd, cursorIdx, leftStrings, leftLines) =
if String.sub (shd, strIdx) = #"\n" then if String.sub (shd, strIdx) = #"\n" then
(* ? -> ? -> \n *) (* ? -> ? -> \n *)
if strIdx > 0 then if strIdx > 0 then
@@ -548,7 +535,13 @@ struct
* so go to beginning of line, * so go to beginning of line,
* starting from graphical-chr *) * starting from graphical-chr *)
startVi0 startVi0
(strIdx - 2, shd, lhd, cursorIdx - 2, leftStrings, leftLines) ( strIdx - 2
, shd
, lhd
, cursorIdx - 2
, leftStrings
, leftLines
)
else else
(* strIdx - 2 is in leftStrings *) (* strIdx - 2 is in leftStrings *)
case (leftStrings, leftLines) of case (leftStrings, leftLines) of
@@ -576,7 +569,8 @@ struct
(* ? -> graphical-chr -> \n (* ? -> graphical-chr -> \n
* Don't expect this case to happen * Don't expect this case to happen
* but if it does, go to start of line. *) * but if it does, go to start of line. *)
startVi0 (strIdx - 1, shd, lhd, cursorIdx - 1, leftStrings, leftLines) startVi0
(strIdx - 1, shd, lhd, cursorIdx - 1, leftStrings, leftLines)
else else
(* strIdx - 1 is in leftStrings *) (* strIdx - 1 is in leftStrings *)
case (leftStrings, leftLines) of case (leftStrings, leftLines) of
@@ -647,35 +641,9 @@ struct
) )
end end
fun viK (lineGap: LineGap.t, cursorIdx) = end)
let
val val viK = ViK.foldPrev
{rightStrings, idx = bufferIdx, rightLines, leftStrings, leftLines, ...} =
lineGap
in
case (rightStrings, rightLines) of
(shd :: stl, lhd :: ltl) =>
let
(* convert absolute cursorIdx to idx relative to hd string *)
val strIdx = cursorIdx - bufferIdx
in
if strIdx < String.size shd then
startViK (strIdx, shd, cursorIdx, leftStrings, lhd, leftLines)
else
case (stl, ltl) of
(stlhd :: stltl, ltlhd :: ltltl) =>
let
val strIdx = strIdx - String.size shd
val leftStrings = shd :: leftStrings
val leftLines = lhd :: leftLines
in
startViK
(strIdx, stlhd, cursorIdx, leftStrings, ltlhd, leftLines)
end
| (_, _) => cursorIdx
end
| (_, _) => (* nowhere to go rightward, so return cursorIdx *) cursorIdx
end
(* equivalent of vi's 'w' command *) (* equivalent of vi's 'w' command *)
val nextWord = ViWordDfa.startOfNextWord val nextWord = ViWordDfa.startOfNextWord
@@ -703,60 +671,36 @@ struct
val endOfWORD = ViWORDDfa.endOfCurrentWORD val endOfWORD = ViWORDDfa.endOfCurrentWORD
val endOfWORDForDelete = ViWORDDfa.endOfCurrentWORDForDelete val endOfWORDForDelete = ViWORDDfa.endOfCurrentWORDForDelete
fun helpFirstNonSpaceChr (strPos, str, absIdx, stl, ltl) = (* Prerequisite:
* LineGap has been moved to start of line (provided with vi0). *)
structure FirstNonSpaceChr =
MakeIfCharFolderPrev
(struct
fun helpFirstNonSpaceChr (strPos, str, absIdx, stl) =
if strPos = String.size str then if strPos = String.size str then
case (stl, ltl) of case stl of
(shd :: stl, lhd :: ltl) => shd :: stl => helpFirstNonSpaceChr (0, shd, absIdx, stl)
helpFirstNonSpaceChr (0, shd, absIdx, stl, ltl) | [] => absIdx - 1
| (_, _) => absIdx - 1
else else
let let
val chr = String.sub (str, strPos) val chr = String.sub (str, strPos)
in in
if chr = #" " then if chr = #" " then
helpFirstNonSpaceChr (strPos + 1, str, absIdx + 1, stl, ltl) helpFirstNonSpaceChr (strPos + 1, str, absIdx + 1, stl)
else else
absIdx absIdx
end end
fun startFirstNonSpaceChr (shd, strIdx, absIdx, stl, ltl) = fun fStart (strIdx, shd, _, absIdx, stl, _) =
if strIdx < String.size shd then if strIdx < String.size shd then
helpFirstNonSpaceChr (strIdx, shd, absIdx, stl, ltl) helpFirstNonSpaceChr (strIdx, shd, absIdx, stl)
else else
case (stl, ltl) of case stl of
(stlhd :: stltl, ltlhd :: ltltl) => stlhd :: stltl => helpFirstNonSpaceChr (0, stlhd, absIdx, stltl)
helpFirstNonSpaceChr (0, stlhd, absIdx, stltl, ltltl) | [] => (* tl is empty; just return absIdx *) absIdx
| (_, _) => (* tl is empty; just return absIdx *) absIdx end)
(* Prerequisite: val firstNonSpaceChr = FirstNonSpaceChr.foldPrev
* LineGap has been moved to start of line (provided with vi0). *)
fun firstNonSpaceChr (lineGap: LineGap.t, cursorIdx) =
let
val {rightStrings, rightLines, idx = bufferIdx, ...} = lineGap
in
case (rightStrings, rightLines) of
(shd :: stl, lhd :: ltl) =>
let
(* convert absolute cursorIdx to idx relative to hd string *)
val strIdx = cursorIdx - bufferIdx
in
if strIdx < String.size shd then
(* strIdx is in this string *)
startFirstNonSpaceChr (shd, strIdx, cursorIdx, stl, ltl)
else
(* strIdx is in tl *)
(case (stl, ltl) of
(stlhd :: stltl, ltlhd :: ltltl) =>
let
val strIdx = strIdx - String.size shd
in
startFirstNonSpaceChr
(stlhd, strIdx, cursorIdx, stltl, ltltl)
end
| (_, _) => cursorIdx)
end
| (_, _) => cursorIdx
end
fun helpToNextChr (strPos, str, absIdx, stl, ltl, origIdx, findChr) = fun helpToNextChr (strPos, str, absIdx, stl, ltl, origIdx, findChr) =
if strPos = String.size str then if strPos = String.size str then