|
|
|
@ -1,11 +1,37 @@
|
|
|
|
|
import strutils, times, math
|
|
|
|
|
|
|
|
|
|
type Progress* = ref object of RootObj
|
|
|
|
|
sout: File
|
|
|
|
|
lastStep, width, maxSteps: int
|
|
|
|
|
startTime: float
|
|
|
|
|
lastInfo: string
|
|
|
|
|
maxValue: BiggestInt
|
|
|
|
|
type
|
|
|
|
|
PBDisplayConfig* = object
|
|
|
|
|
## Progress Bar Display Configuration - controls how the progress bar is
|
|
|
|
|
## displayed to the terminal
|
|
|
|
|
before*: string ## Written at the start, before the bar. This is
|
|
|
|
|
## intended for ANSI control characters and must take
|
|
|
|
|
## up zero characters when printed.
|
|
|
|
|
after*: string ## Written at the end, after the bar This is intended
|
|
|
|
|
## for ANSI control characters and must take up zero
|
|
|
|
|
## characters when printed.
|
|
|
|
|
completed*: string ## Written for each completed step of the bar. This
|
|
|
|
|
## should take up one character of space when printed.
|
|
|
|
|
todo*: string ## Written for each step remaining in the bar. This
|
|
|
|
|
## should take up one character of space when printed.
|
|
|
|
|
separator*: string ## Written for the current step, separating completed
|
|
|
|
|
## and done. This should take up one character of space
|
|
|
|
|
## when printed.
|
|
|
|
|
|
|
|
|
|
Progress* = ref object of RootObj
|
|
|
|
|
sout: File
|
|
|
|
|
lastStep, width, maxSteps: int
|
|
|
|
|
startTime: float
|
|
|
|
|
lastInfo: string
|
|
|
|
|
maxValue: BiggestInt
|
|
|
|
|
displayCfg: PBDisplayConfig
|
|
|
|
|
|
|
|
|
|
const DEFAULT_DISPLAY_CFG* = PBDisplayConfig(
|
|
|
|
|
before: "\x1b[38;5;2m",
|
|
|
|
|
after: "\x1b[0m",
|
|
|
|
|
completed: "━",
|
|
|
|
|
todo: "─",
|
|
|
|
|
separator: "\x1b[38;5;8m")
|
|
|
|
|
|
|
|
|
|
proc getMax*(pd: Progress): BiggestInt =
|
|
|
|
|
return pd.maxValue
|
|
|
|
@ -13,13 +39,20 @@ proc getMax*(pd: Progress): BiggestInt =
|
|
|
|
|
proc setMax*(pd: Progress, maxValue: BiggestInt) =
|
|
|
|
|
pd.maxValue = max(maxValue, 1)
|
|
|
|
|
|
|
|
|
|
proc newProgress*(sout: File, maxValue: BiggestInt): Progress =
|
|
|
|
|
proc newProgress*(
|
|
|
|
|
maxValue: BiggestInt,
|
|
|
|
|
sout: File = stdout,
|
|
|
|
|
width: int = 79,
|
|
|
|
|
maxSteps: int = 35,
|
|
|
|
|
displayCfg: PBDisplayConfig = DEFAULT_DISPLAY_CFG): Progress =
|
|
|
|
|
|
|
|
|
|
return Progress(sout: sout,
|
|
|
|
|
startTime: cpuTime(),
|
|
|
|
|
lastStep: 0,
|
|
|
|
|
maxValue: maxValue,
|
|
|
|
|
width: 79,
|
|
|
|
|
maxSteps: 35)
|
|
|
|
|
maxSteps: 35,
|
|
|
|
|
displayCfg: displayCfg)
|
|
|
|
|
|
|
|
|
|
proc updateProgress*(pd: Progress, newValue: BiggestInt, info: string): void =
|
|
|
|
|
|
|
|
|
@ -32,7 +65,9 @@ proc updateProgress*(pd: Progress, newValue: BiggestInt, info: string): void =
|
|
|
|
|
|
|
|
|
|
let curDuration = cpuTime() - pd.startTime
|
|
|
|
|
let remTime = ((curDuration / curPercent) - curDuration)
|
|
|
|
|
let displayedSteps = max(curStep - 1, 0)
|
|
|
|
|
let displayedSteps =
|
|
|
|
|
if curStep == pd.maxSteps: curStep
|
|
|
|
|
else: max(curStep - 1, 0)
|
|
|
|
|
|
|
|
|
|
pd.lastInfo = info
|
|
|
|
|
var displayedInfo = info
|
|
|
|
@ -43,10 +78,13 @@ proc updateProgress*(pd: Progress, newValue: BiggestInt, info: string): void =
|
|
|
|
|
pd.sout.write('\b'.repeat(pd.width))
|
|
|
|
|
|
|
|
|
|
var line =
|
|
|
|
|
'='.repeat(displayedSteps) & (if curStep > 0: "0" else: "") &
|
|
|
|
|
'-'.repeat(pd.maxSteps - curStep) & " " &
|
|
|
|
|
pd.displayCfg.before &
|
|
|
|
|
pd.displayCfg.completed.repeat(displayedSteps) &
|
|
|
|
|
(if curStep > 0 and curStep < pd.maxSteps: pd.displayCfg.separator else: "") &
|
|
|
|
|
pd.displayCfg.todo.repeat(pd.maxSteps - curStep) &
|
|
|
|
|
pd.displayCfg.after & " " &
|
|
|
|
|
displayedInfo & " -- (" &
|
|
|
|
|
(curPercent * 100).formatFloat(ffDecimal, 2) & "%"
|
|
|
|
|
(curPercent * 100).formatFloat(ffDecimal, 2) & "%"
|
|
|
|
|
|
|
|
|
|
if curPercent > 0.05:
|
|
|
|
|
line &= ", "
|
|
|
|
|