@@ -137,55 +137,21 @@ async fn get(id: &str, format: OutputFormat, profile_name: Option<&str>) -> Resu
137137 drive[ "documentType" ] . as_str( ) . unwrap_or( "-" )
138138 ) ;
139139
140- // Show documents table
140+ // Show contents as a tree with metadata
141141 if let Some ( nodes) = drive. pointer ( "/state/nodes" ) . and_then ( |v| v. as_array ( ) ) {
142- let files: Vec < & Value > = nodes
142+ let files = nodes
143143 . iter ( )
144144 . filter ( |n| n[ "kind" ] . as_str ( ) == Some ( "file" ) )
145- . collect ( ) ;
145+ . count ( ) ;
146146 let folders = nodes
147147 . iter ( )
148148 . filter ( |n| n[ "kind" ] . as_str ( ) == Some ( "folder" ) )
149149 . count ( ) ;
150- println ! ( "\n Contents: {} files, {folders} folders" , files. len( ) ) ;
151-
152- if !files. is_empty ( ) {
153- // Build folder id -> name lookup for the Folder column
154- let folder_map: std:: collections:: HashMap < & str , & str > = nodes
155- . iter ( )
156- . filter ( |n| n[ "kind" ] . as_str ( ) == Some ( "folder" ) )
157- . filter_map ( |n| Some ( ( n[ "id" ] . as_str ( ) ?, n[ "name" ] . as_str ( ) ?) ) )
158- . collect ( ) ;
150+ println ! ( "\n Contents: {files} files, {folders} folders" ) ;
159151
152+ if files > 0 || folders > 0 {
160153 println ! ( ) ;
161- let rows: Vec < Vec < String > > = files
162- . iter ( )
163- . map ( |f| {
164- let folder = f[ "parentFolder" ]
165- . as_str ( )
166- . and_then ( |pid| folder_map. get ( pid) . copied ( ) )
167- . unwrap_or ( "" ) ;
168- vec ! [
169- f[ "id" ] . as_str( ) . unwrap_or( "-" ) . to_string( ) ,
170- f[ "name" ] . as_str( ) . unwrap_or( "-" ) . to_string( ) ,
171- f[ "documentType" ] . as_str( ) . unwrap_or( "-" ) . to_string( ) ,
172- folder. to_string( ) ,
173- ]
174- } )
175- . collect ( ) ;
176- if folders > 0 {
177- print_table ( & [ "ID" , "Name" , "Type" , "Folder" ] , & rows) ;
178- } else {
179- // No folders — skip the Folder column for cleaner output
180- let rows: Vec < Vec < String > > = rows
181- . into_iter ( )
182- . map ( |mut r| {
183- r. pop ( ) ;
184- r
185- } )
186- . collect ( ) ;
187- print_table ( & [ "ID" , "Name" , "Type" ] , & rows) ;
188- }
154+ print_drive_tree ( nodes, None , "" ) ;
189155 }
190156 }
191157 }
@@ -348,3 +314,39 @@ async fn delete(ids: &[String], skip_confirm: bool, profile_name: Option<&str>)
348314 }
349315 Ok ( ( ) )
350316}
317+
318+ /// Print drive contents as an indented tree with metadata (Type, ID) on each file line.
319+ fn print_drive_tree ( nodes : & [ Value ] , parent : Option < & str > , indent : & str ) {
320+ let children: Vec < & Value > = nodes
321+ . iter ( )
322+ . filter ( |n| {
323+ let pf = n[ "parentFolder" ] . as_str ( ) ;
324+ match parent {
325+ None => pf. is_none ( ) || pf == Some ( "" ) ,
326+ Some ( p) => pf == Some ( p) ,
327+ }
328+ } )
329+ . collect ( ) ;
330+
331+ for ( i, child) in children. iter ( ) . enumerate ( ) {
332+ let is_last = i == children. len ( ) - 1 ;
333+ let connector = if is_last {
334+ "\u{2514} \u{2500} \u{2500} "
335+ } else {
336+ "\u{251c} \u{2500} \u{2500} "
337+ } ;
338+ let child_indent = if is_last { " " } else { "\u{2502} " } ;
339+
340+ let name = child[ "name" ] . as_str ( ) . unwrap_or ( "-" ) ;
341+ let kind = child[ "kind" ] . as_str ( ) . unwrap_or ( "file" ) ;
342+ let id = child[ "id" ] . as_str ( ) . unwrap_or ( "-" ) ;
343+
344+ if kind == "folder" {
345+ println ! ( "{indent}{connector}\u{1f4c1} {name}/" ) ;
346+ print_drive_tree ( nodes, Some ( id) , & format ! ( "{indent}{child_indent}" ) ) ;
347+ } else {
348+ let doc_type = child[ "documentType" ] . as_str ( ) . unwrap_or ( "-" ) ;
349+ println ! ( "{indent}{connector}{name} ({doc_type}) [{id}]" ) ;
350+ }
351+ }
352+ }
0 commit comments