import { basename , dirname as pathDirname } from 'path' ; import { Tab , Arguments , CommandLine , Registrar , registerTabCompletionEnumerator , TabCompletionSpec , CompletionResponse , Util } from '@kui-shell/core' ; import { ls } from '../vfs/delegates' ; import { GlobStats } from '../lib/glob' ; function findMatchingFilesFrom ( files , dirToScan , last , lastIsDir ) { const partial = basename ( last ) + ( lastIsDir ? '/' : '' ) ; const partialHasADot = partial . startsWith ( '.' ) ; const matches = files . filter ( _f => { const f = _f . name ; return ( ( lastIsDir || f . indexOf ( partial ) === 0 ) && ! f . endsWith ( '~' ) && f !== '.' && f !== '..' && ( partialHasADot || ! f . startsWith ( '.' ) ) ) ; } ) ; const lastHasPath = /\// . test ( last ) ; return matches . map ( matchStats => { const match = matchStats . nameForDisplay ; const completion = lastIsDir ? match : match . substring ( partial . length ) ; const label = lastHasPath ? basename ( matchStats . nameForDisplay ) : undefined ; if ( matchStats . dirent . isDirectory || matchStats . dirent . isSymbolicLink ) { return { completion : ! /\/$/ . test ( completion ) ? `${ completion }/` : completion , label : label ? ( ! /\/$/ . test ( label ) ? `${ label }/` : label ) : undefined } ; } else { return { completion , addSpace : true , label } ; } } ) ; } /**
 * Tab completion handler for local files
 *
 */ async function completeLocalFiles ( tab , commandLine , { toBeCompleted } ) { return ( await tab . REPL . rexec < CompletionResponse [ ] > ( `fscomplete -- "${ toBeCompleted }"` ) ) . content ; } async function doComplete ( args ) { const last = args . command . substring ( args . command . indexOf ( '-- ' ) + '-- ' . length ) . replace ( /^"(.*)"$/ , '$1' ) ; const lastIsDir = last . charAt ( last . length - 1 ) === '/' ; const dirname = lastIsDir ? last : pathDirname ( last ) ; if ( dirname ) { try { const dirToScan = Util . expandHomeDir ( dirname ) ; const fileList = await ls ( { tab : args . tab , REPL : args . REPL , parsedOptions : { a : true } } , [ dirToScan ] ) ; const _matchingFiles = findMatchingFilesFrom ( await fileList , dirToScan , last , lastIsDir ) ; const matchingFiles = _matchingFiles && _matchingFiles . length !== 0 ? _matchingFiles : [ ] ; return { mode : 'raw' , content : matchingFiles } ; } catch ( err ) { console . error ( 'tab completion vfs.ls error' , err ) ; throw err ; } } } /**
 * Entry point to register tab completion handlers. Register this as a
 * very low priority enumerator. We don't want e.g. to enumerate files
 * when the user is doing a `git checkout myBran<tab>`.
 *
 */ export function preload ( ) { registerTabCompletionEnumerator ( completeLocalFiles , - 100 ) ; } export function plugin ( registrar ) { registrar . listen ( '/fscomplete' , doComplete , { hidden : true , requiresLocal : true } ) ; }