1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-26 11:37:12 +00:00

Split Tee logic into different types

This commit is contained in:
elsid 2024-05-13 00:40:22 +02:00
parent f595015ffc
commit 4ab5871dc4
No known key found for this signature in database
GPG Key ID: 4DE04C198CBA7625

View File

@ -221,51 +221,32 @@ namespace Debug
}; };
#else #else
class Tee : public DebugOutputBase namespace
{ {
public: Color getColor(Level level)
Tee(std::ostream& stream, std::ostream& stream2)
: out(stream)
, out2(stream2)
{ {
// TODO: check which stream is stderr? switch (level)
mUseColor = useColoredOutput(); {
case Error:
mColors[Error] = Red; return Red;
mColors[Warning] = Yellow; case Warning:
mColors[Info] = Reset; return Yellow;
mColors[Verbose] = DarkGray; case Info:
mColors[Debug] = DarkGray; return Reset;
mColors[NoLevel] = Reset; case Verbose:
return DarkGray;
case Debug:
return DarkGray;
case NoLevel:
return Reset;
}
return Reset;
} }
std::streamsize writeImpl(const char* str, std::streamsize size, Level debugLevel) override bool useColoredOutput()
{
out.write(str, size);
out.flush();
if (mUseColor)
{
out2 << "\033[0;" << mColors[debugLevel] << "m";
out2.write(str, size);
out2 << "\033[0;" << Reset << "m";
}
else
{
out2.write(str, size);
}
out2.flush();
return size;
}
virtual ~Tee() = default;
private:
static bool useColoredOutput()
{ {
#if defined(_WIN32) #if defined(_WIN32)
if (getenv("NO_COLOR")) if (std::getenv("NO_COLOR") != nullptr)
return false; return false;
DWORD mode; DWORD mode;
@ -273,22 +254,77 @@ namespace Debug
return true; return true;
// some console emulators may not use the Win32 API, so try the Unixy approach // some console emulators may not use the Win32 API, so try the Unixy approach
char* term = getenv("TERM"); return std::getenv("TERM") != nullptr && GetFileType(GetStdHandle(STD_ERROR_HANDLE)) == FILE_TYPE_CHAR;
return term && GetFileType(GetStdHandle(STD_ERROR_HANDLE)) == FILE_TYPE_CHAR;
#else #else
char* term = getenv("TERM"); return std::getenv("TERM") != nullptr && std::getenv("NO_COLOR") == nullptr && isatty(fileno(stderr));
bool useColor = term && !getenv("NO_COLOR") && isatty(fileno(stderr));
return useColor;
#endif #endif
} }
std::ostream& out; class Identity
std::ostream& out2; {
bool mUseColor; public:
explicit Identity(std::ostream& stream)
: mStream(stream)
{
}
std::map<Level, int> mColors; void write(const char* str, std::streamsize size, Level /*level*/)
}; {
mStream.write(str, size);
mStream.flush();
}
private:
std::ostream& mStream;
};
class Coloured
{
public:
explicit Coloured(std::ostream& stream)
: mStream(stream)
// TODO: check which stream is stderr?
, mUseColor(useColoredOutput())
{
}
void write(const char* str, std::streamsize size, Level level)
{
if (mUseColor)
mStream << "\033[0;" << getColor(level) << 'm';
mStream.write(str, size);
if (mUseColor)
mStream << "\033[0;" << Reset << 'm';
mStream.flush();
}
private:
std::ostream& mStream;
bool mUseColor;
};
template <class First, class Second>
class Tee : public DebugOutputBase
{
public:
explicit Tee(First first, Second second)
: mFirst(first)
, mSecond(second)
{
}
std::streamsize writeImpl(const char* str, std::streamsize size, Level debugLevel) override
{
mFirst.write(str, size, debugLevel);
mSecond.write(str, size, debugLevel);
return size;
}
private:
First mFirst;
Second mSecond;
};
}
#endif #endif
} }
@ -301,8 +337,8 @@ static std::ofstream logfile;
#if defined(_WIN32) && defined(_DEBUG) #if defined(_WIN32) && defined(_DEBUG)
static boost::iostreams::stream_buffer<Debug::DebugOutput> sb; static boost::iostreams::stream_buffer<Debug::DebugOutput> sb;
#else #else
static boost::iostreams::stream_buffer<Debug::Tee> coutsb; static boost::iostreams::stream_buffer<Debug::Tee<Debug::Identity, Debug::Coloured>> coutsb;
static boost::iostreams::stream_buffer<Debug::Tee> cerrsb; static boost::iostreams::stream_buffer<Debug::Tee<Debug::Identity, Debug::Coloured>> cerrsb;
#endif #endif
std::ostream& getRawStdout() std::ostream& getRawStdout()
@ -332,8 +368,8 @@ void setupLogging(const std::filesystem::path& logDir, std::string_view appName,
const std::string logName = Misc::StringUtils::lowerCase(appName) + ".log"; const std::string logName = Misc::StringUtils::lowerCase(appName) + ".log";
logfile.open(logDir / logName, mode); logfile.open(logDir / logName, mode);
coutsb.open(Debug::Tee(logfile, *rawStdout)); coutsb.open(Debug::Tee(Debug::Identity(logfile), Debug::Coloured(*rawStdout)));
cerrsb.open(Debug::Tee(logfile, *rawStderr)); cerrsb.open(Debug::Tee(Debug::Identity(logfile), Debug::Coloured(*rawStderr)));
std::cout.rdbuf(&coutsb); std::cout.rdbuf(&coutsb);
std::cerr.rdbuf(&cerrsb); std::cerr.rdbuf(&cerrsb);