add WORD motions (as opposed to word motions)

This commit is contained in:
2024-10-25 21:01:48 +01:00
parent c2ea6e5e04
commit a198840961
3 changed files with 240 additions and 10 deletions

View File

@@ -132,6 +132,22 @@ struct
in
(newApp, drawMsg)
end
fun nextWORD (app: app_type) =
let
val {buffer, windowWidth, windowHeight, startLine, cursorIdx, ...} = app
val buffer = LineGap.goToIdx (cursorIdx, buffer)
val cursorIdx = Cursor.nextWORD (buffer, cursorIdx)
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
fun prevWord (app: app_type) =
let
@@ -149,6 +165,22 @@ struct
(newApp, drawMsg)
end
fun prevWORD (app: app_type) =
let
val {buffer, windowWidth, windowHeight, startLine, cursorIdx, ...} = app
val buffer = LineGap.goToIdx (cursorIdx, buffer)
val cursorIdx = Cursor.prevWORD (buffer, cursorIdx)
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
fun endOfWord (app: app_type) =
let
val {buffer, windowWidth, windowHeight, startLine, cursorIdx, ...} = app
@@ -165,6 +197,23 @@ struct
(newApp, drawMsg)
end
fun endOfWORD (app: app_type) =
let
val {buffer, windowWidth, windowHeight, startLine, cursorIdx, ...} = app
val buffer = LineGap.goToIdx (cursorIdx, buffer)
val cursorIdx = Cursor.endOfWORD (buffer, cursorIdx)
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
fun handleChr (app: app_type, chr) =
case chr of
#"h" => moveLeft app
@@ -174,8 +223,11 @@ struct
| #"0" => moveToLineStart app
| #"$" => moveToLineEnd app
| #"w" => nextWord app
| #"W" => nextWORD app
| #"b" => prevWord app
| #"B" => prevWORD app
| #"e" => endOfWord app
| #"E" => endOfWORD app
| _ => (app, [])
fun update (app, msg) =

View File

