progress parsing normal mode commands
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user