pass higher order function to word motions, for less code duplication
This commit is contained in:
200
fcore/cursor.sml
200
fcore/cursor.sml
@@ -443,9 +443,7 @@ struct
|
|||||||
else
|
else
|
||||||
case String.sub (str, strPos) of
|
case String.sub (str, strPos) of
|
||||||
#"\n" =>
|
#"\n" =>
|
||||||
if
|
if hasPassedLine then
|
||||||
hasPassedLine
|
|
||||||
then
|
|
||||||
(* reached end of line twice,
|
(* reached end of line twice,
|
||||||
* but line has fewer chars than preferredColumn
|
* but line has fewer chars than preferredColumn
|
||||||
* note: if in double \n\n linebreak,
|
* note: if in double \n\n linebreak,
|
||||||
@@ -939,31 +937,6 @@ struct
|
|||||||
helpNextWord (strPos + 1, str, absIdx + 1, strTl, lineTl)
|
helpNextWord (strPos + 1, str, absIdx + 1, strTl, lineTl)
|
||||||
end
|
end
|
||||||
|
|
||||||
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
|
|
||||||
| (_, _) => cursorIdx
|
|
||||||
end
|
|
||||||
|
|
||||||
fun helpNextWORD (strPos, str, absIdx, strTl, lineTl) =
|
fun helpNextWORD (strPos, str, absIdx, strTl, lineTl) =
|
||||||
if strPos = String.size str then
|
if strPos = String.size str then
|
||||||
case (strTl, lineTl) of
|
case (strTl, lineTl) of
|
||||||
@@ -986,9 +959,7 @@ struct
|
|||||||
helpNextWORD (strPos + 1, str, absIdx + 1, strTl, lineTl)
|
helpNextWORD (strPos + 1, str, absIdx + 1, strTl, lineTl)
|
||||||
end
|
end
|
||||||
|
|
||||||
(* equivalent of vi's W,
|
fun toNextWord (lineGap: LineGap.t, cursorIdx, fNext) =
|
||||||
* which goes to next WORD rather than word *)
|
|
||||||
fun nextWORD (lineGap: LineGap.t, cursorIdx) =
|
|
||||||
let
|
let
|
||||||
val {rightStrings, rightLines, idx = bufferIdx, ...} = lineGap
|
val {rightStrings, rightLines, idx = bufferIdx, ...} = lineGap
|
||||||
in
|
in
|
||||||
@@ -1000,19 +971,27 @@ struct
|
|||||||
in
|
in
|
||||||
if strIdx < String.size shd then
|
if strIdx < String.size shd then
|
||||||
(* strIdx is in this string *)
|
(* strIdx is in this string *)
|
||||||
helpNextWORD (strIdx, shd, cursorIdx, stl, ltl)
|
fNext (strIdx, shd, cursorIdx, stl, ltl)
|
||||||
else
|
else
|
||||||
(* strIdx is in tl *)
|
(* strIdx is in tl *)
|
||||||
(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 helpNextWORD (strIdx, shd, cursorIdx, stl, ltl)
|
in fNext (strIdx, shd, cursorIdx, stl, ltl)
|
||||||
end
|
end
|
||||||
| (_, _) => cursorIdx)
|
| (_, _) => cursorIdx)
|
||||||
end
|
end
|
||||||
| (_, _) => cursorIdx
|
| (_, _) => cursorIdx
|
||||||
end
|
end
|
||||||
|
|
||||||
|
(* equivalent 'f vi's 'w' command *)
|
||||||
|
fun nextWord (lineGap, cursorIdx) =
|
||||||
|
toNextWord (lineGap, cursorIdx, helpNextWord)
|
||||||
|
|
||||||
|
(* equivalent 'f vi's 'W' command *)
|
||||||
|
fun nextWORD (lineGap, cursorIdx) =
|
||||||
|
toNextWord (lineGap, cursorIdx, helpNextWORD)
|
||||||
|
|
||||||
fun helpPrevWord (strPos, str, absIdx, strTl, lineTl) =
|
fun helpPrevWord (strPos, str, absIdx, strTl, lineTl) =
|
||||||
if strPos < 0 then
|
if strPos < 0 then
|
||||||
case (strTl, lineTl) of
|
case (strTl, lineTl) of
|
||||||
@@ -1026,16 +1005,12 @@ struct
|
|||||||
let
|
let
|
||||||
val chr = String.sub (str, strPos)
|
val chr = String.sub (str, strPos)
|
||||||
in
|
in
|
||||||
if
|
if Char.isAlphaNum chr orelse chr = #"_" then
|
||||||
Char.isAlphaNum chr orelse chr = #"_"
|
|
||||||
then
|
|
||||||
if isPrevChrSpace (strPos, str, strTl)
|
if isPrevChrSpace (strPos, str, strTl)
|
||||||
orelse isPrevChrNonBlank (strPos, str, strTl)
|
orelse isPrevChrNonBlank (strPos, str, strTl)
|
||||||
then absIdx
|
then absIdx
|
||||||
else helpPrevWord (strPos - 1, str, absIdx - 1, strTl, lineTl)
|
else helpPrevWord (strPos - 1, str, absIdx - 1, strTl, lineTl)
|
||||||
else if
|
else if Char.isSpace chr then
|
||||||
Char.isSpace chr
|
|
||||||
then
|
|
||||||
helpPrevWord (strPos - 1, str, absIdx - 1, strTl, lineTl)
|
helpPrevWord (strPos - 1, str, absIdx - 1, strTl, lineTl)
|
||||||
else
|
else
|
||||||
(* is NON_BLANK *)
|
(* is NON_BLANK *)
|
||||||
@@ -1047,55 +1022,6 @@ struct
|
|||||||
helpPrevWord (strPos - 1, str, absIdx - 1, strTl, lineTl)
|
helpPrevWord (strPos - 1, str, absIdx - 1, strTl, lineTl)
|
||||||
end
|
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 helpPrevWORD (strPos, str, absIdx, strTl, lineTl) =
|
fun helpPrevWORD (strPos, str, absIdx, strTl, lineTl) =
|
||||||
if strPos < 0 then
|
if strPos < 0 then
|
||||||
case (strTl, lineTl) of
|
case (strTl, lineTl) of
|
||||||
@@ -1120,24 +1046,23 @@ struct
|
|||||||
(strPos - 1, str, absIdx - 1, strTl, lineTl)
|
(strPos - 1, str, absIdx - 1, strTl, lineTl)
|
||||||
end
|
end
|
||||||
|
|
||||||
fun startPrevWORD (shd, strIdx, absIdx, stl, ltl) =
|
fun startPrevWord (shd, strIdx, absIdx, stl, ltl, fPrev) =
|
||||||
(* we want to start iterating from previous character
|
(* we want to start iterating from previous character
|
||||||
* and ignore the character the cursor is at
|
* and ignore the character the cursor is at
|
||||||
* so check previous character *)
|
* so check previous character *)
|
||||||
if strIdx > 0 then
|
if strIdx > 0 then
|
||||||
helpPrevWORD (strIdx - 1, shd, absIdx - 1, stl, ltl)
|
fPrev (strIdx - 1, shd, absIdx - 1, stl, ltl)
|
||||||
else
|
else
|
||||||
case (stl, ltl) of
|
case (stl, ltl) of
|
||||||
(stlhd :: stltl, ltlhd :: ltltl) =>
|
(stlhd :: stltl, ltlhd :: ltltl) =>
|
||||||
let val prevIdx = String.size stlhd - 1
|
let val prevIdx = String.size stlhd - 1
|
||||||
in helpPrevWORD (prevIdx, stlhd, absIdx - 1, stltl, ltltl)
|
in fPrev (prevIdx, stlhd, absIdx - 1, stltl, ltltl)
|
||||||
end
|
end
|
||||||
| (_, _) =>
|
| (_, _) =>
|
||||||
(* tl is empty; just return idx 0 *)
|
(* tl is empty; just return idx 0 *)
|
||||||
0
|
0
|
||||||
|
|
||||||
(* equivalent of vi's `B` command *)
|
fun toPrevWord (lineGap: LineGap.t, cursorIdx, fPrev) =
|
||||||
fun prevWORD (lineGap: LineGap.t, cursorIdx) =
|
|
||||||
let
|
let
|
||||||
val
|
val
|
||||||
{rightStrings, rightLines, leftStrings, leftLines, idx = bufferIdx, ...} =
|
{rightStrings, rightLines, leftStrings, leftLines, idx = bufferIdx, ...} =
|
||||||
@@ -1151,7 +1076,8 @@ struct
|
|||||||
in
|
in
|
||||||
if strIdx < String.size shd then
|
if strIdx < String.size shd then
|
||||||
(* strIdx is in this string *)
|
(* strIdx is in this string *)
|
||||||
startPrevWORD (shd, strIdx, cursorIdx, leftStrings, leftLines)
|
startPrevWord
|
||||||
|
(shd, strIdx, cursorIdx, leftStrings, leftLines, fPrev)
|
||||||
else
|
else
|
||||||
(* strIdx is in tl *)
|
(* strIdx is in tl *)
|
||||||
(case (stl, ltl) of
|
(case (stl, ltl) of
|
||||||
@@ -1161,14 +1087,22 @@ struct
|
|||||||
val leftStrings = shd :: leftStrings
|
val leftStrings = shd :: leftStrings
|
||||||
val leftLines = lhd :: leftLines
|
val leftLines = lhd :: leftLines
|
||||||
in
|
in
|
||||||
startPrevWORD
|
startPrevWord
|
||||||
(stlhd, strIdx, cursorIdx, leftStrings, leftLines)
|
(stlhd, strIdx, cursorIdx, leftStrings, leftLines, fPrev)
|
||||||
end
|
end
|
||||||
| (_, _) => cursorIdx)
|
| (_, _) => cursorIdx)
|
||||||
end
|
end
|
||||||
| (_, _) => cursorIdx
|
| (_, _) => cursorIdx
|
||||||
end
|
end
|
||||||
|
|
||||||
|
(* equivalent of vi's 'b' command *)
|
||||||
|
fun prevWord (lineGap, cursorIdx) =
|
||||||
|
toPrevWord (lineGap, cursorIdx, helpPrevWord)
|
||||||
|
|
||||||
|
(* equivalent of vi's 'B' command *)
|
||||||
|
fun prevWORD (lineGap, cursorIdx) =
|
||||||
|
toPrevWord (lineGap, cursorIdx, helpPrevWORD)
|
||||||
|
|
||||||
fun helpEndOfWord (strPos, str, absIdx, stl, ltl) =
|
fun helpEndOfWord (strPos, str, absIdx, stl, ltl) =
|
||||||
if strPos = String.size str then
|
if strPos = String.size str then
|
||||||
case (stl, ltl) of
|
case (stl, ltl) of
|
||||||
@@ -1178,16 +1112,12 @@ struct
|
|||||||
let
|
let
|
||||||
val chr = String.sub (str, strPos)
|
val chr = String.sub (str, strPos)
|
||||||
in
|
in
|
||||||
if
|
if Char.isAlphaNum chr orelse chr = #"_" then
|
||||||
Char.isAlphaNum chr orelse chr = #"_"
|
|
||||||
then
|
|
||||||
if isNextChrSpace (strPos, str, stl)
|
if isNextChrSpace (strPos, str, stl)
|
||||||
orelse isNextChrNonBlank (strPos, str, stl)
|
orelse isNextChrNonBlank (strPos, str, stl)
|
||||||
then absIdx
|
then absIdx
|
||||||
else helpEndOfWord (strPos + 1, str, absIdx + 1, stl, ltl)
|
else helpEndOfWord (strPos + 1, str, absIdx + 1, stl, ltl)
|
||||||
else if
|
else if Char.isSpace chr then
|
||||||
Char.isSpace chr
|
|
||||||
then
|
|
||||||
helpEndOfWord (strPos + 1, str, absIdx + 1, stl, ltl)
|
helpEndOfWord (strPos + 1, str, absIdx + 1, stl, ltl)
|
||||||
else
|
else
|
||||||
(* is NON_BLANK *)
|
(* is NON_BLANK *)
|
||||||
@@ -1199,45 +1129,6 @@ struct
|
|||||||
helpEndOfWord (strPos + 1, str, absIdx + 1, stl, ltl)
|
helpEndOfWord (strPos + 1, str, absIdx + 1, stl, ltl)
|
||||||
end
|
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
|
|
||||||
|
|
||||||
fun helpEndOfWORD (strPos, str, absIdx, stl, ltl) =
|
fun helpEndOfWORD (strPos, str, absIdx, stl, ltl) =
|
||||||
if strPos = String.size str then
|
if strPos = String.size str then
|
||||||
case (stl, ltl) of
|
case (stl, ltl) of
|
||||||
@@ -1256,20 +1147,19 @@ struct
|
|||||||
helpEndOfWORD (strPos + 1, str, absIdx + 1, stl, ltl)
|
helpEndOfWORD (strPos + 1, str, absIdx + 1, stl, ltl)
|
||||||
end
|
end
|
||||||
|
|
||||||
fun startEndOfWORD (shd, strIdx, absIdx, stl, ltl) =
|
fun startEndOfWord (shd, strIdx, absIdx, stl, ltl, fEnd) =
|
||||||
(* we want to start iterating from next char after strIdx *)
|
(* we want to start iterating from next char after strIdx *)
|
||||||
if strIdx - 1 < String.size shd then
|
if strIdx - 1 < String.size shd then
|
||||||
helpEndOfWORD (strIdx + 1, shd, absIdx + 1, stl, ltl)
|
fEnd (strIdx + 1, shd, absIdx + 1, stl, ltl)
|
||||||
else
|
else
|
||||||
case (stl, ltl) of
|
case (stl, ltl) of
|
||||||
(stlhd :: stltl, ltlhd :: ltltl) =>
|
(stlhd :: stltl, ltlhd :: ltltl) =>
|
||||||
helpEndOfWORD (0, stlhd, absIdx + 1, stltl, ltltl)
|
fEnd (0, stlhd, absIdx + 1, stltl, ltltl)
|
||||||
| (_, _) =>
|
| (_, _) =>
|
||||||
(* tl is empty; just return absIdx *)
|
(* tl is empty; just return absIdx *)
|
||||||
absIdx
|
absIdx
|
||||||
|
|
||||||
(* equivalent of vi's `E` command *)
|
fun toEndOfWord (lineGap: LineGap.t, cursorIdx, fEnd) =
|
||||||
fun endOfWORD (lineGap: LineGap.t, cursorIdx) =
|
|
||||||
let
|
let
|
||||||
val
|
val
|
||||||
{rightStrings, rightLines, leftStrings, leftLines, idx = bufferIdx, ...} =
|
{rightStrings, rightLines, leftStrings, leftLines, idx = bufferIdx, ...} =
|
||||||
@@ -1282,16 +1172,28 @@ struct
|
|||||||
in
|
in
|
||||||
if strIdx < String.size shd then
|
if strIdx < String.size shd then
|
||||||
(* strIdx is in this string *)
|
(* strIdx is in this string *)
|
||||||
startEndOfWORD (shd, strIdx, cursorIdx, rightStrings, rightLines)
|
startEndOfWord
|
||||||
|
(shd, strIdx, cursorIdx, rightStrings, rightLines, fEnd)
|
||||||
else
|
else
|
||||||
(* strIdx is in tl *)
|
(* strIdx is in tl *)
|
||||||
(case (stl, ltl) of
|
(case (stl, ltl) of
|
||||||
(stlhd :: stltl, ltlhd :: ltltl) =>
|
(stlhd :: stltl, ltlhd :: ltltl) =>
|
||||||
let val strIdx = strIdx - String.size shd
|
let
|
||||||
in startEndOfWORD (stlhd, strIdx, cursorIdx, stltl, ltltl)
|
val strIdx = strIdx - String.size shd
|
||||||
|
in
|
||||||
|
startEndOfWord
|
||||||
|
(stlhd, strIdx, cursorIdx, stltl, ltltl, fEnd)
|
||||||
end
|
end
|
||||||
| (_, _) => cursorIdx)
|
| (_, _) => cursorIdx)
|
||||||
end
|
end
|
||||||
| (_, _) => cursorIdx
|
| (_, _) => cursorIdx
|
||||||
end
|
end
|
||||||
|
|
||||||
|
(* equivalent of vi's `e` command *)
|
||||||
|
fun endOfWord (lineGap, cursorIdx) =
|
||||||
|
toEndOfWord (lineGap, cursorIdx, helpEndOfWord)
|
||||||
|
|
||||||
|
(* equivalent of vi's `E` command *)
|
||||||
|
fun endOfWORD (lineGap, cursorIdx) =
|
||||||
|
toEndOfWord (lineGap, cursorIdx, helpEndOfWORD)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user