Skip to content

Commit

Permalink
Log: Introduce the PRINT level and use it for console specific prints
Browse files Browse the repository at this point in the history
This is a first try and is a bit ugly. The PRINT level is like
NOTICE except that a console can ask to be the sole receiver for
PRINTs (so that most commands output will stay on that console only)
So this commit:
 * adds a PRINT level and add the level to Log::Event
 * adds an entry point to Log to change the target for PRINTs
(no target specified = all console)
 * implement that console lock for commands and completion in consoles

The problem is that Com_Printf uses Cmd::GetEnv()->Print() which will
use Print() so commands like /map may end up putting everything in a
single console even though that's not what we want (some things should)
use NOTICE.
  • Loading branch information
Kangz committed Feb 12, 2014
1 parent 2de1744 commit 091929d
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 18 deletions.
5 changes: 5 additions & 0 deletions src/common/Command.h
Expand Up @@ -172,8 +172,13 @@ namespace Cmd {
*/
class Environment {
public:
virtual ~Environment() {};

virtual void Print(Str::StringRef text) = 0;
virtual void ExecuteAfter(Str::StringRef text, bool parseCvars = false) = 0;

virtual void OnCommandStart() {}
virtual void OnCommandEnd() {}
};

// Implementation of templates.
Expand Down
21 changes: 16 additions & 5 deletions src/common/Log.cpp
Expand Up @@ -55,6 +55,11 @@ namespace Log {
return true;
}

if (value == "print") {
result = Log::PRINT;
return true;
}

if (value == "debug" or value == "all") {
result = Log::DEBUG;
return true;
Expand All @@ -69,6 +74,8 @@ namespace Log {
return "error";
case Log::WARNING:
return "warning";
case Log::PRINT:
return "print";
case Log::NOTICE:
return "notice";
case Log::DEBUG:
Expand All @@ -78,25 +85,29 @@ namespace Log {
}
}

//TODO add the time (broken for now because it is journaled) use Sys_Milliseconds instead (Utils::Milliseconds ?)
static const int errorTargets = (1 << GRAPHICAL_CONSOLE) | (1 << TTY_CONSOLE) | (1 << CRASHLOG) | (1 << HUD) | (1 << LOGFILE);
void CodeSourceError(std::string message) {
Log::Dispatch({"^1Error: " + message}, errorTargets);
Log::Dispatch({"^1Error: " + message, ERROR}, errorTargets);
}

static const int warnTargets = (1 << GRAPHICAL_CONSOLE) | (1 << TTY_CONSOLE) | (1 << CRASHLOG) | (1 << LOGFILE);
void CodeSourceWarn(std::string message) {
Log::Dispatch({"^3Warn: " + message}, warnTargets);
Log::Dispatch({"^3Warn: " + message, WARNING}, warnTargets);
}

static const int noticeTargets = (1 << GRAPHICAL_CONSOLE) | (1 << TTY_CONSOLE) | (1 << CRASHLOG) | (1 << LOGFILE);
void CodeSourceNotice(std::string message) {
Log::Dispatch({message}, noticeTargets);
Log::Dispatch({message, NOTICE}, noticeTargets);
}

static const int printTargets = (1 << GRAPHICAL_CONSOLE) | (1 << TTY_CONSOLE);
void CodeSourcePrint(std::string message) {
Log::Dispatch({message, PRINT}, printTargets);
}

static const int debugTargets = (1 << GRAPHICAL_CONSOLE) | (1 << TTY_CONSOLE);
void CodeSourceDebug(std::string message) {
Log::Dispatch({"^5Debug: " + message}, debugTargets);
Log::Dispatch({"^5Debug: " + message, DEBUG}, debugTargets);
}
}

Expand Down
26 changes: 24 additions & 2 deletions src/common/Log.h
Expand Up @@ -48,6 +48,7 @@ namespace Log {

enum Level {
DEBUG,
PRINT,
NOTICE,
WARNING,
ERROR
Expand Down Expand Up @@ -83,6 +84,9 @@ namespace Log {
template<typename ... Args>
void Notice(Str::StringRef format, Args&& ... args);

template<typename ... Args>
void Print(Str::StringRef format, Args&& ... args);

template<typename ... Args>
void Debug(Str::StringRef format, Args&& ... args);

Expand All @@ -107,6 +111,9 @@ namespace Log {
template<typename ... Args>
void Notice(Str::StringRef format, Args&& ... args);

template<typename ... Args>
void Print(Str::StringRef format, Args&& ... args);

template<typename ... Args>
void Debug(Str::StringRef format, Args&& ... args);

Expand All @@ -116,9 +123,10 @@ namespace Log {
*/

struct Event {
Event(std::string text)
: text(std::move(text)) {}
Event(std::string text, Level level)
: text(std::move(text)), level(level) {}
std::string text;
Level level;
};

/*
Expand All @@ -127,6 +135,7 @@ namespace Log {
*/

enum TargetId {
NO_TARGET,
GRAPHICAL_CONSOLE,
TTY_CONSOLE,
CRASHLOG,
Expand All @@ -147,6 +156,7 @@ namespace Log {
void CodeSourceError(std::string message);
void CodeSourceWarn(std::string message);
void CodeSourceNotice(std::string message);
void CodeSourcePrint(std::string message);
void CodeSourceDebug(std::string message);

// Implementation of templates
Expand All @@ -172,6 +182,13 @@ namespace Log {
}
}

template<typename ... Args>
void Logger::Print(Str::StringRef format, Args&& ... args) {
if (filterLevel.Get() <= PRINT) {
CodeSourcePrint(Str::Format(format, std::forward<Args>(args) ...));
}
}

template<typename ... Args>
void Logger::Debug(Str::StringRef format, Args&& ... args) {
if (filterLevel.Get() <= DEBUG) {
Expand All @@ -196,6 +213,11 @@ namespace Log {
CodeSourceNotice(Str::Format(format, std::forward<Args>(args) ...));
}

template<typename ... Args>
void Print(Str::StringRef format, Args&& ... args) {
CodeSourcePrint(Str::Format(format, std::forward<Args>(args) ...));
}

template<typename ... Args>
void Debug(Str::StringRef format, Args&& ... args) {
CodeSourceDebug(Str::Format(format, std::forward<Args>(args) ...));
Expand Down
2 changes: 1 addition & 1 deletion src/engine/client/cl_keys.cpp
Expand Up @@ -47,7 +47,7 @@ key up events are sent even if in console mode

#define CLIP(t) Maths::clamp( (t), 0, MAX_TEAMS - 1 )

Console::Field g_consoleField(INT_MAX);
Console::Field g_consoleField(INT_MAX, Log::GRAPHICAL_CONSOLE);
qboolean chat_irc;

qboolean key_overstrikeMode;
Expand Down
4 changes: 3 additions & 1 deletion src/engine/framework/CommandSystem.cpp
Expand Up @@ -203,7 +203,9 @@ namespace Cmd {
auto it = commands.find(cmdName);
if (it != commands.end()) {
storedEnvironment = env;
storedEnvironment->OnCommandStart();
it->second.cmd->Run(args);
storedEnvironment->OnCommandEnd();
return;
}

Expand Down Expand Up @@ -299,7 +301,7 @@ namespace Cmd {
*/

void DefaultEnvironment::Print(Str::StringRef text) {
Log::CodeSourceNotice(text);
Log::CodeSourcePrint(text);
}

void DefaultEnvironment::ExecuteAfter(Str::StringRef text, bool parseCvars) {
Expand Down
56 changes: 50 additions & 6 deletions src/engine/framework/ConsoleField.cpp
Expand Up @@ -30,14 +30,46 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "ConsoleField.h"
#include "CommandSystem.h"
#include "LogSystem.h"
#include "../../common/String.h"
#include "../qcommon/q_shared.h"
#include <locale>
#include <algorithm>

namespace Console {

Field::Field(int size): LineEditData(size), hist(HISTORY_END) {
class ConsoleEnvironment: public Cmd::DefaultEnvironment {
public:
ConsoleEnvironment(Field* field): field(field), recursive(0) {};

virtual void OnCommandStart() OVERRIDE FINAL {
if (recursive == 0) {
field->StartRedirectPrints();
}
recursive ++;
}
virtual void OnCommandEnd() OVERRIDE FINAL {
recursive --;
if (recursive == 0) {
field->StopRedirectPrints();
}
}

private:
Field* field;
int recursive;
};

Field::Field(int size, Log::TargetId logTarget): LineEditData(size), hist(HISTORY_END), logTarget(logTarget) {
if (logTarget == Log::NO_TARGET) {
env = new Cmd::DefaultEnvironment;
} else {
env = new ConsoleEnvironment(this);
}
}

Field::~Field() {
delete env;
}

void Field::HistoryPrev() {
Expand All @@ -59,11 +91,11 @@ namespace Console {

std::string current = Str::UTF32To8(GetText());
if (current[0] == '/' or current[0] == '\\') {
Cmd::BufferCommandText(current.c_str() + 1, true);
Cmd::BufferCommandText(current.c_str() + 1, true, env);
} else if (defaultCommand.empty()) {
Cmd::BufferCommandText(current, true);
Cmd::BufferCommandText(current, true, env);
} else {
Cmd::BufferCommandText(defaultCommand + " " + Cmd::Escape(current), true);
Cmd::BufferCommandText(defaultCommand + " " + Cmd::Escape(current), true, env);
}
AddToHistory(hist, std::move(current));

Expand Down Expand Up @@ -131,12 +163,24 @@ namespace Console {

//Print the matches if it is ambiguous
if (candidates.size() >= 2) {
Com_Printf(S_COLOR_YELLOW "-> " S_COLOR_WHITE "%s\n", Str::UTF32To8(GetText()).c_str());
StartRedirectPrints();
Log::Print(S_COLOR_YELLOW "-> " S_COLOR_WHITE "%s\n", Str::UTF32To8(GetText()).c_str());
for (auto& candidate : candidates) {
std::string filler(maxCandidateLength - candidate.first.length(), ' ');
Com_Printf(" %s%s %s\n", candidate.first.c_str(), filler.c_str(), candidate.second.c_str());
Log::Print(" %s%s %s\n", candidate.first.c_str(), filler.c_str(), candidate.second.c_str());
}
StopRedirectPrints();
}
}

void Field::StartRedirectPrints() {
if (logTarget != Log::NO_TARGET) {
Log::RedirectPrints(logTarget);
}
}

void Field::StopRedirectPrints() {
Log::RedirectPrints();
}

}
10 changes: 9 additions & 1 deletion src/engine/framework/ConsoleField.h
Expand Up @@ -28,7 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/

#include "../../common/Command.h"
#include "../../common/LineEditData.h"
#include "../../common/Log.h"
#include "../../common/String.h"
#include "ConsoleHistory.h"

Expand All @@ -39,16 +41,22 @@ namespace Console {

class Field : public Util::LineEditData {
public:
Field(int size);
Field(int size, Log::TargetId logTarget = Log::NO_TARGET);
~Field();

void HistoryPrev();
void HistoryNext();

void RunCommand(Str::StringRef defaultCommand = "");
void AutoComplete();

void StartRedirectPrints();
void StopRedirectPrints();

private:
HistoryHandle hist;
Cmd::Environment* env;
Log::TargetId logTarget;
};

}
Expand Down
9 changes: 9 additions & 0 deletions src/engine/framework/LogSystem.cpp
Expand Up @@ -39,13 +39,18 @@ namespace Log {

static Target* targets[MAX_TARGET_ID];

TargetId redirectPrintTarget = NO_TARGET;

//TODO make me reentrant // or check it is actually reentrant when using for (Event e : events) do stuff
//TODO think way more about thread safety
void Dispatch(Log::Event event, int targetControl) {
static std::vector<Log::Event> buffers[MAX_TARGET_ID];
static std::recursive_mutex bufferLocks[MAX_TARGET_ID];

if (event.level == PRINT and redirectPrintTarget != NO_TARGET) {
targetControl = redirectPrintTarget;
}

for (int i = 0; i < MAX_TARGET_ID; i++) {
if ((targetControl >> i) & 1) {
auto& buffer = buffers[i];
Expand All @@ -67,6 +72,10 @@ namespace Log {
}
}

void RedirectPrints(TargetId id) {
redirectPrintTarget = id;
}

void RegisterTarget(TargetId id, Target* target) {
targets[id] = target;
}
Expand Down
1 change: 1 addition & 0 deletions src/engine/framework/LogSystem.h
Expand Up @@ -49,6 +49,7 @@ namespace Log {
// Dispatches the event to all the targets specified by targetControl (flags)
// Can be called by any thread.
void Dispatch(Log::Event event, int targetControl);
void RedirectPrints(TargetId id = NO_TARGET);

class Target {
public:
Expand Down
2 changes: 1 addition & 1 deletion src/engine/sys/con_curses.cpp
Expand Up @@ -70,7 +70,7 @@ void CON_Print_tty( const char *message );
void CON_Clear_tty( void );

static qboolean curses_on = qfalse;
static Console::Field input_field(INT_MAX);
static Console::Field input_field(INT_MAX, Log::TTY_CONSOLE);
static WINDOW *borderwin;
static WINDOW *logwin;
static WINDOW *inputwin;
Expand Down
2 changes: 1 addition & 1 deletion src/engine/sys/con_tty.cpp
Expand Up @@ -75,7 +75,7 @@ static int TTY_eof;

static struct termios TTY_tc;

static Console::Field TTY_field(INT_MAX);
static Console::Field TTY_field(INT_MAX, Log::TTY_CONSOLE);

/*
==================
Expand Down

0 comments on commit 091929d

Please sign in to comment.