From b6de188f7d80854bbec61b0ac9b7ebc8950baa10 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Fri, 12 Sep 2025 08:57:17 +0100 Subject: [PATCH] create a separate directory for different text builders --- fcore/text-builder.sml | 319 +----------------- fcore/text-builder/text-builder-utils.sml | 96 ++++++ .../text-builder/text-builder-with-cursor.sml | 228 +++++++++++++ shf.mlb | 2 + 4 files changed, 329 insertions(+), 316 deletions(-) create mode 100644 fcore/text-builder/text-builder-utils.sml create mode 100644 fcore/text-builder/text-builder-with-cursor.sml diff --git a/fcore/text-builder.sml b/fcore/text-builder.sml index 307d356..ac2ed6a 100644 --- a/fcore/text-builder.sml +++ b/fcore/text-builder.sml @@ -1,320 +1,7 @@ structure TextBuilder = struct structure TC = TextConstants - - type env_data = - { charR: Real32.real - , charG: Real32.real - , charB: Real32.real - - (* different colours for char when cursor is on char *) - , cursorOnCharR: Real32.real - , cursorOnCharG: Real32.real - , cursorOnCharB: Real32.real - - , cursorR: Real32.real - , cursorG: Real32.real - , cursorB: Real32.real - - , highlightR: Real32.real - , highlightG: Real32.real - , highlightB: Real32.real - - , charZ: Real32.real - , cursorZ: Real32.real - , highlightZ: Real32.real - - , startX: int - , startY: int - - , scrollColumnStart: int - , scrollColumnEnd: int - , lastLineNumber: int - - (* fw/fh = float window width and float window height *) - , fw: Real32.real - , fh: Real32.real - , msgs: MailboxType.t list - , searchList: int vector - , searchLen: int - } - - (* different functions to make vectors of different things we want to draw. *) - fun makeCursor (posX, posY, env: env_data) = - Rect.lerp - ( Real32.fromInt (posX - 1) - , Real32.fromInt posY - , #cursorZ env - , TC.scale - , #fw env - , #fh env - , #cursorR env - , #cursorG env - , #cursorB env - ) - - fun makeHighlight (posX, posY, env: env_data) = - Rect.lerp - ( Real32.fromInt (posX - 1) - , Real32.fromInt posY - , #highlightZ env - , TC.scale - , #fw env - , #fh env - , #highlightR env - , #highlightG env - , #highlightB env - ) - - fun makeChr (chr, posX, posY, env: env_data) = - CozetteAscii.make - ( chr - , Real32.fromInt posX - , Real32.fromInt posY - , #charZ env - , TC.scale - , #fw env - , #fh env - , #charR env - , #charG env - , #charB env - ) - - fun makeCursorOnChr (chr, posX, posY, env: env_data) = - CozetteAscii.make - ( chr - , Real32.fromInt posX - , Real32.fromInt posY - , #charZ env - , TC.scale - , #fw env - , #fh env - , #cursorOnCharR env - , #cursorOnCharG env - , #cursorOnCharB env - ) - - structure TextWithCursor = - struct - fun goToFirstLineAfter - (stl, ltl, posY, lineNumber, absIdx, cursorIdx, env, acc) = - case (stl, ltl) of - (shd :: stl, lhd :: ltl) => - if Vector.length lhd > 0 then - let - val lineOffset = Vector.sub (lhd, 0) - val strPos = lineOffset + 1 - val absIdx = absIdx + strPos - val posY = posY + TC.ySpace - val lineNumber = lineNumber + 1 - in - build - ( strPos - , shd - , stl - , lhd - , ltl - , #startX env - , posY - , 0 - , lineNumber - , absIdx - , cursorIdx - , env : env_data - , acc - ) - end - else - (* keep looping until we find a linebreak *) - goToFirstLineAfter - ( stl - , ltl - , posY - , lineNumber - , absIdx + String.size shd - , cursorIdx - , env - , acc - ) - | (_, _) => acc - - and skipToColumnStart - (pos, str, stl, line, ltl, posY, lineNumber, absIdx, cursorIdx, env, acc) = - if Vector.length line = 0 then - let - (* get index of buffer after this string *) - val absIdx = absIdx - pos - 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 env) - in - if searchPos = Vector.length line 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 - , stl - , line - , ltl - , #startX env - , posY - , 0 - , 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 - , cursorIdx - , env - , acc - ) - end - | #"\n" => - let - val acc = - if absIdx = cursorIdx then makeCursor (posX, posY, env) :: acc - else acc - - val nextLineNumber = lineNumber + 1 - in - if nextLineNumber > #lastLineNumber env then - acc - else - build - ( pos + 1 - , str - , stl - , line - , ltl - , #startX env - , posY + TC.ySpace - , 0 - , lineNumber + 1 - , absIdx + 1 - , cursorIdx - , env - , acc - ) - end - | chr => - 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 (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 + structure Utils = TextBuilderUtils fun buildTextString ( pos @@ -327,7 +14,7 @@ struct , cursorPos , cursorAcc , bgAcc - , env: env_data + , env: Utils.env_data ) = if pos < String.size str then case String.sub (str, pos) of @@ -615,7 +302,7 @@ struct , cursorPos , cursorAcc , bgAcc - , env: env_data + , env: Utils.env_data , searchPos ) = if searchPos = Vector.length (#searchList env) then diff --git a/fcore/text-builder/text-builder-utils.sml b/fcore/text-builder/text-builder-utils.sml new file mode 100644 index 0000000..09f9d3f --- /dev/null +++ b/fcore/text-builder/text-builder-utils.sml @@ -0,0 +1,96 @@ +structure TextBuilderUtils = +struct + structure TC = TextConstants + + type env_data = + { charR: Real32.real + , charG: Real32.real + , charB: Real32.real + + (* different colours for char when cursor is on char *) + , cursorOnCharR: Real32.real + , cursorOnCharG: Real32.real + , cursorOnCharB: Real32.real + + , cursorR: Real32.real + , cursorG: Real32.real + , cursorB: Real32.real + + , highlightR: Real32.real + , highlightG: Real32.real + , highlightB: Real32.real + + , charZ: Real32.real + , cursorZ: Real32.real + , highlightZ: Real32.real + + , startX: int + , startY: int + + , scrollColumnStart: int + , scrollColumnEnd: int + , lastLineNumber: int + + (* fw/fh = float window width and float window height *) + , fw: Real32.real + , fh: Real32.real + , msgs: MailboxType.t list + , searchList: int vector + , searchLen: int + } + + (* different functions to make vectors of different things we want to draw. *) + fun makeCursor (posX, posY, env: env_data) = + Rect.lerp + ( Real32.fromInt (posX - 1) + , Real32.fromInt posY + , #cursorZ env + , TC.scale + , #fw env + , #fh env + , #cursorR env + , #cursorG env + , #cursorB env + ) + + fun makeHighlight (posX, posY, env: env_data) = + Rect.lerp + ( Real32.fromInt (posX - 1) + , Real32.fromInt posY + , #highlightZ env + , TC.scale + , #fw env + , #fh env + , #highlightR env + , #highlightG env + , #highlightB env + ) + + fun makeChr (chr, posX, posY, env: env_data) = + CozetteAscii.make + ( chr + , Real32.fromInt posX + , Real32.fromInt posY + , #charZ env + , TC.scale + , #fw env + , #fh env + , #charR env + , #charG env + , #charB env + ) + + fun makeCursorOnChr (chr, posX, posY, env: env_data) = + CozetteAscii.make + ( chr + , Real32.fromInt posX + , Real32.fromInt posY + , #charZ env + , TC.scale + , #fw env + , #fh env + , #cursorOnCharR env + , #cursorOnCharG env + , #cursorOnCharB env + ) +end diff --git a/fcore/text-builder/text-builder-with-cursor.sml b/fcore/text-builder/text-builder-with-cursor.sml new file mode 100644 index 0000000..71ea952 --- /dev/null +++ b/fcore/text-builder/text-builder-with-cursor.sml @@ -0,0 +1,228 @@ +structure TextBuilderWithCursor = +struct + structure TC = TextConstants + structure Utils = TextBuilderUtils + + fun goToFirstLineAfter + (stl, ltl, posY, lineNumber, absIdx, cursorIdx, env, acc) = + case (stl, ltl) of + (shd :: stl, lhd :: ltl) => + if Vector.length lhd > 0 then + let + val lineOffset = Vector.sub (lhd, 0) + val strPos = lineOffset + 1 + val absIdx = absIdx + strPos + val posY = posY + TC.ySpace + val lineNumber = lineNumber + 1 + in + build + ( strPos + , shd + , stl + , lhd + , ltl + , #startX env + , posY + , 0 + , lineNumber + , absIdx + , cursorIdx + , env + , acc + ) + end + else + (* keep looping until we find a linebreak *) + goToFirstLineAfter + ( stl + , ltl + , posY + , lineNumber + , absIdx + String.size shd + , cursorIdx + , env + , acc + ) + | (_, _) => acc + + and skipToColumnStart + (pos, str, stl, line, ltl, posY, lineNumber, absIdx, cursorIdx, env, acc) = + if Vector.length line = 0 then + let + (* get index of buffer after this string *) + val absIdx = absIdx - pos + 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 env) + in + if searchPos = Vector.length line 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 + , stl + , line + , ltl + , #startX env + , posY + , 0 + , lineNumber + , absIdx + , cursorIdx + , env + , acc + ) + end + end + + and build + ( pos + , str + , stl + , line + , ltl + , posX + , posY + , column + , lineNumber + , absIdx + , cursorIdx + , env: Utils.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 + Utils.makeCursor (posX, posY, env) :: acc + else + acc + in + build + ( pos + 1 + , str + , stl + , line + , ltl + , posX + TC.xSpace + , posY + , column + 1 + , lineNumber + , absIdx + 1 + , cursorIdx + , env + , acc + ) + end + | #"\n" => + let + val acc = + if absIdx = cursorIdx then + Utils.makeCursor (posX, posY, env) :: acc + else + acc + + val nextLineNumber = lineNumber + 1 + in + if nextLineNumber > #lastLineNumber env then + acc + else + build + ( pos + 1 + , str + , stl + , line + , ltl + , #startX env + , posY + TC.ySpace + , 0 + , lineNumber + 1 + , absIdx + 1 + , cursorIdx + , env + , acc + ) + end + | chr => + let + val acc = + if absIdx = cursorIdx then + let val acc = Utils.makeCursor (posX, posY, env) :: acc + in Utils.makeCursorOnChr (chr, posX, posY, env) :: acc + end + else + Utils.makeCursor (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 diff --git a/shf.mlb b/shf.mlb index de980ec..7e7b146 100644 --- a/shf.mlb +++ b/shf.mlb @@ -32,6 +32,8 @@ ann in fcore/rect.sml fcore/pipe-cursor.sml + fcore/text-builder/text-builder-utils.sml + fcore/text-builder/text-builder-with-cursor.sml fcore/text-builder.sml fcore/cursor-dfa/make-dfa-loop.sml fcore/cursor-dfa/vi-word-dfa.sml