diff options
| author | ruki <[email protected]> | 2025-11-21 00:49:11 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-11-21 11:28:51 +0800 |
| commit | 66dec67272856110859d38c01043fd2564f9c7a7 (patch) | |
| tree | 88333751ca814ac6b20855d76caf3093330bf30f | |
| parent | 4627107fa7badf70828a6f569e4a8b8ba3d4160d (diff) | |
add waiting indicator
| -rw-r--r-- | tests/modules/scheduler/spinner.lua | 2 | ||||
| -rw-r--r-- | xmake/actions/update/main.lua | 4 | ||||
| -rw-r--r-- | xmake/modules/async/runjobs.lua | 44 | ||||
| -rw-r--r-- | xmake/modules/private/action/require/impl/download_packages.lua | 8 | ||||
| -rw-r--r-- | xmake/modules/private/action/require/impl/install_packages.lua | 8 | ||||
| -rw-r--r-- | xmake/modules/utils/progress.lua | 56 | ||||
| -rw-r--r-- | xmake/modules/utils/waiting_indicator.lua | 83 | ||||
| -rw-r--r-- | xmake/plugins/repo/main.lua | 2 | ||||
| -rw-r--r-- | xmake/rules/go/env/xmake.lua | 2 |
9 files changed, 119 insertions, 90 deletions
diff --git a/tests/modules/scheduler/spinner.lua b/tests/modules/scheduler/spinner.lua index 8d20bf7b7..ee442163d 100644 --- a/tests/modules/scheduler/spinner.lua +++ b/tests/modules/scheduler/spinner.lua @@ -4,7 +4,7 @@ function main() printf("testing .. ") runjobs("test", function () os.sleep(10000) - end, {progress = true}) + end, {waiting_indicator = true}) print("ok") end diff --git a/xmake/actions/update/main.lua b/xmake/actions/update/main.lua index 8607e7ffb..8cfe237ee 100644 --- a/xmake/actions/update/main.lua +++ b/xmake/actions/update/main.lua @@ -238,7 +238,7 @@ function _install(sourcedir) if option.get("verbose") then install_task() else - runjobs("update/install", install_task, {progress = true}) + runjobs("update/install", install_task, {waiting_indicator = true}) end end @@ -512,7 +512,7 @@ function main() if option.get("verbose") then download_task() else - runjobs("update/download", download_task, {progress = true}) + runjobs("update/download", download_task, {waiting_indicator = true}) end -- leave environment diff --git a/xmake/modules/async/runjobs.lua b/xmake/modules/async/runjobs.lua index 642668921..109ccd3f3 100644 --- a/xmake/modules/async/runjobs.lua +++ b/xmake/modules/async/runjobs.lua @@ -21,6 +21,7 @@ -- imports import("core.base.scheduler") import("utils.progress") +import("utils.waiting_indicator") -- print back characters function _print_backchars(backnum) @@ -36,16 +37,17 @@ end function _init_progress(state, opt) opt = opt or {} - -- init progress helper + -- init waiting indicator helper -- we need to hide wait characters if is not a tty - state.show_progress = io.isatty() and (opt.progress or opt.showtips) + local waiting_indicator_opt = opt.waiting_indicator + state.show_waiting_indicator = io.isatty() and (waiting_indicator_opt == true or type(waiting_indicator_opt) == "table") state.backnum = 0 - if state.show_progress then - local progress_opt = nil - if type(state.show_progress) == "table" then - progress_opt = state.show_progress + if state.show_waiting_indicator then + local indicator_opt = nil + if type(waiting_indicator_opt) == "table" then + indicator_opt = waiting_indicator_opt end - state.progress_helper = progress.new(nil, progress_opt) + state.waiting_indicator_helper = waiting_indicator.new(nil, indicator_opt) end -- init progress wrapper @@ -113,10 +115,10 @@ function _progress_refresh_loop(state) end end --- the progress loop -function _progress_loop(state) +-- the waiting indicator loop +function _waiting_indicator_loop(state) local timeout = state.timeout - local progress_helper = state.progress_helper + local waiting_indicator_helper = state.waiting_indicator_helper while not state.stop do os.sleep(timeout) if not state.stop then @@ -146,14 +148,14 @@ function _progress_loop(state) end -- print back characters - progress_helper:clear() + waiting_indicator_helper:clear() _print_backchars(state.backnum) if tips then cprintf("${dim}%s${clear} ", tips) state.backnum = #tips + 1 end - progress_helper:write() + waiting_indicator_helper:write() end end end @@ -257,9 +259,9 @@ function _consume_jobs_loop(state, run_in_remote) -- stop progress progress.show_abort() - if state.show_progress then + if state.show_waiting_indicator then _print_backchars(state.backnum) - state.progress_helper:stop() + state.waiting_indicator_helper:stop() end -- we need re-throw this errors outside scheduler @@ -304,9 +306,9 @@ end -- -- e.g. -- runjobs("test", function (index) print("hello") end, {total = 100, comax = 6, timeout = 1000, on_timer = function (running_jobs_indices) end}) --- runjobs("test", function () os.sleep(10000) end, { progress = true }) --- runjobs("test", function () os.sleep(10000) end, { progress = { chars = {'/','\'} } }) -- see module utils.progress --- runjobs("test", function () os.sleep(10000) end, { progress = true, progress_refresh = true }) -- enable progress refresh timer for multirow progress +-- runjobs("test", function () os.sleep(10000) end, { waiting_indicator = true }) +-- runjobs("test", function () os.sleep(10000) end, { waiting_indicator = { chars = {'/','\'} } }) -- see module utils.waiting_indicator +-- runjobs("test", function () os.sleep(10000) end, { waiting_indicator = true, progress_refresh = true }) -- enable progress refresh timer for multirow progress -- -- local jobs = jobpool.new() -- local root = jobs:addjob("job/root", function (index, total, opt) @@ -363,10 +365,10 @@ function main(name, jobs, opt) scheduler.co_group_begin(group_timer, function (co_group) scheduler.co_start_withopt({name = name .. "/timer", isolate = opt.isolate}, _timer_loop, state) end) - elseif state.show_progress then + elseif state.show_waiting_indicator then group_timer = state.group_name .. "/timer" scheduler.co_group_begin(group_timer, function (co_group) - scheduler.co_start_withopt({name = name .. "/tips", isolate = opt.isolate}, _progress_loop, state) + scheduler.co_start_withopt({name = name .. "/tips", isolate = opt.isolate}, _waiting_indicator_loop, state) end) end @@ -445,9 +447,9 @@ function main(name, jobs, opt) -- stop progress progress.show_abort() - if state.show_progress then + if state.show_waiting_indicator then _print_backchars(state.backnum) - state.progress_helper:stop() + state.waiting_indicator_helper:stop() end -- do exit callback diff --git a/xmake/modules/private/action/require/impl/download_packages.lua b/xmake/modules/private/action/require/impl/download_packages.lua index 4dfe1db9b..9536b1330 100644 --- a/xmake/modules/private/action/require/impl/download_packages.lua +++ b/xmake/modules/private/action/require/impl/download_packages.lua @@ -25,7 +25,7 @@ import("core.base.scheduler") import("core.project.project") import("core.base.tty") import("async.runjobs") -import("utils.progress") +import("utils.waiting_indicator", {alias = "waiting_indicator"}) import("net.fasturl") import("private.action.require.impl.package") import("private.action.require.impl.register_packages") @@ -127,7 +127,7 @@ function _download_packages(packages_download) local term_mode_stdout = tty.term_mode("stdout") -- do download - local progress_helper = show_wait and progress.new() or nil + local waiting_indicator_instance = show_wait and waiting_indicator.new() or nil local packages_downloading = {} local packages_pending = table.copy(packages_download) local working_count = 0 @@ -215,14 +215,14 @@ function _download_packages(packages_download) end -- trace - progress_helper:clear() + waiting_indicator_instance:clear() tty.erase_line_to_start().cr() cprintf("${yellow} => ") if #downloading > 0 then cprintf("downloading ${color.dump.string}%s", table.concat(downloading, ", ")) end cprintf(" .. %s", tips and ("${dim}" .. tips .. "${clear} ") or "") - progress_helper:write() + waiting_indicator_instance:write() end, exit = function(errors) if errors then tty.erase_line_to_start().cr() diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua index dea96b3f8..d719d1544 100644 --- a/xmake/modules/private/action/require/impl/install_packages.lua +++ b/xmake/modules/private/action/require/impl/install_packages.lua @@ -25,7 +25,7 @@ import("core.base.scheduler") import("core.project.project") import("core.base.tty") import("async.runjobs") -import("utils.progress") +import("utils.waiting_indicator", {alias = "waiting_indicator"}) import("net.fasturl") import("private.action.require.impl.package") import("private.action.require.impl.lock_packages") @@ -414,7 +414,7 @@ function _do_install_packages(packages_install, packages_download, installdeps) local term_mode_stdout = tty.term_mode("stdout") -- do install - local progress_helper = show_wait and progress.new() or nil + local waiting_indicator_instance = show_wait and waiting_indicator.new() or nil local packages_installing = {} local packages_downloading = {} local packages_pending = table.copy(packages_install) @@ -606,7 +606,7 @@ function _do_install_packages(packages_install, packages_download, installdeps) end -- trace - progress_helper:clear() + waiting_indicator_instance:clear() tty.erase_line_to_start().cr() cprintf("${yellow} => ") if #downloading > 0 then @@ -616,7 +616,7 @@ function _do_install_packages(packages_install, packages_download, installdeps) cprintf("%sinstalling ${color.dump.string}%s", #downloading > 0 and ", " or "", table.concat(installing, ", ")) end cprintf(" .. %s", tips and ("${dim}" .. tips .. "${clear} ") or "") - progress_helper:write() + waiting_indicator_instance:write() end, exit = function(errors) if errors then tty.erase_line_to_start().cr() diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 60066ddc5..9cc4c53ac 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -20,61 +20,17 @@ -- imports import("core.base.option") -import("core.base.object") import("core.base.colors") import("core.base.tty") import("core.base.scheduler") import("core.theme.theme") import("core.project.project") --- define module -local progress = progress or object { _init = { "_RUNNING", "_INDEX", "_STREAM", "_OPT" } } - -- cache color strings local COLOR_SUPERSLOW = "${color.build.progress_superslow}" local COLOR_VERYSLOW = "${color.build.progress_veryslow}" local COLOR_SLOW = "${color.build.progress_slow}" --- stop the progress indicator, clear written frames -function progress:stop() - if self._RUNNING ~= 0 then - self:clear() - self._RUNNING = 0 - self._INDEX = 0 - end -end - -function progress:_clear() - if self._RUNNING == 1 then - tty.erase_line_to_end() - self._RUNNING = 2 - return true - end -end - --- clear previous frame of the progress indicator -function progress:clear() - if self:_clear() then - self._STREAM:flush() - end -end - --- write next frame of the progress indicator -function progress:write() - local chars = self._OPT.chars[self._INDEX % #self._OPT.chars + 1] - tty.cursor_and_attrs_save() - self._STREAM:write(chars) - self._STREAM:flush() - tty.cursor_and_attrs_restore() - self._INDEX = self._INDEX + 1 - self._RUNNING = 1 -end - --- check if the progress indicator is running -function progress:running() - return self._RUNNING and true or false -end - -- is scroll output? function _is_scroll() local is_scroll = _g.is_scroll @@ -475,15 +431,3 @@ function text(progress, format, ...) end end --- build a progress indicator --- @params stream - stream to write to, will use io.stdout if not provided --- @params opt - options --- - chars - an array of chars for progress indicator -function new(stream, opt) - stream = stream or io.stdout - opt = opt or {} - if opt.chars == nil or #opt.chars == 0 then - opt.chars = theme.get("text.spinner.chars") - end - return progress {_OPT = opt, _STREAM = stream, _RUNNING = 0, _INDEX = 0} -end diff --git a/xmake/modules/utils/waiting_indicator.lua b/xmake/modules/utils/waiting_indicator.lua new file mode 100644 index 000000000..afa5cfb6d --- /dev/null +++ b/xmake/modules/utils/waiting_indicator.lua @@ -0,0 +1,83 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, Xmake Open Source Community. +-- +-- @author ruki +-- @file waiting_indicator.lua +-- + +-- imports +import("core.base.object") +import("core.base.tty") +import("core.theme.theme") + +-- define module +local waiting_indicator = waiting_indicator or object { _init = { "_RUNNING", "_INDEX", "_STREAM", "_OPT" } } + +-- stop the waiting indicator, clear written frames +function waiting_indicator:stop() + if self._RUNNING ~= 0 then + self:clear() + self._RUNNING = 0 + self._INDEX = 0 + end +end + +function waiting_indicator:_clear() + if self._RUNNING == 1 then + tty.erase_line_to_end() + self._RUNNING = 2 + return true + end +end + +-- clear previous frame of the waiting indicator +function waiting_indicator:clear() + if self:_clear() then + self._STREAM:flush() + end +end + +-- write next frame of the waiting indicator +function waiting_indicator:write() + local chars = self._OPT.chars[self._INDEX % #self._OPT.chars + 1] + tty.cursor_and_attrs_save() + self._STREAM:write(chars) + self._STREAM:flush() + tty.cursor_and_attrs_restore() + self._INDEX = self._INDEX + 1 + self._RUNNING = 1 +end + +-- check if the waiting indicator is running +function waiting_indicator:running() + return self._RUNNING and true or false +end + +-- build a waiting indicator +-- @params stream - stream to write to, will use io.stdout if not provided +-- @params opt - options +-- - chars - an array of chars for waiting indicator +function new(stream, opt) + stream = stream or io.stdout + opt = opt or {} + if opt.chars == nil or #opt.chars == 0 then + opt.chars = theme.get("text.spinner.chars") + end + return waiting_indicator {_OPT = opt, _STREAM = stream, _RUNNING = 0, _INDEX = 0} +end + +return {new = new} + diff --git a/xmake/plugins/repo/main.lua b/xmake/plugins/repo/main.lua index 40dad5c20..f11e350c5 100644 --- a/xmake/plugins/repo/main.lua +++ b/xmake/plugins/repo/main.lua @@ -150,7 +150,7 @@ function _update() if option.get("verbose") then task() else - runjobs("update repo", task, {progress = true, isolate = true}) + runjobs("update repo", task, {waiting_indicator = true, isolate = true}) end -- leave environment diff --git a/xmake/rules/go/env/xmake.lua b/xmake/rules/go/env/xmake.lua index 764ca65b5..5ac24297a 100644 --- a/xmake/rules/go/env/xmake.lua +++ b/xmake/rules/go/env/xmake.lua @@ -68,7 +68,7 @@ rule("go.env") if option.get("verbose") then build_task() else - runjobs("build/goenv", build_task, {progress = true}) + runjobs("build/goenv", build_task, {waiting_indicator = true}) end end end |
