void NewBuildTab::DoToggleWindow() { bool success = m_errorCount == 0 && (m_skipWarnings || m_warnCount == 0); bool viewing = ManagerST::Get()->IsPaneVisible(wxT("Output View")) && (clMainFrame::Get()->GetOutputPane()->GetNotebook()->GetCurrentPage() == this); bool skipwarnings(false); if(!success) { if(viewing) { if(m_buildpaneScrollTo != ScrollToEnd) { // The user may have opted to go to the first error, the first item, or /dev/null skipwarnings = (m_errorCount > 0) && (m_buildpaneScrollTo == ScrollToFirstError); BuildLineInfo* bli = NULL; if(skipwarnings && !m_errorsList.empty()) { bli = m_errorsList.front(); } else if(!m_errorsAndWarningsList.empty()) { bli = m_errorsAndWarningsList.front(); } // Sanity if(bli) { CenterLineInView(bli->GetLineInBuildTab()); } } } } else if(m_autoHide && viewing && !m_buildInterrupted) { ManagerST::Get()->HidePane(clMainFrame::Get()->GetOutputPane()->GetCaption()); } else if(m_showMe == BuildTabSettingsData::ShowOnEnd && !m_autoHide) { ManagerST::Get()->ShowOutputPane(BUILD_WIN); } }
void NewBuildTab::MarkEditor(LEditor* editor) { if ( !editor ) return; editor->DelAllCompilerMarkers(); editor->AnnotationClearAll(); editor->AnnotationSetVisible(2); // Visible with box around it BuildTabSettingsData options; EditorConfigST::Get()->ReadObject(wxT("build_tab_settings"), &options); // Are markers or annotations enabled? if( options.GetErrorWarningStyle() == BuildTabSettingsData::EWS_NoMarkers ) { return; } std::pair<MultimapBuildInfo_t::iterator, MultimapBuildInfo_t::iterator> iter = m_buildInfoPerFile.equal_range(editor->GetFileName().GetFullPath()); if ( iter.first == iter.second ) { // could not find any, try the fullname iter = m_buildInfoPerFile.equal_range(editor->GetFileName().GetFullName()); #if defined(__WXGTK__) if ( iter.first == iter.second ) { // Nope. Perhaps it's a symlink iter = m_buildInfoPerFile.equal_range(CLRealPath(editor->GetFileName().GetFullPath())); } #endif } editor->InitializeAnnotations(); // Merge all the errors from the same line into a single error AnnotationInfoByLineMap_t annotations; for(; iter.first != iter.second; ++iter.first) { BuildLineInfo *bli = iter.first->second; wxString text = m_listctrl->GetTextValue(bli->GetLineInBuildTab(), 0).Trim().Trim(false); // strip any build markers StripBuildMarkders(text); // remove the line part from the text text = text.Mid(bli->GetRegexLineMatch()); // if the line starts with ':' remove it as well text.StartsWith(":", &text); text.Trim().Trim(false); if ( !text.IsEmpty() ) { if( bli && (bli->GetSeverity() == SV_ERROR || bli->GetSeverity() == SV_WARNING) ) { if( annotations.count(bli->GetLineNumber()) ) { // we already have an error on this line, concatenate the message AnnotationInfo &info = annotations[bli->GetLineNumber()]; info.text << "\n" << text; if ( bli->GetSeverity() == SV_ERROR ) { // override the severity to ERROR info.severity = SV_ERROR; } } else { // insert new one AnnotationInfo info; info.line = bli->GetLineNumber(); info.severity = bli->GetSeverity(); info.text = text; annotations.insert( std::make_pair(bli->GetLineNumber(), info) ); } } } } AnnotationInfoByLineMap_t::iterator annIter = annotations.begin(); for(; annIter != annotations.end(); ++annIter) { if ( annIter->second.severity == SV_ERROR ) { editor->SetErrorMarker(annIter->first, annIter->second.text); } else { editor->SetWarningMarker(annIter->first, annIter->second.text); } } // now place the errors editor->Refresh(); }
bool NewBuildTab::DoSelectAndOpen(int buildViewLine, bool centerLine) { if(!m_viewData.count(buildViewLine)) { return false; } BuildLineInfo* bli = m_viewData.find(buildViewLine)->second; if(bli) { wxFileName fn(bli->GetFilename()); // Highlight the clicked line on the view m_view->MarkerDeleteAll(LEX_GCC_MARKER); m_view->MarkerAdd(bli->GetLineInBuildTab(), LEX_GCC_MARKER); if(!fn.IsAbsolute()) { std::set<wxString> files; std::vector<wxFileName> candidates; ManagerST::Get()->GetWorkspaceFiles(files); std::for_each(files.begin(), files.end(), [&](const wxString& filepath) { wxFileName fnFilePath(filepath); if(fnFilePath.GetFullName() == fn.GetFullName()) { candidates.push_back(fnFilePath); } }); if(candidates.empty()) { return false; } if(candidates.size() == 1) { fn = candidates.at(0); } else { // prompt the user wxArrayString fileArr; for(size_t i = 0; i < candidates.size(); ++i) { fileArr.Add(candidates.at(i).GetFullPath()); } clSingleChoiceDialog dlg(EventNotifier::Get()->TopFrame(), fileArr); dlg.SetLabel(_("Select a file to open")); if(dlg.ShowModal() != wxID_OK) return false; wxString selection = dlg.GetSelection(); if(selection.IsEmpty()) return false; fn = wxFileName(selection); // if we resolved it now, open the file there is no point in searching this file // in m_buildInfoPerFile since the key on this map is kept as full name clEditor* editor = clMainFrame::Get()->GetMainBook()->FindEditor(fn.GetFullPath()); if(!editor) { editor = clMainFrame::Get()->GetMainBook()->OpenFile(fn.GetFullPath(), wxT(""), bli->GetLineNumber(), wxNOT_FOUND, OF_AddJump); } if(editor) { DoCentreErrorLine(bli, editor, centerLine); return true; } } } if(fn.IsAbsolute()) { // try to locate the editor first clEditor* editor = clMainFrame::Get()->GetMainBook()->FindEditor(fn.GetFullPath()); if(!editor) { // Open it editor = clMainFrame::Get()->GetMainBook()->OpenFile(bli->GetFilename(), wxT(""), bli->GetLineNumber(), wxNOT_FOUND, OF_AddJump); } if(editor) { if(!editor->HasCompilerMarkers()) MarkEditor(editor); int lineNumber = bli->GetLineNumber(); if(lineNumber > 0) { lineNumber--; } DoCentreErrorLine(bli, editor, centerLine); return true; } } } return false; }
void NewBuildTab::DoProcessOutput(bool compilationEnded, bool isSummaryLine) { wxUnusedVar(isSummaryLine); if(!compilationEnded && m_output.Find(wxT("\n")) == wxNOT_FOUND) { // still dont have a complete line return; } wxArrayString lines = ::wxStringTokenize(m_output, wxT("\n"), wxTOKEN_RET_DELIMS); m_output.Clear(); // Process only completed lines (i.e. a line that ends with '\n') for(size_t i = 0; i < lines.GetCount(); ++i) { if(!compilationEnded && !lines.Item(i).EndsWith(wxT("\n"))) { m_output << lines.Item(i); return; } wxString buildLine = lines.Item(i); //.Trim().Trim(false); // If this is a line similar to 'Entering directory `' // add the path in the directories array DoSearchForDirectory(buildLine); BuildLineInfo* buildLineInfo = DoProcessLine(buildLine); // keep the line info if(buildLineInfo->GetFilename().IsEmpty() == false) { m_buildInfoPerFile.insert(std::make_pair(buildLineInfo->GetFilename(), buildLineInfo)); } if(isSummaryLine) { buildLine.Trim(); buildLine.Prepend("===="); buildLine.Append("===="); buildLineInfo->SetSeverity(SV_NONE); } // Keep the line number in the build tab buildLineInfo->SetLineInBuildTab(m_view->GetLineCount() - 1); // -1 because the view always has 1 extra "\n" // Store the line info *before* we add the text // it is needed in the OnStyle function m_viewData.insert(std::make_pair(buildLineInfo->GetLineInBuildTab(), buildLineInfo)); m_view->SetEditable(true); buildLine.Trim(); wxString modText; ::clStripTerminalColouring(buildLine, modText); int curline = m_view->GetLineCount() - 1; m_view->AppendText(modText + "\n"); // get the newly added line width int endPosition = m_view->GetLineEndPosition(curline); // get character position from begin int beginPosition = m_view->PositionFromLine(curline); // and end of line wxPoint beginPos = m_view->PointFromPosition(beginPosition); wxPoint endPos = m_view->PointFromPosition(endPosition); int curLen = (endPos.x - beginPos.x) + 10; m_maxlineWidth = wxMax(m_maxlineWidth, curLen); if(m_maxlineWidth > 0) { m_view->SetScrollWidth(m_maxlineWidth); } m_view->SetEditable(false); if(clConfig::Get().Read(kConfigBuildAutoScroll, true)) { m_view->ScrollToEnd(); } } }
void NewBuildTab::OnBuildEnded(clCommandEvent& e) { e.Skip(); CL_DEBUG("Build Ended!"); m_buildInProgress = false; DoProcessOutput(true, false); std::vector<clEditor*> editors; clMainFrame::Get()->GetMainBook()->GetAllEditors(editors, MainBook::kGetAll_Default); for(size_t i = 0; i < editors.size(); i++) { MarkEditor(editors.at(i)); } // Add a summary line wxString problemcount = wxString::Format(wxT("%d %s, %d %s"), m_errorCount, _("errors"), m_warnCount, _("warnings")); wxString term = problemcount; long elapsed = m_sw.Time() / 1000; if(elapsed > 10) { long sec = elapsed % 60; long hours = elapsed / 3600; long minutes = (elapsed % 3600) / 60; term << wxString::Format(wxT(", %s: %02ld:%02ld:%02ld %s"), _("total time"), hours, minutes, sec, _("seconds")); } m_output = term; DoProcessOutput(true, true); if(m_buildInterrupted) { wxString InterruptedMsg; InterruptedMsg << _("(Build Cancelled)") << wxT("\n\n"); m_output = InterruptedMsg; DoProcessOutput(true, false); } // Hide / Show the build tab according to the settings DoToggleWindow(); // make it invalid m_curError = m_errorsAndWarningsList.begin(); CL_DEBUG("Posting wxEVT_BUILD_ENDED event"); // 0 = first error // 1 = first error or warning // 2 = to the end if(m_buildTabSettings.GetBuildPaneScrollDestination() == ScrollToFirstError && !m_errorsList.empty()) { BuildLineInfo* bli = m_errorsList.front(); DoSelectAndOpen(bli->GetLineInBuildTab(), true); } if(m_buildTabSettings.GetBuildPaneScrollDestination() == ScrollToFirstItem && !m_errorsAndWarningsList.empty()) { BuildLineInfo* bli = m_errorsAndWarningsList.front(); DoSelectAndOpen(bli->GetLineInBuildTab(), true); } if(m_buildTabSettings.GetBuildPaneScrollDestination() == ScrollToEnd) { m_view->ScrollToEnd(); } // notify the plugins that the build has ended clBuildEvent buildEvent(wxEVT_BUILD_ENDED); buildEvent.SetErrorCount(m_errorCount); buildEvent.SetWarningCount(m_warnCount); EventNotifier::Get()->AddPendingEvent(buildEvent); }