| 36 | } |
| 37 | |
| 38 | void indicatorThread() { |
| 39 | if (!is_tty.err || output_silent || progress_silent) return; |
| 40 | |
| 41 | bool hasFocus = true; |
| 42 | |
| 43 | makeTerminalRaw(); |
| 44 | |
| 45 | fprintf(stderr, "\033[?25l"); // hide the cursor |
| 46 | fflush(stderr); |
| 47 | |
| 48 | int columns = thisTerminalSize().columns; |
| 49 | |
| 50 | std::unique_lock<std::mutex> lock(m); |
| 51 | |
| 52 | auto start = std::chrono::steady_clock::now(); |
| 53 | |
| 54 | bool readyToPollFocus = false; |
| 55 | |
| 56 | int step = 0; |
| 57 | |
| 58 | auto poll_focus = [&] { |
| 59 | if (!readyToPollFocus) { // add a time duration check because on some slow systems over SSH, the reporting characters show up in the terminal |
| 60 | if (std::chrono::steady_clock::now() - start > std::chrono::milliseconds(50)) |
| 61 | readyToPollFocus = true; |
| 62 | else |
| 63 | return; |
| 64 | printf("\033[?1004h"); // enable focus tracking |
| 65 | fflush(stdout); |
| 66 | } |
| 67 | std::array<char, 32> buf; |
| 68 | #if defined(_WIN32) || defined(_WIN64) |
| 69 | DWORD bytesAvailable = 0; |
| 70 | PeekNamedPipe(GetStdHandle(STD_INPUT_HANDLE), nullptr, 0, nullptr, &bytesAvailable, nullptr); |
| 71 | if (bytesAvailable < 3) return; |
| 72 | #endif |
| 73 | if (read(STDIN_FILENO, buf.data(), buf.size()) >= 3) { |
| 74 | if (buf.at(0) == '\033' && buf.at(1) == '[' && buf.at(2) == 'I') hasFocus = true; |
| 75 | if (buf.at(0) == '\033' && buf.at(1) == '[' && buf.at(2) == 'O') hasFocus = false; |
| 76 | } |
| 77 | }; |
| 78 | |
| 79 | auto display_progress = [&](const auto& formattedNum, const std::string_view& actionText = doing_action[action]) { |
| 80 | if (std::chrono::steady_clock::now() - start < std::chrono::milliseconds(500)) { |
| 81 | cv.wait_for(lock, std::chrono::milliseconds(17), [&] { return progress_state != IndicatorState::Active; }); |
| 82 | return; |
| 83 | } |
| 84 | std::string progressBar; |
| 85 | if (step < 40) { |
| 86 | progressBar += repeatString("█", step); |
| 87 | progressBar += repeatString("▒", 39 - step); |
| 88 | } else { |
| 89 | progressBar += repeatString("▒", step - 40); |
| 90 | progressBar += repeatString("█", 39 - (step - 40)); |
| 91 | } |
| 92 | std::string formattedSeconds = std::to_string(std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - start).count()) + "s"; |
| 93 | fprintf(stderr, working_message().data(), actionText.data(), formattedNum, formattedSeconds.data(), progressBar.data()); |
| 94 | fprintf(stderr, "\033]0;%s (%s) - Clipboard\007", actionText.data(), formattedNum); // set the terminal title |
| 95 | fflush(stderr); |
nothing calls this directly
no test coverage detected