@@ -1575,7 +1575,8 @@ def tree(
15751575 display_size : bool = False ,
15761576 prefix : str = "" ,
15771577 is_last : bool = True ,
1578- first : bool = True
1578+ first : bool = True ,
1579+ indent_size : int = 4
15791580 ):
15801581 """
15811582 Display a tree-like structure of the filesystem starting from the given path.
@@ -1589,6 +1590,7 @@ def tree(
15891590 prefix: Current line prefix for visual tree structure
15901591 is_last: Whether current item is last in its level
15911592 first: Whether this is the first call (displays root path)
1593+ indent_size: Number of spaces by indent
15921594
15931595 Example
15941596 -------
@@ -1601,44 +1603,58 @@ def tree(
16011603 └── folder2
16021604 └── file3.txt (2.345MB)
16031605 """
1606+ def format_bytes (n : int ) -> str :
1607+ """Format bytes as text."""
1608+ for prefix , k in (
1609+ ("P" , 2 ** 50 ),
1610+ ("T" , 2 ** 40 ),
1611+ ("G" , 2 ** 30 ),
1612+ ("M" , 2 ** 20 ),
1613+ ("k" , 2 ** 10 ),
1614+ ):
1615+ if n >= 0.9 * k :
1616+ return f"{ n / k :.2f} { prefix } b"
1617+ return f"{ n } B"
1618+
16041619 if first :
16051620 print (path )
16061621 if recursion_limit :
1607- try :
1608- contents = self .ls (path , detail = True )
1609- contents .sort (key = lambda x : (not x .get ('type' ) == 'directory' , x .get ('name' , '' )))
1610-
1611- if max_display is not None and len (contents ) > max_display :
1612- displayed_contents = contents [:max_display ]
1613- remaining_count = len (contents ) - max_display
1614- else :
1615- displayed_contents = contents
1616- remaining_count = 0
1617-
1618- for i , item in enumerate (displayed_contents ):
1619- is_last_item = (i == len (displayed_contents ) - 1 ) and (remaining_count == 0 )
1620-
1621- branch = "└── " if is_last_item else "├── "
1622- new_prefix = prefix + (" " if is_last_item else "│ " )
1623-
1624- name = os .path .basename (item .get ('name' , '' ))
1625- size = f" ({ item .get ('size' , 0 ) / 2 ** 20 :.3f} Mb)" if display_size and item .get ('type' ) == 'file' else ""
1622+ indent = " " * indent_size
1623+ contents = self .ls (path , detail = True )
1624+ contents .sort (key = lambda x : (not x .get ('type' ) == 'directory' , x .get ('name' , '' )))
16261625
1627- print (f"{ prefix } { branch } { name } { size } " )
1628-
1629- if item .get ('type' ) == 'directory' and recursion_limit > 0 :
1630- self .tree (item .get ('name' , '' ), recursion_limit - 1 , max_display , new_prefix , is_last_item , display_size = display_size , first = False )
1631-
1632- if remaining_count > 0 :
1633- more_message = f"{ remaining_count } more item(s) not displayed."
1634- print (f"{ prefix } { '└── ' if is_last else '├── ' } { more_message } " )
1635-
1636- except FileNotFoundError :
1637- print (f"{ prefix } Error: Path not found - { path } " )
1638- except PermissionError :
1639- print (f"{ prefix } Error: Permission denied - { path } " )
1640- except Exception as e :
1641- print (f"{ prefix } Unexpected error: { str (e )} " )
1626+ if max_display is not None and len (contents ) > max_display :
1627+ displayed_contents = contents [:max_display ]
1628+ remaining_count = len (contents ) - max_display
1629+ else :
1630+ displayed_contents = contents
1631+ remaining_count = 0
1632+
1633+ for i , item in enumerate (displayed_contents ):
1634+ is_last_item = (i == len (displayed_contents ) - 1 ) and (remaining_count == 0 )
1635+
1636+ branch = "└" + ('─' * (indent_size - 2 )) if is_last_item else "├" + ('─' * (indent_size - 2 ))
1637+ branch += ' '
1638+ new_prefix = prefix + (indent if is_last_item else "│" + " " * (indent_size - 1 ))
1639+
1640+ name = os .path .basename (item .get ('name' , '' ))
1641+ size = f" ({ format_bytes (item .get ('size' , 0 ))} )" if display_size and item .get ('type' ) == 'file' else ""
1642+
1643+ print (f"{ prefix } { branch } { name } { size } " )
1644+
1645+ if item .get ('type' ) == 'directory' and recursion_limit > 0 :
1646+ self .tree (path = item .get ('name' , '' ),
1647+ recursion_limit = recursion_limit - 1 ,
1648+ max_display = max_display ,
1649+ display_size = display_size ,
1650+ prefix = new_prefix ,
1651+ is_last = is_last_item ,
1652+ first = False ,
1653+ indent_size = indent_size )
1654+
1655+ if remaining_count > 0 :
1656+ more_message = f"{ remaining_count } more item(s) not displayed."
1657+ print (f"{ prefix } { '└── ' if is_last else '├── ' } { more_message } " )
16421658
16431659 # ------------------------------------------------------------------------
16441660 # Aliases
0 commit comments