Initial commit
This commit is contained in:
commit
f06242ebb5
33 changed files with 6060 additions and 0 deletions
97
src/util/progress.luau
Normal file
97
src/util/progress.luau
Normal file
|
@ -0,0 +1,97 @@
|
|||
--!strict
|
||||
--> Inspired by Rokit's progress bar: https://github.com/rojo-rbx/rokit/blob/a303faf/src/util/progress.rs
|
||||
-- Original: https://github.com/pesde-pkg/tooling/blob/main/toolchainlib/src/utils/progress.luau
|
||||
local task = require("@lune/task")
|
||||
local stdio = require("@lune/stdio")
|
||||
|
||||
local result = require("./result")
|
||||
|
||||
-- FORMAT: {SPINNER} {MESSAGE} {BAR} {STAGE}
|
||||
local SPINNERS = { "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏" }
|
||||
local BAR_COMPONENT = "▇"
|
||||
local MAX_BAR_LENGTH = 30
|
||||
|
||||
local ProgressBar = {}
|
||||
type ProgressBar = {
|
||||
stages: { { tag: string, message: string } },
|
||||
currentStageIndex: number,
|
||||
finished: boolean,
|
||||
thread: thread?,
|
||||
}
|
||||
export type ProgressBarImpl = typeof(setmetatable({} :: ProgressBar, { __index = ProgressBar }))
|
||||
|
||||
function ProgressBar.new(): ProgressBarImpl
|
||||
return setmetatable(
|
||||
{
|
||||
stages = {},
|
||||
currentStageIndex = 1,
|
||||
finished = false,
|
||||
} :: ProgressBar,
|
||||
{
|
||||
__index = ProgressBar,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function ProgressBar.withStage(self: ProgressBarImpl, tag: string, msg: string): ProgressBarImpl
|
||||
table.insert(self.stages, { tag = tag, message = msg })
|
||||
return self
|
||||
end
|
||||
|
||||
function ProgressBar.start(self: ProgressBarImpl)
|
||||
local BAR_LENGTH = MAX_BAR_LENGTH // #self.stages
|
||||
local TOTAL_BAR_LENGTH = BAR_LENGTH * #self.stages
|
||||
local BAR = string.rep(BAR_COMPONENT, BAR_LENGTH)
|
||||
local MAX_MESSAGE_LENGTH = 0
|
||||
for _, stage in self.stages do
|
||||
local len = #stage.message
|
||||
if len > MAX_MESSAGE_LENGTH then
|
||||
MAX_MESSAGE_LENGTH = len
|
||||
end
|
||||
end
|
||||
|
||||
self.thread = task.spawn(function()
|
||||
while true do
|
||||
for _, spinner in SPINNERS do
|
||||
if self.finished then
|
||||
return
|
||||
end
|
||||
|
||||
local stage = self.stages[self.currentStageIndex]
|
||||
stdio.ewrite(
|
||||
`\x1b[2K\x1b[0G{stdio.color("cyan")}{spinner} {stage.message}{stdio.color("reset")}{string.rep(
|
||||
" ",
|
||||
MAX_MESSAGE_LENGTH - #stage.message
|
||||
)} [{stdio.style("dim")}{string.rep(BAR, self.currentStageIndex)}{string.rep(
|
||||
" ",
|
||||
TOTAL_BAR_LENGTH - (BAR_LENGTH * self.currentStageIndex)
|
||||
)}{stdio.style("reset")}] {stdio.style("bold")}{self.currentStageIndex} / {#self.stages}{stdio.style(
|
||||
"reset"
|
||||
)}`
|
||||
)
|
||||
|
||||
task.wait(0.1)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ProgressBar.stop(self: ProgressBarImpl)
|
||||
-- Trigger upvalue, kill thread and clean progress bar remnant
|
||||
self.finished = true
|
||||
stdio.ewrite("\x1b[2K\x1b[0G")
|
||||
end
|
||||
|
||||
function ProgressBar.nextStage(self: ProgressBarImpl): result.Identity<nil>
|
||||
local inc = self.currentStageIndex + 1
|
||||
if inc > #self.stages then
|
||||
-- TODO: Make this a result
|
||||
self.finished = true
|
||||
return result(false, "OutOfBounds - Attempted to advance past last stage")
|
||||
end
|
||||
|
||||
self.currentStageIndex = inc
|
||||
return result(true, nil)
|
||||
end
|
||||
|
||||
return ProgressBar
|
24
src/util/result.luau
Normal file
24
src/util/result.luau
Normal file
|
@ -0,0 +1,24 @@
|
|||
--!strict
|
||||
export type Identity<T> = {
|
||||
ok: true,
|
||||
val: T,
|
||||
} | {
|
||||
ok: false,
|
||||
err: string,
|
||||
}
|
||||
|
||||
local function construct<T>(ok: boolean, value: T & string): Identity<T>
|
||||
if ok then
|
||||
return {
|
||||
ok = true,
|
||||
val = value,
|
||||
}
|
||||
else
|
||||
return {
|
||||
ok = false,
|
||||
err = value,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return (construct :: any) :: (<T>(ok: true, value: T) -> Identity<T>) & (<T>(ok: false, value: string) -> Identity<T>)
|
Loading…
Add table
Add a link
Reference in a new issue