diff --git a/fcore/cursor-dfa/make-dfa-loop.sml b/fcore/cursor-dfa/make-dfa-loop.sml index 2493804..30cebc3 100644 --- a/fcore/cursor-dfa/make-dfa-loop.sml +++ b/fcore/cursor-dfa/make-dfa-loop.sml @@ -61,3 +61,24 @@ struct | [] => cursorIdx end end + +functor MakePrevDfaLoopMinus1(M: MAKE_DFA_LOOP) = +struct + fun prev (lineGap: LineGap.t, cursorIdx) = + let + val {idx = bufferIdx, leftStrings, ...} = lineGap + val strIdx = cursorIdx - bufferIdx - 1 + val absIdx = cursorIdx - 1 + in + if strIdx < 0 then + case leftStrings of + lhd :: ltl => + M.fStart (String.size lhd - 1, absIdx, lhd, ltl, M.startState, 1) + | [] => 0 + else + case #rightStrings lineGap of + rhd :: _ => + M.fStart (strIdx, absIdx, rhd, leftStrings, M.startState, 1) + | [] => Int.max (0, cursorIdx - 2) + end +end diff --git a/fcore/cursor-dfa/vi-WORD-dfa.sml b/fcore/cursor-dfa/vi-WORD-dfa.sml index b19b835..f661f60 100644 --- a/fcore/cursor-dfa/vi-WORD-dfa.sml +++ b/fcore/cursor-dfa/vi-WORD-dfa.sml @@ -108,52 +108,35 @@ struct end 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) + val startOfNextWORD = StartOfNextWORD.next val endOfPrevWORD = EndOfPrevWORD.prev - - fun loopStartOfCurrentWORD (idx, absIdx, str, tl, currentState, counter) = - if idx < 0 then - case tl of - str :: tl => - loopStartOfCurrentWORD - (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 - loopStartOfCurrentWORD - (idx - 1, absIdx - 1, str, tl, startState, counter - 1) - else - loopStartOfCurrentWORD - (idx - 1, absIdx - 1, str, tl, newState, counter) - end - - (* we do not rely on MakeDfaLoop functor because we want to - * ignore the character the cursor is currently on, - * and start tracking state from the character before the current one. *) - fun startOfCurrentWORD (lineGap: LineGap.t, cursorIdx) = - let - val {idx = bufferIdx, leftStrings, ...} = lineGap - val strIdx = cursorIdx - bufferIdx - 1 - val absIdx = cursorIdx - 1 - in - if strIdx < 0 then - case leftStrings of - lhd :: ltl => - loopStartOfCurrentWORD - (String.size lhd - 1, absIdx, lhd, ltl, startState, 1) - | [] => 0 - else - case #rightStrings lineGap of - rhd :: _ => - loopStartOfCurrentWORD - (strIdx, absIdx, rhd, leftStrings, startState, 1) - | [] => Int.max (0, cursorIdx - 2) - end + val startOfCurrentWORD = StartOfCurrentWORD.prev end