Commit 2eff957f authored by twanvl's avatar twanvl

If possible all errors are sent to stderr

parent 9608d74b
...@@ -69,6 +69,7 @@ void CLISetInterface::run() { ...@@ -69,6 +69,7 @@ void CLISetInterface::run() {
running = true; running = true;
while (running) { while (running) {
if (!cli.canGetLine()) break; if (!cli.canGetLine()) break;
handle_pending_errors();
// show prompt // show prompt
if (!quiet) { if (!quiet) {
cli << GRAY << _("> ") << NORMAL; cli << GRAY << _("> ") << NORMAL;
...@@ -153,7 +154,7 @@ void CLISetInterface::handleCommand(const String& command) { ...@@ -153,7 +154,7 @@ void CLISetInterface::handleCommand(const String& command) {
vector<ScriptParseError> errors; vector<ScriptParseError> errors;
ScriptP script = parse(command,nullptr,false,errors); ScriptP script = parse(command,nullptr,false,errors);
if (!errors.empty()) { if (!errors.empty()) {
FOR_EACH(error,errors) showError(error.what()); FOR_EACH(error,errors) cli.showError(error.what());
return; return;
} }
// execute command // execute command
...@@ -164,10 +165,6 @@ void CLISetInterface::handleCommand(const String& command) { ...@@ -164,10 +165,6 @@ void CLISetInterface::handleCommand(const String& command) {
cli << result->toCode() << ENDL; cli << result->toCode() << ENDL;
} }
} catch (const Error& e) { } catch (const Error& e) {
showError(e.what()); cli.showError(e.what());
} }
} }
void CLISetInterface::showError(const String& error) {
cli << RED << _("ERROR: ") << NORMAL << replace_all(error,_("\n"),_("\n ")) << ENDL;
}
...@@ -32,7 +32,6 @@ class CLISetInterface : public SetView { ...@@ -32,7 +32,6 @@ class CLISetInterface : public SetView {
void showWelcome(); void showWelcome();
void showUsage(); void showUsage();
void handleCommand(const String& command); void handleCommand(const String& command);
void showError(const String& error);
/// our own context, when no set is loaded /// our own context, when no set is loaded
Context& getContext(); Context& getContext();
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <util/prec.hpp> #include <util/prec.hpp>
#include <cli/text_io_handler.hpp> #include <cli/text_io_handler.hpp>
#include <util/error.hpp>
// ----------------------------------------------------------------------------- : Text I/O handler // ----------------------------------------------------------------------------- : Text I/O handler
...@@ -17,22 +18,29 @@ const Char* PARAM = _("\x1B[33m"); ...@@ -17,22 +18,29 @@ const Char* PARAM = _("\x1B[33m");
const Char* FILE_EXT = _("\x1B[0;1m"); const Char* FILE_EXT = _("\x1B[0;1m");
const Char* GRAY = _("\x1B[1;30m"); const Char* GRAY = _("\x1B[1;30m");
const Char* RED = _("\x1B[1;31m"); const Char* RED = _("\x1B[1;31m");
const Char* YELLOW = _("\x1B[1;33m");
const Char* ENDL = _("\n"); const Char* ENDL = _("\n");
TextIOHandler cli; TextIOHandler cli;
#ifdef __WXMSW__
bool StdHandleOk(DWORD std_handle) {
// GetStdHandle sometimes returns an invalid handle instead of INVALID_HANDLE_VALUE
// check with GetHandleInformation
HANDLE h = GetStdHandle(std_handle);
DWORD flags;
return GetHandleInformation(h,&flags);
}
#endif
void TextIOHandler::init() { void TextIOHandler::init() {
bool have_stderr;
#ifdef __WXMSW__ #ifdef __WXMSW__
have_console = false; have_console = false;
escapes = false; escapes = false;
// Detect whether to use console output // Detect whether to use console output
// GetStdHandle sometimes returns an invalid handle instead of INVALID_HANDLE_VALUE have_console = StdHandleOk(STD_OUTPUT_HANDLE);
// check with GetHandleInformation have_stderr = StdHandleOk(STD_ERROR_HANDLE);
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD flags;
bool ok = GetHandleInformation(h,&flags);
if (ok) have_console = true;
// Detect the --color flag, indicating we should allow escapes // Detect the --color flag, indicating we should allow escapes
if (have_console) { if (have_console) {
for (int i = 1 ; i < wxTheApp->argc ; ++i) { for (int i = 1 ; i < wxTheApp->argc ; ++i) {
...@@ -45,8 +53,14 @@ void TextIOHandler::init() { ...@@ -45,8 +53,14 @@ void TextIOHandler::init() {
#else #else
// always use console on *nix (?) // always use console on *nix (?)
have_console = true; have_console = true;
escapes = true; have_stderr = true;
escapes = true; // TODO: detect output redirection
#endif #endif
stream = stdout;
// always write to stderr if possible
if (have_console) {
write_errors_to_cli = true;
}
} }
bool TextIOHandler::haveConsole() const { bool TextIOHandler::haveConsole() const {
...@@ -56,20 +70,10 @@ bool TextIOHandler::haveConsole() const { ...@@ -56,20 +70,10 @@ bool TextIOHandler::haveConsole() const {
// ----------------------------------------------------------------------------- : Output // ----------------------------------------------------------------------------- : Output
void TextIOHandler::flush() {
if (have_console) {
fflush(stdout);
} else if (!buffer.empty()) {
// Show message box
wxMessageBox(buffer, _("Magic Set Editor"), wxOK | wxICON_INFORMATION);
buffer.clear();
}
}
TextIOHandler& TextIOHandler::operator << (const Char* str) { TextIOHandler& TextIOHandler::operator << (const Char* str) {
if (escapes || str[0] != 27) { if (escapes || str[0] != 27) {
if (have_console) { if (have_console) {
IF_UNICODE(wprintf,printf)(str); IF_UNICODE(fwprintf,fprintf)(stream,str);
} else { } else {
buffer += str; buffer += str;
} }
...@@ -80,7 +84,7 @@ TextIOHandler& TextIOHandler::operator << (const Char* str) { ...@@ -80,7 +84,7 @@ TextIOHandler& TextIOHandler::operator << (const Char* str) {
TextIOHandler& TextIOHandler::operator << (const String& str) { TextIOHandler& TextIOHandler::operator << (const String& str) {
if (escapes || str.empty() || str.GetChar(0) != 27) { if (escapes || str.empty() || str.GetChar(0) != 27) {
if (have_console) { if (have_console) {
IF_UNICODE(wprintf,printf)(str.c_str()); IF_UNICODE(fwprintf,fprintf)(stream,str.c_str());
} else { } else {
buffer += str; buffer += str;
} }
...@@ -88,6 +92,16 @@ TextIOHandler& TextIOHandler::operator << (const String& str) { ...@@ -88,6 +92,16 @@ TextIOHandler& TextIOHandler::operator << (const String& str) {
return *this; return *this;
} }
void TextIOHandler::flush() {
if (have_console) {
fflush(stream);
} else if (!buffer.empty()) {
// Show message box
wxMessageBox(buffer, _("Magic Set Editor"), wxOK | wxICON_INFORMATION);
buffer.clear();
}
}
// ----------------------------------------------------------------------------- : Input // ----------------------------------------------------------------------------- : Input
String TextIOHandler::getLine() { String TextIOHandler::getLine() {
...@@ -109,3 +123,19 @@ String TextIOHandler::getLine() { ...@@ -109,3 +123,19 @@ String TextIOHandler::getLine() {
bool TextIOHandler::canGetLine() { bool TextIOHandler::canGetLine() {
return !feof(stdin); return !feof(stdin);
} }
// ----------------------------------------------------------------------------- : Errors
void TextIOHandler::showError(const String& message) {
stream = stdout;
*this << RED << _("ERROR: ") << NORMAL << replace_all(message,_("\n"),_("\n ")) << ENDL;
flush();
stream = stdout;
}
void TextIOHandler::showWarning(const String& message) {
stream = stdout;
*this << YELLOW << _("WARNING: ") << NORMAL << replace_all(message,_("\n"),_("\n ")) << ENDL;
flush();
stream = stdout;
}
...@@ -36,9 +36,15 @@ class TextIOHandler { ...@@ -36,9 +36,15 @@ class TextIOHandler {
/// Flush output /// Flush output
void flush(); void flush();
/// Show an error message
void showError(const String& message);
/// Show a warning message
void showWarning(const String& message);
private: private:
bool have_console; bool have_console;
bool escapes; bool escapes;
FILE* stream;
String buffer; ///< Buffer when not writing to console String buffer; ///< Buffer when not writing to console
}; };
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <util/prec.hpp> #include <util/prec.hpp>
#include <util/error.hpp> #include <util/error.hpp>
#include <cli/text_io_handler.hpp>
DECLARE_TYPEOF_COLLECTION(ScriptParseError); DECLARE_TYPEOF_COLLECTION(ScriptParseError);
...@@ -62,6 +63,7 @@ String pending_errors; ...@@ -62,6 +63,7 @@ String pending_errors;
String pending_warnings; String pending_warnings;
DECLARE_TYPEOF_COLLECTION(String); DECLARE_TYPEOF_COLLECTION(String);
wxMutex crit_error_handling; wxMutex crit_error_handling;
bool write_errors_to_cli = false;
void show_pending_errors(); void show_pending_errors();
void show_pending_warnings(); void show_pending_warnings();
...@@ -82,7 +84,7 @@ void handle_error(const String& e, bool allow_duplicate = true, bool now = true) ...@@ -82,7 +84,7 @@ void handle_error(const String& e, bool allow_duplicate = true, bool now = true)
pending_errors += e; pending_errors += e;
} }
// show messages // show messages
if (now && wxThread::IsMain()) { if ((write_errors_to_cli || now) && wxThread::IsMain()) {
show_pending_warnings(); // warnings are older, show them first show_pending_warnings(); // warnings are older, show them first
show_pending_errors(); show_pending_errors();
} }
...@@ -106,7 +108,7 @@ void handle_warning(const String& w, bool now) { ...@@ -106,7 +108,7 @@ void handle_warning(const String& w, bool now) {
pending_warnings += w; pending_warnings += w;
} }
// show messages // show messages
if (now && wxThread::IsMain()) { if ((write_errors_to_cli || now) && wxThread::IsMain()) {
show_pending_errors(); show_pending_errors();
show_pending_warnings(); show_pending_warnings();
} }
...@@ -122,7 +124,11 @@ void show_pending_errors() { ...@@ -122,7 +124,11 @@ void show_pending_errors() {
if (crit_error_handling.TryLock() != wxMUTEX_NO_ERROR) if (crit_error_handling.TryLock() != wxMUTEX_NO_ERROR)
return; return;
if (!pending_errors.empty()) { if (!pending_errors.empty()) {
wxMessageBox(pending_errors, _("Error"), wxOK | wxICON_ERROR); if (write_errors_to_cli) {
cli.showError(pending_errors);
} else {
wxMessageBox(pending_errors, _("Error"), wxOK | wxICON_ERROR);
}
pending_errors.clear(); pending_errors.clear();
} }
crit_error_handling.Unlock(); crit_error_handling.Unlock();
...@@ -132,7 +138,11 @@ void show_pending_warnings() { ...@@ -132,7 +138,11 @@ void show_pending_warnings() {
if (crit_error_handling.TryLock() != wxMUTEX_NO_ERROR) if (crit_error_handling.TryLock() != wxMUTEX_NO_ERROR)
return; return;
if (!pending_warnings.empty()) { if (!pending_warnings.empty()) {
wxMessageBox(pending_warnings, _("Warning"), wxOK | wxICON_EXCLAMATION); if (write_errors_to_cli) {
cli.showWarning(pending_warnings);
} else {
wxMessageBox(pending_warnings, _("Warning"), wxOK | wxICON_EXCLAMATION);
}
pending_warnings.clear(); pending_warnings.clear();
} }
crit_error_handling.Unlock(); crit_error_handling.Unlock();
......
...@@ -110,6 +110,9 @@ class ScriptError : public Error { ...@@ -110,6 +110,9 @@ class ScriptError : public Error {
// ----------------------------------------------------------------------------- : Error handling // ----------------------------------------------------------------------------- : Error handling
/// Should errors be written to stdout?
extern bool write_errors_to_cli;
/// Handle an error by showing a message box /// Handle an error by showing a message box
/** If !allow_duplicate and the error is the same as the previous error, does nothing. /** If !allow_duplicate and the error is the same as the previous error, does nothing.
* If !now the error is handled by a later call to handle_pending_errors() * If !now the error is handled by a later call to handle_pending_errors()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment