mirror of
https://github.com/PrismLauncher/PrismLauncher.git
synced 2025-06-12 05:07:46 +02:00
feat(ansi-console): Format console with ansi excapes
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
@ -125,6 +125,7 @@
|
||||
#include <FileSystem.h>
|
||||
#include <LocalPeer.h>
|
||||
|
||||
#include <QStringLiteral>
|
||||
#include <stdlib.h>
|
||||
#include <sys.h>
|
||||
#include "SysInfo.h"
|
||||
@ -153,11 +154,16 @@
|
||||
#endif
|
||||
|
||||
#if defined Q_OS_WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <QStyleHints>
|
||||
#include "console/WindowsConsole.h"
|
||||
#endif
|
||||
|
||||
#include "console/Console.h"
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
|
||||
@ -165,6 +171,69 @@ static const QLatin1String liveCheckFile("live.check");
|
||||
|
||||
PixmapCache* PixmapCache::s_instance = nullptr;
|
||||
|
||||
static bool isANSIColorConsole;
|
||||
|
||||
static QString defaultLogFormat = QStringLiteral(
|
||||
"%{time process}"
|
||||
" "
|
||||
"%{if-debug}D%{endif}"
|
||||
"%{if-info}I%{endif}"
|
||||
"%{if-warning}W%{endif}"
|
||||
"%{if-critical}C%{endif}"
|
||||
"%{if-fatal}F%{endif}"
|
||||
" "
|
||||
"|"
|
||||
" "
|
||||
"%{function}:%{line}"
|
||||
" "
|
||||
"|"
|
||||
" "
|
||||
"%{if-category}[%{category}]: %{endif}"
|
||||
"%{message}");
|
||||
|
||||
#define ansi_reset "\x1b[0m"
|
||||
#define ansi_bold "\x1b[1m"
|
||||
#define ansi_faint "\x1b[2m"
|
||||
#define ansi_italic "\x1b[3m"
|
||||
#define ansi_red_fg "\x1b[31m"
|
||||
#define ansi_green_fg "\x1b[32m"
|
||||
#define ansi_yellow_fg "\x1b[33m"
|
||||
#define ansi_blue_fg "\x1b[34m"
|
||||
#define ansi_purple_fg "\x1b[35m"
|
||||
|
||||
static QString ansiLogFormat = QStringLiteral(
|
||||
"%{time process}"
|
||||
" "
|
||||
"%{if-debug}" ansi_bold ansi_blue_fg "D" ansi_reset
|
||||
"%{endif}"
|
||||
"%{if-info}" ansi_bold ansi_green_fg "I" ansi_reset
|
||||
"%{endif}"
|
||||
"%{if-warning}" ansi_bold ansi_yellow_fg "W" ansi_reset
|
||||
"%{endif}"
|
||||
"%{if-critical}" ansi_bold ansi_red_fg "C" ansi_reset
|
||||
"%{endif}"
|
||||
"%{if-fatal}" ansi_bold ansi_red_fg "F" ansi_reset
|
||||
"%{endif}"
|
||||
" "
|
||||
"|"
|
||||
" " ansi_faint ansi_italic "%{function}:%{line}" ansi_reset
|
||||
" "
|
||||
"|"
|
||||
" "
|
||||
"%{if-category}[" ansi_bold ansi_purple_fg "%{category}" ansi_reset
|
||||
"]: %{endif}"
|
||||
"%{message}");
|
||||
|
||||
#undef ansi_purple_fg
|
||||
#undef ansi_blue_fg
|
||||
#undef ansi_yellow_fg
|
||||
#undef ansi_green_fg
|
||||
#undef ansi_red_fg
|
||||
#undef ansi_italic
|
||||
#undef ansi_faint
|
||||
#undef ansi_bold
|
||||
#undef ansi_reset
|
||||
|
||||
namespace {
|
||||
|
||||
/** This is used so that we can output to the log file in addition to the CLI. */
|
||||
@ -173,11 +242,24 @@ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QSt
|
||||
static std::mutex loggerMutex;
|
||||
const std::lock_guard<std::mutex> lock(loggerMutex); // synchronized, QFile logFile is not thread-safe
|
||||
|
||||
if (isANSIColorConsole) {
|
||||
// ensure default is set for log file
|
||||
qSetMessagePattern(defaultLogFormat);
|
||||
}
|
||||
|
||||
QString out = qFormatLogMessage(type, context, msg);
|
||||
out += QChar::LineFeed;
|
||||
|
||||
APPLICATION->logFile->write(out.toUtf8());
|
||||
APPLICATION->logFile->flush();
|
||||
|
||||
if (isANSIColorConsole) {
|
||||
// format ansi for console;
|
||||
qSetMessagePattern(ansiLogFormat);
|
||||
out = qFormatLogMessage(type, context, msg);
|
||||
out += QChar::LineFeed;
|
||||
}
|
||||
|
||||
QTextStream(stderr) << out.toLocal8Bit();
|
||||
fflush(stderr);
|
||||
}
|
||||
@ -218,8 +300,18 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
// attach the parent console if stdout not already captured
|
||||
if (AttachWindowsConsole()) {
|
||||
consoleAttached = true;
|
||||
if (auto err = EnableAnsiSupport(); !err) {
|
||||
isANSIColorConsole = true;
|
||||
} else {
|
||||
std::cout << "Error setting up ansi console" << err.message() << std::endl;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (console::isConsole()) {
|
||||
isANSIColorConsole = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
setOrganizationName(BuildConfig.LAUNCHER_NAME);
|
||||
setOrganizationDomain(BuildConfig.LAUNCHER_DOMAIN);
|
||||
setApplicationName(BuildConfig.LAUNCHER_NAME);
|
||||
@ -448,27 +540,14 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
return;
|
||||
}
|
||||
qInstallMessageHandler(appDebugOutput);
|
||||
|
||||
qSetMessagePattern(
|
||||
"%{time process}"
|
||||
" "
|
||||
"%{if-debug}D%{endif}"
|
||||
"%{if-info}I%{endif}"
|
||||
"%{if-warning}W%{endif}"
|
||||
"%{if-critical}C%{endif}"
|
||||
"%{if-fatal}F%{endif}"
|
||||
" "
|
||||
"|"
|
||||
" "
|
||||
"%{if-category}[%{category}]: %{endif}"
|
||||
"%{message}");
|
||||
qSetMessagePattern(defaultLogFormat);
|
||||
|
||||
bool foundLoggingRules = false;
|
||||
|
||||
auto logRulesFile = QStringLiteral("qtlogging.ini");
|
||||
auto logRulesPath = FS::PathCombine(dataPath, logRulesFile);
|
||||
|
||||
qDebug() << "Testing" << logRulesPath << "...";
|
||||
qInfo() << "Testing" << logRulesPath << "...";
|
||||
foundLoggingRules = QFile::exists(logRulesPath);
|
||||
|
||||
// search the dataPath()
|
||||
@ -476,7 +555,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
if (!foundLoggingRules && !isPortable() && dirParam.isEmpty() && dataDirEnv.isEmpty()) {
|
||||
logRulesPath = QStandardPaths::locate(QStandardPaths::AppDataLocation, FS::PathCombine("..", logRulesFile));
|
||||
if (!logRulesPath.isEmpty()) {
|
||||
qDebug() << "Found" << logRulesPath << "...";
|
||||
qInfo() << "Found" << logRulesPath << "...";
|
||||
foundLoggingRules = true;
|
||||
}
|
||||
}
|
||||
@ -487,28 +566,28 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
#else
|
||||
logRulesPath = FS::PathCombine(m_rootPath, logRulesFile);
|
||||
#endif
|
||||
qDebug() << "Testing" << logRulesPath << "...";
|
||||
qInfo() << "Testing" << logRulesPath << "...";
|
||||
foundLoggingRules = QFile::exists(logRulesPath);
|
||||
}
|
||||
|
||||
if (foundLoggingRules) {
|
||||
// load and set logging rules
|
||||
qDebug() << "Loading logging rules from:" << logRulesPath;
|
||||
qInfo() << "Loading logging rules from:" << logRulesPath;
|
||||
QSettings loggingRules(logRulesPath, QSettings::IniFormat);
|
||||
loggingRules.beginGroup("Rules");
|
||||
QStringList rule_names = loggingRules.childKeys();
|
||||
QStringList rules;
|
||||
qDebug() << "Setting log rules:";
|
||||
qInfo() << "Setting log rules:";
|
||||
for (auto rule_name : rule_names) {
|
||||
auto rule = QString("%1=%2").arg(rule_name).arg(loggingRules.value(rule_name).toString());
|
||||
rules.append(rule);
|
||||
qDebug() << " " << rule;
|
||||
qInfo() << " " << rule;
|
||||
}
|
||||
auto rules_str = rules.join("\n");
|
||||
QLoggingCategory::setFilterRules(rules_str);
|
||||
}
|
||||
|
||||
qDebug() << "<> Log initialized.";
|
||||
qInfo() << "<> Log initialized.";
|
||||
}
|
||||
|
||||
{
|
||||
@ -525,33 +604,33 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
}
|
||||
|
||||
{
|
||||
qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME + ", " + QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
|
||||
qDebug() << "Version : " << BuildConfig.printableVersionString();
|
||||
qDebug() << "Platform : " << BuildConfig.BUILD_PLATFORM;
|
||||
qDebug() << "Git commit : " << BuildConfig.GIT_COMMIT;
|
||||
qDebug() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
|
||||
qDebug() << "Compiled for : " << BuildConfig.systemID();
|
||||
qDebug() << "Compiled by : " << BuildConfig.compilerID();
|
||||
qDebug() << "Build Artifact : " << BuildConfig.BUILD_ARTIFACT;
|
||||
qDebug() << "Updates Enabled : " << (updaterEnabled() ? "Yes" : "No");
|
||||
qInfo() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME + ", " + QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", "));
|
||||
qInfo() << "Version : " << BuildConfig.printableVersionString();
|
||||
qInfo() << "Platform : " << BuildConfig.BUILD_PLATFORM;
|
||||
qInfo() << "Git commit : " << BuildConfig.GIT_COMMIT;
|
||||
qInfo() << "Git refspec : " << BuildConfig.GIT_REFSPEC;
|
||||
qInfo() << "Compiled for : " << BuildConfig.systemID();
|
||||
qInfo() << "Compiled by : " << BuildConfig.compilerID();
|
||||
qInfo() << "Build Artifact : " << BuildConfig.BUILD_ARTIFACT;
|
||||
qInfo() << "Updates Enabled : " << (updaterEnabled() ? "Yes" : "No");
|
||||
if (adjustedBy.size()) {
|
||||
qDebug() << "Work dir before adjustment : " << origcwdPath;
|
||||
qDebug() << "Work dir after adjustment : " << QDir::currentPath();
|
||||
qDebug() << "Adjusted by : " << adjustedBy;
|
||||
qInfo() << "Work dir before adjustment : " << origcwdPath;
|
||||
qInfo() << "Work dir after adjustment : " << QDir::currentPath();
|
||||
qInfo() << "Adjusted by : " << adjustedBy;
|
||||
} else {
|
||||
qDebug() << "Work dir : " << QDir::currentPath();
|
||||
qInfo() << "Work dir : " << QDir::currentPath();
|
||||
}
|
||||
qDebug() << "Binary path : " << binPath;
|
||||
qDebug() << "Application root path : " << m_rootPath;
|
||||
qInfo() << "Binary path : " << binPath;
|
||||
qInfo() << "Application root path : " << m_rootPath;
|
||||
if (!m_instanceIdToLaunch.isEmpty()) {
|
||||
qDebug() << "ID of instance to launch : " << m_instanceIdToLaunch;
|
||||
qInfo() << "ID of instance to launch : " << m_instanceIdToLaunch;
|
||||
}
|
||||
if (!m_serverToJoin.isEmpty()) {
|
||||
qDebug() << "Address of server to join :" << m_serverToJoin;
|
||||
qInfo() << "Address of server to join :" << m_serverToJoin;
|
||||
} else if (!m_worldToJoin.isEmpty()) {
|
||||
qDebug() << "Name of the world to join :" << m_worldToJoin;
|
||||
qInfo() << "Name of the world to join :" << m_worldToJoin;
|
||||
}
|
||||
qDebug() << "<> Paths set.";
|
||||
qInfo() << "<> Paths set.";
|
||||
}
|
||||
|
||||
if (m_liveCheck) {
|
||||
@ -818,7 +897,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
|
||||
PixmapCache::setInstance(new PixmapCache(this));
|
||||
|
||||
qDebug() << "<> Settings loaded.";
|
||||
qInfo() << "<> Settings loaded.";
|
||||
}
|
||||
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
@ -834,7 +913,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
QString user = settings()->get("ProxyUser").toString();
|
||||
QString pass = settings()->get("ProxyPass").toString();
|
||||
updateProxySettings(proxyTypeStr, addr, port, user, pass);
|
||||
qDebug() << "<> Network done.";
|
||||
qInfo() << "<> Network done.";
|
||||
}
|
||||
|
||||
// load translations
|
||||
@ -842,8 +921,8 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
m_translations.reset(new TranslationsModel("translations"));
|
||||
auto bcp47Name = m_settings->get("Language").toString();
|
||||
m_translations->selectLanguage(bcp47Name);
|
||||
qDebug() << "Your language is" << bcp47Name;
|
||||
qDebug() << "<> Translations loaded.";
|
||||
qInfo() << "Your language is" << bcp47Name;
|
||||
qInfo() << "<> Translations loaded.";
|
||||
}
|
||||
|
||||
// Instance icons
|
||||
@ -854,7 +933,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
m_icons.reset(new IconList(instFolders, setting->get().toString()));
|
||||
connect(setting.get(), &Setting::SettingChanged,
|
||||
[this](const Setting&, QVariant value) { m_icons->directoryChanged(value.toString()); });
|
||||
qDebug() << "<> Instance icons initialized.";
|
||||
qInfo() << "<> Instance icons initialized.";
|
||||
}
|
||||
|
||||
// Themes
|
||||
@ -866,25 +945,25 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
// instance path: check for problems with '!' in instance path and warn the user in the log
|
||||
// and remember that we have to show him a dialog when the gui starts (if it does so)
|
||||
QString instDir = InstDirSetting->get().toString();
|
||||
qDebug() << "Instance path : " << instDir;
|
||||
qInfo() << "Instance path : " << instDir;
|
||||
if (FS::checkProblemticPathJava(QDir(instDir))) {
|
||||
qWarning() << "Your instance path contains \'!\' and this is known to cause java problems!";
|
||||
}
|
||||
m_instances.reset(new InstanceList(m_settings, instDir, this));
|
||||
connect(InstDirSetting.get(), &Setting::SettingChanged, m_instances.get(), &InstanceList::on_InstFolderChanged);
|
||||
qDebug() << "Loading Instances...";
|
||||
qInfo() << "Loading Instances...";
|
||||
m_instances->loadList();
|
||||
qDebug() << "<> Instances loaded.";
|
||||
qInfo() << "<> Instances loaded.";
|
||||
}
|
||||
|
||||
// and accounts
|
||||
{
|
||||
m_accounts.reset(new AccountList(this));
|
||||
qDebug() << "Loading accounts...";
|
||||
qInfo() << "Loading accounts...";
|
||||
m_accounts->setListFilePath("accounts.json", true);
|
||||
m_accounts->loadList();
|
||||
m_accounts->fillQueue();
|
||||
qDebug() << "<> Accounts loaded.";
|
||||
qInfo() << "<> Accounts loaded.";
|
||||
}
|
||||
|
||||
// init the http meta cache
|
||||
@ -905,7 +984,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
|
||||
m_metacache->addBase("meta", QDir("meta").absolutePath());
|
||||
m_metacache->addBase("java", QDir("cache/java").absolutePath());
|
||||
m_metacache->Load();
|
||||
qDebug() << "<> Cache initialized.";
|
||||
qInfo() << "<> Cache initialized.";
|
||||
}
|
||||
|
||||
// now we have network, download translation updates
|
||||
|
Reference in New Issue
Block a user