import Debug from 'debug' ; import { encodeComponent , Arguments , Registrar , KResponse } from '@kui-shell/core' ; import { FStat } from '../' ; import { fslice } from '../vfs/delegates' ; import { HeadOptions , showResponseAsMMR } from './head' ; const debug = Debug ( 'plugins/bash-like/cmds/tail' ) ; type TailOptions = HeadOptions & { q : boolean ; f : boolean ; F : boolean ; } ; async function tail ( args ) { if ( args . parsedOptions . q || args . parsedOptions . f || args . parsedOptions . F ) { return args . REPL . qexec ( `sendtopty ${ args . command }` , undefined , undefined , Object . assign ( args . execOptions , { quiet : false } ) ) ; } const { argvNoOptions , parsedOptions } = args ; const filepath = argvNoOptions [ argvNoOptions . indexOf ( 'tail' ) + 1 ] ; debug ( 'tail' , filepath ) ; if ( typeof filepath === 'number' && filepath < 0 ) { const newarg = `-n ${ filepath * - 1 }` ; return args . REPL . qexec ( args . command . replace ( filepath , newarg ) ) ; } const { size } = ( await args . REPL . rexec < FStat > ( `vfs fstat ${ encodeComponent ( filepath ) }` ) ) . content ; try { let data = '' ; if ( parsedOptions . c ) { data = await fslice ( filepath , size - parsedOptions . c , parsedOptions . c , 'bytes' ) ; } else { const nLinesDesired = parsedOptions . n || 10 ; let nLinesLeft = nLinesDesired ; const chunkSize = 4 * 1024 ; let offset = Math . max ( 0 , size - chunkSize ) ; while ( nLinesLeft > 0 && offset >= 0 ) { const rawData = await fslice ( filepath , offset , - nLinesLeft , 'lines' , offset + chunkSize ) ; const rawDataNLines = rawData . split ( /\n/ ) . length ; nLinesLeft -= rawDataNLines ; offset -= chunkSize ; data += rawData ; } } return showResponseAsMMR ( filepath , data ) ; } catch ( err ) { throw new Error ( `tail: ${ err . message }` ) ; } } /**
 * Register command handlers
 *
 */ export default ( registrar ) => { registrar . listen ( '/tail' , tail , { requiresLocal : true , flags : { boolean : [ 'f' , 'F' , 'q' ] } } ) ; } ;