11import os, strutils, math, terminal, fusion/ btreetables
22
3- const HistogramBlocks = [" █" ," ▉" ," ▊" ," ▋" ," ▌" ," ▍" ," ▎" ," ▏" ]
4- const ProgressChars = [" ▀" , " ▜" , " ▐" , " ▟" , " ▄" , " ▙" , " ▌" , " ▛" ]
3+ const
4+ HistogramBlocks = [" █" ," ▉" ," ▊" ," ▋" ," ▌" ," ▍" ," ▎" ," ▏" ]
5+ ProgressChars = [" ▀" , " ▜" , " ▐" , " ▟" , " ▄" , " ▙" , " ▌" , " ▛" ]
56
67type
78 Stat = object
1011 maxSize: BiggestInt
1112 minSize: BiggestInt
1213
13- type
1414 FsStat = object
1515 stat: Stat
1616 table: CountTable [BiggestInt ]
@@ -29,7 +29,7 @@ func initFsStat(): FsStat =
2929 table: initCountTable [BiggestInt ](1024 )
3030 )
3131
32- template incStatsTmpl (s: Stat ; size: BiggestInt ) =
32+ proc addFile (s: var Stat ; size: BiggestInt ) =
3333 s.minSize = min (s.minSize, size)
3434 s.maxSize = max (s.maxSize, size)
3535 s.totalSize += size
@@ -49,13 +49,15 @@ func getLog2Stats(fs: FsStat): seq[Stat] =
4949 0
5050 else :
5151 toInt (floor (log2 (toBiggestFloat (size)) / 2 )) + 1
52- incStatsTmpl (result [bin], size)
52+ addFile (result [bin], size)
5353
5454func drawBar (num, maxNum: Natural ; width: Natural ): string =
55- let f = toFloat (num) / toFloat (maxNum) * toFloat (width)
56- let full = toInt (floor (f))
57- let tail = f - trunc (f)
58- var partial = toInt (round (7.0 * tail))
55+ let
56+ f = toFloat (num) / toFloat (maxNum) * toFloat (width)
57+ full = toInt (floor (f))
58+ tail = f - trunc (f)
59+ var
60+ partial = toInt (round (7.0 * tail))
5961 if partial == 0 and full == 0 and num > 0 :
6062 partial = 1
6163 for _ in 1 .. full:
@@ -71,23 +73,25 @@ proc progressUpdate(mainThreadBusy: ptr bool) {.thread.} =
7173 sleep (250 )
7274
7375proc walkFs (path: string ): FsStat =
74- var fs = initFsStat ()
75- var check = 0
76- var thProgress: Thread [ptr bool ]
77- var mainThreadBusy = true
76+ result = initFsStat ()
77+ var
78+ check = 0
79+ thProgress: Thread [ptr bool ]
80+ mainThreadBusy = true
7881 createThread (thProgress, progressUpdate, addr mainThreadBusy)
7982 for file in walkDirRec (path, {pcFile}, {pcDir}):
80- let fInfo = getFileInfo (file, false )
81- let fSize = fInfo.size
82- fs.stat.filesSeen.inc ()
83+ let
84+ fInfo = getFileInfo (file, false )
85+ fSize = fInfo.size
86+ result .stat.filesSeen.inc ()
8387 check.inc ()
84- fs .stat.totalSize += fSize
85- fs .stat.maxSize = max (fs .stat.maxSize,fSize)
86- fs .stat.minSize = min (fs .stat.minSize,fSize)
87- fs .table.inc (fSize)
88+ result .stat.totalSize += fSize
89+ result .stat.maxSize = max (result .stat.maxSize,fSize)
90+ result .stat.minSize = min (result .stat.minSize,fSize)
91+ result .table.inc (fSize)
8892 mainThreadBusy = false
93+ joinThread (thProgress)
8994 stdout.write (" \r " )
90- result = move (fs)
9195
9296when isMainModule :
9397 var startPath = if paramCount () > 0 :
@@ -96,18 +100,19 @@ when isMainModule:
96100 getCurrentDir ()
97101 let startInfo = getFileInfo (startPath)
98102 if startInfo.kind != pcDir and not startInfo.permissions.contains (fpUserRead):
99- echo (" Error reading directory " , startPath)
100- quit ()
103+ quit (" Error reading directory " & startPath)
101104 let fs = walkFs (startPath)
102105 echo (" Files scanned: " , fs.stat.filesSeen, " , total: " , formatSize (fs.stat.totalSize))
103106 var stats = fs.getLog2Stats ()
104107 echo (" Stats for files by size strata; Bars: file count." )
105- var statStrSeq: seq [(string ,BiggestInt )]
106- var maxNum:BiggestInt = 0
107- var maxLineLen = 0
108+ var
109+ statStrSeq: seq [(string ,BiggestInt )]
110+ maxNum:BiggestInt = 0
111+ maxLineLen = 0
108112 for bin, s in stats.pairs:
109- let maxSize = if s.filesSeen == 0 : BiggestInt (0 ) else : s.maxSize
110- let line = if bin == 0 :
113+ let
114+ maxSize = if s.filesSeen == 0 : BiggestInt (0 ) else : s.maxSize
115+ line = if bin == 0 :
111116 format (" $1: Max: $2; $3 files" , [
112117 align (formatSize (0 ), 16 ),
113118 align (formatSize (maxSize), 11 ),
0 commit comments