From 8ec1b785c8c353a22f48fde609b5fbee8ffb2669 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 28 Oct 2025 22:44:42 +0800 Subject: improve progress --- xmake/modules/utils/progress.lua | 105 +++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 33 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 264ab3bfd..7682d4bad 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -68,6 +68,73 @@ function progress:running() return self._RUNNING and true or false end +-- is scroll output? +function _is_scroll() + local is_scroll = _g.is_scroll + if is_scroll == nil then + local style = theme.get("text.build.progress_style") or "scroll" + if style == "scroll" then + is_scroll = true + end + _g.is_scroll = is_scroll + end + return is_scroll +end + +-- is single-row refresh output? +function _is_singlerow_refresh() + local is_singlerow_refresh = _g.is_singlerow_refresh + if is_singlerow_refresh == nil then + local style = theme.get("text.build.progress_style") + if style == "singlerow_refresh" then + is_singlerow_refresh = true + end + _g.is_singlerow_refresh = is_singlerow_refresh + end + return is_singlerow_refresh +end + +-- show progress with verbose information +function _show_progress_with_verbose(progress, format, ...) + progress = type(progress) == "table" and progress:percent() or math.floor(progress) + local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + cprint(progress_prefix .. "${dim}" .. format, progress, ...) +end + +-- show progress with scroll +function _show_progress_with_scroll(progress, format, ...) + progress = type(progress) == "table" and progress:percent() or math.floor(progress) + local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + cprint(progress_prefix .. format, progress, ...) +end + +-- show progress with single-row refresh (ninja style) +function _show_progress_with_singlerow_refresh(progress, format, ...) + progress = type(progress) == "table" and progress:percent() or math.floor(progress) + local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + + tty.erase_line_to_start().cr() + local msg = vformat(progress_prefix .. format, progress, ...) + local msg_plain = colors.translate(msg, {plain = true}) + local maxwidth = os.getwinsize().width + if #msg_plain <= maxwidth then + cprintf(msg) + else + -- windows width is too small? strip the partial message in middle + local partlen = math.floor(maxwidth / 2) - 3 + local sep = msg_plain:sub(partlen + 1, #msg_plain - partlen - 1) + local split = msg:split(sep, {plain = true, strict = true}) + cprintf(table.concat(split, "...")) + end + if math.floor(progress) == 100 then + print("") + _g.showing_without_scroll = false + else + _g.showing_without_scroll = true + end + io.flush() +end + -- showing progress line without scroll? function showing_without_scroll() return _g.showing_without_scroll @@ -78,37 +145,11 @@ function show(progress, format, ...) progress = type(progress) == "table" and progress:percent() or math.floor(progress) local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " if option.get("verbose") then - cprint(progress_prefix .. "${dim}" .. format, progress, ...) - else - local is_scroll = _g.is_scroll - if is_scroll == nil then - is_scroll = theme.get("text.build.progress_style") == "scroll" - _g.is_scroll = is_scroll - end - if is_scroll then - cprint(progress_prefix .. format, progress, ...) - else - tty.erase_line_to_start().cr() - local msg = vformat(progress_prefix .. format, progress, ...) - local msg_plain = colors.translate(msg, {plain = true}) - local maxwidth = os.getwinsize().width - if #msg_plain <= maxwidth then - cprintf(msg) - else - -- windows width is too small? strip the partial message in middle - local partlen = math.floor(maxwidth / 2) - 3 - local sep = msg_plain:sub(partlen + 1, #msg_plain - partlen - 1) - local split = msg:split(sep, {plain = true, strict = true}) - cprintf(table.concat(split, "...")) - end - if math.floor(progress) == 100 then - print("") - _g.showing_without_scroll = false - else - _g.showing_without_scroll = true - end - io.flush() - end + _show_progress_with_verbose(progress, format, ...) + elseif _is_scroll() then + _show_progress_with_scroll(progress, format, ...) + elseif _is_singlerow_refresh() then + _show_progress_with_singlerow_refresh(progress, format, ...) end end @@ -128,8 +169,6 @@ end -- @params opt - options -- - chars - an array of chars for progress indicator function new(stream, opt) - - -- set default values stream = stream or io.stdout opt = opt or {} if opt.chars == nil or #opt.chars == 0 then -- cgit v1.3.1 From d5caf9d3f6055c8565caac2a8a0d2b8503beb996 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 28 Oct 2025 22:46:24 +0800 Subject: check tty --- xmake/modules/utils/progress.lua | 29 ++++++++++++++++++++++++++++- xmake/themes/default/xmake.lua | 2 +- 2 files changed, 29 insertions(+), 2 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 7682d4bad..f202b11f3 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -81,12 +81,25 @@ function _is_scroll() return is_scroll end +-- is multi-row refresh output? +function _is_multirow_refresh() + local is_multirow_refresh = _g.is_multirow_refresh + if is_multirow_refresh == nil then + local style = theme.get("text.build.progress_style") + if style == "multirow_refresh" and tty.has_vtansi() and io.isatty() then + is_multirow_refresh = true + end + _g.is_multirow_refresh = is_multirow_refresh + end + return is_multirow_refresh +end + -- is single-row refresh output? function _is_singlerow_refresh() local is_singlerow_refresh = _g.is_singlerow_refresh if is_singlerow_refresh == nil then local style = theme.get("text.build.progress_style") - if style == "singlerow_refresh" then + if style == "singlerow_refresh" and tty.has_vtansi() and io.isatty() then is_singlerow_refresh = true end _g.is_singlerow_refresh = is_singlerow_refresh @@ -108,6 +121,16 @@ function _show_progress_with_scroll(progress, format, ...) cprint(progress_prefix .. format, progress, ...) end +-- show progress with multi-row refresh +-- @see https://github.com/xmake-io/xmake/issues/6805 +function _show_progress_with_multirow_refresh(progress, format, ...) + progress = type(progress) == "table" and progress:percent() or math.floor(progress) + local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + + -- TODO + print("todo") +end + -- show progress with single-row refresh (ninja style) function _show_progress_with_singlerow_refresh(progress, format, ...) progress = type(progress) == "table" and progress:percent() or math.floor(progress) @@ -148,8 +171,12 @@ function show(progress, format, ...) _show_progress_with_verbose(progress, format, ...) elseif _is_scroll() then _show_progress_with_scroll(progress, format, ...) + elseif _is_multirow_refresh() then + _show_progress_with_multirow_refresh(progress, format, ...) elseif _is_singlerow_refresh() then _show_progress_with_singlerow_refresh(progress, format, ...) + else + _show_progress_with_scroll(progress, format, ...) end end diff --git a/xmake/themes/default/xmake.lua b/xmake/themes/default/xmake.lua index d9c0a48ab..ee0c3a0b9 100644 --- a/xmake/themes/default/xmake.lua +++ b/xmake/themes/default/xmake.lua @@ -43,7 +43,7 @@ theme("default") -- the building progress set_text("build.progress_format", "[%3d%%]") - set_text("build.progress_style", "scroll") + set_text("build.progress_style", "multirow_refresh") set_color("build.progress", "green bright") -- the building object file -- cgit v1.3.1 From 8ab036cbb9ce3870be032f1aea5920061dc351e2 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 28 Oct 2025 22:54:46 +0800 Subject: impl multi-row output --- xmake/modules/utils/progress.lua | 78 ++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 22 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index f202b11f3..3e138b375 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -23,6 +23,7 @@ import("core.base.option") import("core.base.object") import("core.base.colors") import("core.base.tty") +import("core.base.scheduler") import("core.theme.theme") -- define module @@ -107,16 +108,30 @@ function _is_singlerow_refresh() return is_singlerow_refresh end +-- get progress line +function _get_progress_line(progress, format, ...) + local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + local msg = vformat(progress_prefix .. format, progress, ...) + local msg_plain = colors.translate(msg, {plain = true}) + local maxwidth = os.getwinsize().width + if #msg_plain > maxwidth then + -- windows width is too small? strip the partial message in middle + local partlen = math.floor(maxwidth / 2) - 3 + local sep = msg_plain:sub(partlen + 1, #msg_plain - partlen - 1) + local split = msg:split(sep, {plain = true, strict = true}) + msg = table.concat(split, "...") + end + return msg +end + -- show progress with verbose information function _show_progress_with_verbose(progress, format, ...) - progress = type(progress) == "table" and progress:percent() or math.floor(progress) local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " cprint(progress_prefix .. "${dim}" .. format, progress, ...) end -- show progress with scroll function _show_progress_with_scroll(progress, format, ...) - progress = type(progress) == "table" and progress:percent() or math.floor(progress) local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " cprint(progress_prefix .. format, progress, ...) end @@ -124,32 +139,51 @@ end -- show progress with multi-row refresh -- @see https://github.com/xmake-io/xmake/issues/6805 function _show_progress_with_multirow_refresh(progress, format, ...) - progress = type(progress) == "table" and progress:percent() or math.floor(progress) - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + local running = scheduler.co_running() + if not running then + _show_progress_with_scroll(progress, format, ...) + return + end + + local is_finished = math.floor(progress) == 100 + local progress_line = _get_progress_line(progress, format, ...) + local progress_lines = _g.progress_lines + if progress_lines == nil then + progress_lines = {} + _g.progress_lines = progress_lines + end + progress_lines[running] = progress_line + + local previous_line_count = _g.previous_line_count or 0 + if previous_line_count > 0 then + tty.cursor_move_up(previous_line_count) + end - -- TODO - print("todo") + local line_count = 0 + for _, progress_line in table.orderpairs(progress_lines) do + tty.erase_line_to_start().cr() + cprint(progress_line) + line_count = line_count + 1 + end + if is_finished then + print("") + _g.showing_without_scroll = false + _g.progress_lines = nil + _g.previous_line_count = 0 + else + _g.showing_without_scroll = true + _g.previous_line_count = line_count + end + io.flush() end -- show progress with single-row refresh (ninja style) function _show_progress_with_singlerow_refresh(progress, format, ...) - progress = type(progress) == "table" and progress:percent() or math.floor(progress) - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " - + local is_finished = math.floor(progress) == 100 + local progress_line = _get_progress_line(progress, format, ...) tty.erase_line_to_start().cr() - local msg = vformat(progress_prefix .. format, progress, ...) - local msg_plain = colors.translate(msg, {plain = true}) - local maxwidth = os.getwinsize().width - if #msg_plain <= maxwidth then - cprintf(msg) - else - -- windows width is too small? strip the partial message in middle - local partlen = math.floor(maxwidth / 2) - 3 - local sep = msg_plain:sub(partlen + 1, #msg_plain - partlen - 1) - local split = msg:split(sep, {plain = true, strict = true}) - cprintf(table.concat(split, "...")) - end - if math.floor(progress) == 100 then + cprintf(progress_line) + if is_finished then print("") _g.showing_without_scroll = false else -- cgit v1.3.1 From 94d9242722047708b23a30656c3bfed8550eaab0 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 28 Oct 2025 23:01:32 +0800 Subject: optimize to show progress --- xmake/modules/utils/progress.lua | 53 ++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 16 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 3e138b375..addf553da 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -121,7 +121,7 @@ function _get_progress_line(progress, format, ...) local split = msg:split(sep, {plain = true, strict = true}) msg = table.concat(split, "...") end - return msg + return msg, math.min(#msg, maxwidth) end -- show progress with verbose information @@ -145,34 +145,55 @@ function _show_progress_with_multirow_refresh(progress, format, ...) return end + -- get progress line local is_finished = math.floor(progress) == 100 - local progress_line = _get_progress_line(progress, format, ...) - local progress_lines = _g.progress_lines - if progress_lines == nil then - progress_lines = {} - _g.progress_lines = progress_lines + local progress_line, line_charnum = _get_progress_line(progress, format, ...) + local progress_lineinfos = _g.progress_lineinfos + if progress_lineinfos == nil then + progress_lineinfos = {} + _g.progress_lineinfos = progress_lineinfos + tty.cursor_hide() end - progress_lines[running] = progress_line - local previous_line_count = _g.previous_line_count or 0 - if previous_line_count > 0 then - tty.cursor_move_up(previous_line_count) + -- update line count + local linecount = _g.linecount + if linecount == nil then + linecount = 0 + else + linecount = linecount + 1 end + _g.linecount = linecount - local line_count = 0 - for _, progress_line in table.orderpairs(progress_lines) do + -- update the progress line + local lineinfo = progress_lineinfos[running] + if lineinfo == nil then + lineinfo = {progress_line = progress_line, line_index = linecount, line_charnum = line_charnum} + progress_lineinfos[running] = lineinfo tty.erase_line_to_start().cr() cprint(progress_line) - line_count = line_count + 1 + else + lineinfo.progress_line = progress_line + local moveline = lineinfo.line_index + local line_charnum = lineinfo.line_charnum + if moveline > 0 then + tty.cursor_move_up(moveline) + if line_charnum > 0 then + tty.cursor_move_to_col(line_charnum) + end + tty.erase_line_to_start().cr() + cprintf(progress_line) + tty.cursor_move_down(moveline) + end end + if is_finished then print("") _g.showing_without_scroll = false - _g.progress_lines = nil - _g.previous_line_count = 0 + _g.progress_lineinfos = nil + _g.linecount = 0 + tty.cursor_show() else _g.showing_without_scroll = true - _g.previous_line_count = line_count end io.flush() end -- cgit v1.3.1 From 9773535b0c6989dffcc01d42035c0d50f58ddd51 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 28 Oct 2025 23:18:26 +0800 Subject: improve progress --- xmake/modules/utils/progress.lua | 67 ++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 33 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index addf553da..6dc90d309 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -108,10 +108,8 @@ function _is_singlerow_refresh() return is_singlerow_refresh end --- get progress line -function _get_progress_line(progress, format, ...) - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " - local msg = vformat(progress_prefix .. format, progress, ...) +-- strip progress line +function _strip_progress_line(msg) local msg_plain = colors.translate(msg, {plain = true}) local maxwidth = os.getwinsize().width if #msg_plain > maxwidth then @@ -121,7 +119,7 @@ function _get_progress_line(progress, format, ...) local split = msg:split(sep, {plain = true, strict = true}) msg = table.concat(split, "...") end - return msg, math.min(#msg, maxwidth) + return msg end -- show progress with verbose information @@ -146,44 +144,47 @@ function _show_progress_with_multirow_refresh(progress, format, ...) end -- get progress line + local is_first = false local is_finished = math.floor(progress) == 100 - local progress_line, line_charnum = _get_progress_line(progress, format, ...) + local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + local progress_msg = vformat(format, ...) + local progress_line = _strip_progress_line(vformat(progress_prefix, progress) .. progress_msg) local progress_lineinfos = _g.progress_lineinfos if progress_lineinfos == nil then progress_lineinfos = {} _g.progress_lineinfos = progress_lineinfos tty.cursor_hide() + is_first = true end - -- update line count - local linecount = _g.linecount - if linecount == nil then - linecount = 0 - else - linecount = linecount + 1 - end - _g.linecount = linecount - - -- update the progress line + -- update the progress info + local linecount = _g.linecount or 0 local lineinfo = progress_lineinfos[running] + local current_time = os.mclock() if lineinfo == nil then - lineinfo = {progress_line = progress_line, line_index = linecount, line_charnum = line_charnum} + _g.linecount = linecount + 1 + local subprogress_line = _strip_progress_line(" ${dim}0.00s " .. progress_msg) + lineinfo = {progress_line = subprogress_line, running = running, start_time = current_time} progress_lineinfos[running] = lineinfo - tty.erase_line_to_start().cr() - cprint(progress_line) else - lineinfo.progress_line = progress_line - local moveline = lineinfo.line_index - local line_charnum = lineinfo.line_charnum - if moveline > 0 then - tty.cursor_move_up(moveline) - if line_charnum > 0 then - tty.cursor_move_to_col(line_charnum) - end - tty.erase_line_to_start().cr() - cprintf(progress_line) - tty.cursor_move_down(moveline) - end + local subprogress_line = _strip_progress_line(vformat(" ${dim}%0.02fs ", (current_time - lineinfo.start_time) / 1000) .. progress_msg) + lineinfo.progress_line = subprogress_line + lineinfo.start_time = current_time + end + + local maxwidth = os.getwinsize().width + if not is_first and linecount > 0 then + tty.cursor_move_to_col(maxwidth) + tty.cursor_move_up(linecount + 1) + end + + tty.erase_line_to_start().cr() + cprint(progress_line) + + for _, progress_lineinfo in table.orderpairs(progress_lineinfos) do + tty.cursor_move_to_col(maxwidth) + tty.erase_line_to_start().cr() + cprint(progress_lineinfo.progress_line) end if is_finished then @@ -201,9 +202,9 @@ end -- show progress with single-row refresh (ninja style) function _show_progress_with_singlerow_refresh(progress, format, ...) local is_finished = math.floor(progress) == 100 - local progress_line = _get_progress_line(progress, format, ...) + local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " tty.erase_line_to_start().cr() - cprintf(progress_line) + cprintf(progress_prefix .. format, progress, ...) if is_finished then print("") _g.showing_without_scroll = false -- cgit v1.3.1 From bfb71ee9883ac2d0e115913f089bef36899645c2 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 28 Oct 2025 23:21:16 +0800 Subject: sort progress --- xmake/modules/utils/progress.lua | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 6dc90d309..28e1a7eb9 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -163,14 +163,21 @@ function _show_progress_with_multirow_refresh(progress, format, ...) local current_time = os.mclock() if lineinfo == nil then _g.linecount = linecount + 1 - local subprogress_line = _strip_progress_line(" ${dim}0.00s " .. progress_msg) - lineinfo = {progress_line = subprogress_line, running = running, start_time = current_time} + lineinfo = {start_time = current_time, spent_time = 0} progress_lineinfos[running] = lineinfo else - local subprogress_line = _strip_progress_line(vformat(" ${dim}%0.02fs ", (current_time - lineinfo.start_time) / 1000) .. progress_msg) - lineinfo.progress_line = subprogress_line + lineinfo.spent_time = current_time - lineinfo.start_time lineinfo.start_time = current_time end + local timecolor = "" + local spent_time = lineinfo.spent_time + if spent_time > 1000 then + timecolor = "${magenta}" + elseif spent_time > 500 then + timecolor = "${yellow}" + end + local subprogress_line = _strip_progress_line(vformat(" ${dim}> %s%0.02fs${clear}${dim} ", timecolor, spent_time / 1000) .. progress_msg) + lineinfo.progress_line = subprogress_line local maxwidth = os.getwinsize().width if not is_first and linecount > 0 then @@ -181,10 +188,15 @@ function _show_progress_with_multirow_refresh(progress, format, ...) tty.erase_line_to_start().cr() cprint(progress_line) - for _, progress_lineinfo in table.orderpairs(progress_lineinfos) do + local lineinfos = {} + for _, progress_lineinfo in pairs(progress_lineinfos) do + table.insert(lineinfos, progress_lineinfo) + end + table.sort(lineinfos, function (a, b) return a.spent_time > b.spent_time end) + for _, lineinfo in ipairs(lineinfos) do tty.cursor_move_to_col(maxwidth) tty.erase_line_to_start().cr() - cprint(progress_lineinfo.progress_line) + cprint(lineinfo.progress_line) end if is_finished then -- cgit v1.3.1 From b0d93f0996b95ee5e74b0ddbca3237d7734a789f Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Oct 2025 00:56:54 +0800 Subject: improve theme --- xmake/modules/utils/progress.lua | 8 +++----- xmake/themes/default/xmake.lua | 3 +++ 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 28e1a7eb9..6a8d9e156 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -153,7 +153,6 @@ function _show_progress_with_multirow_refresh(progress, format, ...) if progress_lineinfos == nil then progress_lineinfos = {} _g.progress_lineinfos = progress_lineinfos - tty.cursor_hide() is_first = true end @@ -172,11 +171,11 @@ function _show_progress_with_multirow_refresh(progress, format, ...) local timecolor = "" local spent_time = lineinfo.spent_time if spent_time > 1000 then - timecolor = "${magenta}" + timecolor = "${color.build.progress_veryslow}" elseif spent_time > 500 then - timecolor = "${yellow}" + timecolor = "${color.build.progress_slow}" end - local subprogress_line = _strip_progress_line(vformat(" ${dim}> %s%0.02fs${clear}${dim} ", timecolor, spent_time / 1000) .. progress_msg) + local subprogress_line = _strip_progress_line(vformat(" > %s%0.02fs${clear} ", timecolor, spent_time / 1000) .. progress_msg) lineinfo.progress_line = subprogress_line local maxwidth = os.getwinsize().width @@ -204,7 +203,6 @@ function _show_progress_with_multirow_refresh(progress, format, ...) _g.showing_without_scroll = false _g.progress_lineinfos = nil _g.linecount = 0 - tty.cursor_show() else _g.showing_without_scroll = true end diff --git a/xmake/themes/default/xmake.lua b/xmake/themes/default/xmake.lua index ee0c3a0b9..ee7533afa 100644 --- a/xmake/themes/default/xmake.lua +++ b/xmake/themes/default/xmake.lua @@ -45,6 +45,9 @@ theme("default") set_text("build.progress_format", "[%3d%%]") set_text("build.progress_style", "multirow_refresh") set_color("build.progress", "green bright") + -- only for multirow_refresh + set_color("build.progress_veryslow", "magenta") + set_color("build.progress_slow", "yellow") -- the building object file set_color("build.object", "") -- cgit v1.3.1 From 88e30eca65d91dcdb569a866a35f5cc1d15c1f61 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Oct 2025 22:37:39 +0800 Subject: check idle progress --- xmake/modules/async/runjobs.lua | 2 ++ xmake/modules/utils/progress.lua | 49 +++++++++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 16 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/async/runjobs.lua b/xmake/modules/async/runjobs.lua index e43286a13..be1cc2ad5 100644 --- a/xmake/modules/async/runjobs.lua +++ b/xmake/modules/async/runjobs.lua @@ -196,6 +196,7 @@ function _consume_jobs_loop(state, run_in_remote) end -- run job + co_running:data_set("runjobs.running", true) local job_index = state.finished_count + 1 state.running_jobs_indices[job_index] = job_index if job_func then @@ -206,6 +207,7 @@ function _consume_jobs_loop(state, run_in_remote) job_func(job_index, total, {progress = state.progress_wrapper}) end state.running_jobs_indices[job_index] = nil + co_running:data_set("runjobs.running", false) end, catch { diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 6a8d9e156..c291854ea 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -156,13 +156,21 @@ function _show_progress_with_multirow_refresh(progress, format, ...) is_first = true end - -- update the progress info + -- show the total progress line local linecount = _g.linecount or 0 - local lineinfo = progress_lineinfos[running] + local maxwidth = os.getwinsize().width + if not is_first and linecount > 0 then + tty.cursor_move_to_col(maxwidth) + tty.cursor_move_up(linecount + 1) + end + tty.erase_line_to_start().cr() + cprint(progress_line) + + -- update the subprogress infos local current_time = os.mclock() + local lineinfo = progress_lineinfos[running] if lineinfo == nil then - _g.linecount = linecount + 1 - lineinfo = {start_time = current_time, spent_time = 0} + lineinfo = {start_time = current_time, spent_time = 0, running = running} progress_lineinfos[running] = lineinfo else lineinfo.spent_time = current_time - lineinfo.start_time @@ -175,36 +183,45 @@ function _show_progress_with_multirow_refresh(progress, format, ...) elseif spent_time > 500 then timecolor = "${color.build.progress_slow}" end - local subprogress_line = _strip_progress_line(vformat(" > %s%0.02fs${clear} ", timecolor, spent_time / 1000) .. progress_msg) - lineinfo.progress_line = subprogress_line - - local maxwidth = os.getwinsize().width - if not is_first and linecount > 0 then - tty.cursor_move_to_col(maxwidth) - tty.cursor_move_up(linecount + 1) + if is_finished then + lineinfo.progress_line = nil + else + local subprogress_line = _strip_progress_line(vformat(" > %s%0.02fs${clear} ", timecolor, spent_time / 1000) .. progress_msg) + lineinfo.progress_line = subprogress_line end - tty.erase_line_to_start().cr() - cprint(progress_line) - + -- sort the progress lines by the spent time local lineinfos = {} for _, progress_lineinfo in pairs(progress_lineinfos) do table.insert(lineinfos, progress_lineinfo) end table.sort(lineinfos, function (a, b) return a.spent_time > b.spent_time end) + + -- show the subprocess lines + local linecount = 0 for _, lineinfo in ipairs(lineinfos) do + -- we need not show it if the progress job is idle in runjobs now + local progress_running = lineinfo.running + if progress_running and progress_running:data("runjobs.running") == false then + lineinfo.progress_line = nil + end tty.cursor_move_to_col(maxwidth) tty.erase_line_to_start().cr() - cprint(lineinfo.progress_line) + if lineinfo.progress_line then + cprint(lineinfo.progress_line) + else + print("") + end + linecount = linecount + 1 end if is_finished then - print("") _g.showing_without_scroll = false _g.progress_lineinfos = nil _g.linecount = 0 else _g.showing_without_scroll = true + _g.linecount = linecount end io.flush() end -- cgit v1.3.1 From a0b1b3d0d2d1138856aed1cce9078247b94862e5 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Oct 2025 22:39:08 +0800 Subject: hide cursor --- xmake/modules/utils/progress.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index c291854ea..d17bd876b 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -155,6 +155,12 @@ function _show_progress_with_multirow_refresh(progress, format, ...) _g.progress_lineinfos = progress_lineinfos is_first = true end + if is_first then + tty.cursor_hide() + os.atexit(function (ok, errors) + tty.cursor_show() + end) + end -- show the total progress line local linecount = _g.linecount or 0 @@ -219,6 +225,7 @@ function _show_progress_with_multirow_refresh(progress, format, ...) _g.showing_without_scroll = false _g.progress_lineinfos = nil _g.linecount = 0 + tty.cursor_show() else _g.showing_without_scroll = true _g.linecount = linecount -- cgit v1.3.1 From a2974bf870a7ef03a5cf7c5154d65bc5a38b18fa Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Oct 2025 23:25:41 +0800 Subject: fix linecount --- xmake/modules/utils/progress.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index d17bd876b..fadc443e1 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -204,7 +204,7 @@ function _show_progress_with_multirow_refresh(progress, format, ...) table.sort(lineinfos, function (a, b) return a.spent_time > b.spent_time end) -- show the subprocess lines - local linecount = 0 + linecount = 0 for _, lineinfo in ipairs(lineinfos) do -- we need not show it if the progress job is idle in runjobs now local progress_running = lineinfo.running -- cgit v1.3.1 From d6255d98b9a09366d238e8579b18be9add773222 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Oct 2025 23:58:15 +0800 Subject: add progress.show_output --- .../custom_toolchain/xmake/modules/core/tools/cl6x.lua | 5 +---- xmake/actions/build/deprecated/build.lua | 4 ++-- xmake/modules/core/tools/armasm.lua | 5 +---- xmake/modules/core/tools/armasm_msvc.lua | 5 +---- xmake/modules/core/tools/armcc.lua | 5 +---- xmake/modules/core/tools/armlink.lua | 5 +---- xmake/modules/core/tools/c51.lua | 5 +---- xmake/modules/core/tools/cl.lua | 5 +---- xmake/modules/core/tools/cl2000.lua | 5 +---- xmake/modules/core/tools/cl6x.lua | 5 +---- xmake/modules/core/tools/gcc.lua | 5 +---- xmake/modules/core/tools/iccarm.lua | 5 +---- xmake/modules/core/tools/nvcc.lua | 5 +---- xmake/modules/core/tools/sdasstm8.lua | 7 +------ xmake/modules/core/tools/sdcc.lua | 5 +---- xmake/modules/utils/progress.lua | 14 +++++++++----- 16 files changed, 25 insertions(+), 65 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/tests/apis/custom_toolchain/xmake/modules/core/tools/cl6x.lua b/tests/apis/custom_toolchain/xmake/modules/core/tools/cl6x.lua index ba6bc6e5e..37ceec0b8 100644 --- a/tests/apis/custom_toolchain/xmake/modules/core/tools/cl6x.lua +++ b/tests/apis/custom_toolchain/xmake/modules/core/tools/cl6x.lua @@ -183,10 +183,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) -- print some warnings if warnings and #warnings > 0 and policy.build_warnings(opt) then - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) + progress.show_output("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) end -- generate the dependent includes diff --git a/xmake/actions/build/deprecated/build.lua b/xmake/actions/build/deprecated/build.lua index 336a7bb0d..26c86c9a3 100644 --- a/xmake/actions/build/deprecated/build.lua +++ b/xmake/actions/build/deprecated/build.lua @@ -273,8 +273,8 @@ function main(targets_root, opt) local curdir = os.curdir() runjobs("build", batchjobs, {on_exit = function (errors) import("utils.progress") - if errors and progress.showing_without_scroll() then - print("") + if errors then + progress.show_output(errors) end end, comax = option.get("jobs") or 1, curdir = curdir, distcc = distcc}) os.cd(curdir) diff --git a/xmake/modules/core/tools/armasm.lua b/xmake/modules/core/tools/armasm.lua index 33b77d915..2324e7d16 100644 --- a/xmake/modules/core/tools/armasm.lua +++ b/xmake/modules/core/tools/armasm.lua @@ -128,10 +128,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) -- print some warnings if warnings and #warnings > 0 and policy.build_warnings(opt) then - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) + progress.show_output("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) end end } diff --git a/xmake/modules/core/tools/armasm_msvc.lua b/xmake/modules/core/tools/armasm_msvc.lua index 3afac67f4..f62820ce2 100644 --- a/xmake/modules/core/tools/armasm_msvc.lua +++ b/xmake/modules/core/tools/armasm_msvc.lua @@ -122,10 +122,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) -- print some warnings if warnings and #warnings > 0 and policy.build_warnings(opt) then - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) + progress.show_output("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) end end } diff --git a/xmake/modules/core/tools/armcc.lua b/xmake/modules/core/tools/armcc.lua index 93d59aa8d..5179796c7 100644 --- a/xmake/modules/core/tools/armcc.lua +++ b/xmake/modules/core/tools/armcc.lua @@ -177,10 +177,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) -- print some warnings if warnings and #warnings > 0 and policy.build_warnings(opt) then - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) + progress.show_output("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) end -- generate the dependent includes diff --git a/xmake/modules/core/tools/armlink.lua b/xmake/modules/core/tools/armlink.lua index 8b8639754..7d5184a50 100644 --- a/xmake/modules/core/tools/armlink.lua +++ b/xmake/modules/core/tools/armlink.lua @@ -116,10 +116,7 @@ function link(self, objectfiles, targetkind, targetfile, flags, opt) lines = table.slice(lines, 1, (#lines > 16 and 16 or #lines)) end local warnings = table.concat(lines, "\n") - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", warnings) + progress.show_output("${color.warning}%s", warnings) end end diff --git a/xmake/modules/core/tools/c51.lua b/xmake/modules/core/tools/c51.lua index 0df971f8d..87a602fcc 100644 --- a/xmake/modules/core/tools/c51.lua +++ b/xmake/modules/core/tools/c51.lua @@ -119,10 +119,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) lines = table.slice(lines, 1, (#lines > 16 and 16 or #lines)) end local warnings = table.concat(lines, "\n") - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", warnings) + progress.show_output("${color.warning}%s", warnings) end end end diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua index 0a6416ded..fa88ab5a4 100644 --- a/xmake/modules/core/tools/cl.lua +++ b/xmake/modules/core/tools/cl.lua @@ -764,10 +764,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) lines = table.slice(lines, 1, (#lines > 16 and 16 or #lines)) end local warnings = table.concat(lines, "\r\n") - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", warnings) + progress.show_output("${color.warning}%s", warnings) end end end diff --git a/xmake/modules/core/tools/cl2000.lua b/xmake/modules/core/tools/cl2000.lua index 8b8f1f563..b977bc947 100644 --- a/xmake/modules/core/tools/cl2000.lua +++ b/xmake/modules/core/tools/cl2000.lua @@ -183,10 +183,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) -- print some warnings if warnings and #warnings > 0 and policy.build_warnings(opt) then - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) + progress.show_output("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) end -- generate the dependent includes diff --git a/xmake/modules/core/tools/cl6x.lua b/xmake/modules/core/tools/cl6x.lua index ba6bc6e5e..37ceec0b8 100644 --- a/xmake/modules/core/tools/cl6x.lua +++ b/xmake/modules/core/tools/cl6x.lua @@ -183,10 +183,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) -- print some warnings if warnings and #warnings > 0 and policy.build_warnings(opt) then - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) + progress.show_output("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) end -- generate the dependent includes diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua index f4cd684e0..6d5f59fac 100644 --- a/xmake/modules/core/tools/gcc.lua +++ b/xmake/modules/core/tools/gcc.lua @@ -1058,10 +1058,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) lines = table.slice(lines, 1, (#lines > 16 and 16 or #lines)) end local warnings = table.concat(lines, "\n") - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", warnings) + progress.show_output("${color.warning}%s", warnings) end end diff --git a/xmake/modules/core/tools/iccarm.lua b/xmake/modules/core/tools/iccarm.lua index 50f9260cb..c1b763550 100644 --- a/xmake/modules/core/tools/iccarm.lua +++ b/xmake/modules/core/tools/iccarm.lua @@ -141,10 +141,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) -- print some warnings if warnings and #warnings > 0 and not warnings:find("Warnings: none", 1, true) and policy.build_warnings(opt) then - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) + progress.show_output("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) end end } diff --git a/xmake/modules/core/tools/nvcc.lua b/xmake/modules/core/tools/nvcc.lua index aab088bf4..27f0340f5 100644 --- a/xmake/modules/core/tools/nvcc.lua +++ b/xmake/modules/core/tools/nvcc.lua @@ -450,10 +450,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) -- print some warnings if warnings and #warnings > 0 and policy.build_warnings(opt) then - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n', {plain = true}), 1, 8), '\n')) + progress.show_output("${color.warning}%s", table.concat(table.slice(warnings:split('\n', {plain = true}), 1, 8), '\n')) end -- generate the dependent includes diff --git a/xmake/modules/core/tools/sdasstm8.lua b/xmake/modules/core/tools/sdasstm8.lua index 883d31345..b9ad0e153 100644 --- a/xmake/modules/core/tools/sdasstm8.lua +++ b/xmake/modules/core/tools/sdasstm8.lua @@ -83,13 +83,8 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) finally { function (ok, warnings) - - -- print some warnings if warnings and #warnings > 0 and policy.build_warnings(opt) then - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) + progress.show_output("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) end end } diff --git a/xmake/modules/core/tools/sdcc.lua b/xmake/modules/core/tools/sdcc.lua index b6461cafe..ebf8ef519 100644 --- a/xmake/modules/core/tools/sdcc.lua +++ b/xmake/modules/core/tools/sdcc.lua @@ -234,10 +234,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt) -- show warnings if warnings and #warnings > 0 and policy.build_warnings(opt) then - if progress.showing_without_scroll() then - print("") - end - cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) + progress.show_output("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n')) end -- generate the dependent includes diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index fadc443e1..ca6a9ec01 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -248,11 +248,6 @@ function _show_progress_with_singlerow_refresh(progress, format, ...) io.flush() end --- showing progress line without scroll? -function showing_without_scroll() - return _g.showing_without_scroll -end - -- show the message with progress function show(progress, format, ...) progress = type(progress) == "table" and progress:percent() or math.floor(progress) @@ -270,6 +265,15 @@ function show(progress, format, ...) end end +-- print additional output logs with colors outside the progress log area, such as warning logs. +-- it's used when the progress style is multirow/singlerow refresh. +function show_output(format, ...) + if _g.showing_without_scroll then + print("") + end + cprint(format, ...) +end + -- get the message text with progress function text(progress, format, ...) progress = type(progress) == "table" and progress:percent() or math.floor(progress) -- cgit v1.3.1 From 291738879dc7a14540121a7f595124b683d2f8b5 Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 29 Oct 2025 23:59:49 +0800 Subject: improve show_output --- xmake/modules/utils/progress.lua | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index ca6a9ec01..ed2a911c1 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -222,12 +222,12 @@ function _show_progress_with_multirow_refresh(progress, format, ...) end if is_finished then - _g.showing_without_scroll = false + _g.is_refreshing = false _g.progress_lineinfos = nil _g.linecount = 0 tty.cursor_show() else - _g.showing_without_scroll = true + _g.is_refreshing = true _g.linecount = linecount end io.flush() @@ -241,9 +241,9 @@ function _show_progress_with_singlerow_refresh(progress, format, ...) cprintf(progress_prefix .. format, progress, ...) if is_finished then print("") - _g.showing_without_scroll = false + _g.is_refreshing = false else - _g.showing_without_scroll = true + _g.is_refreshing = true end io.flush() end @@ -268,9 +268,11 @@ end -- print additional output logs with colors outside the progress log area, such as warning logs. -- it's used when the progress style is multirow/singlerow refresh. function show_output(format, ...) - if _g.showing_without_scroll then - print("") + if not _g.is_refreshing then + return end + + print("") cprint(format, ...) end -- cgit v1.3.1 From f79809d802ec7a34656ac1991128c192822fc78c Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Oct 2025 00:59:51 +0800 Subject: improve progress spent time --- xmake/actions/build/deprecated/build.lua | 2 +- xmake/modules/private/action/build/target.lua | 8 ++--- xmake/modules/utils/progress.lua | 50 +++++++++++++++------------ 3 files changed, 33 insertions(+), 27 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/actions/build/deprecated/build.lua b/xmake/actions/build/deprecated/build.lua index 26c86c9a3..dd6698b96 100644 --- a/xmake/actions/build/deprecated/build.lua +++ b/xmake/actions/build/deprecated/build.lua @@ -274,7 +274,7 @@ function main(targets_root, opt) runjobs("build", batchjobs, {on_exit = function (errors) import("utils.progress") if errors then - progress.show_output(errors) + progress.show_output("") end end, comax = option.get("jobs") or 1, curdir = curdir, distcc = distcc}) os.cd(curdir) diff --git a/xmake/modules/private/action/build/target.lua b/xmake/modules/private/action/build/target.lua index 19d4db853..315feab61 100644 --- a/xmake/modules/private/action/build/target.lua +++ b/xmake/modules/private/action/build/target.lua @@ -787,8 +787,8 @@ function run_targetjobs(targets_root, opt) local curdir = os.curdir() async_runjobs(job_kind, jobgraph, {on_exit = function (errors) import("utils.progress") - if errors and progress.showing_without_scroll() then - print("") + if errors then + progress.show_output("") end end, comax = opt.jobs or option.get("jobs") or 1, curdir = curdir, @@ -807,8 +807,8 @@ function run_filejobs(targets_root, opt) local curdir = os.curdir() async_runjobs(job_kind, jobgraph, {on_exit = function (errors) import("utils.progress") - if errors and progress.showing_without_scroll() then - print("") + if errors then + progress.show_output("") end end, comax = opt.jobs or option.get("jobs") or 1, curdir = curdir, diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index ed2a911c1..0da5b4cbb 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -172,40 +172,46 @@ function _show_progress_with_multirow_refresh(progress, format, ...) tty.erase_line_to_start().cr() cprint(progress_line) - -- update the subprogress infos + -- update the current progress info local current_time = os.mclock() - local lineinfo = progress_lineinfos[running] - if lineinfo == nil then - lineinfo = {start_time = current_time, spent_time = 0, running = running} - progress_lineinfos[running] = lineinfo - else - lineinfo.spent_time = current_time - lineinfo.start_time - lineinfo.start_time = current_time - end - local timecolor = "" - local spent_time = lineinfo.spent_time - if spent_time > 1000 then - timecolor = "${color.build.progress_veryslow}" - elseif spent_time > 500 then - timecolor = "${color.build.progress_slow}" + local current_lineinfo = progress_lineinfos[running] + if current_lineinfo == nil then + current_lineinfo = {start_time = current_time, spent_time = 0, running = running} + progress_lineinfos[running] = current_lineinfo end if is_finished then - lineinfo.progress_line = nil + current_lineinfo.progress_msg = nil else - local subprogress_line = _strip_progress_line(vformat(" > %s%0.02fs${clear} ", timecolor, spent_time / 1000) .. progress_msg) - lineinfo.progress_line = subprogress_line + current_lineinfo.progress_msg = progress_msg end -- sort the progress lines by the spent time - local lineinfos = {} + local order_lineinfos = {} for _, progress_lineinfo in pairs(progress_lineinfos) do - table.insert(lineinfos, progress_lineinfo) + local progress_msg = progress_lineinfo.progress_msg + if progress_msg then + local timecolor = "" + local spent_time = current_time - progress_lineinfo.start_time + if spent_time > 1000 then + timecolor = "${color.build.progress_veryslow}" + elseif spent_time > 500 then + timecolor = "${color.build.progress_slow}" + end + progress_lineinfo.spent_time = spent_time + local subprogress_line = _strip_progress_line(vformat(" > %s%0.02fs${clear} ", timecolor, spent_time / 1000) .. progress_msg) + progress_lineinfo.progress_line = subprogress_line + table.insert(order_lineinfos, progress_lineinfo) + else + progress_lineinfo.spent_time = 0 + progress_lineinfo.progress_line = nil + end end - table.sort(lineinfos, function (a, b) return a.spent_time > b.spent_time end) + table.sort(order_lineinfos, function (a, b) return a.spent_time > b.spent_time end) + current_lineinfo.start_time = current_time -- show the subprocess lines linecount = 0 - for _, lineinfo in ipairs(lineinfos) do + for _, lineinfo in ipairs(order_lineinfos) do -- we need not show it if the progress job is idle in runjobs now local progress_running = lineinfo.running if progress_running and progress_running:data("runjobs.running") == false then -- cgit v1.3.1 From a584140350e5960a5d5dd87b2fd27e6b5e0ec4db Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Oct 2025 22:08:57 +0800 Subject: add progress color --- xmake/modules/utils/progress.lua | 29 +++++++++++++++++++---------- xmake/themes/soong/xmake.lua | 1 + 2 files changed, 20 insertions(+), 10 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 0da5b4cbb..590ebd105 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -192,7 +192,9 @@ function _show_progress_with_multirow_refresh(progress, format, ...) if progress_msg then local timecolor = "" local spent_time = current_time - progress_lineinfo.start_time - if spent_time > 1000 then + if spent_time > 30000 then + timecolor = "${color.build.progress_superslow}" + elseif spent_time > 1000 then timecolor = "${color.build.progress_veryslow}" elseif spent_time > 500 then timecolor = "${color.build.progress_slow}" @@ -228,12 +230,12 @@ function _show_progress_with_multirow_refresh(progress, format, ...) end if is_finished then - _g.is_refreshing = false + _g.refresh_mode = nil _g.progress_lineinfos = nil _g.linecount = 0 tty.cursor_show() else - _g.is_refreshing = true + _g.refresh_mode = "multirow" _g.linecount = linecount end io.flush() @@ -247,9 +249,9 @@ function _show_progress_with_singlerow_refresh(progress, format, ...) cprintf(progress_prefix .. format, progress, ...) if is_finished then print("") - _g.is_refreshing = false + _g.refresh_mode = nil else - _g.is_refreshing = true + _g.refresh_mode = "singlerow" end io.flush() end @@ -274,12 +276,19 @@ end -- print additional output logs with colors outside the progress log area, such as warning logs. -- it's used when the progress style is multirow/singlerow refresh. function show_output(format, ...) - if not _g.is_refreshing then - return + local refresh_mode = _g.refresh_mode + if refresh_mode == "singlerow" then + print("") + cprint(format, ...) + elseif refresh_mode == "multirow" then + local linecount = (_g.linecount or 0) + 1 + for i = 1, linecount do + print("") + end + cprint(format, ...) + else + cprint(format, ...) end - - print("") - cprint(format, ...) end -- get the message text with progress diff --git a/xmake/themes/soong/xmake.lua b/xmake/themes/soong/xmake.lua index e418104b8..090e8f017 100644 --- a/xmake/themes/soong/xmake.lua +++ b/xmake/themes/soong/xmake.lua @@ -46,6 +46,7 @@ theme("soong") set_text("build.progress_style", "multirow_refresh") set_color("build.progress", "green bright") -- only for multirow_refresh + set_color("build.progress_superslow", "red") set_color("build.progress_veryslow", "magenta") set_color("build.progress_slow", "yellow") -- cgit v1.3.1 From 10c6280634086074ad5bdcb6c4c4ce6013adcf3c Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Oct 2025 22:44:10 +0800 Subject: improve show_output --- xmake/modules/utils/progress.lua | 161 ++++++++++++++++++++++++++++----------- 1 file changed, 116 insertions(+), 45 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 590ebd105..e3094223b 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -134,6 +134,84 @@ function _show_progress_with_scroll(progress, format, ...) cprint(progress_prefix .. format, progress, ...) end +-- build ordered subprocess line infos from progress_lineinfos (internal helper) +function _build_ordered_subprocess_lineinfos() + local progress_lineinfos = _g.progress_lineinfos + if not progress_lineinfos then + return {} + end + + local current_time = os.mclock() + local order_lineinfos = {} + + for _, progress_lineinfo in pairs(progress_lineinfos) do + local progress_msg = progress_lineinfo.progress_msg + if progress_msg then + local timecolor = "" + local spent_time = current_time - progress_lineinfo.start_time + if spent_time > 30000 then + timecolor = "${color.build.progress_superslow}" + elseif spent_time > 1000 then + timecolor = "${color.build.progress_veryslow}" + elseif spent_time > 500 then + timecolor = "${color.build.progress_slow}" + end + progress_lineinfo.spent_time = spent_time + local subprogress_line = _strip_progress_line(vformat(" > %s%0.02fs${clear} ", timecolor, spent_time / 1000) .. progress_msg) + progress_lineinfo.progress_line = subprogress_line + table.insert(order_lineinfos, progress_lineinfo) + else + progress_lineinfo.spent_time = 0 + progress_lineinfo.progress_line = nil + end + end + + table.sort(order_lineinfos, function (a, b) return a.spent_time > b.spent_time end) + return order_lineinfos +end + +-- display subprocess progress lines (internal helper) +function _display_subprocess_lines(order_lineinfos) + local maxwidth = os.getwinsize().width + local linecount = 0 + + for _, lineinfo in ipairs(order_lineinfos) do + -- we need not show it if the progress job is idle in runjobs now + local progress_running = lineinfo.running + if progress_running and progress_running:data("runjobs.running") == false then + lineinfo.progress_line = nil + end + tty.cursor_move_to_col(maxwidth) + tty.erase_line_to_start().cr() + if lineinfo.progress_line then + cprint(lineinfo.progress_line) + else + print("") + end + linecount = linecount + 1 + end + + _g.linecount = linecount +end + +-- redraw the multirow progress area (internal helper) +function _redraw_multirow_progress() + local last_total_progress = _g.last_total_progress + if not last_total_progress then + return + end + + -- redraw the total progress line + tty.erase_line_to_start().cr() + cprint(last_total_progress) + + -- build and display the subprocess lines + local order_lineinfos = _build_ordered_subprocess_lineinfos() + _display_subprocess_lines(order_lineinfos) + + io.flush() +end + -- show progress with multi-row refresh -- @see https://github.com/xmake-io/xmake/issues/6805 function _show_progress_with_multirow_refresh(progress, format, ...) @@ -172,6 +250,10 @@ function _show_progress_with_multirow_refresh(progress, format, ...) tty.erase_line_to_start().cr() cprint(progress_line) + -- save the total progress line and progress value for potential redraw in show_output + _g.last_total_progress = progress_line + _g.last_total_progress_value = progress + -- update the current progress info local current_time = os.mclock() local current_lineinfo = progress_lineinfos[running] @@ -185,58 +267,20 @@ function _show_progress_with_multirow_refresh(progress, format, ...) current_lineinfo.progress_msg = progress_msg end - -- sort the progress lines by the spent time - local order_lineinfos = {} - for _, progress_lineinfo in pairs(progress_lineinfos) do - local progress_msg = progress_lineinfo.progress_msg - if progress_msg then - local timecolor = "" - local spent_time = current_time - progress_lineinfo.start_time - if spent_time > 30000 then - timecolor = "${color.build.progress_superslow}" - elseif spent_time > 1000 then - timecolor = "${color.build.progress_veryslow}" - elseif spent_time > 500 then - timecolor = "${color.build.progress_slow}" - end - progress_lineinfo.spent_time = spent_time - local subprogress_line = _strip_progress_line(vformat(" > %s%0.02fs${clear} ", timecolor, spent_time / 1000) .. progress_msg) - progress_lineinfo.progress_line = subprogress_line - table.insert(order_lineinfos, progress_lineinfo) - else - progress_lineinfo.spent_time = 0 - progress_lineinfo.progress_line = nil - end - end - table.sort(order_lineinfos, function (a, b) return a.spent_time > b.spent_time end) + -- build and display the subprocess lines + local order_lineinfos = _build_ordered_subprocess_lineinfos() current_lineinfo.start_time = current_time - - -- show the subprocess lines - linecount = 0 - for _, lineinfo in ipairs(order_lineinfos) do - -- we need not show it if the progress job is idle in runjobs now - local progress_running = lineinfo.running - if progress_running and progress_running:data("runjobs.running") == false then - lineinfo.progress_line = nil - end - tty.cursor_move_to_col(maxwidth) - tty.erase_line_to_start().cr() - if lineinfo.progress_line then - cprint(lineinfo.progress_line) - else - print("") - end - linecount = linecount + 1 - end + _display_subprocess_lines(order_lineinfos) if is_finished then _g.refresh_mode = nil _g.progress_lineinfos = nil + _g.last_total_progress = nil + _g.last_total_progress_value = nil _g.linecount = 0 tty.cursor_show() else _g.refresh_mode = "multirow" - _g.linecount = linecount end io.flush() end @@ -281,11 +325,38 @@ function show_output(format, ...) print("") cprint(format, ...) elseif refresh_mode == "multirow" then + -- get the number of fixed progress lines at the bottom + -- +1 for the total progress line local linecount = (_g.linecount or 0) + 1 - for i = 1, linecount do - print("") + local maxwidth = os.getwinsize().width + + -- move to the top of progress area and clear to bottom + tty.cursor_move_to_col(maxwidth) + tty.cursor_move_up(linecount) + tty.erase_down() + tty.cr() + + -- show the current task's progress line before the log output + local progress_lineinfos = _g.progress_lineinfos + if progress_lineinfos then + local running = scheduler.co_running() + if running then + local current_lineinfo = progress_lineinfos[running] + if current_lineinfo and current_lineinfo.progress_msg then + local progress_value = _g.last_total_progress_value or 0 + local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + local progress_line = _strip_progress_line(vformat(progress_prefix, math.floor(progress_value)) .. current_lineinfo.progress_msg) + tty.erase_line_to_end() + cprint(progress_line) + end + end end + + -- print the log output, which will scroll naturally cprint(format, ...) + + -- redraw the progress area immediately + _redraw_multirow_progress() else cprint(format, ...) end -- cgit v1.3.1 From aa46a3037fbd036e060fc86bfc886cc073d7e112 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Oct 2025 22:50:56 +0800 Subject: improve isatty --- xmake/core/base/io.lua | 5 +++++ xmake/modules/utils/progress.lua | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/core/base/io.lua b/xmake/core/base/io.lua index d58d46297..f35c01ab3 100644 --- a/xmake/core/base/io.lua +++ b/xmake/core/base/io.lua @@ -254,6 +254,10 @@ end -- this file is a tty? function _file:isatty() + local isatty_cached = self._ISATTY + if isatty_cached ~= nil then + return isatty_cached + end -- ensure opened local ok, errors = self:_ensure_opened() @@ -266,6 +270,7 @@ function _file:isatty() if ok == nil and errors then errors = string.format("%s: %s", self, errors) end + self._ISATTY = ok return ok, errors end diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index e3094223b..223b7840a 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -269,9 +269,9 @@ function _show_progress_with_multirow_refresh(progress, format, ...) -- build and display the subprocess lines local order_lineinfos = _build_ordered_subprocess_lineinfos() - current_lineinfo.start_time = current_time _display_subprocess_lines(order_lineinfos) + current_lineinfo.start_time = current_time if is_finished then _g.refresh_mode = nil _g.progress_lineinfos = nil -- cgit v1.3.1 From 10273ea53ed499719d8a2884bd652243db7032a1 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Oct 2025 22:55:05 +0800 Subject: fix singlerow progress --- xmake/modules/utils/progress.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 223b7840a..6c07ff662 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -289,8 +289,10 @@ end function _show_progress_with_singlerow_refresh(progress, format, ...) local is_finished = math.floor(progress) == 100 local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + local progress_msg = vformat(format, ...) + local progress_line = _strip_progress_line(vformat(progress_prefix, progress) .. progress_msg) tty.erase_line_to_start().cr() - cprintf(progress_prefix .. format, progress, ...) + cprintf(progress_line) if is_finished then print("") _g.refresh_mode = nil -- cgit v1.3.1 From 172a9f2cc96e68ae4caef115af8546a3935b4b90 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Oct 2025 22:58:07 +0800 Subject: optimize getwinsize --- xmake/modules/utils/progress.lua | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 6c07ff662..efd6e0206 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -109,9 +109,8 @@ function _is_singlerow_refresh() end -- strip progress line -function _strip_progress_line(msg) +function _strip_progress_line(msg, maxwidth) local msg_plain = colors.translate(msg, {plain = true}) - local maxwidth = os.getwinsize().width if #msg_plain > maxwidth then -- windows width is too small? strip the partial message in middle local partlen = math.floor(maxwidth / 2) - 3 @@ -135,7 +134,7 @@ function _show_progress_with_scroll(progress, format, ...) end -- build ordered subprocess line infos from progress_lineinfos (internal helper) -function _build_ordered_subprocess_lineinfos() +function _build_ordered_subprocess_lineinfos(maxwidth) local progress_lineinfos = _g.progress_lineinfos if not progress_lineinfos then return {} @@ -157,7 +156,7 @@ function _build_ordered_subprocess_lineinfos() timecolor = "${color.build.progress_slow}" end progress_lineinfo.spent_time = spent_time - local subprogress_line = _strip_progress_line(vformat(" > %s%0.02fs${clear} ", timecolor, spent_time / 1000) .. progress_msg) + local subprogress_line = _strip_progress_line(vformat(" > %s%0.02fs${clear} ", timecolor, spent_time / 1000) .. progress_msg, maxwidth) progress_lineinfo.progress_line = subprogress_line table.insert(order_lineinfos, progress_lineinfo) else @@ -171,8 +170,7 @@ function _build_ordered_subprocess_lineinfos() end -- display subprocess progress lines (internal helper) -function _display_subprocess_lines(order_lineinfos) - local maxwidth = os.getwinsize().width +function _display_subprocess_lines(order_lineinfos, maxwidth) local linecount = 0 for _, lineinfo in ipairs(order_lineinfos) do @@ -195,7 +193,7 @@ function _display_subprocess_lines(order_lineinfos) end -- redraw the multirow progress area (internal helper) -function _redraw_multirow_progress() +function _redraw_multirow_progress(maxwidth) local last_total_progress = _g.last_total_progress if not last_total_progress then return @@ -206,8 +204,8 @@ function _redraw_multirow_progress() cprint(last_total_progress) -- build and display the subprocess lines - local order_lineinfos = _build_ordered_subprocess_lineinfos() - _display_subprocess_lines(order_lineinfos) + local order_lineinfos = _build_ordered_subprocess_lineinfos(maxwidth) + _display_subprocess_lines(order_lineinfos, maxwidth) io.flush() end @@ -221,12 +219,15 @@ function _show_progress_with_multirow_refresh(progress, format, ...) return end + -- get window size once + local maxwidth = os.getwinsize().width + -- get progress line local is_first = false local is_finished = math.floor(progress) == 100 local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " local progress_msg = vformat(format, ...) - local progress_line = _strip_progress_line(vformat(progress_prefix, progress) .. progress_msg) + local progress_line = _strip_progress_line(vformat(progress_prefix, progress) .. progress_msg, maxwidth) local progress_lineinfos = _g.progress_lineinfos if progress_lineinfos == nil then progress_lineinfos = {} @@ -242,7 +243,6 @@ function _show_progress_with_multirow_refresh(progress, format, ...) -- show the total progress line local linecount = _g.linecount or 0 - local maxwidth = os.getwinsize().width if not is_first and linecount > 0 then tty.cursor_move_to_col(maxwidth) tty.cursor_move_up(linecount + 1) @@ -268,10 +268,10 @@ function _show_progress_with_multirow_refresh(progress, format, ...) end -- build and display the subprocess lines - local order_lineinfos = _build_ordered_subprocess_lineinfos() - _display_subprocess_lines(order_lineinfos) - + local order_lineinfos = _build_ordered_subprocess_lineinfos(maxwidth) current_lineinfo.start_time = current_time + _display_subprocess_lines(order_lineinfos, maxwidth) + if is_finished then _g.refresh_mode = nil _g.progress_lineinfos = nil @@ -287,10 +287,11 @@ end -- show progress with single-row refresh (ninja style) function _show_progress_with_singlerow_refresh(progress, format, ...) + local maxwidth = os.getwinsize().width local is_finished = math.floor(progress) == 100 local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " local progress_msg = vformat(format, ...) - local progress_line = _strip_progress_line(vformat(progress_prefix, progress) .. progress_msg) + local progress_line = _strip_progress_line(vformat(progress_prefix, progress) .. progress_msg, maxwidth) tty.erase_line_to_start().cr() cprintf(progress_line) if is_finished then @@ -327,10 +328,10 @@ function show_output(format, ...) print("") cprint(format, ...) elseif refresh_mode == "multirow" then - -- get the number of fixed progress lines at the bottom + -- get window size once and the number of fixed progress lines at the bottom -- +1 for the total progress line - local linecount = (_g.linecount or 0) + 1 local maxwidth = os.getwinsize().width + local linecount = (_g.linecount or 0) + 1 -- move to the top of progress area and clear to bottom tty.cursor_move_to_col(maxwidth) @@ -347,7 +348,7 @@ function show_output(format, ...) if current_lineinfo and current_lineinfo.progress_msg then local progress_value = _g.last_total_progress_value or 0 local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " - local progress_line = _strip_progress_line(vformat(progress_prefix, math.floor(progress_value)) .. current_lineinfo.progress_msg) + local progress_line = _strip_progress_line(vformat(progress_prefix, math.floor(progress_value)) .. current_lineinfo.progress_msg, maxwidth) tty.erase_line_to_end() cprint(progress_line) end @@ -358,7 +359,7 @@ function show_output(format, ...) cprint(format, ...) -- redraw the progress area immediately - _redraw_multirow_progress() + _redraw_multirow_progress(maxwidth) else cprint(format, ...) end -- cgit v1.3.1 From 53bc40cbe89a1e85b1c154e1b26deeafba29be0a Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Oct 2025 23:02:06 +0800 Subject: optimize current time --- xmake/modules/utils/progress.lua | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index efd6e0206..08bce022c 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -134,15 +134,13 @@ function _show_progress_with_scroll(progress, format, ...) end -- build ordered subprocess line infos from progress_lineinfos (internal helper) -function _build_ordered_subprocess_lineinfos(maxwidth) +function _build_ordered_subprocess_lineinfos(maxwidth, current_time) local progress_lineinfos = _g.progress_lineinfos if not progress_lineinfos then return {} end - local current_time = os.mclock() local order_lineinfos = {} - for _, progress_lineinfo in pairs(progress_lineinfos) do local progress_msg = progress_lineinfo.progress_msg if progress_msg then @@ -172,7 +170,6 @@ end -- display subprocess progress lines (internal helper) function _display_subprocess_lines(order_lineinfos, maxwidth) local linecount = 0 - for _, lineinfo in ipairs(order_lineinfos) do -- we need not show it if the progress job is idle in runjobs now local progress_running = lineinfo.running @@ -188,7 +185,6 @@ function _display_subprocess_lines(order_lineinfos, maxwidth) end linecount = linecount + 1 end - _g.linecount = linecount end @@ -199,14 +195,15 @@ function _redraw_multirow_progress(maxwidth) return end + local current_time = os.mclock() + -- redraw the total progress line tty.erase_line_to_start().cr() cprint(last_total_progress) -- build and display the subprocess lines - local order_lineinfos = _build_ordered_subprocess_lineinfos(maxwidth) + local order_lineinfos = _build_ordered_subprocess_lineinfos(maxwidth, current_time) _display_subprocess_lines(order_lineinfos, maxwidth) - io.flush() end @@ -268,7 +265,7 @@ function _show_progress_with_multirow_refresh(progress, format, ...) end -- build and display the subprocess lines - local order_lineinfos = _build_ordered_subprocess_lineinfos(maxwidth) + local order_lineinfos = _build_ordered_subprocess_lineinfos(maxwidth, current_time) current_lineinfo.start_time = current_time _display_subprocess_lines(order_lineinfos, maxwidth) -- cgit v1.3.1 From 39cf539b6cd73bd4ee8a0487f019ff9a761b3203 Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Oct 2025 23:21:23 +0800 Subject: improve erase line --- xmake/modules/utils/progress.lua | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 08bce022c..a8271db63 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -176,8 +176,7 @@ function _display_subprocess_lines(order_lineinfos, maxwidth) if progress_running and progress_running:data("runjobs.running") == false then lineinfo.progress_line = nil end - tty.cursor_move_to_col(maxwidth) - tty.erase_line_to_start().cr() + tty.erase_line().cr() if lineinfo.progress_line then cprint(lineinfo.progress_line) else @@ -198,7 +197,7 @@ function _redraw_multirow_progress(maxwidth) local current_time = os.mclock() -- redraw the total progress line - tty.erase_line_to_start().cr() + tty.erase_line().cr() cprint(last_total_progress) -- build and display the subprocess lines @@ -241,10 +240,9 @@ function _show_progress_with_multirow_refresh(progress, format, ...) -- show the total progress line local linecount = _g.linecount or 0 if not is_first and linecount > 0 then - tty.cursor_move_to_col(maxwidth) tty.cursor_move_up(linecount + 1) end - tty.erase_line_to_start().cr() + tty.erase_line().cr() cprint(progress_line) -- save the total progress line and progress value for potential redraw in show_output @@ -289,7 +287,7 @@ function _show_progress_with_singlerow_refresh(progress, format, ...) local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " local progress_msg = vformat(format, ...) local progress_line = _strip_progress_line(vformat(progress_prefix, progress) .. progress_msg, maxwidth) - tty.erase_line_to_start().cr() + tty.erase_line().cr() cprintf(progress_line) if is_finished then print("") @@ -331,7 +329,6 @@ function show_output(format, ...) local linecount = (_g.linecount or 0) + 1 -- move to the top of progress area and clear to bottom - tty.cursor_move_to_col(maxwidth) tty.cursor_move_up(linecount) tty.erase_down() tty.cr() -- cgit v1.3.1 From 4221c4d0041cc5f53969f8179132217c7eddb9af Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Oct 2025 23:21:51 +0800 Subject: remove unused maxwidth --- xmake/modules/utils/progress.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index a8271db63..37beb9764 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -168,7 +168,7 @@ function _build_ordered_subprocess_lineinfos(maxwidth, current_time) end -- display subprocess progress lines (internal helper) -function _display_subprocess_lines(order_lineinfos, maxwidth) +function _display_subprocess_lines(order_lineinfos) local linecount = 0 for _, lineinfo in ipairs(order_lineinfos) do -- we need not show it if the progress job is idle in runjobs now @@ -194,15 +194,14 @@ function _redraw_multirow_progress(maxwidth) return end - local current_time = os.mclock() - -- redraw the total progress line tty.erase_line().cr() cprint(last_total_progress) -- build and display the subprocess lines + local current_time = os.mclock() local order_lineinfos = _build_ordered_subprocess_lineinfos(maxwidth, current_time) - _display_subprocess_lines(order_lineinfos, maxwidth) + _display_subprocess_lines(order_lineinfos) io.flush() end @@ -265,7 +264,7 @@ function _show_progress_with_multirow_refresh(progress, format, ...) -- build and display the subprocess lines local order_lineinfos = _build_ordered_subprocess_lineinfos(maxwidth, current_time) current_lineinfo.start_time = current_time - _display_subprocess_lines(order_lineinfos, maxwidth) + _display_subprocess_lines(order_lineinfos) if is_finished then _g.refresh_mode = nil -- cgit v1.3.1 From 8f4090acd166b5b1db0e0fd22270d40c70504d7c Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Oct 2025 23:38:11 +0800 Subject: optimize progress --- xmake/modules/utils/progress.lua | 54 ++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 19 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 37beb9764..87788350e 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -29,6 +29,11 @@ import("core.theme.theme") -- 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 @@ -108,6 +113,14 @@ function _is_singlerow_refresh() return is_singlerow_refresh end +-- get progress prefix +function _get_progress_prefix() + if not _g.progress_prefix then + _g.progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + end + return _g.progress_prefix +end + -- strip progress line function _strip_progress_line(msg, maxwidth) local msg_plain = colors.translate(msg, {plain = true}) @@ -123,14 +136,12 @@ end -- show progress with verbose information function _show_progress_with_verbose(progress, format, ...) - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " - cprint(progress_prefix .. "${dim}" .. format, progress, ...) + cprint(_get_progress_prefix() .. "${dim}" .. format, progress, ...) end -- show progress with scroll function _show_progress_with_scroll(progress, format, ...) - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " - cprint(progress_prefix .. format, progress, ...) + cprint(_get_progress_prefix() .. format, progress, ...) end -- build ordered subprocess line infos from progress_lineinfos (internal helper) @@ -144,17 +155,25 @@ function _build_ordered_subprocess_lineinfos(maxwidth, current_time) for _, progress_lineinfo in pairs(progress_lineinfos) do local progress_msg = progress_lineinfo.progress_msg if progress_msg then - local timecolor = "" local spent_time = current_time - progress_lineinfo.start_time + local time_seconds = spent_time / 1000 + + -- determine color based on time (use cached color constants) + local timecolor if spent_time > 30000 then - timecolor = "${color.build.progress_superslow}" + timecolor = COLOR_SUPERSLOW elseif spent_time > 1000 then - timecolor = "${color.build.progress_veryslow}" + timecolor = COLOR_VERYSLOW elseif spent_time > 500 then - timecolor = "${color.build.progress_slow}" + timecolor = COLOR_SLOW + else + timecolor = "" end + progress_lineinfo.spent_time = spent_time - local subprogress_line = _strip_progress_line(vformat(" > %s%0.02fs${clear} ", timecolor, spent_time / 1000) .. progress_msg, maxwidth) + -- use string.format instead of vformat for better performance + local time_str = string.format("%s%0.02fs${clear} ", timecolor, time_seconds) + local subprogress_line = _strip_progress_line(" > " .. time_str .. progress_msg, maxwidth) progress_lineinfo.progress_line = subprogress_line table.insert(order_lineinfos, progress_lineinfo) else @@ -214,15 +233,16 @@ function _show_progress_with_multirow_refresh(progress, format, ...) return end - -- get window size once + -- get window size and time once local maxwidth = os.getwinsize().width + local current_time = os.mclock() -- get progress line local is_first = false local is_finished = math.floor(progress) == 100 - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " local progress_msg = vformat(format, ...) - local progress_line = _strip_progress_line(vformat(progress_prefix, progress) .. progress_msg, maxwidth) + local progress_line = _strip_progress_line(string.format(_get_progress_prefix(), progress) .. progress_msg, maxwidth) + local progress_lineinfos = _g.progress_lineinfos if progress_lineinfos == nil then progress_lineinfos = {} @@ -249,7 +269,6 @@ function _show_progress_with_multirow_refresh(progress, format, ...) _g.last_total_progress_value = progress -- update the current progress info - local current_time = os.mclock() local current_lineinfo = progress_lineinfos[running] if current_lineinfo == nil then current_lineinfo = {start_time = current_time, spent_time = 0, running = running} @@ -283,9 +302,8 @@ end function _show_progress_with_singlerow_refresh(progress, format, ...) local maxwidth = os.getwinsize().width local is_finished = math.floor(progress) == 100 - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " local progress_msg = vformat(format, ...) - local progress_line = _strip_progress_line(vformat(progress_prefix, progress) .. progress_msg, maxwidth) + local progress_line = _strip_progress_line(string.format(_get_progress_prefix(), progress) .. progress_msg, maxwidth) tty.erase_line().cr() cprintf(progress_line) if is_finished then @@ -300,7 +318,6 @@ end -- show the message with progress function show(progress, format, ...) progress = type(progress) == "table" and progress:percent() or math.floor(progress) - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " if option.get("verbose") then _show_progress_with_verbose(progress, format, ...) elseif _is_scroll() then @@ -340,8 +357,7 @@ function show_output(format, ...) local current_lineinfo = progress_lineinfos[running] if current_lineinfo and current_lineinfo.progress_msg then local progress_value = _g.last_total_progress_value or 0 - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " - local progress_line = _strip_progress_line(vformat(progress_prefix, math.floor(progress_value)) .. current_lineinfo.progress_msg, maxwidth) + local progress_line = _strip_progress_line(string.format(_get_progress_prefix(), math.floor(progress_value)) .. current_lineinfo.progress_msg, maxwidth) tty.erase_line_to_end() cprint(progress_line) end @@ -361,7 +377,7 @@ end -- get the message text with progress function text(progress, format, ...) progress = type(progress) == "table" and progress:percent() or math.floor(progress) - local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} " + local progress_prefix = _get_progress_prefix() if option.get("verbose") then return string.format(progress_prefix .. "${dim}" .. format, progress, ...) else -- cgit v1.3.1 From 1a6b82357bb1ba437984fc46c77aa812873a169c Mon Sep 17 00:00:00 2001 From: ruki Date: Thu, 30 Oct 2025 23:44:18 +0800 Subject: fix output end --- xmake/modules/utils/progress.lua | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'xmake/modules/utils/progress.lua') diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua index 87788350e..a29d7cd2b 100644 --- a/xmake/modules/utils/progress.lua +++ b/xmake/modules/utils/progress.lua @@ -195,13 +195,11 @@ function _display_subprocess_lines(order_lineinfos) if progress_running and progress_running:data("runjobs.running") == false then lineinfo.progress_line = nil end - tty.erase_line().cr() if lineinfo.progress_line then + tty.erase_line().cr() cprint(lineinfo.progress_line) - else - print("") + linecount = linecount + 1 end - linecount = linecount + 1 end _g.linecount = linecount end @@ -281,19 +279,23 @@ function _show_progress_with_multirow_refresh(progress, format, ...) end -- build and display the subprocess lines - local order_lineinfos = _build_ordered_subprocess_lineinfos(maxwidth, current_time) - current_lineinfo.start_time = current_time - _display_subprocess_lines(order_lineinfos) - - if is_finished then + if not is_finished then + local order_lineinfos = _build_ordered_subprocess_lineinfos(maxwidth, current_time) + current_lineinfo.start_time = current_time + _display_subprocess_lines(order_lineinfos) + _g.refresh_mode = "multirow" + else + -- when finished, clear all subprocess lines without leaving empty lines + local old_linecount = _g.linecount or 0 + if old_linecount > 0 then + tty.erase_down() + end _g.refresh_mode = nil _g.progress_lineinfos = nil _g.last_total_progress = nil _g.last_total_progress_value = nil _g.linecount = 0 tty.cursor_show() - else - _g.refresh_mode = "multirow" end io.flush() end -- cgit v1.3.1