@@ -128,12 +128,35 @@ export function moveVertical(
128128 * In normal mode, cursor should never go past the last character.
129129 */
130130export function moveWordForward ( text : string , cursor : number ) : number {
131- let i = cursor ;
132131 const n = text . length ;
133- while ( i < n && / [ A - Z a - z 0 - 9 _ ] / . test ( text [ i ] ) ) i ++ ;
134- while ( i < n && / \s / . test ( text [ i ] ) ) i ++ ;
135- // Clamp to last character position in normal mode (never past the end)
136- return Math . min ( i , Math . max ( 0 , n - 1 ) ) ;
132+ if ( n === 0 ) return 0 ;
133+
134+ let i = Math . max ( 0 , Math . min ( cursor , n - 1 ) ) ;
135+ const isWord = ( ch : string ) => / [ A - Z a - z 0 - 9 _ ] / . test ( ch ) ;
136+
137+ const advancePastWord = ( idx : number ) : number => {
138+ let j = idx ;
139+ while ( j < n && isWord ( text [ j ] ) ) j ++ ;
140+ return j ;
141+ } ;
142+
143+ const advanceToWord = ( idx : number ) : number => {
144+ let j = idx ;
145+ while ( j < n && ! isWord ( text [ j ] ) ) j ++ ;
146+ return j ;
147+ } ;
148+
149+ if ( isWord ( text [ i ] ) ) {
150+ i = advancePastWord ( i ) ;
151+ }
152+
153+ i = advanceToWord ( i ) ;
154+
155+ if ( i >= n ) {
156+ return Math . max ( 0 , n - 1 ) ;
157+ }
158+
159+ return i ;
137160}
138161
139162/**
@@ -144,32 +167,34 @@ export function moveWordForward(text: string, cursor: number): number {
144167 */
145168export function moveWordEnd ( text : string , cursor : number ) : number {
146169 const n = text . length ;
170+ if ( n === 0 ) return 0 ;
147171 if ( cursor >= n - 1 ) return Math . max ( 0 , n - 1 ) ;
148172
149- let i = cursor ;
173+ const clamp = Math . max ( 0 , Math . min ( cursor , n - 1 ) ) ;
150174 const isWord = ( ch : string ) => / [ A - Z a - z 0 - 9 _ ] / . test ( ch ) ;
151175
152- // If on a word char, check if we're at the end of it
153- if ( isWord ( text [ i ] ) ) {
154- // If next char is not a word char, we're at the end - move to next word
155- if ( i < n - 1 && ! isWord ( text [ i + 1 ] ) ) {
156- // Skip whitespace to find next word
157- i ++ ;
158- while ( i < n - 1 && ! isWord ( text [ i ] ) ) i ++ ;
159- // Move to end of next word
160- while ( i < n - 1 && isWord ( text [ i + 1 ] ) ) i ++ ;
161- return i ;
162- }
163- // Not at end yet, move to end of current word
176+ if ( ! isWord ( text [ clamp ] ) ) {
177+ let i = clamp ;
178+ while ( i < n && ! isWord ( text [ i ] ) ) i ++ ;
179+ if ( i >= n ) return Math . max ( 0 , n - 1 ) ;
164180 while ( i < n - 1 && isWord ( text [ i + 1 ] ) ) i ++ ;
165181 return i ;
166182 }
167183
168- // If on whitespace, skip to next word then go to its end
169- while ( i < n - 1 && ! isWord ( text [ i ] ) ) i ++ ;
170- while ( i < n - 1 && isWord ( text [ i + 1 ] ) ) i ++ ;
184+ let endOfCurrent = clamp ;
185+ while ( endOfCurrent < n - 1 && isWord ( text [ endOfCurrent + 1 ] ) ) endOfCurrent ++ ;
186+
187+ if ( clamp < endOfCurrent ) {
188+ return endOfCurrent ;
189+ }
190+
191+ let j = endOfCurrent + 1 ;
192+ while ( j < n && ! isWord ( text [ j ] ) ) j ++ ;
193+ if ( j >= n ) return Math . max ( 0 , n - 1 ) ;
171194
172- return Math . min ( i , Math . max ( 0 , n - 1 ) ) ;
195+ let endOfNext = j ;
196+ while ( endOfNext < n - 1 && isWord ( text [ endOfNext + 1 ] ) ) endOfNext ++ ;
197+ return endOfNext ;
173198}
174199
175200/**
0 commit comments