11#ifdef PLATFORM_WINDOWS
34 cout <<
'/' << (defaultResponse ==
Response::No ?
'N' :
'n');
39 if (line ==
"y" || line ==
"Y" || (defaultResponse ==
Response::Yes && line.empty())) {
41 }
else if (line ==
"n" || line ==
"N" || (defaultResponse ==
Response::No && line.empty())) {
44 cout <<
"Please enter [y] or [n]: ";
55 const char *envValue = std::getenv(variableName);
59 for (; *envValue; ++envValue) {
78#ifndef PLATFORM_WINDOWS
79 ioctl(STDOUT_FILENO, TIOCGWINSZ,
reinterpret_cast<winsize *
>(&size));
81 CONSOLE_SCREEN_BUFFER_INFO consoleBufferInfo;
82 if (
const HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE)) {
83 GetConsoleScreenBufferInfo(stdHandle, &consoleBufferInfo);
84 if (consoleBufferInfo.dwSize.X > 0) {
85 size.
columns =
static_cast<unsigned short>(consoleBufferInfo.dwSize.X);
87 if (consoleBufferInfo.dwSize.Y > 0) {
88 size.
rows =
static_cast<unsigned short>(consoleBufferInfo.dwSize.Y);
95#ifdef PLATFORM_WINDOWS
101 static const auto mintty = [] {
102 const char *
const msyscon = std::getenv(
"MSYSCON");
103 const char *
const termprog = std::getenv(
"TERM_PROGRAM");
104 return (msyscon && std::strstr(msyscon,
"mintty")) || (termprog && std::strstr(termprog,
"mintty"));
114static bool enableVirtualTerminalProcessing(DWORD nStdHandle)
116 auto stdHandle = GetStdHandle(nStdHandle);
117 if (stdHandle == INVALID_HANDLE_VALUE) {
120 auto dwMode = DWORD();
121 if (!GetConsoleMode(stdHandle, &dwMode)) {
124 dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
125 return SetConsoleMode(stdHandle, dwMode);
132bool handleVirtualTerminalProcessing()
135 if (enableVirtualTerminalProcessing(STD_OUTPUT_HANDLE) && enableVirtualTerminalProcessing(STD_ERROR_HANDLE)) {
142 if (
const char *
const term = std::getenv(
"TERM"); term && std::strstr(term,
"xterm")) {
157 if (GetConsoleWindow()) {
192 if (GetConsoleWindow()) {
197 if (
const auto e =
isEnvVariableSet(
"ENABLE_CONSOLE"); !e.has_value() || !e.value()) {
202 auto pos = std::fpos_t();
203 std::fgetpos(stdout, &pos);
204 const auto skipstdout = pos >= 0;
205 std::fgetpos(stderr, &pos);
206 const auto skipstderr = pos >= 0;
207 std::fgetpos(stdin, &pos);
208 const auto skipstdin = pos >= 0;
209 const auto skip = skipstdout || skipstderr || skipstdin;
212 if (!skip && (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole())) {
217 freopen_s(&fp,
"CONOUT$",
"w", stdout);
222 freopen_s(&fp,
"CONOUT$",
"w", stderr);
226 freopen_s(&fp,
"CONIN$",
"r", stdin);
230 auto hConOut = CreateFile(
231 _T(
"CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
232 auto hConIn = CreateFile(
233 _T(
"CONIN$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
235 SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
240 SetStdHandle(STD_ERROR_HANDLE, hConOut);
244 SetStdHandle(STD_INPUT_HANDLE, hConIn);
249 auto stdHandle = std::intptr_t();
250 auto conHandle = int();
252 stdHandle =
reinterpret_cast<intptr_t
>(GetStdHandle(STD_OUTPUT_HANDLE));
253 conHandle = _open_osfhandle(stdHandle, _O_TEXT);
254 fp = _fdopen(conHandle,
"w");
256 setvbuf(stdout,
nullptr, _IONBF, 0);
260 stdHandle =
reinterpret_cast<intptr_t
>(GetStdHandle(STD_INPUT_HANDLE));
261 conHandle = _open_osfhandle(stdHandle, _O_TEXT);
262 fp = _fdopen(conHandle,
"r");
264 setvbuf(stdin,
nullptr, _IONBF, 0);
268 stdHandle =
reinterpret_cast<intptr_t
>(GetStdHandle(STD_ERROR_HANDLE));
269 conHandle = _open_osfhandle(stdHandle, _O_TEXT);
270 fp = _fdopen(conHandle,
"w");
272 setvbuf(stderr,
nullptr, _IONBF, 0);
275 ios::sync_with_stdio(
true);
278 std::atexit(stopConsole);
282 if (
const auto e =
isEnvVariableSet(
"ENABLE_CP_UTF8"); !e.has_value() || e.value()) {
283 SetConsoleCP(CP_UTF8);
284 SetConsoleOutputCP(CP_UTF8);
288 if (
const auto e =
isEnvVariableSet(
"ENABLE_HANDLING_VIRTUAL_TERMINAL_PROCESSING"); !e.has_value() || e.value()) {
289 handleVirtualTerminalProcessing();
297pair<vector<unique_ptr<char[]>>, vector<char *>> convertArgsToUtf8()
299 pair<vector<unique_ptr<char[]>>, vector<char *>> res;
302 LPWSTR *argv_w = CommandLineToArgvW(GetCommandLineW(), &argc);
303 if (!argv_w || argc <= 0) {
307 res.first.reserve(
static_cast<size_t>(argc));
308 res.second.reserve(
static_cast<size_t>(argc));
309 for (LPWSTR *
i = argv_w, *end = argv_w + argc;
i != end; ++
i) {
310 int requiredSize = WideCharToMultiByte(CP_UTF8, 0, *
i, -1,
nullptr, 0, 0, 0);
311 if (requiredSize <= 0) {
315 auto argv = make_unique<char[]>(
static_cast<size_t>(requiredSize));
316 requiredSize = WideCharToMultiByte(CP_UTF8, 0, *
i, -1, argv.get(), requiredSize, 0, 0);
317 if (requiredSize <= 0) {
321 res.second.emplace_back(argv.get());
322 res.first.emplace_back(std::move(argv));
CPP_UTILITIES_EXPORT bool enabled
Controls whether the functions inside the EscapeCodes namespace actually make use of escape codes.
Contains all utilities provided by the c++utilities library.
CPP_UTILITIES_EXPORT TerminalSize determineTerminalSize()
Returns the current size of the terminal.
Response
The Response enum is used to specify the default response for the confirmPrompt() method.
CPP_UTILITIES_EXPORT bool confirmPrompt(const char *message, Response defaultResponse=Response::None)
Prompts for confirmation displaying the specified message.
CPP_UTILITIES_EXPORT std::optional< bool > isEnvVariableSet(const char *variableName)
Returns whether the specified env variable is set to a non-zero and non-white-space-only value.
The TerminalSize struct describes a terminal size.
unsigned short columns
number of columns
unsigned short rows
number of rows