Fancy console output for Windows

This commit is contained in:
Marcus Holland-Moritz 2023-06-27 11:14:09 +02:00
parent 3364972027
commit 6770c13c08
5 changed files with 83 additions and 7 deletions

View File

@ -43,6 +43,8 @@ class console_writer : public logger {
level_type threshold, display_mode mode = NORMAL,
bool verbose = false);
~console_writer();
void write(level_type level, const std::string& output, char const* file,
int line) override;

View File

@ -48,6 +48,8 @@ enum class termcolor {
bool stream_is_fancy_terminal(std::ostream& os);
bool set_cursor_state(bool enabled);
char const* terminal_color(termcolor color);
std::string

View File

@ -75,18 +75,29 @@ console_writer::console_writer(std::ostream& os, progress_mode pg_mode,
} else {
set_policy<prod_logger_policy>();
}
set_cursor_state(false);
}
console_writer::~console_writer() { set_cursor_state(true); }
void console_writer::rewind() {
if (!statebuf_.empty()) {
int lines = 0;
switch (mode_) {
case NORMAL:
os_ << "\x1b[A\r\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A";
lines = 8;
break;
case REWRITE:
os_ << "\x1b[A\r\x1b[A\x1b[A\x1b[A";
lines = 4;
break;
}
os_ << '\r';
for (int i = 0; i < lines; ++i) {
os_ << "\x1b[A";
}
}
}

View File

@ -26,17 +26,68 @@
#include <cstring>
#include <iostream>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <folly/portability/Unistd.h>
#include <folly/portability/Windows.h>
#include "dwarfs/terminal.h"
namespace dwarfs {
#if defined(_WIN32)
void WindowsEmulateVT100Terminal(DWORD std_handle) {
static bool done = false;
if (done) {
return;
}
done = true;
// TODO?
// ::SetConsoleOutputCP(CP_UTF8);
// ::SetConsoleCP(CP_UTF8);
// Enable VT processing on stdout and stdin
auto hdl = ::GetStdHandle(STD_OUTPUT_HANDLE);
DWORD out_mode = 0;
::GetConsoleMode(hdl, &out_mode);
// https://docs.microsoft.com/en-us/windows/console/setconsolemode
static constexpr DWORD enable_virtual_terminal_processing = 0x0004;
static constexpr DWORD disable_newline_auto_return = 0x0008;
out_mode |= enable_virtual_terminal_processing;
out_mode |= disable_newline_auto_return;
::SetConsoleMode(hdl, out_mode);
}
#endif
bool set_cursor_state(bool enabled [[maybe_unused]]) {
bool was_enabled = true;
#ifdef _WIN32
auto hdl = ::GetStdHandle(STD_OUTPUT_HANDLE);
::CONSOLE_CURSOR_INFO cursorInfo;
::GetConsoleCursorInfo(hdl, &cursorInfo);
was_enabled = cursorInfo.bVisible;
cursorInfo.bVisible = enabled;
::SetConsoleCursorInfo(hdl, &cursorInfo);
#endif
return was_enabled;
}
bool stream_is_fancy_terminal(std::ostream& os [[maybe_unused]]) {
#ifdef _WIN32
// TODO
if (&os == &std::cout) {
WindowsEmulateVT100Terminal(STD_OUTPUT_HANDLE);
return true;
}
if (&os == &std::cerr) {
WindowsEmulateVT100Terminal(STD_ERROR_HANDLE);
return true;
}
return false;
#else
if (&os == &std::cout && !::isatty(::fileno(stdout))) {

View File

@ -114,9 +114,19 @@ const std::map<std::string, console_writer::progress_mode> progress_modes{
{"none", console_writer::NONE},
{"simple", console_writer::SIMPLE},
{"ascii", console_writer::ASCII},
#ifndef _WIN32
{"unicode", console_writer::UNICODE},
#endif
};
const std::string default_progress_mode =
#ifdef _WIN32
"ascii"
#else
"unicode"
#endif
;
const std::map<std::string, debug_filter_mode> debug_filter_modes{
{"included", debug_filter_mode::INCLUDED},
{"included-files", debug_filter_mode::INCLUDED_FILES},
@ -539,7 +549,7 @@ int mkdwarfs_main(int argc, sys_char** argv) {
po::value<std::string>(&log_level_str)->default_value("info"),
"log level (error, warn, info, debug, trace)")
("progress",
po::value<std::string>(&progress_mode)->default_value("unicode"),
po::value<std::string>(&progress_mode)->default_value(default_progress_mode),
progress_desc.c_str())
("no-progress",
po::value<bool>(&no_progress)->zero_tokens(),