From 0ff67da077ec9216b1c1a9e60612c73828e22ff7 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Sun, 7 Jun 2020 18:21:59 +0200 Subject: [PATCH] Parameter to specify a logging file --- ChangeLog | 4 ++ examples/opti-move.cpp | 4 ++ examples/termcap.cpp | 2 +- examples/ui.cpp | 3 -- examples/windows.cpp | 4 +- src/fapplication.cpp | 83 ++++++++++++++++++++++--------- src/include/final/fapplication.h | 2 + src/include/final/flog.h | 1 + src/include/final/flogger.h | 5 ++ src/include/final/fstartoptions.h | 7 ++- test/flogger-test.cpp | 17 +++++-- 11 files changed, 98 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index a63619fb..73d27379 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2020-06-07 Markus Gans + * The --log-file parameter stores log output to any file. The file + can be viewed directly on another terminal with "tail -f". + 2020-06-06 Markus Gans * Now, the terminal is not initialized before the method show() is called. Or you force it explicitly via the FApplication object. diff --git a/examples/opti-move.cpp b/examples/opti-move.cpp index 5e931ace..72b8a3d0 100644 --- a/examples/opti-move.cpp +++ b/examples/opti-move.cpp @@ -163,6 +163,10 @@ class DirectLogger final : public finalcut::FLog // An implementation is not required in this context } + void flush() override + { + output.flush(); + } void setOutputStream (const std::ostream& os) override { output.rdbuf(os.rdbuf()); } diff --git a/examples/termcap.cpp b/examples/termcap.cpp index 6f2c1675..e5e52dda 100644 --- a/examples/termcap.cpp +++ b/examples/termcap.cpp @@ -310,7 +310,7 @@ int main (int argc, char* argv[]) // Force terminal initialization without calling show() term_app.initTerminal(); - if ( term_app.isQuit() ) + if ( finalcut::FApplication::isQuit() ) return 0; std::cout << "--------\r\nFTermcap\r\n--------\r\n\n"; diff --git a/examples/ui.cpp b/examples/ui.cpp index a9a14a6b..c65d0ff1 100644 --- a/examples/ui.cpp +++ b/examples/ui.cpp @@ -1067,9 +1067,6 @@ int main (int argc, char* argv[]) finalcut::FTerm::redefineDefaultColors(true); finalcut::FTerm::setTermTitle (title); - // Force vt100 encoding - //finalcut::FTerm::setEncoding(finalcut::fc::VT100); - // Sets the terminal size to 94×30 //finalcut::FTerm::setTermSize(FSize{94, 30}); diff --git a/examples/windows.cpp b/examples/windows.cpp index f53a7f77..c9264857 100644 --- a/examples/windows.cpp +++ b/examples/windows.cpp @@ -84,12 +84,12 @@ SmallWindow::SmallWindow (finalcut::FWidget* parent) right_arrow.ignorePadding(); right_arrow.setGeometry (FPoint{int(getWidth()) - 1, 2}, FSize{1, 1}); - top_left_label = "menu"; + top_left_label.setText("menu"); top_left_label.setForegroundColor (wc->label_inactive_fg); top_left_label.setEmphasis(); top_left_label.setGeometry (FPoint{1, 1}, FSize{6, 1}); - top_right_label = "zoom"; + top_right_label.setText("zoom"); top_right_label.setAlignment (fc::alignRight); top_right_label.setForegroundColor (wc->label_inactive_fg); top_right_label.setEmphasis(); diff --git a/src/fapplication.cpp b/src/fapplication.cpp index 130cc68e..d68ef3e0 100644 --- a/src/fapplication.cpp +++ b/src/fapplication.cpp @@ -20,6 +20,7 @@ * . * ***********************************************************************/ +#include #include #include @@ -366,7 +367,56 @@ void FApplication::init (uInt64 key_time, uInt64 dblclick_time) mouse->setDblclickInterval (dblclick_time); // Initialize logging - getLog()->setLineEnding(FLog::CRLF); + if ( ! getStartOptions().logfile_stream.is_open() ) + getLog()->setLineEnding(FLog::CRLF); +} + +//---------------------------------------------------------------------- +void FApplication::setTerminalEncoding (const FString& enc_str) +{ + const FString& enc = enc_str.toLower(); + + if ( enc.includes("utf8") ) + getStartOptions().encoding = fc::UTF8; + else if ( enc.includes("vt100") ) + getStartOptions().encoding = fc::VT100; + else if ( enc.includes("pc") ) + getStartOptions().encoding = fc::PC; + else if ( enc.includes("ascii") ) + getStartOptions().encoding = fc::ASCII; + else if ( enc.includes("help") ) + showParameterUsage(); + else + { + auto ftermdata = FTerm::getFTermData(); + ftermdata->setExitMessage ( "Unknown encoding \"" + enc_str + + "\"\n(Valid encodings are utf8, " + + "vt100, pc and ascii)" ); + exit(EXIT_FAILURE); + } +} + +//---------------------------------------------------------------------- +void FApplication::setLogFile (const FString& filename) +{ + // Get the global logger object + FLog& log = *FApplication::getLog(); + auto& log_stream = getStartOptions().logfile_stream; + log_stream.open(filename, std::ofstream::out); + + if ( log_stream.is_open() ) + { + log.setOutputStream(log_stream); + log.enableTimestamp(); + log.setLineEnding (finalcut::FLog::LF); + } + else + { + auto ftermdata = FTerm::getFTermData(); + ftermdata->setExitMessage ( "Could not open log file \"" + + FString(optarg) + "\"" ); + exit(EXIT_FAILURE); + } } //---------------------------------------------------------------------- @@ -379,6 +429,7 @@ void FApplication::cmd_options (const int& argc, char* argv[]) static struct option long_options[] = { {"encoding", required_argument, nullptr, 0 }, + {"log-file", required_argument, nullptr, 0 }, {"no-mouse", no_argument, nullptr, 0 }, {"no-optimized-cursor", no_argument, nullptr, 0 }, {"no-terminal-detection", no_argument, nullptr, 0 }, @@ -409,28 +460,10 @@ void FApplication::cmd_options (const int& argc, char* argv[]) if ( c == 0 ) { if ( std::strcmp(long_options[idx].name, "encoding") == 0 ) - { - FString encoding{optarg}; - encoding = encoding.toLower(); + setTerminalEncoding(FString(optarg)); - if ( encoding.includes("utf8") ) - getStartOptions().encoding = fc::UTF8; - else if ( encoding.includes("vt100") ) - getStartOptions().encoding = fc::VT100; - else if ( encoding.includes("pc") ) - getStartOptions().encoding = fc::PC; - else if ( encoding.includes("ascii") ) - getStartOptions().encoding = fc::ASCII; - else if ( encoding.includes("help") ) - showParameterUsage(); - else - { - auto ftermdata = FTerm::getFTermData(); - ftermdata->setExitMessage ( "Unknown encoding " - + std::string(encoding.c_str()) ); - exit(EXIT_FAILURE); - } - } + if ( std::strcmp(long_options[idx].name, "log-file") == 0 ) + setLogFile(FString(optarg)); if ( std::strcmp(long_options[idx].name, "no-mouse") == 0 ) getStartOptions().mouse_support = false; @@ -488,10 +521,12 @@ void FApplication::showParameterUsage() << " Display this help and exit\n" << "\n" << "The Final Cut options:\n" - << " --encoding " + << " --encoding= " << " Sets the character encoding mode\n" << " " << " {utf8, vt100, pc, ascii}\n" + << " --log-file= " + << " Writes log output to FILE\n" << " --no-mouse " << " Disable mouse support\n" << " --no-optimized-cursor " @@ -1199,6 +1234,8 @@ void FApplication::processLogger() if ( ! logger->str().empty() ) logger->pubsync(); + + logger->flush(); } //---------------------------------------------------------------------- diff --git a/src/include/final/fapplication.h b/src/include/final/fapplication.h index 521ad2fa..a808fa77 100644 --- a/src/include/final/fapplication.h +++ b/src/include/final/fapplication.h @@ -147,6 +147,8 @@ class FApplication : public FWidget // Methods void init (uInt64, uInt64); + static void setTerminalEncoding (const FString&); + static void setLogFile (const FString&); static void cmd_options (const int&, char*[]); static FStartOptions& getStartOptions(); static void showParameterUsage(); diff --git a/src/include/final/flog.h b/src/include/final/flog.h index ef5d372c..9ff759dc 100644 --- a/src/include/final/flog.h +++ b/src/include/final/flog.h @@ -89,6 +89,7 @@ class FLog : public std::stringbuf virtual void warn (const std::string&) = 0; virtual void error (const std::string&) = 0; virtual void debug (const std::string&) = 0; + virtual void flush() = 0; virtual void setOutputStream (const std::ostream&) = 0; virtual void setLineEnding (LineEnding) = 0; virtual void enableTimestamp() = 0; diff --git a/src/include/final/flogger.h b/src/include/final/flogger.h index cdba1192..a7fcd17f 100644 --- a/src/include/final/flogger.h +++ b/src/include/final/flogger.h @@ -77,6 +77,7 @@ class FLogger : public FLog void warn (const std::string&) override; void error (const std::string&) override; void debug (const std::string&) override; + void flush() override; void setOutputStream (const std::ostream&) override; void setLineEnding (LineEnding) override; void enableTimestamp() override; @@ -127,6 +128,10 @@ inline void FLogger::debug (const std::string& msg) printLogLine (msg); } +//---------------------------------------------------------------------- +inline void FLogger::flush() +{ output.flush(); } + //---------------------------------------------------------------------- inline void FLogger::setOutputStream (const std::ostream& os) { output.rdbuf(os.rdbuf()); } diff --git a/src/include/final/fstartoptions.h b/src/include/final/fstartoptions.h index c541559e..3c164130 100644 --- a/src/include/final/fstartoptions.h +++ b/src/include/final/fstartoptions.h @@ -35,7 +35,8 @@ #error "Only can be included directly." #endif -#include +#include +#include #include "final/fc.h" #include "final/fstring.h" @@ -82,7 +83,6 @@ class FStartOptions final uInt8 sgr_optimizer : 1; uInt8 vgafont : 1; uInt8 newfont : 1; - fc::encoding encoding{fc::UNKNOWN}; #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(UNIT_TEST) uInt8 meta_sends_escape : 1; @@ -95,6 +95,9 @@ class FStartOptions final uInt16 dark_theme : 1; uInt16 : 15; // padding bits + + fc::encoding encoding{fc::UNKNOWN}; + std::ofstream logfile_stream; static FStartOptions* start_options; }; diff --git a/test/flogger-test.cpp b/test/flogger-test.cpp index 176f6e89..b14a3183 100644 --- a/test/flogger-test.cpp +++ b/test/flogger-test.cpp @@ -59,17 +59,28 @@ class myLogger : public finalcut::FLog output << "Debug: " << entry << std::endl; } + void flush() override + { + // An implementation is not required in this context + } + void setOutputStream (const std::ostream& os) override { output.rdbuf(os.rdbuf()); } void setLineEnding (LineEnding) override - { } + { + // An implementation is not required in this context + } void enableTimestamp() override - { } + { + // An implementation is not required in this context + } void disableTimestamp() override - { } + { + // An implementation is not required in this context + } private: // Data member