progress with equivalent of vi's 'x' command
This commit is contained in:
@@ -6,6 +6,14 @@ struct
|
|||||||
open DrawMsg
|
open DrawMsg
|
||||||
open InputMsg
|
open InputMsg
|
||||||
|
|
||||||
|
fun clearMode app =
|
||||||
|
let
|
||||||
|
val mode = NORMAL_MODE ""
|
||||||
|
val newApp = AppWith.mode (app, mode)
|
||||||
|
in
|
||||||
|
(newApp, [])
|
||||||
|
end
|
||||||
|
|
||||||
fun resizeText (app: app_type, newWidth, newHeight) =
|
fun resizeText (app: app_type, newWidth, newHeight) =
|
||||||
let
|
let
|
||||||
val {buffer, windowWidth, windowHeight, startLine, cursorIdx, ...} = app
|
val {buffer, windowWidth, windowHeight, startLine, cursorIdx, ...} = app
|
||||||
@@ -170,8 +178,6 @@ struct
|
|||||||
then
|
then
|
||||||
(* if visible, just need to redraw; no need to get line *)
|
(* if visible, just need to redraw; no need to get line *)
|
||||||
let
|
let
|
||||||
val buffer = LineGap.goToLine (startLine, buffer)
|
|
||||||
|
|
||||||
val newApp = AppWith.bufferAndCursorIdx
|
val newApp = AppWith.bufferAndCursorIdx
|
||||||
(app, buffer, cursorIdx, NORMAL_MODE "", startLine)
|
(app, buffer, cursorIdx, NORMAL_MODE "", startLine)
|
||||||
|
|
||||||
@@ -226,6 +232,72 @@ struct
|
|||||||
(newApp, drawMsg)
|
(newApp, drawMsg)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
(* equivalent of vi's 'x' command *)
|
||||||
|
fun deleteChr (app: app_type, count) =
|
||||||
|
let
|
||||||
|
val {buffer, cursorIdx, startLine, windowWidth, windowHeight, ...} = app
|
||||||
|
val buffer = LineGap.goToIdx (cursorIdx, buffer)
|
||||||
|
|
||||||
|
(* Explanation of how Vi's 'x' command behaves:
|
||||||
|
* If the cursor is at the end of the file,
|
||||||
|
* then it is decremented by 1.
|
||||||
|
* If the character after the cursor is a line break,
|
||||||
|
* then it is also decremented by 1.
|
||||||
|
* If the character before the cursor is a linee break, the cursor stays
|
||||||
|
* where it is.
|
||||||
|
* If the chracter AT the cursor is a line break and the characater
|
||||||
|
* AFTER the cursor is also a line break, then nothing is deleted.
|
||||||
|
* Otherwise, the same cursor is returned.
|
||||||
|
* All decrement cases do not decrement when the cursor is 0. *)
|
||||||
|
val cursorIsStart = Cursor.isCursorAtStartOfLine (buffer, cursorIdx)
|
||||||
|
val nextIsEnd = Cursor.isNextChrEndOfLine (buffer, cursorIdx)
|
||||||
|
in
|
||||||
|
if nextIsEnd andalso cursorIsStart then
|
||||||
|
(* vi simply doesn't do anything on 'x' command
|
||||||
|
* when cursor is at start of line, and next chr is line break *)
|
||||||
|
clearMode app
|
||||||
|
else if cursorIsStart then
|
||||||
|
let val _ = print "260\n" in
|
||||||
|
clearMode app end
|
||||||
|
else if nextIsEnd then
|
||||||
|
let
|
||||||
|
(* delete char at cursor and then decrement cursorIdx by 1
|
||||||
|
* if cursorIdx is not 0 *)
|
||||||
|
val newBuffer = LineGap.delete (cursorIdx, 1, buffer)
|
||||||
|
val cursorIdx =
|
||||||
|
if Cursor.isPrevChrStartOfLine (newBuffer, cursorIdx)
|
||||||
|
orelse cursorIdx = 0 then
|
||||||
|
cursorIdx
|
||||||
|
else cursorIdx - 1
|
||||||
|
|
||||||
|
val newBuffer = LineGap.goToLine (startLine, newBuffer)
|
||||||
|
val newApp = AppWith.bufferAndCursorIdx
|
||||||
|
(app, newBuffer, cursorIdx, NORMAL_MODE "", startLine)
|
||||||
|
|
||||||
|
val drawMsg =
|
||||||
|
TextBuilder.build
|
||||||
|
(startLine, cursorIdx, newBuffer, windowWidth, windowHeight)
|
||||||
|
in
|
||||||
|
(newApp, drawMsg)
|
||||||
|
end
|
||||||
|
else if Cursor.isPrevChrStartOfLine (buffer, cursorIdx) then
|
||||||
|
clearMode app
|
||||||
|
else
|
||||||
|
let
|
||||||
|
val newBuffer = LineGap.delete (cursorIdx, 1, buffer)
|
||||||
|
|
||||||
|
val newBuffer = LineGap.goToLine (startLine, newBuffer)
|
||||||
|
val newApp = AppWith.bufferAndCursorIdx
|
||||||
|
(app, newBuffer, cursorIdx, NORMAL_MODE "", startLine)
|
||||||
|
|
||||||
|
val drawMsg =
|
||||||
|
TextBuilder.build
|
||||||
|
(startLine, cursorIdx, newBuffer, windowWidth, windowHeight)
|
||||||
|
in
|
||||||
|
(newApp, drawMsg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
(* number of characters which are integers *)
|
(* number of characters which are integers *)
|
||||||
fun getNumLength (pos, str) =
|
fun getNumLength (pos, str) =
|
||||||
if pos = String.size str then
|
if pos = String.size str then
|
||||||
@@ -295,6 +367,7 @@ struct
|
|||||||
else
|
else
|
||||||
moveToLine (app, count - 1)
|
moveToLine (app, count - 1)
|
||||||
| #"%" => moveToMatchingPair app
|
| #"%" => moveToMatchingPair app
|
||||||
|
| #"x" => deleteChr (app, count)
|
||||||
(* multi-char commands which can be appended *)
|
(* multi-char commands which can be appended *)
|
||||||
| #"t" => appendChr (app, chr, str)
|
| #"t" => appendChr (app, chr, str)
|
||||||
| #"T" => appendChr (app, chr, str)
|
| #"T" => appendChr (app, chr, str)
|
||||||
@@ -355,15 +428,6 @@ struct
|
|||||||
in helpMoveToChr (app, buffer, cursorIdx, count, fMove, chr)
|
in helpMoveToChr (app, buffer, cursorIdx, count, fMove, chr)
|
||||||
end
|
end
|
||||||
|
|
||||||
(* temp placeholder function *)
|
|
||||||
fun clearMode app =
|
|
||||||
let
|
|
||||||
val mode = NORMAL_MODE ""
|
|
||||||
val newApp = AppWith.mode (app, mode)
|
|
||||||
in
|
|
||||||
(newApp, [])
|
|
||||||
end
|
|
||||||
|
|
||||||
fun handleMoveToChr (count, app, fMove, newCmd) =
|
fun handleMoveToChr (count, app, fMove, newCmd) =
|
||||||
case newCmd of
|
case newCmd of
|
||||||
CHAR_EVENT chr => moveToChr (app, count, fMove, chr)
|
CHAR_EVENT chr => moveToChr (app, count, fMove, chr)
|
||||||
|
|||||||
102
fcore/cursor.sml
102
fcore/cursor.sml
@@ -31,7 +31,8 @@ struct
|
|||||||
cursorIdx
|
cursorIdx
|
||||||
else
|
else
|
||||||
(* not at newline so start iterating *)
|
(* not at newline so start iterating *)
|
||||||
helpVi0 (strIdx - 1, strHd, cursorIdx - 1, strTl, lnTl)
|
helpVi0
|
||||||
|
(strIdx - 1, strHd, cursorIdx - 1, leftStrings, leftLines)
|
||||||
else
|
else
|
||||||
(* strIdx must be in the strTl *)
|
(* strIdx must be in the strTl *)
|
||||||
(case (strTl, lnTl) of
|
(case (strTl, lnTl) of
|
||||||
@@ -977,18 +978,18 @@ struct
|
|||||||
(case (stl, ltl) of
|
(case (stl, ltl) of
|
||||||
(stlhd :: stltl, ltlhd :: ltltl) =>
|
(stlhd :: stltl, ltlhd :: ltltl) =>
|
||||||
let val strIdx = strIdx - String.size shd
|
let val strIdx = strIdx - String.size shd
|
||||||
in fNext (strIdx, shd, cursorIdx, stltl, ltltl)
|
in fNext (strIdx, stlhd, cursorIdx, stltl, ltltl)
|
||||||
end
|
end
|
||||||
| (_, _) => cursorIdx)
|
| (_, _) => cursorIdx)
|
||||||
end
|
end
|
||||||
| (_, _) => cursorIdx
|
| (_, _) => cursorIdx
|
||||||
end
|
end
|
||||||
|
|
||||||
(* equivalent 'f vi's 'w' command *)
|
(* equivalent of vi's 'w' command *)
|
||||||
fun nextWord (lineGap, cursorIdx) =
|
fun nextWord (lineGap, cursorIdx) =
|
||||||
toNextWord (lineGap, cursorIdx, helpNextWord)
|
toNextWord (lineGap, cursorIdx, helpNextWord)
|
||||||
|
|
||||||
(* equivalent 'f vi's 'W' command *)
|
(* equivalent of vi's 'W' command *)
|
||||||
fun nextWORD (lineGap, cursorIdx) =
|
fun nextWORD (lineGap, cursorIdx) =
|
||||||
toNextWord (lineGap, cursorIdx, helpNextWORD)
|
toNextWord (lineGap, cursorIdx, helpNextWORD)
|
||||||
|
|
||||||
@@ -1742,4 +1743,97 @@ struct
|
|||||||
| (_, _) => 0)
|
| (_, _) => 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
(* Prerequisite: lineGap is moved to cursorIdx *)
|
||||||
|
fun isCursorAtStartOfLine (lineGap: LineGap.t, cursorIdx) =
|
||||||
|
let
|
||||||
|
val {rightStrings, idx = bufferIdx, ...} = lineGap
|
||||||
|
in
|
||||||
|
case rightStrings of
|
||||||
|
hd :: tl =>
|
||||||
|
let
|
||||||
|
(* convert absolute cursorIdx to idx relative to hd string *)
|
||||||
|
val strIdx = cursorIdx - bufferIdx
|
||||||
|
in
|
||||||
|
if strIdx < String.size hd then
|
||||||
|
(* chr is in hd *)
|
||||||
|
String.sub (hd, strIdx) = #"\n"
|
||||||
|
else
|
||||||
|
(* chr is in tl *)
|
||||||
|
(case tl of
|
||||||
|
tlhd :: _ =>
|
||||||
|
let
|
||||||
|
val strIdx = strIdx - String.size hd
|
||||||
|
in
|
||||||
|
String.sub (tlhd, strIdx) = #"\n"
|
||||||
|
end
|
||||||
|
| [] => true)
|
||||||
|
end
|
||||||
|
| [] => true
|
||||||
|
end
|
||||||
|
|
||||||
|
(* Prerequisite: lineGap is moved to cursorIdx *)
|
||||||
|
fun isPrevChrStartOfLine (lineGap: LineGap.t, cursorIdx) =
|
||||||
|
let
|
||||||
|
val {rightStrings, idx = bufferIdx, leftStrings, ...} = lineGap
|
||||||
|
in
|
||||||
|
case rightStrings of
|
||||||
|
hd :: tl =>
|
||||||
|
let
|
||||||
|
(* convert absolute cursorIdx to idx relative to hd string *)
|
||||||
|
val strIdx = cursorIdx - bufferIdx
|
||||||
|
in
|
||||||
|
if strIdx > 0 then
|
||||||
|
(* prev chr is in hd *)
|
||||||
|
String.sub (hd, strIdx - 1) = #"\n"
|
||||||
|
else
|
||||||
|
(* prev chr if in leftStrings *)
|
||||||
|
(case leftStrings of
|
||||||
|
lhd :: _ =>
|
||||||
|
String.sub (lhd, String.size lhd - 1) = #"\n"
|
||||||
|
| [] =>
|
||||||
|
(* cursorIdx = 0 which means we are at start of file/line *)
|
||||||
|
true)
|
||||||
|
end
|
||||||
|
| [] =>
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
fun helpIsNextChrEndOfLine (strIdx, hd, tl) =
|
||||||
|
if strIdx + 1 < String.size hd then
|
||||||
|
(* next chr is in this string *)
|
||||||
|
String.sub (hd, strIdx + 1) = #"\n"
|
||||||
|
else
|
||||||
|
(* next chr, if it exists, is in tl *)
|
||||||
|
(case tl of
|
||||||
|
tlhd :: _ =>
|
||||||
|
String.sub (tlhd, 0) = #"\n"
|
||||||
|
| [] =>
|
||||||
|
true)
|
||||||
|
|
||||||
|
(* Prerequisite: lineGap is moved to cursorIdx *)
|
||||||
|
fun isNextChrEndOfLine (lineGap: LineGap.t, cursorIdx) =
|
||||||
|
let
|
||||||
|
val {rightStrings, idx = bufferIdx, ...} = lineGap
|
||||||
|
in
|
||||||
|
case rightStrings of
|
||||||
|
hd :: tl =>
|
||||||
|
let
|
||||||
|
(* convert absolute cursorIdx to idx relative to hd string *)
|
||||||
|
val strIdx = cursorIdx - bufferIdx
|
||||||
|
in
|
||||||
|
if strIdx < String.size hd then
|
||||||
|
helpIsNextChrEndOfLine (strIdx, hd, tl)
|
||||||
|
else
|
||||||
|
(* strIdx is in tl *)
|
||||||
|
(case tl of
|
||||||
|
tlhd :: tltl =>
|
||||||
|
helpIsNextChrEndOfLine (strIdx, tlhd, tltl)
|
||||||
|
| [] =>
|
||||||
|
(* strIdx is at end of lineGap
|
||||||
|
* which also means at end of line *)
|
||||||
|
true)
|
||||||
|
end
|
||||||
|
| [] => true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user