import { Command } from '../../command/types' ; import { MatchedCommand , MatchedCommands } from './types' ; const findNextQuote = ( text , quote , startPosition ) : number => { const index = text . indexOf ( quote , startPosition ) ; if ( index === - 1 ) { return index ; } else if ( text . substring ( index - 1 , 1 ) === '\\' ) { return findNextQuote ( text , quote , index + 1 ) ; } else { return index ; } } ; const matchFreeTextCommandUnderQuotes = ( commandText , freeTextCommand , quote ) : MatchedCommand => { const index = findNextQuote ( commandText , quote , 1 ) ; if ( index === - 1 ) { return { command : { ... freeTextCommand , command : commandText . trim ( ) } , left : '' } ; } else { let realCommand = commandText . substring ( 0 , index ) ; if ( realCommand . startsWith ( quote ) ) { realCommand = realCommand . substring ( 1 ) ; } return { command : { ... freeTextCommand , command : realCommand } , left : commandText . substring ( index + 1 ) } ; } } ; const matchFreeTextCommand = ( commandText , startCommand ) : MatchedCommand => { const freeTextCommand = startCommand . trails . find ( cmd => cmd . command === '' ) ; if ( freeTextCommand ) { if ( commandText . startsWith ( '"' ) ) { return matchFreeTextCommandUnderQuotes ( commandText , freeTextCommand , '"' ) ; } else if ( commandText . startsWith ( '\'' ) ) { return matchFreeTextCommandUnderQuotes ( commandText , freeTextCommand , '"' ) ; } else { return { command : { ... freeTextCommand , command : commandText . trim ( ) } , left : '' } ; } } else { return { left : commandText } ; } } ; const findFirstCommand = ( startCommand , commandText , greedy ) : MatchedCommand => { const fixCommands = startCommand . trails . filter ( cmd => cmd . command !== '' ) ; if ( greedy ) { let found = fixCommands . find ( cmd => commandText === cmd . command ) ; if ( found ) { return { command : found , left : '' } ; } found = fixCommands . find ( cmd => commandText . startsWith ( `${ cmd . command } ` ) ) ; if ( found ) { return { command : found , left : found ? commandText . substring ( found . command . length ) . trimLeft ( ) : commandText } ; } return matchFreeTextCommand ( commandText , startCommand ) ; } else { const found = fixCommands . find ( cmd => commandText . startsWith ( `${ cmd . command } ` ) ) ; if ( found ) { return { command : found , left : found ? commandText . substring ( found . command . length ) . trimLeft ( ) : commandText } ; } if ( commandText . endsWith ( ' ' ) ) { return matchFreeTextCommand ( commandText , startCommand ) ; } else { return { left : commandText } ; } } } ; export const matchCommand = ( options ) => { const { matched , startCommand , commandText , greedy } = options ; let found = findFirstCommand ( startCommand , commandText , greedy ) ; if ( found . command ) { matched . commands . push ( found . command ) ; const leftText = found . left ; if ( leftText . trim ( ) . length !== 0 && found . command . trails . length !== 0 ) { matchCommand ( { matched , startCommand : found . command , commandText : leftText , greedy } ) ; } else if ( leftText . trim ( ) . length === 0 ) { matched . left = '' ; } else if ( found . command . trails . length === 0 ) { matched . left = leftText ; } } else { matched . left = found . left ; } } ; export const matchCommandText = ( options ) => { const { text , greedy , allCommands , pickedCommands } = options ; let startCommand ; if ( text . trimLeft ( ) . startsWith ( '/' ) ) { startCommand = { trails : allCommands } as Command ; } else if ( pickedCommands . length === 0 ) { startCommand = { trails : allCommands } as Command ; } else { startCommand = pickedCommands [ pickedCommands . length - 1 ] ; } const matched = { commands : [ ] , left : '' } ; if ( text . trim ( ) ) { matchCommand ( { matched , startCommand , commandText : text . trimLeft ( ) , greedy } ) ; } return matched ; } ;