1- import os, strutils, math, terminal, fusion/ btreetables
1+ import std/ [os, strutils, math, terminal],
2+ fusion/ btreetables, threading/ atomics
23
3- const
4+ const
45 HistogramBlocks = [" █" , " ▉" , " ▊" , " ▋" , " ▌" , " ▍" , " ▎" , " ▏" ]
56 ProgressChars = [" ▀" , " ▜" , " ▐" , " ▟" , " ▄" , " ▙" , " ▌" , " ▛" ]
67
@@ -40,7 +41,7 @@ func getLog2Stats(fs: FsStat): seq[Stat] =
4041 if fs.stat.maxSize < 0 :
4142 0
4243 else :
43- toInt (floor (log2 (toBiggestFloat (fs.stat.maxSize)) / 2 )) + 1
44+ toInt (floor (log2 (toBiggestFloat (fs.stat.maxSize)) / 2 )) + 1
4445 for n in 0 .. bins:
4546 result .add (initStat ())
4647 for size, n in fs.table.pairs:
@@ -49,49 +50,48 @@ func getLog2Stats(fs: FsStat): seq[Stat] =
4950 if size == 0 :
5051 0
5152 else :
52- toInt (floor (log2 (toBiggestFloat (size)) / 2 )) + 1
53+ toInt (floor (log2 (toBiggestFloat (size)) / 2 )) + 1
5354 addFile (result [bin], size)
5455
5556func drawBar (num, maxNum, width: Natural ): string =
56- let
57+ let
5758 f = toFloat (num) / toFloat (maxNum) * toFloat (width)
5859 full = toInt (floor (f))
5960 tail = f - trunc (f)
60- var
61+ var
6162 partial = toInt (round (7.0 * tail))
62- if partial == 0 and full == 0 and num > 0 :
63+ if partial == 0 and full == 0 and num > 0 : # draw a thin line even if too small
6364 partial = 1
6465 for _ in 1 .. full:
6566 result .add (HistogramBlocks [0 ])
6667 if partial > 0 :
6768 result .add (HistogramBlocks [^ partial])
6869
69- proc progressUpdate (mainThreadBusy: ptr bool ) {.thread .} =
70- while mainThreadBusy[] :
70+ proc progressUpdate (mainThreadBusy: ptr Atomic [ bool ] ) {.thread .} =
71+ while true :
7172 for i in 0 .. 7 :
72- stdout.write (" \r " , ProgressChars [i], " Scanning the file system..." )
73- flushFile (stdout)
73+ stderr.write (" \r " , ProgressChars [i], " Scanning the file system..." )
74+ flushFile (stderr)
75+ if not mainThreadBusy[].load: return
7476 sleep (250 )
7577
7678proc walkFs (path: string ): FsStat =
7779 result = initFsStat ()
78- var
79- check = 0
80- thProgress: Thread [ptr bool ]
81- mainThreadBusy = true
80+ var
81+ thProgress: Thread [ptr Atomic [bool ]]
82+ mainThreadBusy = Atomic (true )
8283 createThread (thProgress, progressUpdate, addr mainThreadBusy)
8384 for file in walkDirRec (path, {pcFile}, {pcDir}):
84- let
85+ let
8586 fInfo = getFileInfo (file, false )
8687 fSize = fInfo.size
8788 result .stat.filesSeen.inc ()
88- check.inc ()
8989 result .stat.totalSize += fSize
9090 result .stat.maxSize = max (result .stat.maxSize, fSize)
9191 result .stat.minSize = min (result .stat.minSize, fSize)
9292 result .table.inc (fSize)
9393 defer :
94- mainThreadBusy = false
94+ mainThreadBusy. store ( false )
9595 joinThread (thProgress)
9696 stdout.write (" \r " )
9797
@@ -103,12 +103,12 @@ when isMainModule:
103103 getCurrentDir ()
104104 let startInfo = getFileInfo (startPath)
105105 if startInfo.kind != pcDir and not startInfo.permissions.contains (fpUserRead):
106- quit (" Error reading directory " & startPath)
106+ quit (" Error reading directory " & startPath, 1 )
107107 let fs = walkFs (startPath)
108108 echo (" Files scanned: " , fs.stat.filesSeen, " , total: " , formatSize (fs.stat.totalSize))
109109 var stats = fs.getLog2Stats ()
110110 echo (" Stats for files by size strata; Bars: file count." )
111- var
111+ var
112112 statStrSeq: seq [(string ,BiggestInt )]
113113 maxNum: BiggestInt = 0
114114 maxLineLen = 0
@@ -137,4 +137,4 @@ when isMainModule:
137137 let maxWidth = terminalWidth () - maxLineLen - 1
138138 for (line, n) in statStrSeq:
139139 let bar = drawBar (n, maxNum, maxWidth)
140- echo (alignLeft (line, maxLineLen+ 1 , ' ' ), bar)
140+ echo (alignLeft (line, maxLineLen + 1 , ' ' ), bar)
0 commit comments