diff --git a/fcore/cursor-dfa/vi-WORD-dfa.sml b/fcore/cursor-dfa/vi-WORD-dfa.sml index 6662df0..952ab87 100644 --- a/fcore/cursor-dfa/vi-WORD-dfa.sml +++ b/fcore/cursor-dfa/vi-WORD-dfa.sml @@ -108,59 +108,64 @@ struct end end) + fun startOfCurrentWORD (idx, absIdx, str, tl, currentState, counter) = + if idx < 0 then + case tl of + str :: tl => + startOfCurrentWORD + (String.size str - 1, absIdx, str, tl, currentState, counter) + | [] => 0 + else + let + val chr = String.sub (str, idx) + val newState = next (currentState, chr) + in + if newState = spaceAfterNonBlankState then + if counter - 1 = 0 then + absIdx + 1 + else + startOfCurrentWORD + (idx - 1, absIdx - 1, str, tl, startState, counter - 1) + else + startOfCurrentWORD (idx - 1, absIdx - 1, str, tl, newState, counter) + end + + fun endOfCurrentWORD (idx, absIdx, str, tl, currentState, counter) = + if idx = String.size str then + case tl of + str :: tl => + endOfCurrentWORD (0, absIdx, str, tl, currentState, counter) + | [] => Int.max (0, absIdx - 2) + else + let + val chr = String.sub (str, idx) + val newState = next (currentState, chr) + in + if newState = spaceAfterNonBlankState then + if counter - 1 = 0 then + Int.max (0, absIdx - 1) + else + endOfCurrentWORD + (idx + 1, absIdx + 1, str, tl, startState, counter - 1) + else + endOfCurrentWORD (idx + 1, absIdx + 1, str, tl, newState, counter) + end + structure StartOfCurrentWORD = MakePrevDfaLoopMinus1 - (struct - val startState = startState - - fun fStart (idx, absIdx, str, tl, currentState, counter) = - if idx < 0 then - case tl of - str :: tl => - fStart - (String.size str - 1, absIdx, str, tl, currentState, counter) - | [] => 0 - else - let - val chr = String.sub (str, idx) - val newState = next (currentState, chr) - in - if newState = spaceAfterNonBlankState then - if counter - 1 = 0 then - absIdx + 1 - else - fStart - (idx - 1, absIdx - 1, str, tl, startState, counter - 1) - else - fStart (idx - 1, absIdx - 1, str, tl, newState, counter) - end - end) + (struct val startState = startState val fStart = startOfCurrentWORD end) structure EndOfCurrentWORD = MakeNextDfaLoopPlus1 - (struct - val startState = startState + (struct val startState = startState val fStart = endOfCurrentWORD end) - fun fStart (idx, absIdx, str, tl, currentState, counter) = - if idx = String.size str then - case tl of - str :: tl => fStart (0, absIdx, str, tl, currentState, counter) - | [] => Int.max (0, absIdx - 2) - else - let - val chr = String.sub (str, idx) - val newState = next (currentState, chr) - in - if newState = spaceAfterNonBlankState then - if counter - 1 = 0 then - Int.max (0, absIdx - 1) - else - fStart - (idx + 1, absIdx + 1, str, tl, startState, counter - 1) - else - fStart (idx + 1, absIdx + 1, str, tl, newState, counter) - end - end) + structure StartOfNextWORDStrict = + MakePrevDfaLoop + (struct val startState = startState val fStart = startOfCurrentWORD end) + + structure EndOfCurrentWORDStrict = + MakeNextDfaLoop + (struct val startState = startState val fStart = endOfCurrentWORD end) (* W *) val startOfNextWORD = StartOfNextWORD.next @@ -170,4 +175,20 @@ struct val startOfCurrentWORD = StartOfCurrentWORD.prev (* E *) val endOfCurrentWORD = EndOfCurrentWORD.next + + (* functions to strictly get the start and end of the current word. + * Problem: We want to support Vi motions like viW (selects a single word), + * as well as ciW (change one WORD) and diW (delete one WORD). + * + * The 'startOfCurrentWORD' and 'endOfCurrentWORD' functions do this + * (representing the vi 'B' and 'E' commands respectively), + * except that 'B' goes to the previous WORD if the cursor is on the first + * character of the current WORD, and 'E' goes to the next WORD if the cursor + * is on the last character of the current WORD. + * + * What is meant by "strict" is that these below functions always stay + * within the current WORD, not making the two exceptions mentioned above. + *) + val startOfCurrentWORDStrict = StartOfNextWORDStrict.prev + val endOfCurrentWORDStrict = EndOfCurrentWORDStrict.next end diff --git a/fcore/cursor-dfa/vi-word-dfa.sml b/fcore/cursor-dfa/vi-word-dfa.sml index e1321c8..fc0823b 100644 --- a/fcore/cursor-dfa/vi-word-dfa.sml +++ b/fcore/cursor-dfa/vi-word-dfa.sml @@ -147,69 +147,73 @@ struct end end) + fun startOfCurrentWord (idx, absIdx, str, tl, currentState, counter) = + if idx < 0 then + case tl of + str :: tl => + startOfCurrentWord + (String.size str - 1, absIdx, str, tl, currentState, counter) + | [] => 0 + else + let + val chr = String.sub (str, idx) handle _ => (print "156\n"; raise Empty) + val newState = + next (currentState, chr) + handle _ => + (print ("158: " ^ Word8.toString currentState ^ "\n"); raise Empty) + in + if + newState = alphaToSpace orelse newState = punctToSpace + orelse newState = alphaToPunct orelse newState = punctToAlpha + then + if counter - 1 = 0 then + absIdx + 1 + else + startOfCurrentWord + (idx - 1, absIdx - 1, str, tl, startState, counter - 1) + else + startOfCurrentWord (idx - 1, absIdx - 1, str, tl, newState, counter) + end + structure StartOfCurrentWord = MakePrevDfaLoopMinus1 - (struct - val startState = startState + (struct val startState = startState val fStart = startOfCurrentWord end) - fun fStart (idx, absIdx, str, tl, currentState, counter) = - if idx < 0 then - case tl of - str :: tl => - fStart - (String.size str - 1, absIdx, str, tl, currentState, counter) - | [] => 0 - else - let - val chr = String.sub (str, idx) - handle _ => (print "156\n"; raise Empty) - val newState = - next (currentState, chr) - handle _ => - ( print ("158: " ^ Word8.toString currentState ^ "\n") - ; raise Empty - ) - in - if - newState = alphaToSpace orelse newState = punctToSpace - orelse newState = alphaToPunct orelse newState = punctToAlpha - then - if counter - 1 = 0 then - absIdx + 1 - else - fStart - (idx - 1, absIdx - 1, str, tl, startState, counter - 1) - else - fStart (idx - 1, absIdx - 1, str, tl, newState, counter) - end - end) + structure StartOfCurrentWordStrict = + MakePrevDfaLoop + (struct val startState = startState val fStart = startOfCurrentWord end) - structure EndOfCurrentWord = MakeNextDfaLoopPlus1 ( - struct - val startState = startState - - fun fStart (idx, absIdx, str, tl, currentState, counter) = - if idx = String.size str then - case tl of - str :: tl => - fStart (0, absIdx, str, tl, currentState, counter) - | [] => Int.max (0, absIdx - 2) - else - let - val chr = String.sub (str, idx) - val newState = next (currentState, chr) - in - if newState = alphaToSpace orelse newState = punctToSpace - orelse newState = alphaToPunct orelse newState = punctToAlpha then - if counter - 1 = 0 then - absIdx - 1 - else - fStart (idx + 1, absIdx + 1, str, tl, startState, counter - 1) + fun endOfCurrentWord (idx, absIdx, str, tl, currentState, counter) = + if idx = String.size str then + case tl of + str :: tl => + endOfCurrentWord (0, absIdx, str, tl, currentState, counter) + | [] => Int.max (0, absIdx - 2) + else + let + val chr = String.sub (str, idx) + val newState = next (currentState, chr) + in + if + newState = alphaToSpace orelse newState = punctToSpace + orelse newState = alphaToPunct orelse newState = punctToAlpha + then + if counter - 1 = 0 then + absIdx - 1 else - fStart (idx + 1, absIdx + 1, str, tl, newState, counter) - end - end - ) + endOfCurrentWord + (idx + 1, absIdx + 1, str, tl, startState, counter - 1) + else + endOfCurrentWord (idx + 1, absIdx + 1, str, tl, newState, counter) + end + + structure EndOfCurrentWord = + MakeNextDfaLoopPlus1 + (struct val startState = startState val fStart = endOfCurrentWord end) + + structure EndOfCurrentWordStrict = + MakeNextDfaLoop + (struct val startState = startState val fStart = endOfCurrentWord end) (* w *) val startOfNextWord = StartOfNextWord.next @@ -219,4 +223,9 @@ struct val startOfCurrentWord = StartOfCurrentWord.prev (* e *) val endOfCurrentWord = EndOfCurrentWord.next + + (* the meaning of "Strict" and the utility of these two functions + * is described in vi-WORD-dfa.sml *) + val startOfCurrentWordStrict = StartOfCurrentWordStrict.prev + val endOfCurrentWordStrict = EndOfCurrentWordStrict.next end