diff options
| author | Dan Engelbrecht <[email protected]> | 2025-04-04 15:23:50 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2025-04-04 15:23:50 +0200 |
| commit | d142c80beb9cc5c43192ba978198280906c5bd39 (patch) | |
| tree | 6f26fbb7807f5bfcf630e741d0eda53b13bc8068 /src | |
| parent | blobstore size limit (#342) (diff) | |
| download | zen-d142c80beb9cc5c43192ba978198280906c5bd39.tar.xz zen-d142c80beb9cc5c43192ba978198280906c5bd39.zip | |
progress bar improvements (#346)
* hide ETA until at least 5% is complete
* dynamically adjust progres output length
Diffstat (limited to 'src')
| -rw-r--r-- | src/zen/zen.cpp | 100 |
1 files changed, 82 insertions, 18 deletions
diff --git a/src/zen/zen.cpp b/src/zen/zen.cpp index 6f831349b..50ee43341 100644 --- a/src/zen/zen.cpp +++ b/src/zen/zen.cpp @@ -58,7 +58,8 @@ ZEN_THIRD_PARTY_INCLUDES_END #include <zencore/memory/newdelete.h> -#ifndef ZEN_PLATFORM_WINDOWS +#if ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC +# include <sys/ioctl.h> # include <unistd.h> #endif @@ -329,29 +330,92 @@ ProgressBar::UpdateState(const State& NewState, bool DoLinebreak) { size_t ProgressBarSize = 20; - size_t ProgressBarCount = (ProgressBarSize * PercentDone) / 100; - uint64_t Completed = NewState.TotalCount - NewState.RemainingCount; - uint64_t ETAMS = (Completed > 0) ? (ElapsedTimeMS * NewState.RemainingCount) / Completed : 0; - std::string ETA = (ETAMS > 0) ? fmt::format(" ETA {}", NiceTimeSpanMs(ETAMS)) : ""; - - std::string Output = fmt::format("\r{} {:#3}%: |{}{}|: {}{}{}", - NewState.Task, - PercentDone, - std::string(ProgressBarCount, '#'), - std::string(ProgressBarSize - ProgressBarCount, ' '), - NiceTimeSpanMs(ElapsedTimeMS), - ETA, - NewState.Details.empty() ? "" : fmt::format(". {}", NewState.Details)); + size_t ProgressBarCount = (ProgressBarSize * PercentDone) / 100; + uint64_t Completed = NewState.TotalCount - NewState.RemainingCount; + uint64_t ETAMS = (PercentDone > 5) ? (ElapsedTimeMS * NewState.RemainingCount) / Completed : 0; + +#if ZEN_PLATFORM_WINDOWS + static HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(hStdOut, &csbi); + uint32_t ConsoleColumns = (uint32_t)(csbi.srWindow.Right - csbi.srWindow.Left + 1); +#else + struct winsize w; + ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); + uint32_t ConsoleColumns = (uint32_t)w.ws_col; +#endif + + std::string_view TaskString = NewState.Task; + + const std::string PercentString = fmt::format("{:#3}%", PercentDone); + + const std::string ProgressBarString = + fmt::format(": |{}{}|", std::string(ProgressBarCount, '#'), std::string(ProgressBarSize - ProgressBarCount, ' ')); + + const std::string ElapsedString = fmt::format(": {}", NiceTimeSpanMs(ElapsedTimeMS)); + + const std::string ETAString = (ETAMS > 0) ? fmt::format(" ETA {}", NiceTimeSpanMs(ETAMS)) : ""; + + const std::string DetailsString = (!NewState.Details.empty()) ? fmt::format(". {}", NewState.Details) : ""; + + ExtendableStringBuilder<256> OutputBuilder; + + OutputBuilder << "\r" << TaskString << PercentString; + if (OutputBuilder.Size() + 1 < ConsoleColumns) + { + size_t RemainingSpace = ConsoleColumns - (OutputBuilder.Size() + 1); + bool ElapsedFits = RemainingSpace >= ElapsedString.length(); + RemainingSpace -= ElapsedString.length(); + bool ETAFits = ElapsedFits && RemainingSpace >= ETAString.length(); + RemainingSpace -= ETAString.length(); + bool DetailsFits = ETAFits && RemainingSpace >= DetailsString.length(); + RemainingSpace -= DetailsString.length(); + bool ProgressBarFits = DetailsFits && RemainingSpace >= ProgressBarString.length(); + RemainingSpace -= ProgressBarString.length(); + + if (ProgressBarFits) + { + OutputBuilder << ProgressBarString; + } + if (ElapsedFits) + { + OutputBuilder << ElapsedString; + } + if (ETAFits) + { + OutputBuilder << ETAString; + } + if (DetailsFits) + { + OutputBuilder << DetailsString; + } + } + + std::string_view Output = OutputBuilder.ToView(); std::string::size_type EraseLength = m_LastOutputLength > Output.length() ? (m_LastOutputLength - Output.length()) : 0; - ExtendableStringBuilder<128> LineToPrint; - LineToPrint << Output << std::string(EraseLength, ' '); + ExtendableStringBuilder<256> LineToPrint; + + if (Output.length() + EraseLength >= ConsoleColumns) + { + if (m_LastOutputLength > 0) + { + LineToPrint << "\n"; + } + LineToPrint << Output.substr(1); + DoLinebreak = true; + } + else + { + LineToPrint << Output << std::string(EraseLength, ' '); + } + if (DoLinebreak) + { LineToPrint << "\n"; + } #if ZEN_PLATFORM_WINDOWS - static HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - if (m_StdoutIsTty) { WriteConsoleA(hStdOut, LineToPrint.c_str(), (DWORD)LineToPrint.Size(), 0, 0); |