diff --git a/src/cli/cli_main.cpp b/src/cli/cli_main.cpp index 7fe65c53..a4abc99b 100644 --- a/src/cli/cli_main.cpp +++ b/src/cli/cli_main.cpp @@ -65,11 +65,11 @@ void CLISetInterface::onChangeSet() { void CLISetInterface::run() { // show welcome logo if (!quiet) showWelcome(); + handle_pending_errors(); // loop running = true; while (running) { if (!cli.canGetLine()) break; - handle_pending_errors(); // show prompt if (!quiet) { cli << GRAY << _("> ") << NORMAL; @@ -79,6 +79,7 @@ void CLISetInterface::run() { String command = cli.getLine(); handleCommand(command); cli.flush(); + cli.flushRaw(); } } diff --git a/src/cli/text_io_handler.cpp b/src/cli/text_io_handler.cpp index 85117e23..4786409e 100644 --- a/src/cli/text_io_handler.cpp +++ b/src/cli/text_io_handler.cpp @@ -56,7 +56,9 @@ void TextIOHandler::init() { have_stderr = true; escapes = true; // TODO: detect output redirection #endif + // write to standard output stream = stdout; + raw_mode = false; // always write to stderr if possible if (have_console) { write_errors_to_cli = true; @@ -71,8 +73,8 @@ bool TextIOHandler::haveConsole() const { // ----------------------------------------------------------------------------- : Output TextIOHandler& TextIOHandler::operator << (const Char* str) { - if (escapes || str[0] != 27) { - if (have_console) { + if ((escapes && !raw_mode) || str[0] != 27) { + if (have_console && !raw_mode) { IF_UNICODE(fwprintf,fprintf)(stream,str); } else { buffer += str; @@ -82,17 +84,11 @@ TextIOHandler& TextIOHandler::operator << (const Char* str) { } TextIOHandler& TextIOHandler::operator << (const String& str) { - if (escapes || str.empty() || str.GetChar(0) != 27) { - if (have_console) { - IF_UNICODE(fwprintf,fprintf)(stream,str.c_str()); - } else { - buffer += str; - } - } - return *this; + return *this << str.c_str(); } void TextIOHandler::flush() { + if (raw_mode) return; if (have_console) { fflush(stream); } else if (!buffer.empty()) { @@ -124,6 +120,38 @@ bool TextIOHandler::canGetLine() { return !feof(stdin); } +// ----------------------------------------------------------------------------- : Raw mode + +void TextIOHandler::enableRaw() { + raw_mode = true; + raw_mode_status = 0; +} + +void TextIOHandler::flushRaw() { + if (!raw_mode) return; + // always end in a newline + if (!buffer.empty() && buffer.GetChar(buffer.size()-1) != _('\n')) { + buffer += _('\n'); + } + // count newlines + int newline_count = 0; + FOR_EACH_CONST(c,buffer) if (c==_('\n')) newline_count++; + // write record + printf("%d\n%d\n", raw_mode_status, newline_count); + if (!buffer.empty()) { + #ifdef UNICODE + wxCharBuffer buf = buffer.mb_str(wxConvUTF8); + puts(buf); + #else + puts(buffer.c_str()); + #endif + } + fflush(stdout); + // clear + buffer.clear(); + raw_mode_status = 0; +} + // ----------------------------------------------------------------------------- : Errors void TextIOHandler::showError(const String& message) { @@ -131,6 +159,7 @@ void TextIOHandler::showError(const String& message) { *this << RED << _("ERROR: ") << NORMAL << replace_all(message,_("\n"),_("\n ")) << ENDL; flush(); stream = stdout; + if (raw_mode) raw_mode_status = max(raw_mode_status, 2); } void TextIOHandler::showWarning(const String& message) { @@ -138,4 +167,5 @@ void TextIOHandler::showWarning(const String& message) { *this << YELLOW << _("WARNING: ") << NORMAL << replace_all(message,_("\n"),_("\n ")) << ENDL; flush(); stream = stdout; + if (raw_mode) raw_mode_status = max(raw_mode_status, 1); } diff --git a/src/cli/text_io_handler.hpp b/src/cli/text_io_handler.hpp index aa0f5238..fcc1f7bb 100644 --- a/src/cli/text_io_handler.hpp +++ b/src/cli/text_io_handler.hpp @@ -41,11 +41,19 @@ class TextIOHandler { /// Show a warning message void showWarning(const String& message); + /// Enable raw mode + void enableRaw(); + /// Output a single raw-mode record + /// Has no effect unless enableRaw() was called + void flushRaw(); + private: bool have_console; bool escapes; FILE* stream; String buffer; ///< Buffer when not writing to console + bool raw_mode; + int raw_mode_status; }; /// The global TextIOHandler object diff --git a/src/main.cpp b/src/main.cpp index 66dd0e80..463f4d28 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -191,9 +191,18 @@ int MSE::OnRun() { cli << _("\n \tIMAGE is the same format as for 'export all card images'."); cli << _("\n\n ") << BRIGHT << _("--cli") << NORMAL << _(" [") << PARAM << _("FILE") << NORMAL << _("] [") - << BRIGHT << _("--quiet") << NORMAL << _("]"); + << BRIGHT << _("--quiet") << NORMAL << _("] [") + << BRIGHT << _("--raw") << NORMAL << _("]"); cli << _("\n \tStart the command line interface for performing commands on the set file."); cli << _("\n \tUse ") << BRIGHT << _("-q") << NORMAL << _(" or ") << BRIGHT << _("--quiet") << NORMAL << _(" to supress the startup banner and prompts."); + cli << _("\n \tUse ") << BRIGHT << _("-raw") << NORMAL << _(" for raw output mode."); + cli << _("\n\nRaw output mode is intended for use by other programs:"); + cli << _("\n - The only output is only in response to commands."); + cli << _("\n - For each command a single 'record' is written to the standard output."); + cli << _("\n - The record consists of:"); + cli << _("\n - A line with an integer status code, 0 for ok, 1 for warnings, 2 for errors"); + cli << _("\n - A line containing an integer k, the number of lines to follow"); + cli << _("\n - k lines, each containing UTF-8 encoded string data."); cli << ENDL; cli.flush(); return EXIT_SUCCESS; @@ -214,6 +223,9 @@ int MSE::OnRun() { set = import_set(arg); } else if (arg == _("-q") || arg == _("--quiet")) { quiet = true; + } else if (arg == _("-r") || arg == _("--raw")) { + quiet = true; + cli.enableRaw(); } } CLISetInterface cli_interface(set,quiet);