begin moving text window when cursor goes off screen (currently, we only move the window when cursor goes backwards but this works fine and as expected)
This commit is contained in:
@@ -24,6 +24,8 @@ struct
|
||||
let
|
||||
val {windowWidth, windowHeight, startLine, ...} = app
|
||||
(* todo: get new startLine if cursor has moved out of screen *)
|
||||
val startLine = TextWindow.getStartLine
|
||||
(buffer, startLine, cursorIdx, windowWidth, windowHeight)
|
||||
|
||||
(* move LineGap to first line displayed on screen, and build new text *)
|
||||
val buffer = LineGap.goToLine (startLine, buffer)
|
||||
@@ -31,7 +33,8 @@ struct
|
||||
(startLine, cursorIdx, buffer, windowWidth, windowHeight)
|
||||
|
||||
val mode = NORMAL_MODE ""
|
||||
val newApp = AppWith.bufferAndCursorIdx (app, buffer, cursorIdx, mode)
|
||||
val newApp = AppWith.bufferAndCursorIdx
|
||||
(app, buffer, cursorIdx, mode, startLine)
|
||||
in
|
||||
(newApp, drawMsg)
|
||||
end
|
||||
@@ -61,7 +64,8 @@ struct
|
||||
(startLine, cursorIdx, buffer, windowWidth, windowHeight)
|
||||
|
||||
val mode = NORMAL_MODE ""
|
||||
val newApp = AppWith.bufferAndCursorIdx (app, buffer, cursorIdx, mode)
|
||||
val newApp = AppWith.bufferAndCursorIdx
|
||||
(app, buffer, cursorIdx, mode, startLine)
|
||||
in
|
||||
(newApp, drawMsg)
|
||||
end
|
||||
@@ -99,7 +103,8 @@ struct
|
||||
(startLine, cursorIdx, buffer, windowWidth, windowHeight)
|
||||
|
||||
val mode = NORMAL_MODE ""
|
||||
val newApp = AppWith.bufferAndCursorIdx (app, buffer, cursorIdx, mode)
|
||||
val newApp = AppWith.bufferAndCursorIdx
|
||||
(app, buffer, cursorIdx, mode, startLine)
|
||||
in
|
||||
(newApp, drawMsg)
|
||||
end
|
||||
@@ -109,11 +114,8 @@ struct
|
||||
if pos = String.size str then
|
||||
pos
|
||||
else
|
||||
let
|
||||
val chr = String.sub (str, pos)
|
||||
in
|
||||
if Char.isDigit chr then getNumLength (pos + 1, str)
|
||||
else pos
|
||||
let val chr = String.sub (str, pos)
|
||||
in if Char.isDigit chr then getNumLength (pos + 1, str) else pos
|
||||
end
|
||||
|
||||
fun appendChr (app: app_type, chr, str) =
|
||||
@@ -180,10 +182,7 @@ struct
|
||||
* such as "2dw" to delete two word
|
||||
* so add current chr to mode, and save it in the app state *)
|
||||
let
|
||||
val str =
|
||||
if Char.isDigit chr
|
||||
then str ^ Char.toString chr
|
||||
else ""
|
||||
val str = if Char.isDigit chr then str ^ Char.toString chr else ""
|
||||
val mode = NORMAL_MODE str
|
||||
val newApp = AppWith.mode (app, mode)
|
||||
in
|
||||
@@ -202,7 +201,8 @@ struct
|
||||
(startLine, cursorIdx, buffer, windowWidth, windowHeight)
|
||||
|
||||
val mode = NORMAL_MODE ""
|
||||
val newApp = AppWith.bufferAndCursorIdx (app, buffer, cursorIdx, mode)
|
||||
val newApp = AppWith.bufferAndCursorIdx
|
||||
(app, buffer, cursorIdx, mode, startLine)
|
||||
in
|
||||
(newApp, drawMsg)
|
||||
end
|
||||
@@ -262,24 +262,16 @@ struct
|
||||
| #"T" =>
|
||||
(* to just before chr, backward *)
|
||||
handleNextChr (1, app, Cursor.tillPrevChr, newCmd)
|
||||
| #"y" =>
|
||||
(* yank *)
|
||||
clearMode app
|
||||
| #"d" =>
|
||||
(* delete *)
|
||||
clearMode app
|
||||
| #"y" => (* yank *) clearMode app
|
||||
| #"d" => (* delete *) clearMode app
|
||||
| #"f" =>
|
||||
(* to chr, forward *)
|
||||
handleNextChr (count, app, Cursor.toNextChr, newCmd)
|
||||
| #"F" =>
|
||||
(* to chr, backward *)
|
||||
handleNextChr (count, app, Cursor.toPrevChr, newCmd)
|
||||
| #"g" =>
|
||||
(* go *)
|
||||
handleGo (count, app, newCmd)
|
||||
| #"c" =>
|
||||
(* change *)
|
||||
clearMode app
|
||||
| #"g" => (* go *) handleGo (count, app, newCmd)
|
||||
| #"c" => (* change *) clearMode app
|
||||
| _ =>
|
||||
(* isn't a non-terminal cmd
|
||||
* this case should never happen*)
|
||||
|
||||
@@ -22,7 +22,8 @@ struct
|
||||
}
|
||||
end
|
||||
|
||||
fun bufferAndCursorIdx (app: app_type, newBuffer, newCursorIdx, newMode) =
|
||||
fun bufferAndCursorIdx
|
||||
(app: app_type, newBuffer, newCursorIdx, newMode, newStartLine) =
|
||||
let
|
||||
val
|
||||
{ mode = _
|
||||
@@ -30,15 +31,15 @@ struct
|
||||
, cursorIdx = _
|
||||
, windowWidth
|
||||
, windowHeight
|
||||
, startLine
|
||||
, startLine = _
|
||||
} = app
|
||||
in
|
||||
{ mode = newMode
|
||||
, buffer = newBuffer
|
||||
, cursorIdx = newCursorIdx
|
||||
, startLine = newStartLine
|
||||
, windowWidth = windowWidth
|
||||
, windowHeight = windowHeight
|
||||
, startLine = startLine
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -7,10 +7,7 @@ end
|
||||
|
||||
structure TextBuilder :> TEXT_BUILDER =
|
||||
struct
|
||||
val xSpace = 13
|
||||
val xSpace3 = xSpace * 3
|
||||
val ySpace = 25
|
||||
val fontSize = 30.0
|
||||
open TextConstants
|
||||
|
||||
fun accToDrawMsg (textAcc, cursorAcc) =
|
||||
let
|
||||
@@ -480,7 +477,6 @@ struct
|
||||
fun build
|
||||
(startLine, cursorPos, lineGap: LineGap.t, windowWidth, windowHeight) =
|
||||
let
|
||||
val lineGap = LineGap.goToLine (startLine, lineGap)
|
||||
val {rightStrings, rightLines, line = curLine, idx = curIdx, ...} = lineGap
|
||||
in
|
||||
case (rightStrings, rightLines) of
|
||||
@@ -504,9 +500,7 @@ struct
|
||||
end
|
||||
else
|
||||
0
|
||||
|
||||
val absIdx = curIdx + startIdx
|
||||
|
||||
in
|
||||
if cursorPos < curIdx + String.size rStrHd then
|
||||
(* if cursor is within string *)
|
||||
|
||||
7
fcore/text-constants.sml
Normal file
7
fcore/text-constants.sml
Normal file
@@ -0,0 +1,7 @@
|
||||
structure TextConstants =
|
||||
struct
|
||||
val xSpace = 13
|
||||
val xSpace3 = xSpace * 3
|
||||
val ySpace = 25
|
||||
val fontSize : Real32.real = 30.0
|
||||
end
|
||||
81
fcore/text-window.sml
Normal file
81
fcore/text-window.sml
Normal file
@@ -0,0 +1,81 @@
|
||||
structure TextWindow =
|
||||
struct
|
||||
open TextConstants
|
||||
|
||||
fun isPrevChrLn (str, strPos, strTl) =
|
||||
if strPos > 0 then
|
||||
String.sub (str, strPos - 1) = #"\n"
|
||||
else
|
||||
case strTl of
|
||||
hd :: _ =>
|
||||
String.sub (hd, String.size hd - 1) = #"\n"
|
||||
| [] => false
|
||||
|
||||
fun getStartLineBefore (sIdx, shd, lineNum, absIdx, cursorIdx, stl) =
|
||||
if sIdx < 0 then
|
||||
case stl of
|
||||
hd :: tl =>
|
||||
getStartLineBefore
|
||||
(String.size hd - 1, hd, lineNum, absIdx, cursorIdx, tl)
|
||||
| [] =>
|
||||
0
|
||||
else
|
||||
let
|
||||
val chr = String.sub (shd, sIdx)
|
||||
in
|
||||
if chr = #"\n" then
|
||||
if absIdx <> cursorIdx then
|
||||
getStartLineBefore
|
||||
(sIdx - 1, shd, lineNum - 1, absIdx - 1, cursorIdx, stl)
|
||||
else
|
||||
(* we have found cursor, and it is at \n *)
|
||||
lineNum - 1
|
||||
else
|
||||
if absIdx <> cursorIdx then
|
||||
getStartLineBefore
|
||||
(sIdx - 1, shd, lineNum, absIdx - 1, cursorIdx, stl)
|
||||
else
|
||||
(* we have found cursor; return line *)
|
||||
lineNum - 1
|
||||
end
|
||||
|
||||
(* Prerequisite: LineGap is moved to oldLine first. *)
|
||||
fun getStartLine (lineGap: LineGap.t, oldLine, cursorIdx, maxWidth, maxHeight) =
|
||||
let
|
||||
val {rightStrings, rightLines, line = curLine, idx = curIdx, leftStrings, ...} = lineGap
|
||||
in
|
||||
case (rightStrings, rightLines) of
|
||||
(rStrHd :: rStrTl, rLnHd :: _) =>
|
||||
let
|
||||
(* get index of line to start building from *)
|
||||
val startIdx =
|
||||
if oldLine > curLine then
|
||||
let
|
||||
val lnPos = oldLine - curLine - 1
|
||||
val startIdx = Vector.sub (rLnHd, lnPos)
|
||||
in
|
||||
startIdx - 1
|
||||
end
|
||||
else
|
||||
0
|
||||
val absIdx = curIdx + startIdx
|
||||
in
|
||||
if cursorIdx < absIdx then
|
||||
(* move upwards *)
|
||||
getStartLineBefore
|
||||
(startIdx, rStrHd, oldLine, absIdx, cursorIdx, leftStrings)
|
||||
else if cursorIdx = absIdx + 1 then
|
||||
(* double linebreak *)
|
||||
getStartLineBefore
|
||||
(startIdx + 1, rStrHd, oldLine, absIdx + 1, cursorIdx, leftStrings)
|
||||
else if cursorIdx > absIdx then
|
||||
(* possibly move downwards *)
|
||||
oldLine
|
||||
else
|
||||
(* keep current line *)
|
||||
Int.max (oldLine - 1, 0)
|
||||
end
|
||||
| (_, _) =>
|
||||
oldLine
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user