From 88cfef0821933dfa4e840c793cdb9352d4b4423b Mon Sep 17 00:00:00 2001 From: Sylvain Joubert Date: Tue, 5 Nov 2019 17:07:42 +0100 Subject: ccmake: redirect stdout/stderr to the displayed logs Use cmSystemTools to report some messages. These should now be caught and displayed properly, both in ccmake and cmake-gui Avoid log display flickering during processing - Don't clear the screen each time the long message form is rendered. It always renders the whole screen again so clearing it only causes flickering. - Add scroll down capabilities to the long message form so that it can draw itself directly in the correct state. This removes the need to programatically scroll down just after that also caused flickering. Fixes #19882 Fixes #13288 --- Source/CursesDialog/ccmake.cxx | 22 +++++++++++++++++++-- Source/CursesDialog/cmCursesLongMessageForm.cxx | 22 ++++++++------------- Source/CursesDialog/cmCursesLongMessageForm.h | 13 ++++++++----- Source/CursesDialog/cmCursesMainForm.cxx | 26 +++++++++++++------------ Source/cmake.cxx | 7 +++---- 5 files changed, 53 insertions(+), 37 deletions(-) diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index 7732105..01fce85 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -155,10 +155,28 @@ int main(int argc, char const* const* argv) return 1; } + /* + * The message is stored in a list by the form which will be + * joined by '\n' before display. + * Removing any trailing '\n' avoid extra empty lines in the final results + */ + auto cleanMessage = [](const std::string& message) -> std::string { + auto msg = message; + if (!msg.empty() && msg.back() == '\n') { + msg.pop_back(); + } + return msg; + }; cmSystemTools::SetMessageCallback( - [myform](const std::string& message, const char* title) { - myform->AddError(message, title); + [&](const std::string& message, const char* title) { + myform->AddError(cleanMessage(message), title); }); + cmSystemTools::SetStderrCallback([&](const std::string& message) { + myform->AddError(cleanMessage(message), ""); + }); + cmSystemTools::SetStdoutCallback([&](const std::string& message) { + myform->UpdateProgress(cleanMessage(message), -1); + }); cmCursesForm::CurrentForm = myform; diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx index a69fdee..806e663 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.cxx +++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx @@ -17,7 +17,9 @@ inline int ctrl(int z) } cmCursesLongMessageForm::cmCursesLongMessageForm( - std::vector const& messages, const char* title) + std::vector const& messages, const char* title, + ScrollBehavior scrollBehavior) + : Scrolling(scrollBehavior) { // Append all messages into on big string this->Messages = cmJoin(messages, "\n"); @@ -109,8 +111,6 @@ void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/, const char* msg = this->Messages.c_str(); - curses_clear(); - if (this->Fields[0]) { free_field(this->Fields[0]); this->Fields[0] = nullptr; @@ -133,7 +133,11 @@ void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/, } i++; } - form_driver(this->Form, REQ_BEG_FIELD); + if (this->Scrolling == ScrollBehavior::ScrollDown) { + form_driver(this->Form, REQ_END_FIELD); + } else { + form_driver(this->Form, REQ_BEG_FIELD); + } this->UpdateStatusBar(); touchwin(stdscr); @@ -174,13 +178,3 @@ void cmCursesLongMessageForm::HandleInput() wrefresh(stdscr); } } - -void cmCursesLongMessageForm::ScrollDown() -{ - if (this->Form) { - form_driver(this->Form, REQ_END_FIELD); - this->UpdateStatusBar(); - touchwin(stdscr); - wrefresh(stdscr); - } -} diff --git a/Source/CursesDialog/cmCursesLongMessageForm.h b/Source/CursesDialog/cmCursesLongMessageForm.h index dde5bff..88efe62 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.h +++ b/Source/CursesDialog/cmCursesLongMessageForm.h @@ -14,8 +14,14 @@ class cmCursesLongMessageForm : public cmCursesForm { public: + enum class ScrollBehavior + { + NoScroll, + ScrollDown + }; + cmCursesLongMessageForm(std::vector const& messages, - const char* title); + const char* title, ScrollBehavior scrollBehavior); ~cmCursesLongMessageForm() override; cmCursesLongMessageForm(cmCursesLongMessageForm const&) = delete; @@ -26,10 +32,6 @@ public: void HandleInput() override; // Description: - // Scroll down to the end of the content - void ScrollDown(); - - // Description: // Display form. Use a window of size width x height, starting // at top, left. void Render(int left, int top, int width, int height) override; @@ -47,6 +49,7 @@ public: protected: std::string Messages; std::string Title; + ScrollBehavior Scrolling; FIELD* Fields[2]; }; diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index ffc9528..dff2afe 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -546,13 +546,13 @@ int cmCursesMainForm::Configure(int noconfigure) if (cmSystemTools::GetErrorOccuredFlag()) { title = "Configure failed with the following output"; } - cmCursesLongMessageForm* msgs = - new cmCursesLongMessageForm(this->Outputs, title); + cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( + this->Outputs, title, + cmCursesLongMessageForm::ScrollBehavior::ScrollDown); // reset error condition cmSystemTools::ResetErrorOccuredFlag(); CurrentForm = msgs; msgs->Render(1, 1, xx, yy); - msgs->ScrollDown(); msgs->HandleInput(); // If they typed the wrong source directory, we report // an error and exit @@ -603,11 +603,11 @@ int cmCursesMainForm::Generate() if (cmSystemTools::GetErrorOccuredFlag()) { title = "Generate failed with the following output"; } - cmCursesLongMessageForm* msgs = - new cmCursesLongMessageForm(this->Outputs, title); + cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( + this->Outputs, title, + cmCursesLongMessageForm::ScrollBehavior::ScrollDown); CurrentForm = msgs; msgs->Render(1, 1, xx, yy); - msgs->ScrollDown(); msgs->HandleInput(); // If they typed the wrong source directory, we report // an error and exit @@ -858,8 +858,9 @@ void cmCursesMainForm::HandleInput() this->HelpMessage[1] = ""; } - cmCursesLongMessageForm* msgs = - new cmCursesLongMessageForm(this->HelpMessage, "Help"); + cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( + this->HelpMessage, "Help", + cmCursesLongMessageForm::ScrollBehavior::NoScroll); CurrentForm = msgs; msgs->Render(1, 1, x, y); msgs->HandleInput(); @@ -871,7 +872,8 @@ void cmCursesMainForm::HandleInput() else if (key == 'l') { getmaxyx(stdscr, y, x); cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm( - this->Outputs, "CMake produced the following output"); + this->Outputs, "CMake produced the following output", + cmCursesLongMessageForm::ScrollBehavior::NoScroll); CurrentForm = msgs; msgs->Render(1, 1, x, y); msgs->HandleInput(); @@ -1048,12 +1050,12 @@ void cmCursesMainForm::DisplayOutputs() int yi; getmaxyx(stdscr, yi, xi); - auto newLogForm = - new cmCursesLongMessageForm(this->Outputs, this->LastProgress.c_str()); + auto newLogForm = new cmCursesLongMessageForm( + this->Outputs, this->LastProgress.c_str(), + cmCursesLongMessageForm::ScrollBehavior::ScrollDown); CurrentForm = newLogForm; this->LogForm.reset(newLogForm); this->LogForm->Render(1, 1, xi, yi); - this->LogForm->ScrollDown(); } const char* cmCursesMainForm::s_ConstHelpMessage = diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 4a6108d..b1c6e8f 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -330,9 +330,8 @@ bool cmake::SetCacheArgs(const std::vector& args) } } } else { - std::cerr << "Parse error in command line argument: " << arg << "\n" - << "Should be: VAR:type=value\n"; - cmSystemTools::Error("No cmake script provided."); + cmSystemTools::Error("Parse error in command line argument: " + arg + + "\n" + "Should be: VAR:type=value\n"); return false; } } else if (cmHasLiteralPrefix(arg, "-W")) { @@ -422,7 +421,7 @@ bool cmake::SetCacheArgs(const std::vector& args) return false; } } - std::cout << "loading initial cache file " << path << "\n"; + cmSystemTools::Stdout("loading initial cache file " + path + "\n"); // Resolve script path specified on command line relative to $PWD. path = cmSystemTools::CollapseFullPath(path); this->ReadListFile(args, path); -- cgit v0.12