diff --git a/fcore/app-update.sml b/fcore/app-update.sml index b5c6120..b67ac23 100644 --- a/fcore/app-update.sml +++ b/fcore/app-update.sml @@ -19,6 +19,26 @@ struct (newApp, drawMsg) end + fun centreToCursor (app: app_type) = + let + val {buffer, windowWidth, windowHeight, startLine = origLine, cursorIdx, ...} = app + val buffer = LineGap.goToIdx (cursorIdx, buffer) + + val startLine = TextWindow.getStartLineWithCursorCentered + (buffer, cursorIdx, origLine, windowWidth, windowHeight) + + val buffer = LineGap.goToLine (startLine, buffer) + + val newApp = AppWith.bufferAndCursorIdx + (app, buffer, cursorIdx, NORMAL_MODE "", startLine) + + val drawMsg = + TextBuilder.build + (startLine, cursorIdx, buffer, windowWidth, windowHeight) + in + (newApp, drawMsg) + end + fun moveToStart (app: app_type) = let val {buffer, windowWidth, windowHeight, startLine, ...} = app @@ -131,6 +151,7 @@ struct | #"B" => move (app, count, Cursor.prevWORD) | #"e" => move (app, count, Cursor.endOfWord) | #"E" => move (app, count, Cursor.endOfWORD) + | #"z" => centreToCursor app (* can only move to start or end of line once * so hardcode count as 1 *) | #"0" => diff --git a/fcore/text-window.sml b/fcore/text-window.sml index 97c30ba..74629a1 100644 --- a/fcore/text-window.sml +++ b/fcore/text-window.sml @@ -144,4 +144,121 @@ struct | (_, _) => oldLine end + + fun helpCentreCursor (strPos, str, lineNum, stl, maxW, halfH, curW, curH) = + if strPos < 0 then + case stl of + hd :: tl => + helpCentreCursor + (String.size hd - 1, hd, lineNum, tl, maxW, halfH, curW, curH) + | [] => + (* return 0 for start of buffer *) + 0 + else + let + val chr = String.sub (str, strPos) + in + if chr = #"\n" then + if curH + (ySpace * 3) >= halfH then + (* if we exceeded half the screen *) + lineNum + else + helpCentreCursor + ( strPos - 1, str, lineNum - 1, stl, maxW, halfH + , 0, curH + ySpace + ) + else + if curW + xSpace <= maxW then + let + val curW = curW + xSpace + in + helpCentreCursor + ( strPos - 1, str, lineNum, stl, maxW, halfH + , curW + xSpace, curH + ) + end + else + (* have to create visual line break *) + if curH + (ySpace * 3) >= halfH then + (* if at limit, return current line lineNum *) + lineNum + else + helpCentreCursor + ( strPos - 1, str, lineNum - 1, stl, maxW, halfH + , 0, curH + ySpace + ) + end + + (* search for prev \n, and once found, + * call function to return startLine where cursor is centered *) + fun getCursorStartLine (strPos, str, lineNum, stl, maxW, halfH) = + if strPos < 0 then + case stl of + hd :: tl => + getCursorStartLine + (String.size hd - 1, str, lineNum, tl, maxW, halfH) + | [] => + 0 + else + let + val chr = String.sub (str, strPos) + in + if chr = #"\n" then + (* \n found *) + helpCentreCursor + (strPos - 1, str, lineNum - 1, stl, maxW, halfH, xSpace, ySpace) + else + getCursorStartLine + (strPos - 1, str, lineNum, stl, maxW, halfH) + end + + (* Prerequisite: LineGap is moved to cursor *) + fun getStartLineWithCursorCentered + (lineGap: LineGap.t, cursorIdx, origLine, maxWidth, maxHeight) = + let + val {rightStrings, rightLines, idx = bufferIdx, line = bufferLine, leftStrings, ...} = 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 hd *) + let + val lineNum = + if Vector.length lhd = 0 then + bufferLine + else if Vector.length lhd = 1 then + let + val lineIdx = Vector.sub (lhd, 0) + in + if lineIdx < strIdx then + bufferLine + 1 + else + bufferLine + end + else + let + val firstLineIdx = Vector.sub (lhd, 0) + in + if firstLineIdx > strIdx then + bufferLine + else if firstLineIdx < strIdx then + Cursor.binSearch (strIdx - 1, lhd) + bufferLine + else + bufferLine + 1 + end + in + getCursorStartLine + (strIdx, shd, lineNum, leftStrings, maxWidth, maxHeight div 2) + end + else + (* todo: strIdx is in tl *) + raise Match + end + | (_, _) => + origLine + end end diff --git a/shf b/shf index e825cc8..e9a82b4 100755 Binary files a/shf and b/shf differ diff --git a/shf.mlb b/shf.mlb index bc9f4eb..10c5d02 100644 --- a/shf.mlb +++ b/shf.mlb @@ -18,9 +18,9 @@ ann in fcore/text-builder.sml end +fcore/cursor.sml fcore/text-window.sml -fcore/cursor.sml fcore/app-update.sml (* IMPERATIVE SHELL *)