Beispiel #1
0
void XMLCodeCompletion::OnCodeCompleted(clCodeCompletionEvent& event)
{
    event.Skip();
    if(event.GetEventObject() != this) {
        return;
    }

    // sanity
    IEditor* editor = clGetManager()->GetActiveEditor();
    if(!editor) return;

    // HTML triggered the code complete?
    if(m_completeReason == kHtmlOpenSequence) {
        event.Skip(false);
        const wxString& selection = event.GetWord();
        if(XMLBuffer::IsEmptyHtmlTag(selection) && !HasSpecialInsertPattern(selection)) {

            // an empty html tag, just complete it
            wxString textToInsert = selection;
            textToInsert << ">";

            int selStart = GetWordStartPos(editor);
            int selEnd = editor->GetCurrentPosition();
            if((selEnd - selStart) >= 0) {
                editor->SelectText(selStart, selEnd - selStart);
                editor->ReplaceSelection(textToInsert);
                editor->SetCaretAt(selStart + textToInsert.length());
            }
        } else {
            wxString completePattern = GetCompletePattern(selection);
            int caretPos = completePattern.Find("|");
            completePattern.Replace("|", "");
            int selStart = GetWordStartPos(editor);

            int selEnd = editor->GetCurrentPosition();
            if((selEnd - selStart) >= 0) {
                editor->SelectText(selStart, selEnd - selStart);
                editor->ReplaceSelection(completePattern);
                editor->SetCaretAt(selStart + caretPos);
            }
        }
    } else if(m_completeReason == kCloseSequence) {
        // User typed "</"
        event.Skip(false);
        const wxString& selection = event.GetWord();
        int selStart = GetWordStartPos(editor);
        int selEnd = editor->GetCurrentPosition();
        if((selEnd - selStart) >= 0) {
            editor->SelectText(selStart, selEnd - selStart);
            editor->ReplaceSelection(selection);
            editor->SetCaretAt(selStart + selection.length());
        }
    } else {
        event.Skip();
    }
}
Beispiel #2
0
void XMLCodeCompletion::HtmlCodeComplete(IEditor* editor)
{
    if(!m_htmlCcEnabeld) return;

    // Perform HTML code completion
    wxStyledTextCtrl* ctrl = editor->GetCtrl();

    wxChar ch = ctrl->GetCharAt(ctrl->PositionBefore(ctrl->GetCurrentPos()));
    if(ch == '/') {
        SuggestClosingTag(editor, true);

    } else {
        wxCodeCompletionBox::BmpVec_t bitmaps;
        bitmaps.push_back(wxXmlResource::Get()->LoadBitmap("code-tags"));

        wxCodeCompletionBoxEntry::Vec_t entries;
        for(size_t i = 0; i < m_htmlCompletions.size(); ++i) {
            wxCodeCompletionBoxEntry::Ptr_t entry = wxCodeCompletionBoxEntry::New(m_htmlCompletions.at(i).m_tag, 0);
            entry->SetComment(m_htmlCompletions.at(i).m_comment);
            entries.push_back(entry);
        }
        m_completeReason = kHtmlOpenSequence;
        wxCodeCompletionBoxManager::Get().ShowCompletionBox(editor->GetCtrl(), entries, bitmaps, 0,
                                                            GetWordStartPos(editor), this);
    }
}
Beispiel #3
0
void XMLCodeCompletion::SuggestClosingTag(IEditor* editor, bool html)
{
    // CC was triggered by "</"
    // Read backward until we find the matching open tag
    wxStyledTextCtrl* ctrl = editor->GetCtrl();
    XMLBuffer buffer(ctrl->GetTextRange(0, ctrl->GetCurrentPos()), html);
    buffer.Parse();
    if(buffer.InCData() || buffer.InComment()) {
        // dont offer code completion when inside CDATA or COMMENT blocks
        return;
    }

    XMLBuffer::Scope currentScope = buffer.GetCurrentScope();
    if(!currentScope.IsOk()) return;

    wxCodeCompletionBox::BmpVec_t bitmaps;
    bitmaps.push_back(wxXmlResource::Get()->LoadBitmap("code-tags"));

    wxCodeCompletionBoxEntry::Vec_t entries;
    wxCodeCompletionBoxEntry::Ptr_t entry = wxCodeCompletionBoxEntry::New("</" + currentScope.tag + ">", 0);
    entries.push_back(entry);

    m_completeReason = kCloseSequence;
    wxCodeCompletionBoxManager::Get().ShowCompletionBox(
        editor->GetCtrl(), entries, bitmaps, 0, GetWordStartPos(editor), this);
}
void wxCodeCompletionBoxManager::InsertSelection(wxCodeCompletionBoxEntry::Ptr_t match)
{
    IManager* manager = ::clGetManager();
    IEditor* editor = manager->GetActiveEditor();
    wxString entryText = match->GetInsertText();
    if(editor) {
        wxStyledTextCtrl* ctrl = editor->GetCtrl();
        bool addParens(false);
        bool moveCaretRight = false;
        bool moveCaretLeft = false;
        int start = wxNOT_FOUND, end = wxNOT_FOUND;
        std::vector<std::pair<int, int> > ranges;
        if(ctrl->GetSelections() > 1) {
            for(int i = 0; i < ctrl->GetSelections(); ++i) {
                int nStart = GetWordStartPos(ctrl, ctrl->GetSelectionNCaret(i), entryText.Contains(":"));
                int nEnd = ctrl->GetSelectionNCaret(i);
                ranges.push_back(std::make_pair(nStart, nEnd));
            }
            std::sort(ranges.begin(), ranges.end(), [&](const std::pair<int, int>& e1, const std::pair<int, int>& e2) {
                return e1.first < e2.first;
            });
        } else {
            // Default behviour: remove the partial text from the editor and replace it
            // with the selection
            start = GetWordStartPos(ctrl, ctrl->GetCurrentPos(), entryText.Contains(":"));
            end = ctrl->GetCurrentPos();
            ctrl->SetSelection(start, end);
            wxChar endChar = ctrl->GetCharAt(end);
            if((ctrl->GetCharAt(end) != '(')) {
                addParens = true;
                moveCaretLeft = true;
            } else if(endChar == '(') {
                moveCaretRight = true;
            }
        }

        if(match->IsFunction()) {
            // a function like
            wxString textToInsert = entryText.BeforeFirst('(');

            // Build the function signature
            wxString funcSig = match->GetSignature();
            bool userProvidedSignature = (match->GetText().Find("(") != wxNOT_FOUND);
            clDEBUG() << "Inserting selection:" << textToInsert;
            clDEBUG() << "Signature is:" << funcSig;

            // Check if already have an open paren, don't add another
            if(addParens) { textToInsert << "()"; }

            if(!ranges.empty()) {
                // Multiple carets
                int offset = 0;
                for(size_t i = 0; i < ranges.size(); ++i) {
                    int from = ranges.at(i).first;
                    int to = ranges.at(i).second;
                    from += offset;
                    to += offset;
                    // Once we enter that text into the editor, it will change the original
                    // offsets (in most cases the entered text is larger than that typed text)
                    offset += textToInsert.length() - (to - from);
                    ctrl->Replace(from, to, textToInsert);
                    ctrl->SetSelectionNStart(i, from + textToInsert.length());
                    ctrl->SetSelectionNEnd(i, from + textToInsert.length());
                }
            } else {
                ctrl->ReplaceSelection(textToInsert);
                if(!userProvidedSignature || (!funcSig.IsEmpty() && (funcSig != "()"))) {

                    // Place the caret between the parenthesis
                    int caretPos(wxNOT_FOUND);
                    if(moveCaretLeft) {
                        caretPos = start + textToInsert.length() - 1;
                    } else if(moveCaretRight) {
                        // Move the caret one char to the right
                        caretPos = start + textToInsert.length() + 1;
                    } else {
                        caretPos = start + textToInsert.length();
                    }

                    ctrl->SetCurrentPos(caretPos);
                    ctrl->SetSelection(caretPos, caretPos);

                    // trigger a code complete for function calltip.
                    // We do this by simply mimicing the user action of going to the menubar:
                    // Edit->Display Function Calltip
                    wxCommandEvent event(wxEVT_MENU, XRCID("function_call_tip"));
                    wxTheApp->GetTopWindow()->GetEventHandler()->AddPendingEvent(event);
                }
            }
        } else {
            if(!ranges.empty()) {
                // Multiple carets
                int offset = 0;
                for(size_t i = 0; i < ranges.size(); ++i) {
                    int from = ranges.at(i).first;
                    int to = ranges.at(i).second;
                    from += offset;
                    to += offset;
                    // Once we enter that text into the editor, it will change the original
                    // offsets (in most cases the entered text is larger than that typed text)
                    offset += entryText.length() - (to - from);
                    ctrl->Replace(from, to, entryText);
                    ctrl->SetSelectionNStart(i, from + entryText.length());
                    ctrl->SetSelectionNEnd(i, from + entryText.length());
                }
            } else {
                // Default
                ctrl->ReplaceSelection(entryText);
            }
        }
    }
}