Пример #1
0
void CodeFormatter::OnFormatString(clSourceFormatEvent& e)
{
    wxString str = e.GetInputString();
    if(str.IsEmpty()) {
        e.SetFormattedString(str);
        return;
    }

    // execute the formatter
    FormatOptions fmtroptions;
    m_mgr->GetConfigTool()->ReadObject(wxT("FormatterOptions"), &fmtroptions);

    wxString output;
    if(FileExtManager::IsPHPFile(e.GetFileName())) {

        if(fmtroptions.GetPhpEngine() == kPhpFormatEngineBuiltin) {
            // use the built-in PHP formatter
            // Construct the formatting options
            PHPFormatterOptions phpOptions;
            phpOptions.flags = fmtroptions.GetPHPFormatterOptions();
            if(m_mgr->GetEditorSettings()->GetIndentUsesTabs()) {
                phpOptions.flags |= kPFF_UseTabs;
            }
            phpOptions.indentSize = m_mgr->GetEditorSettings()->GetTabWidth();
            phpOptions.eol = m_mgr->GetEditorSettings()->GetEOLAsString();
            // Create the formatter buffer
            PHPFormatterBuffer buffer(e.GetInputString(), phpOptions);

            // Format the source
            buffer.format();

            // set the output
            output = buffer.GetBuffer();
        } else {
            wxFileName php(fmtroptions.GetPhpExecutable());
            if(!php.Exists()) {
                ::wxMessageBox(_("Can not format file using PHP-CS-Fixer: Missing PHP executable path"),
                               "Code Formatter",
                               wxICON_ERROR | wxOK | wxCENTER);
                return;
            }
            wxFileName phar(fmtroptions.GetPHPCSFixerPhar());
            if(!phar.Exists()) {
                ::wxMessageBox(_("Can not format file using PHP-CS-Fixer: Missing PHAR file"),
                               "Code Formatter",
                               wxICON_ERROR | wxOK | wxCENTER);
                return;
            }

            // Run the command, PHP-CS-Fixer works directly on the file
            //
            output.Clear();
            IProcess::Ptr_t phpFixer(::CreateSyncProcess(fmtroptions.GetPhpFixerCommand(),
                                                         IProcessCreateDefault | IProcessCreateWithHiddenConsole));
            CHECK_PTR_RET(phpFixer);
            phpFixer->WaitForTerminate(output);
        }
    } else if(fmtroptions.GetEngine() == kFormatEngineAStyle) {
        wxString options = fmtroptions.AstyleOptionsAsString();

        // determine indentation method and amount
        bool useTabs = m_mgr->GetEditorSettings()->GetIndentUsesTabs();
        int tabWidth = m_mgr->GetEditorSettings()->GetTabWidth();
        int indentWidth = m_mgr->GetEditorSettings()->GetIndentWidth();
        options << (useTabs && tabWidth == indentWidth ? wxT(" -t") : wxT(" -s")) << indentWidth;

        AstyleFormat(str, options, output);
        output << DoGetGlobalEOLString();

    } else if(fmtroptions.GetEngine() == kFormatEngineClangFormat) {
        ClangPreviewFormat(str, output, fmtroptions);

    } else {
        // ??
    }
    e.SetFormattedString(output);
}
Пример #2
0
void CodeFormatter::DoFormatFile(IEditor* editor)
{
    int curpos = editor->GetCurrentPosition();

    // execute the formatter
    FormatOptions fmtroptions;
    m_mgr->GetConfigTool()->ReadObject(wxT("FormatterOptions"), &fmtroptions);
    if(FileExtManager::IsPHPFile(editor->GetFileName())) {

        if(fmtroptions.GetPhpEngine() == kPhpFormatEngineBuiltin) {

            // use the built-in PHP formatter

            // Construct the formatting options
            PHPFormatterOptions phpOptions;
            phpOptions.flags = fmtroptions.GetPHPFormatterOptions();
            if(m_mgr->GetEditorSettings()->GetIndentUsesTabs()) {
                phpOptions.flags |= kPFF_UseTabs;
            }
            phpOptions.indentSize = m_mgr->GetEditorSettings()->GetTabWidth();
            phpOptions.eol = m_mgr->GetEditorSettings()->GetEOLAsString();
            // Create the formatter buffer
            PHPFormatterBuffer buffer(editor->GetCtrl()->GetText(), phpOptions);

            // Format the source
            buffer.format();

            // Restore line
            if(!buffer.GetBuffer().IsEmpty()) {
                clSTCLineKeeper lk(editor);
                editor->GetCtrl()->BeginUndoAction();
                // Replace the text with the new formatted buffer
                editor->SetEditorText(buffer.GetBuffer());
                editor->GetCtrl()->EndUndoAction();
            }
        } else {
            wxFileName php(fmtroptions.GetPhpExecutable());
            if(!php.Exists()) {
                ::wxMessageBox(_("Can not format file using PHP-CS-Fixer: Missing PHP executable path"),
                               "Code Formatter",
                               wxICON_ERROR | wxOK | wxCENTER);
                return;
            }
            wxFileName phar(fmtroptions.GetPHPCSFixerPhar());
            if(!phar.Exists()) {
                ::wxMessageBox(_("Can not format file using PHP-CS-Fixer: Missing PHAR file"),
                               "Code Formatter",
                               wxICON_ERROR | wxOK | wxCENTER);
                return;
            }

            // Run the command, PHP-CS-Fixer works directly on the file
            // so create a copy of the file and format it, then replace the buffers
            // we do this like this so we won't lose our ability to undo the action
            wxString output;
            wxString command, filename, tmpfile;
            filename = editor->GetFileName().GetFullPath();
            tmpfile << filename << ".php-cs-fixer";
            if(!FileUtils::WriteFileContent(tmpfile, editor->GetEditorText())) {
                ::wxMessageBox(_("Can not format file using PHP-CS-Fixer:\nFailed to write temporary file"),
                               "Code Formatter",
                               wxICON_ERROR | wxOK | wxCENTER);
                return;
            }

            // Ensure that the temporary file is deleted once we are done with it
            FileUtils::Deleter fd(tmpfile);

            ::WrapWithQuotes(tmpfile);
            command << fmtroptions.GetPhpFixerCommand() << " " << tmpfile;
            ::WrapInShell(command);
            IProcess::Ptr_t phpFixer(
                ::CreateSyncProcess(command, IProcessCreateDefault | IProcessCreateWithHiddenConsole));
            CHECK_PTR_RET(phpFixer);
            phpFixer->WaitForTerminate(output);

            output.clear();
            if(!FileUtils::ReadFileContent(tmpfile, output)) {
                ::wxMessageBox(_("Can not format file using PHP-CS-Fixer:\nfailed to read temporary file content"),
                               "Code Formatter",
                               wxICON_ERROR | wxOK | wxCENTER);
                return;
            }

            // Update the editor
            clEditorStateLocker lk(editor->GetCtrl());
            editor->GetCtrl()->BeginUndoAction();
            editor->SetEditorText(output);
            editor->GetCtrl()->EndUndoAction();
        }

    } else {
        // We allow ClangFormat to work only when the source file is known to be
        // a C/C++ source file or JavaScript (these are the types of files that clang-format can handle properly)
        if(fmtroptions.GetEngine() == kFormatEngineClangFormat &&
           (FileExtManager::IsCxxFile(editor->GetFileName()) ||
            FileExtManager::IsJavascriptFile(editor->GetFileName()))) {

            int from = wxNOT_FOUND, length = wxNOT_FOUND;
            wxString formattedOutput;
            if(editor->GetSelectionStart() != wxNOT_FOUND) {
                // we got a selection, only format it
                from = editor->GetSelectionStart();
                length = editor->GetSelectionEnd() - from;
                if(length <= 0) {
                    from = wxNOT_FOUND;
                    length = wxNOT_FOUND;
                }
            }

            // Make sure we format the editor string and _not_ the file (there might be some newly added lines
            // that could be missing ...)
            if(!ClangFormatBuffer(
                   editor->GetCtrl()->GetText(), editor->GetFileName(), formattedOutput, curpos, from, length)) {
                ::wxMessageBox(_("Source code formatting error!"), "CodeLite", wxICON_ERROR | wxOK | wxCENTER);
                return;
            }

            clEditorStateLocker lk(editor->GetCtrl());
            editor->GetCtrl()->BeginUndoAction();
            editor->SetEditorText(formattedOutput);
            editor->SetCaretAt(curpos);
            editor->GetCtrl()->EndUndoAction();

        } else {
            // AStyle
            wxString options = fmtroptions.AstyleOptionsAsString();

            // determine indentation method and amount
            bool useTabs = m_mgr->GetEditorSettings()->GetIndentUsesTabs();
            int tabWidth = m_mgr->GetEditorSettings()->GetTabWidth();
            int indentWidth = m_mgr->GetEditorSettings()->GetIndentWidth();
            options << (useTabs && tabWidth == indentWidth ? wxT(" -t") : wxT(" -s")) << indentWidth;

            wxString output;
            wxString inputString;
            bool formatSelectionOnly(editor->GetSelection().IsEmpty() == false);

            if(formatSelectionOnly) {
                // get the lines contained in the selection
                int selStart = editor->GetSelectionStart();
                int selEnd = editor->GetSelectionEnd();
                int lineNumber = editor->LineFromPos(selStart);

                selStart = editor->PosFromLine(lineNumber);
                selEnd = editor->LineEnd(editor->LineFromPos(selEnd));

                editor->SelectText(selStart, selEnd - selStart);
                inputString = editor->GetSelection();

            } else {
                inputString = editor->GetEditorText();
            }

            AstyleFormat(inputString, options, output);
            if(!output.IsEmpty()) {

                // append new-line
                wxString eol;
                if(editor->GetEOL() == 0) { // CRLF
                    eol = wxT("\r\n");
                } else if(editor->GetEOL() == 1) { // CR
                    eol = wxT("\r");
                } else {
                    eol = wxT("\n");
                }

                if(!formatSelectionOnly) output << eol;

                if(formatSelectionOnly) {
                    clEditorStateLocker lk(editor->GetCtrl());
                    // format the text (add the indentation)
                    output = editor->FormatTextKeepIndent(output,
                                                          editor->GetSelectionStart(),
                                                          Format_Text_Indent_Prev_Line | Format_Text_Save_Empty_Lines);
                    editor->ReplaceSelection(output);

                } else {
                    clEditorStateLocker lk(editor->GetCtrl());
                    editor->SetEditorText(output);
                }
            }
        }
    }
    // Notify that a file was indented
    wxCommandEvent evt(wxEVT_CODEFORMATTER_INDENT_COMPLETED);
    evt.SetString(editor->GetFileName().GetFullPath());
    EventNotifier::Get()->AddPendingEvent(evt);
}