bool CodeFormatter::ClangBatchFormat(const std::vector<wxFileName>& files, const FormatOptions& options) { if(options.GetClangFormatExe().IsEmpty()) { return false; } wxProgressDialog dlg( _("Source Code Formatter"), _("Formatting files..."), (int)files.size(), m_mgr->GetTheApp()->GetTopWindow()); clClangFormatLocator locator; double version = locator.GetVersion(options.GetClangFormatExe()); for(size_t i = 0; i < files.size(); ++i) { wxString command, file; command << options.GetClangFormatExe(); ::WrapWithQuotes(command); command << " -i "; // inline editing command << options.ClangFormatOptionsAsString(files.at(i), version); file = files.at(i).GetFullPath(); ::WrapWithQuotes(file); command << " " << file; // Wrap the command in the local shell ::WrapInShell(command); // Log the command CL_DEBUG("CodeForamtter: running:\n%s\n", command); wxString msg; msg << "[ " << i << " / " << files.size() << " ] " << files.at(i).GetFullName(); dlg.Update(i, msg); // Execute clang-format and read the output IProcess::Ptr_t clangFormatProc( ::CreateSyncProcess(command, IProcessCreateDefault | IProcessCreateWithHiddenConsole)); CHECK_PTR_RET_FALSE(clangFormatProc); wxString output; clangFormatProc->WaitForTerminate(output); CL_DEBUG("clang-format returned with:\n%s\n", output); } EventNotifier::Get()->PostReloadExternallyModifiedEvent(false); return true; }
CodeFormatter::CodeFormatter(IManager* manager) : IPlugin(manager) { m_longName = _("Source Code Formatter"); m_shortName = wxT("Source Code Formatter"); EventNotifier::Get()->Connect( wxEVT_FORMAT_STRING, clSourceFormatEventHandler(CodeFormatter::OnFormatString), NULL, this); EventNotifier::Get()->Connect( wxEVT_FORMAT_FILE, clSourceFormatEventHandler(CodeFormatter::OnFormatFile), NULL, this); m_mgr->GetTheApp()->Connect(ID_TOOL_SOURCE_CODE_FORMATTER, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CodeFormatter::OnFormatProject), NULL, this); EventNotifier::Get()->Bind(wxEVT_BEFORE_EDITOR_SAVE, clCommandEventHandler(CodeFormatter::OnBeforeFileSave), this); // Migrate settings if needed FormatOptions fmtroptions; m_mgr->GetConfigTool()->ReadObject("FormatterOptions", &fmtroptions); if(fmtroptions.GetEngine() == kFormatEngineClangFormat) { // check to see that the selected clang executable exists wxFileName clangFomatExe(fmtroptions.GetClangFormatExe()); if(fmtroptions.GetClangFormatExe().IsEmpty() || !clangFomatExe.Exists()) { // No valid clang executable found, try to locate one clClangFormatLocator locator; wxString clangFormatPath; if(locator.Locate(clangFormatPath)) { fmtroptions.SetClangFormatExe(clangFormatPath); } else { // Change the active engine to AStyle fmtroptions.SetEngine(kFormatEngineAStyle); fmtroptions.SetClangFormatExe(""); // Clear the non existed executable } } } // Save the options EditorConfigST::Get()->WriteObject("FormatterOptions", &fmtroptions); }
bool CodeFormatter::DoClangFormat(const wxFileName& filename, wxString& formattedOutput, int& cursorPosition, int startOffset, int length, const FormatOptions& options) { // clang-format // Build the command line to run if(options.GetClangFormatExe().IsEmpty()) { return false; } wxString command, file; clClangFormatLocator locator; double version = locator.GetVersion(options.GetClangFormatExe()); command << options.GetClangFormatExe(); file = filename.GetFullPath(); ::WrapWithQuotes(command); ::WrapWithQuotes(file); command << options.ClangFormatOptionsAsString(filename, version); if(cursorPosition != wxNOT_FOUND) { command << " -cursor=" << cursorPosition; } if(startOffset != wxNOT_FOUND && length != wxNOT_FOUND) { command << " -offset=" << startOffset << " -length=" << length; } command << " " << file; // Wrap the command in the local shell ::WrapInShell(command); // Log the command CL_DEBUG("CodeForamtter: running:\n%s\n", command); // Execute clang-format and reand the output formattedOutput.Clear(); IProcess::Ptr_t clangFormatProc( ::CreateSyncProcess(command, IProcessCreateDefault | IProcessCreateWithHiddenConsole)); CHECK_PTR_RET_FALSE(clangFormatProc); clangFormatProc->WaitForTerminate(formattedOutput); CL_DEBUG("clang-format returned with:\n%s\n", formattedOutput); if(formattedOutput.IsEmpty()) { // crash? return false; } // The first line contains the cursor position if(cursorPosition != wxNOT_FOUND) { wxString metadata = formattedOutput.BeforeFirst('\n'); JSONRoot root(metadata); cursorPosition = root.toElement().namedObject("cursor").toInt(wxNOT_FOUND); formattedOutput = formattedOutput.AfterFirst('\n'); } return true; }