@@ -275,100 +275,56 @@ export namespace Ripgrep {
275275 log . info ( "tree" , input )
276276 const files = await Array . fromAsync ( Ripgrep . files ( { cwd : input . cwd , signal : input . signal } ) )
277277 interface Node {
278- path : string [ ]
279- children : Node [ ]
278+ name : string
279+ children : Map < string , Node >
280280 }
281281
282- function getPath ( node : Node , parts : string [ ] , create : boolean ) {
283- if ( parts . length === 0 ) return node
284- let current = node
285- for ( const part of parts ) {
286- let existing = current . children . find ( ( x ) => x . path . at ( - 1 ) === part )
287- if ( ! existing ) {
288- if ( ! create ) return
289- existing = {
290- path : current . path . concat ( part ) ,
291- children : [ ] ,
292- }
293- current . children . push ( existing )
294- }
295- current = existing
296- }
297- return current
282+ function dir ( node : Node , name : string ) {
283+ const existing = node . children . get ( name )
284+ if ( existing ) return existing
285+ const next = { name, children : new Map ( ) }
286+ node . children . set ( name , next )
287+ return next
298288 }
299289
300- const root : Node = {
301- path : [ ] ,
302- children : [ ] ,
303- }
290+ const root : Node = { name : "" , children : new Map ( ) }
304291 for ( const file of files ) {
305292 if ( file . includes ( ".opencode" ) ) continue
306293 const parts = file . split ( path . sep )
307- getPath ( root , parts , true )
308- }
309-
310- function sort ( node : Node ) {
311- node . children . sort ( ( a , b ) => {
312- if ( ! a . children . length && b . children . length ) return 1
313- if ( ! b . children . length && a . children . length ) return - 1
314- return a . path . at ( - 1 ) ! . localeCompare ( b . path . at ( - 1 ) ! )
315- } )
316- for ( const child of node . children ) {
317- sort ( child )
294+ if ( parts . length < 2 ) continue
295+ let node = root
296+ for ( const part of parts . slice ( 0 , - 1 ) ) {
297+ node = dir ( node , part )
318298 }
319299 }
320- sort ( root )
321-
322- let current = [ root ]
323- const result : Node = {
324- path : [ ] ,
325- children : [ ] ,
326- }
327300
328- let processed = 0
329- const limit = input . limit ?? 50
330- while ( current . length > 0 ) {
331- const next = [ ]
332- for ( const node of current ) {
333- if ( node . children . length ) next . push ( ...node . children )
334- }
335- const max = Math . max ( ...current . map ( ( x ) => x . children . length ) )
336- for ( let i = 0 ; i < max && processed < limit ; i ++ ) {
337- for ( const node of current ) {
338- const child = node . children [ i ]
339- if ( ! child ) continue
340- getPath ( result , child . path , true )
341- processed ++
342- if ( processed >= limit ) break
343- }
344- }
345- if ( processed >= limit ) {
346- for ( const node of [ ...current , ...next ] ) {
347- const compare = getPath ( result , node . path , false )
348- if ( ! compare ) continue
349- if ( compare ?. children . length !== node . children . length ) {
350- const diff = node . children . length - compare . children . length
351- compare . children . push ( {
352- path : compare . path . concat ( `[${ diff } truncated]` ) ,
353- children : [ ] ,
354- } )
355- }
356- }
357- break
301+ function count ( node : Node ) : number {
302+ let total = 0
303+ for ( const child of node . children . values ( ) ) {
304+ total += 1 + count ( child )
358305 }
359- current = next
306+ return total
360307 }
361308
309+ const total = count ( root )
310+ const limit = input . limit ?? total
362311 const lines : string [ ] = [ ]
312+ const queue : { node : Node ; path : string } [ ] = [ ]
313+ for ( const child of Array . from ( root . children . values ( ) ) . sort ( ( a , b ) => a . name . localeCompare ( b . name ) ) ) {
314+ queue . push ( { node : child , path : child . name } )
315+ }
363316
364- function render ( node : Node , depth : number ) {
365- const indent = "\t" . repeat ( depth )
366- lines . push ( indent + node . path . at ( - 1 ) + ( node . children . length ? "/" : "" ) )
367- for ( const child of node . children ) {
368- render ( child , depth + 1 )
317+ let used = 0
318+ for ( let i = 0 ; i < queue . length && used < limit ; i ++ ) {
319+ const { node, path } = queue [ i ]
320+ lines . push ( path )
321+ used ++
322+ for ( const child of Array . from ( node . children . values ( ) ) . sort ( ( a , b ) => a . name . localeCompare ( b . name ) ) ) {
323+ queue . push ( { node : child , path : `${ path } /${ child . name } ` } )
369324 }
370325 }
371- result . children . map ( ( x ) => render ( x , 0 ) )
326+
327+ if ( total > used ) lines . push ( `[${ total - used } truncated]` )
372328
373329 return lines . join ( "\n" )
374330 }
0 commit comments