mirror of
https://github.com/mhx/dwarfs.git
synced 2025-09-08 20:12:56 -04:00
Fancy console output for Windows
This commit is contained in:
parent
3364972027
commit
6770c13c08
@ -43,6 +43,8 @@ class console_writer : public logger {
|
|||||||
level_type threshold, display_mode mode = NORMAL,
|
level_type threshold, display_mode mode = NORMAL,
|
||||||
bool verbose = false);
|
bool verbose = false);
|
||||||
|
|
||||||
|
~console_writer();
|
||||||
|
|
||||||
void write(level_type level, const std::string& output, char const* file,
|
void write(level_type level, const std::string& output, char const* file,
|
||||||
int line) override;
|
int line) override;
|
||||||
|
|
||||||
|
@ -48,6 +48,8 @@ enum class termcolor {
|
|||||||
|
|
||||||
bool stream_is_fancy_terminal(std::ostream& os);
|
bool stream_is_fancy_terminal(std::ostream& os);
|
||||||
|
|
||||||
|
bool set_cursor_state(bool enabled);
|
||||||
|
|
||||||
char const* terminal_color(termcolor color);
|
char const* terminal_color(termcolor color);
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
|
@ -75,18 +75,29 @@ console_writer::console_writer(std::ostream& os, progress_mode pg_mode,
|
|||||||
} else {
|
} else {
|
||||||
set_policy<prod_logger_policy>();
|
set_policy<prod_logger_policy>();
|
||||||
}
|
}
|
||||||
|
set_cursor_state(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console_writer::~console_writer() { set_cursor_state(true); }
|
||||||
|
|
||||||
void console_writer::rewind() {
|
void console_writer::rewind() {
|
||||||
if (!statebuf_.empty()) {
|
if (!statebuf_.empty()) {
|
||||||
|
int lines = 0;
|
||||||
|
|
||||||
switch (mode_) {
|
switch (mode_) {
|
||||||
case NORMAL:
|
case NORMAL:
|
||||||
os_ << "\x1b[A\r\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A\x1b[A";
|
lines = 8;
|
||||||
break;
|
break;
|
||||||
case REWRITE:
|
case REWRITE:
|
||||||
os_ << "\x1b[A\r\x1b[A\x1b[A\x1b[A";
|
lines = 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os_ << '\r';
|
||||||
|
|
||||||
|
for (int i = 0; i < lines; ++i) {
|
||||||
|
os_ << "\x1b[A";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,17 +26,68 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#ifndef _WIN32
|
#include <folly/portability/Unistd.h>
|
||||||
#include <unistd.h>
|
#include <folly/portability/Windows.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "dwarfs/terminal.h"
|
#include "dwarfs/terminal.h"
|
||||||
|
|
||||||
namespace dwarfs {
|
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]]) {
|
bool stream_is_fancy_terminal(std::ostream& os [[maybe_unused]]) {
|
||||||
#ifdef _WIN32
|
#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;
|
return false;
|
||||||
#else
|
#else
|
||||||
if (&os == &std::cout && !::isatty(::fileno(stdout))) {
|
if (&os == &std::cout && !::isatty(::fileno(stdout))) {
|
||||||
|
@ -114,9 +114,19 @@ const std::map<std::string, console_writer::progress_mode> progress_modes{
|
|||||||
{"none", console_writer::NONE},
|
{"none", console_writer::NONE},
|
||||||
{"simple", console_writer::SIMPLE},
|
{"simple", console_writer::SIMPLE},
|
||||||
{"ascii", console_writer::ASCII},
|
{"ascii", console_writer::ASCII},
|
||||||
|
#ifndef _WIN32
|
||||||
{"unicode", console_writer::UNICODE},
|
{"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{
|
const std::map<std::string, debug_filter_mode> debug_filter_modes{
|
||||||
{"included", debug_filter_mode::INCLUDED},
|
{"included", debug_filter_mode::INCLUDED},
|
||||||
{"included-files", debug_filter_mode::INCLUDED_FILES},
|
{"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"),
|
po::value<std::string>(&log_level_str)->default_value("info"),
|
||||||
"log level (error, warn, info, debug, trace)")
|
"log level (error, warn, info, debug, trace)")
|
||||||
("progress",
|
("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())
|
progress_desc.c_str())
|
||||||
("no-progress",
|
("no-progress",
|
||||||
po::value<bool>(&no_progress)->zero_tokens(),
|
po::value<bool>(&no_progress)->zero_tokens(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user