@@ -921,8 +921,10 @@ struct
val chr = String.sub (str, strPos)
in
if Char.isAlphaNum chr orelse chr = #"_" then
if isNextChrNonBlank (strPos, str, strTl) then absIdx + 1
else helpNextWord (strPos + 1, str, absIdx + 1, strTl, lineTl)
if isNextChrNonBlank (strPos, str, strTl) then
absIdx + 1
else
helpNextWord (strPos + 1, str, absIdx + 1, strTl, lineTl)
else if Char.isSpace chr then
if notIsNextChrSpace (strPos, str, strTl) then
absIdx + 1
@@ -932,14 +934,11 @@ struct
else
(* chr is NON_BLANK. *)
if isNextChrAlphaNum (strPos, str, strTl) then
absIdx + 1
else
helpNextWord (strPos + 1, str, absIdx + 1, strTl, lineTl)
absIdx + 1
else
helpNextWord (strPos + 1, str, absIdx + 1, strTl, lineTl)
end
fun startNextWord (shd, strIdx, absIdx, stl, ltl) =
helpNextWord (strIdx, shd, absIdx, stl, ltl)
fun nextWord (lineGap: LineGap.t, cursorIdx) =
let
val {rightStrings, rightLines, idx = bufferIdx, ...} = lineGap
@@ -952,13 +951,62 @@ struct
in
if strIdx < String.size shd then
(* strIdx is in this string *)
startNextWord (shd, strIdx, cursorIdx, stl, ltl)
helpNextWord (strIdx, shd, cursorIdx, stl, ltl)
else
(* strIdx is in tl *)
(case (stl, ltl) of
(stlhd :: stltl, ltlhd :: ltltl) =>
let val strIdx = strIdx - String.size shd
in startNextWord (stlhd, strIdx, cursorIdx, stltl, ltltl)
in helpNextWord (strIdx, shd, cursorIdx, stl, ltl)
end
| (_, _) => cursorIdx)
end
| (_, _) => cursorIdx
end
fun helpNextWORD (strPos, str, absIdx, strTl, lineTl) =
if strPos = String.size str then
case (strTl, lineTl) of
(shd :: stl, lhd :: ltl) =>
helpNextWORD (0, shd, absIdx, stl, ltl)
| (_, _) =>
(* reached end of lineGap;
* return last valid chr position *)
absIdx - 1
else
let
val chr = String.sub (str, strPos)
in
if Char.isSpace chr then
if notIsNextChrSpace (strPos, str, strTl) then
absIdx + 1
else
helpNextWORD (strPos + 1, str, absIdx + 1, strTl, lineTl)
else
helpNextWORD (strPos + 1, str, absIdx + 1, strTl, lineTl)
end
(* equivalent of vi's W,
* which goes to next WORD rather than word *)
fun nextWORD (lineGap: LineGap.t, cursorIdx) =
let
val {rightStrings, rightLines, idx = bufferIdx, ...} = 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 this string *)
helpNextWORD (strIdx, shd, cursorIdx, stl, ltl)
else
(* strIdx is in tl *)
(case (stl, ltl) of
(stlhd :: stltl, ltlhd :: ltltl) =>
let val strIdx = strIdx - String.size shd
in helpNextWORD (strIdx, shd, cursorIdx, stl, ltl)
end
| (_, _) => cursorIdx)
end
@@ -1048,6 +1096,79 @@ struct
| (_, _) => cursorIdx
end
fun helpPrevWORD (strPos, str, absIdx, strTl, lineTl) =
if strPos < 0 then
case (strTl, lineTl) of
(shd :: stl, lhd :: ltl) =>
helpPrevWORD (String.size shd - 1, shd, absIdx, stl, ltl)
| (_, _) =>
(* reached start of lineGap;
* return 0 which is start idx *)
0
else
let
val chr = String.sub (str, strPos)
in
if Char.isSpace chr then
helpPrevWORD
(strPos - 1, str, absIdx - 1, strTl, lineTl)
else
if isPrevChrSpace (strPos, str, strTl) then
absIdx
else
helpPrevWORD
(strPos - 1, str, absIdx - 1, strTl, lineTl)
end
fun startPrevWORD (shd, strIdx, absIdx, stl, ltl) =
(* we want to start iterating from previous character
* and ignore the character the cursor is at
* so check previous character *)
if strIdx > 0 then
helpPrevWORD (strIdx - 1, shd, absIdx - 1, stl, ltl)
else
case (stl, ltl) of
(stlhd :: stltl, ltlhd :: ltltl) =>
let val prevIdx = String.size stlhd - 1
in helpPrevWORD (prevIdx, stlhd, absIdx - 1, stltl, ltltl)
end
| (_, _) =>
(* tl is empty; just return idx 0 *)
0
(* equivalent of vi's `B` command *)
fun prevWORD (lineGap: LineGap.t, cursorIdx) =
let
val
{rightStrings, rightLines, leftStrings, leftLines, idx = bufferIdx, ...} =
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 this string *)
startPrevWORD (shd, strIdx, cursorIdx, leftStrings, leftLines)
else
(* strIdx is in tl *)
(case (stl, ltl) of
(stlhd :: stltl, ltlhd :: ltltl) =>
let
val strIdx = strIdx - String.size shd
val leftStrings = shd :: leftStrings
val leftLines = lhd :: leftLines
in
startPrevWORD
(stlhd, strIdx, cursorIdx, leftStrings, leftLines)
end
| (_, _) => cursorIdx)
end
| (_, _) => cursorIdx
end
fun helpEndOfWord (strPos, str, absIdx, stl, ltl) =
if strPos = String.size str then
case (stl, ltl) of
@@ -1116,4 +1237,61 @@ struct
end
| (_, _) => cursorIdx
end
fun helpEndOfWORD (strPos, str, absIdx, stl, ltl) =
if strPos = String.size str then
case (stl, ltl) of
(shd :: stl, lhd :: ltl) => helpEndOfWORD (0, shd, absIdx, stl, ltl)
| (_, _) => absIdx - 1
else
let
val chr = String.sub (str, strPos)
in
if Char.isSpace chr then
helpEndOfWORD (strPos + 1, str, absIdx + 1, stl, ltl)
else
if isNextChrSpace (strPos, str, stl) then
absIdx
else
helpEndOfWORD (strPos + 1, str, absIdx + 1, stl, ltl)
end
fun startEndOfWORD (shd, strIdx, absIdx, stl, ltl) =
(* we want to start iterating from next char after strIdx *)
if strIdx - 1 < String.size shd then
helpEndOfWORD (strIdx + 1, shd, absIdx + 1, stl, ltl)
else
case (stl, ltl) of
(stlhd :: stltl, ltlhd :: ltltl) =>
helpEndOfWORD (0, stlhd, absIdx + 1, stltl, ltltl)
| (_, _) =>
(* tl is empty; just return absIdx *)
absIdx
(* equivalent of vi's `E` command *)
fun endOfWORD (lineGap: LineGap.t, cursorIdx) =
let
val
{rightStrings, rightLines, leftStrings, leftLines, idx = bufferIdx, ...} =
lineGap
in
case (rightStrings, rightLines) of
(shd :: stl, lhd :: ltl) =>
let
val strIdx = cursorIdx - bufferIdx
in
if strIdx < String.size shd then
(* strIdx is in this string *)
startEndOfWORD (shd, strIdx, cursorIdx, rightStrings, rightLines)
else
(* strIdx is in tl *)
(case (stl, ltl) of
(stlhd :: stltl, ltlhd :: ltltl) =>
let val strIdx = strIdx - String.size shd
in startEndOfWORD (stlhd, strIdx, cursorIdx, stltl, ltltl)
end
| (_, _) => cursorIdx)
end
| (_, _) => cursorIdx
end
end

BIN
shf

Binary file not shown.