add mutually recursive functions to skip to start of next line in text builder

This commit is contained in:
2025-09-12 08:05:19 +01:00
parent 4fb35d075f
commit a2c3df65f7

View File

@@ -94,131 +94,227 @@ struct
, #cursorOnCharB env , #cursorOnCharB env
) )
fun buildTextString structure TextWithCursor =
( pos struct
, str fun goToFirstLineAfter
, stl (stl, ltl, posY, lineNumber, absIdx, cursorIdx, env, acc) =
, line
, ltl
, posX
, posY
, column
, lineNumber
, absIdx
, cursorIdx
, env: env_data
, acc
) =
if pos = String.size str then
case (stl, ltl) of case (stl, ltl) of
(str :: stl, line :: ltl) => (shd :: stl, lhd :: ltl) =>
buildTextString if Vector.length lhd > 0 then
( 0 let
, str val lineOffset = Vector.sub (lhd, 0)
, stl val strPos = lineOffset + 1
, line val absIdx = absIdx + strPos
, ltl val posY = posY + TC.ySpace
, posX val lineNumber = lineNumber + 1
, posY in
, column build
, lineNumber ( strPos
, absIdx , shd
, cursorIdx , stl
, env , lhd
, acc , ltl
) , #startX env
| (_, _) => acc , posY
else if column < #scrollColumnStart env then , 0
skipToColumnStart , lineNumber
( pos , absIdx
, str , cursorIdx
, stl , env : env_data
, line , acc
, ltl )
, posY end
, lineNumber else
, absIdx (* keep looping until we find a linebreak *)
, cursorIdx goToFirstLineAfter
, env ( stl
, acc
)
else
case String.sub (str, pos) of
#" " =>
let
val acc =
if absIdx = cursorIdx then makeCursor (posX, posY, env) :: acc
else acc
in
buildTextString
( pos + 1
, str
, stl
, line
, ltl , ltl
, posX + TC.xSpace
, posY , posY
, column + 1
, lineNumber , lineNumber
, absIdx + 1 , absIdx + String.size shd
, cursorIdx , cursorIdx
, env , env
, acc , acc
) )
end | (_, _) => acc
| #"\n" =>
let
val acc =
if absIdx = cursorIdx then makeCursor (posX, posY, env) :: acc
else acc
val nextLineNumber = lineNumber + 1 and skipToColumnStart
in (pos, str, stl, line, ltl, posY, lineNumber, absIdx, cursorIdx, env, acc) =
if nextLineNumber > #lastLineNumber env then if Vector.length line = 0 then
acc let
else (* get index of buffer after this string *)
buildTextString val absIdx = absIdx - pos
( pos + 1 val absIdx = absIdx + String.size str
in
goToFirstLineAfter
(stl, ltl, posY, lineNumber, absIdx, cursorIdx, env, acc)
end
else
(* bin search lines *)
let
val searchPos = BinSearch.equalOrMore (pos + 1, searchList)
in
if searchPos = Vector.length lines then
(* next line is not in this node *)
let
val absIdx = absIdx - pos
val absIdx = absIdx + String.size str
in
goToFirstLineAfter
(stl, ltl, posY, lineNumber, absIdx, cursorIdx, env, acc)
end
else
let
val lineOffset = Vector.sub (line, searchPos)
val newStrPos = lineOffset + 1
val absIdx = absIdx - pos + newStrPos
val posY = posY + TC.ySpace
val lineNumber = lineNumber + 1
in
build
( newStrPos
, str , str
, stl , stl
, line , line
, ltl , ltl
, #startX env , #startX env
, posY + TC.ySpace , posY
, 0 , 0
, lineNumber + 1 , lineNumber
, absIdx
, cursorIdx
, env
, acc
)
end
end
and build
( pos
, str
, stl
, line
, ltl
, posX
, posY
, column
, lineNumber
, absIdx
, cursorIdx
, env: env_data
, acc
) =
if pos = String.size str then
case (stl, ltl) of
(str :: stl, line :: ltl) =>
build
( 0
, str
, stl
, line
, ltl
, posX
, posY
, column
, lineNumber
, absIdx
, cursorIdx
, env
, acc
)
| (_, _) => acc
else if column < #scrollColumnStart env then
skipToColumnStart
( pos
, str
, stl
, line
, ltl
, posY
, lineNumber
, absIdx
, cursorIdx
, env
, acc
)
else
case String.sub (str, pos) of
#" " =>
let
val acc =
if absIdx = cursorIdx then makeCursor (posX, posY, env) :: acc
else acc
in
build
( pos + 1
, str
, stl
, line
, ltl
, posX + TC.xSpace
, posY
, column + 1
, lineNumber
, absIdx + 1 , absIdx + 1
, cursorIdx , cursorIdx
, env , env
, acc , acc
) )
end end
| chr => | #"\n" =>
let let
val acc = val acc =
if absIdx = cursorIdx then if absIdx = cursorIdx then makeCursor (posX, posY, env) :: acc
let val acc = makeCursor (posX, posY, env) :: acc else acc
in makeCursorOnChr (chr, posX, posY, env) :: acc
end val nextLineNumber = lineNumber + 1
in
if nextLineNumber > #lastLineNumber env then
acc
else else
makeCursor (chr, posX, posY, env) :: acc build
in ( pos + 1
buildTextString , str
( pos + 1 , stl
, str , line
, stl , ltl
, line , #startX env
, ltl , posY + TC.ySpace
, posX + TC.xSpace , 0
, posY , lineNumber + 1
, column + 1 , absIdx + 1
, lineNumber , cursorIdx
, absIdx + 1 , env
, cursorIdx , acc
, env )
, acc end
) | chr =>
end let
val acc =
if absIdx = cursorIdx then
let val acc = makeCursor (posX, posY, env) :: acc
in makeCursorOnChr (chr, posX, posY, env) :: acc
end
else
makeCursor (chr, posX, posY, env) :: acc
in
build
( pos + 1
, str
, stl
, line
, ltl
, posX + TC.xSpace
, posY
, column + 1
, lineNumber
, absIdx + 1
, cursorIdx
, env
, acc
)
end
end
fun buildTextString fun buildTextString
( pos ( pos