import { Position , TextDocument } from 'vscode' ; export enum CharacterClass { REGULAR = 0 , WORD_SEPARATOR = 1 , WHITESPACE = 2 } export enum WordType { NONE = 0 , SEPARATOR = 1 , REGULAR = 2 } export type WordCharacters = CharacterClass [ ] ; export interface IWord { start : number ; end : number ; wordType : WordType ; } export class Words { public static createWordCharacters ( wordSeparators ) { const result = [ ] ; for ( let chCode = 0 ; chCode < 256 ; chCode ++ ) { result [ chCode ] = CharacterClass . REGULAR ; } for ( let i = 0 , len = wordSeparators . length ; i < len ; i ++ ) { result [ wordSeparators . charCodeAt ( i ) ] = CharacterClass . WORD_SEPARATOR ; } result [ ' ' . charCodeAt ( 0 ) ] = CharacterClass . WHITESPACE ; result [ '\t' . charCodeAt ( 0 ) ] = CharacterClass . WHITESPACE ; return result ; } public static findNextWord ( doc , pos , wordCharacterClass ) { const lineContent = doc . lineAt ( pos . line ) . text ; let wordType = WordType . NONE ; const len = lineContent . length ; for ( let chIndex = pos . character ; chIndex < len ; chIndex ++ ) { const chCode = lineContent . charCodeAt ( chIndex ) ; const chClass = ( wordCharacterClass [ chCode ] || CharacterClass . REGULAR ) ; if ( chClass === CharacterClass . REGULAR ) { if ( wordType === WordType . SEPARATOR ) { return this . _createWord ( lineContent , wordType , this . _findStartOfWord ( lineContent , wordCharacterClass , wordType , chIndex - 1 ) , chIndex ) ; } wordType = WordType . REGULAR ; } else if ( chClass === CharacterClass . WORD_SEPARATOR ) { if ( wordType === WordType . REGULAR ) { return this . _createWord ( lineContent , wordType , this . _findStartOfWord ( lineContent , wordCharacterClass , wordType , chIndex - 1 ) , chIndex ) ; } wordType = WordType . SEPARATOR ; } else if ( chClass === CharacterClass . WHITESPACE ) { if ( wordType !== WordType . NONE ) { return this . _createWord ( lineContent , wordType , this . _findStartOfWord ( lineContent , wordCharacterClass , wordType , chIndex - 1 ) , chIndex ) ; } } } if ( wordType !== WordType . NONE ) { return this . _createWord ( lineContent , wordType , this . _findStartOfWord ( lineContent , wordCharacterClass , wordType , len - 1 ) , len ) ; } return null ; } private static _findStartOfWord ( lineContent , wordCharacterClass , wordType , startIndex ) { for ( let chIndex = startIndex ; chIndex >= 0 ; chIndex -- ) { const chCode = lineContent . charCodeAt ( chIndex ) ; const chClass = ( wordCharacterClass [ chCode ] || CharacterClass . REGULAR ) ; if ( chClass === CharacterClass . WHITESPACE ) { return chIndex + 1 ; } if ( wordType === WordType . REGULAR && chClass === CharacterClass . WORD_SEPARATOR ) { return chIndex + 1 ; } if ( wordType === WordType . SEPARATOR && chClass === CharacterClass . REGULAR ) { return chIndex + 1 ; } } return 0 ; } private static _createWord ( lineContent , wordType , start , end ) { return { start : start , end : end , wordType : wordType } ; } }