summaryrefslogtreecommitdiff
path: root/hyprpm/src/progress/CProgressBar.cpp
blob: 19a14d9c6f8472c73fb0bfcf3b48897b136124e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "CProgressBar.hpp"

#include <sys/ioctl.h>
#include <unistd.h>
#include <cmath>
#include <format>
#include <print>
#include <cstdio>

#include <algorithm>
#include <sstream>
#include <hyprutils/memory/Casts.hpp>
#include "../helpers/Colors.hpp"

using namespace Hyprutils::Memory;

static winsize getTerminalSize() {
    winsize w{};
    ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
    return w;
}

static void clearCurrentLine() {
    std::print("\r\33[2K"); // ansi escape sequence to clear entire line
}

void CProgressBar::printMessageAbove(const std::string& msg) {
    clearCurrentLine();
    std::print("\r{}\n", msg);

    print(); // reprint bar underneath
}

void CProgressBar::print() {
    const auto w = getTerminalSize();

    if (m_bFirstPrint) {
        std::print("\n");
        m_bFirstPrint = false;
    }

    clearCurrentLine();

    float percentDone = 0.0f;
    if (m_fPercentage >= 0.0f)
        percentDone = m_fPercentage;
    else {
        // check for divide-by-zero
        percentDone = m_iMaxSteps > 0 ? sc<float>(m_iSteps) / m_iMaxSteps : 0.0f;
    }
    // clamp to ensure no overflows (sanity check)
    percentDone = std::clamp(percentDone, 0.0f, 1.0f);

    const size_t       BARWIDTH = std::clamp<size_t>(w.ws_col - m_szCurrentMessage.length() - 2, 0, 50);

    std::ostringstream oss;
    oss << ' ' << Colors::GREEN;

    size_t filled = std::floor(percentDone * BARWIDTH);
    size_t i      = 0;

    for (; i < filled; ++i)
        oss << "━";

    if (i < BARWIDTH) {
        oss << "╍" << Colors::RESET;
        ++i;
        for (; i < BARWIDTH; ++i)
            oss << "━";
    } else
        oss << Colors::RESET;

    if (m_fPercentage >= 0.0f)
        oss << "  " << std::format("{}%", sc<int>(percentDone * 100.0)) << ' ';
    else
        oss << "  " << std::format("{} / {}", m_iSteps, m_iMaxSteps) << ' ';

    std::print("{} {}", oss.str(), m_szCurrentMessage);
    std::fflush(stdout);
}