progress parsing normal mode commands

This commit is contained in:
2024-10-26 06:01:48 +01:00
parent defb17af20
commit 816f064558
3 changed files with 141 additions and 53 deletions

View File

@@ -19,49 +19,69 @@ struct
(newApp, drawMsg) (newApp, drawMsg)
end end
fun moveBackward (app: app_type, fMove) = fun helpMoveBackward (app: app_type, buffer, cursorIdx, count, fMove) =
let if count = 0 then
val {buffer, windowWidth, windowHeight, startLine, cursorIdx, ...} = app let
val {windowWidth, windowHeight, startLine, ...} = app
(* todo: get new startLine if cursor has moved out of screen *)
(* move LineGap to first line displayed on screen, and build new text *)
val buffer = LineGap.goToLine (startLine, buffer)
val drawMsg = TextBuilder.build
(startLine, cursorIdx, buffer, windowWidth, windowHeight)
val mode = NORMAL_MODE ""
val newApp = AppWith.bufferAndCursorIdx (app, buffer, cursorIdx, mode)
in
(newApp, drawMsg)
end
else
(* move LineGap to cursorIdx, which is necessary for finding newCursorIdx *) (* move LineGap to cursorIdx, which is necessary for finding newCursorIdx *)
val buffer = LineGap.goToIdx (cursorIdx, buffer) let
val cursorIdx = fMove (buffer, cursorIdx) val buffer = LineGap.goToIdx (cursorIdx, buffer)
val cursorIdx = fMove (buffer, cursorIdx)
in
helpMoveBackward (app, buffer, cursorIdx, count - 1, fMove)
end
(* todo: get new startLine if cursor has moved out of screen *) fun moveBackward (app: app_type, count, fMove) =
let val {cursorIdx, buffer, ...} = app
(* move LineGap to first line displayed on screen, and build new text *) in helpMoveBackward (app, buffer, cursorIdx, count, fMove)
val buffer = LineGap.goToLine (startLine, buffer)
val drawMsg = TextBuilder.build
(startLine, cursorIdx, buffer, windowWidth, windowHeight)
val newApp = AppWith.bufferAndCursorIdx (app, buffer, cursorIdx)
in
(newApp, drawMsg)
end end
fun moveFowrards (app: app_type, fMove) = fun helpMoveForwards (app: app_type, buffer, cursorIdx, count, fMove) =
let if count = 0 then
val {buffer, windowWidth, windowHeight, startLine, cursorIdx, ...} = app let
val {windowWidth, windowHeight, startLine, ...} = app
(* todo: get new startLine if cursor has moved out of screen *)
(* move LineGap to cursorIdx, which is necessary for finding newCursorIdx *) (* move LineGap to first line displayed on screen, and build new text *)
val buffer = LineGap.goToIdx (cursorIdx, buffer) val buffer = LineGap.goToLine (startLine, buffer)
val cursorIdx = fMove (buffer, cursorIdx) val drawMsg = TextBuilder.build
(startLine, cursorIdx, buffer, windowWidth, windowHeight)
(* todo: get new startLine if cursor has moved out of screen *) val mode = NORMAL_MODE ""
val newApp = AppWith.bufferAndCursorIdx (app, buffer, cursorIdx, mode)
in
(newApp, drawMsg)
end
else
let
(* move LineGap to cursorIdx, which is necessary for finding newCursorIdx *)
val buffer = LineGap.goToIdx (cursorIdx, buffer)
val cursorIdx = fMove (buffer, cursorIdx)
in
helpMoveForwards (app, buffer, cursorIdx, count - 1, fMove)
end
(* move LineGap to first line displayed on screen, and build new text *) fun moveForwards (app: app_type, count, fMove) =
val buffer = LineGap.goToLine (startLine, buffer) let val {cursorIdx, buffer, ...} = app
val drawMsg = TextBuilder.build in helpMoveForwards (app, buffer, cursorIdx, count, fMove)
(startLine, cursorIdx, buffer, windowWidth, windowHeight)
val newApp = AppWith.bufferAndCursorIdx (app, buffer, cursorIdx)
in
(newApp, drawMsg)
end end
fun firstNonSpaceChr (app: app_type) = fun firstNonSpaceChr (app: app_type) =
let let
val {buffer, windowWidth, windowHeight, startLine, cursorIdx, ...} = app val {buffer, cursorIdx, windowWidth, windowHeight, startLine, ...} = app
(* move LineGap and buffer to start of line *) (* move LineGap and buffer to start of line *)
val buffer = LineGap.goToIdx (cursorIdx, buffer) val buffer = LineGap.goToIdx (cursorIdx, buffer)
@@ -78,30 +98,79 @@ struct
val drawMsg = TextBuilder.build val drawMsg = TextBuilder.build
(startLine, cursorIdx, buffer, windowWidth, windowHeight) (startLine, cursorIdx, buffer, windowWidth, windowHeight)
val newApp = AppWith.bufferAndCursorIdx (app, buffer, cursorIdx) val mode = NORMAL_MODE ""
val newApp = AppWith.bufferAndCursorIdx (app, buffer, cursorIdx, mode)
in in
(newApp, drawMsg) (newApp, drawMsg)
end end
fun handleChr (app: app_type, chr) = (* number of characters which are integers *)
fun getNumLength (pos, str) =
if pos = String.size str then
pos
else
let
val chr = String.sub (str, pos)
in
if chr >= #"0" andalso chr <= #"9" then getNumLength (pos + 1, str)
else pos
end
fun handleChr (app: app_type, count, chr, str) =
case chr of case chr of
#"h" => moveBackward (app, Cursor.viH) #"h" => moveBackward (app, count, Cursor.viH)
| #"j" => moveFowrards (app, Cursor.viJ) | #"j" => moveForwards (app, count, Cursor.viJ)
| #"k" => moveBackward (app, Cursor.viK) | #"k" => moveBackward (app, count, Cursor.viK)
| #"l" => moveFowrards (app, Cursor.viL) | #"l" => moveForwards (app, count, Cursor.viL)
| #"0" => moveBackward (app, Cursor.vi0) | #"0" => moveBackward (app, 1, Cursor.vi0)
| #"$" => moveFowrards (app, Cursor.viDlr) | #"$" => moveForwards (app, 1, Cursor.viDlr)
| #"w" => moveFowrards (app, Cursor.nextWord) | #"w" => moveForwards (app, count, Cursor.nextWord)
| #"W" => moveFowrards (app, Cursor.nextWORD) | #"W" => moveForwards (app, count, Cursor.nextWORD)
| #"b" => moveBackward (app, Cursor.prevWord) | #"b" => moveBackward (app, count, Cursor.prevWord)
| #"B" => moveBackward (app, Cursor.prevWORD) | #"B" => moveBackward (app, count, Cursor.prevWORD)
| #"e" => moveFowrards (app, Cursor.endOfWord) | #"e" => moveForwards (app, count, Cursor.endOfWord)
| #"E" => moveFowrards (app, Cursor.endOfWORD) | #"E" => moveForwards (app, count, Cursor.endOfWORD)
| #"^" => firstNonSpaceChr app | #"^" => firstNonSpaceChr app
| _ => (app, []) | _ =>
(* user may be entering a cmd with more than one chr
* such as "2dw" to delete two word
* so add current chr to mode, and save it in the app state *)
let
val str =
if chr >= #"0" andalso chr <= #"9" then str ^ Char.toString chr
else ""
val mode = NORMAL_MODE str
val newApp = AppWith.mode (app, mode)
in
(newApp, [])
end
fun parseNormalModeCommand (app, str, newCmd) =
if String.size str = 0 then
case newCmd of
RESIZE_EVENT (width, height) => resizeText (app, width, height)
| CHAR_EVENT chr => handleChr (app, 1, chr, str)
else
let
val numLength = getNumLength (0, str)
val count = String.substring (str, 0, numLength)
val count =
case Int.fromString count of
SOME x => x
| NONE => 1
in
if numLength = String.size str then
(* reached end of str; str only contained numbers *)
case newCmd of
RESIZE_EVENT (width, height) => resizeText (app, width, height)
| CHAR_EVENT chr => handleChr (app, count, chr, str)
else
(* todo: continue parsing. *)
raise Match
end
fun updateNormalMode (app, str, msg) = parseNormalModeCommand (app, str, msg)
fun update (app, msg) = fun update (app, msg) =
case msg of case #mode app of NORMAL_MODE str => updateNormalMode (app, str, msg)
RESIZE_EVENT (width, height) => resizeText (app, width, height)
| CHAR_EVENT chr => handleChr (app, chr)
end end

View File

@@ -22,13 +22,18 @@ struct
} }
end end
fun bufferAndCursorIdx (app: app_type, newBuffer, newCursorIdx) = fun bufferAndCursorIdx (app: app_type, newBuffer, newCursorIdx, newMode) =
let let
val val
{mode, buffer = _, cursorIdx = _, windowWidth, windowHeight, startLine} = { mode = _
app , buffer = _
, cursorIdx = _
, windowWidth
, windowHeight
, startLine
} = app
in in
{ mode = mode { mode = newMode
, buffer = newBuffer , buffer = newBuffer
, cursorIdx = newCursorIdx , cursorIdx = newCursorIdx
, windowWidth = windowWidth , windowWidth = windowWidth
@@ -36,4 +41,18 @@ struct
, startLine = startLine , startLine = startLine
} }
end end
fun mode (app: app_type, newMode) =
let
val {mode = _, buffer, cursorIdx, windowWidth, windowHeight, startLine} =
app
in
{ mode = newMode
, buffer = buffer
, cursorIdx = cursorIdx
, windowWidth = windowWidth
, windowHeight = windowHeight
, startLine = startLine
}
end
end end

BIN
shf

Binary file not shown.