~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/plugins/contrib/SmartIndent/SmartIndentXML.cpp

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "SmartIndentXML.h"
 
2
 
 
3
#include <sdk.h> // Code::Blocks SDK
 
4
 
 
5
#ifndef CB_PRECOMP
 
6
    #include <cbeditor.h>
 
7
    #include <configmanager.h>
 
8
    #include <editormanager.h>
 
9
    #include <editorcolourset.h>
 
10
    #include <manager.h>
 
11
#endif
 
12
 
 
13
#include <wx/regex.h>
 
14
 
 
15
#include <cbstyledtextctrl.h>
 
16
 
 
17
// Register the plugin with Code::Blocks.
 
18
// We are using an anonymous namespace so we don't litter the global one.
 
19
namespace
 
20
{
 
21
    PluginRegistrant<SmartIndentXML> reg(wxT("SmartIndentXML"));
 
22
}
 
23
 
 
24
void SmartIndentXML::OnEditorHook(cbEditor* ed, wxScintillaEvent& event) const
 
25
{
 
26
    // check if smart indent is enabled
 
27
    // check the event type and the currently set language
 
28
    // if it is not a CharAdded event or the language is neither XML nor HTML return
 
29
 
 
30
    if (!ed)
 
31
        return;
 
32
 
 
33
    if ( !SmartIndentEnabled() )
 
34
        return;
 
35
 
 
36
    wxEventType type = event.GetEventType();
 
37
    if ( type != wxEVT_SCI_CHARADDED )
 
38
        return;
 
39
 
 
40
    cbStyledTextCtrl* stc = ed->GetControl();
 
41
    if (!stc)
 
42
        return;
 
43
 
 
44
    const int lexer = stc->GetLexer();
 
45
    if (lexer != wxSCI_LEX_XML && lexer != wxSCI_LEX_HTML)
 
46
        return;
 
47
 
 
48
    ed->AutoIndentDone(); // we are responsible
 
49
 
 
50
    int pos = stc->GetCurrentPos();
 
51
    int currLine = stc->LineFromPosition(pos);
 
52
 
 
53
    const wxChar ch = event.GetKey();
 
54
    wxRegEx reTag(wxT("***:<[ \t]*?(|/)[ \t]*?([a-zA-Z][a-zA-Z0-9_-]*).*?(|/)[ \t]*?>"));
 
55
 
 
56
    bool complQuote = true;
 
57
    if ( SelectionBraceCompletionEnabled() || stc->IsBraceShortcutActive() )
 
58
    {
 
59
        if (stc->DoSelectionBraceCompletion(ch))
 
60
        {
 
61
            complQuote = false;
 
62
            pos = stc->GetCurrentPos();
 
63
            currLine = stc->LineFromPosition(pos);
 
64
        }
 
65
    }
 
66
 
 
67
    if (BraceCompletionEnabled())
 
68
    {
 
69
        int curSty = stc->GetStyleAt(pos);
 
70
        // finish XML/HTML tag
 
71
        if ( ch == wxT('>') && !stc->IsString(curSty) )
 
72
        {
 
73
            wxString tag;
 
74
            for (int i = pos - 2; i > 0; --i)
 
75
            {
 
76
                if (stc->GetCharAt(i) == wxT('<') || stc->GetCharAt(i) == wxT('>'))
 
77
                {
 
78
                    tag = stc->GetTextRange(i, pos);
 
79
                    break;
 
80
                }
 
81
            }
 
82
            // is open tag
 
83
            if (reTag.Matches(tag) && reTag.GetMatch(tag, 1).IsEmpty() && reTag.GetMatch(tag, 3).IsEmpty())
 
84
                stc->InsertText(pos, wxT("</") + reTag.GetMatch(tag, 2) + wxT(">"));
 
85
        }
 
86
        // close string
 
87
        else if (complQuote && (ch == wxT('"') || ch == wxT('\'')))
 
88
        {
 
89
            if (stc->GetCharAt(pos) == ch)
 
90
            {
 
91
                stc->DeleteBack();
 
92
                stc->CharRight();
 
93
            }
 
94
            else if (!stc->IsString(stc->GetStyleAt(pos - 2)))
 
95
                stc->InsertText(pos, ch);
 
96
        }
 
97
        else if (ch == wxT('?') && stc->GetCharAt(pos - 2) == wxT('<'))
 
98
        {
 
99
            wxString tag;
 
100
            for (int i = pos; i < stc->GetLength(); ++i)
 
101
            {
 
102
                if (stc->GetCharAt(i) == wxT('<') || stc->GetCharAt(i) == wxT('>'))
 
103
                {
 
104
                    tag = stc->GetTextRange(i - 1, i + 1);
 
105
                    break;
 
106
                }
 
107
            }
 
108
            if (tag != wxT("?>"))
 
109
                stc->InsertText(pos, wxT(" ?>"));
 
110
        }
 
111
        // close CDATA
 
112
        else if (ch == wxT('[') && pos > 8 && stc->GetTextRange(pos - 9, pos - 1) == wxT("<![CDATA"))
 
113
        {
 
114
            wxString tag;
 
115
            for (int i = pos; i < stc->GetLength(); ++i)
 
116
            {
 
117
                if (stc->GetCharAt(i) == wxT('<') || stc->GetCharAt(i) == wxT('>'))
 
118
                {
 
119
                    tag = stc->GetTextRange(i - 2, i + 1);
 
120
                    break;
 
121
                }
 
122
            }
 
123
            if (tag != wxT("]]>"))
 
124
                stc->InsertText(pos, wxT("]]>"));
 
125
        }
 
126
        // embedded languages
 
127
        else if (complQuote && curSty >= wxSCI_HJ_START && curSty <= wxSCI_HPHP_OPERATOR && !stc->IsString(curSty))
 
128
        {
 
129
            stc->DoBraceCompletion(ch);
 
130
        }
 
131
    }
 
132
    // indent
 
133
    if (   AutoIndentEnabled()
 
134
        && ( (ch == wxT('\n')) || ((stc->GetEOLMode() == wxSCI_EOL_CR) && (ch == wxT('\r'))) ) )
 
135
    {
 
136
        wxString indent = ed->GetLineIndentString(currLine - 1);
 
137
        stc->BeginUndoAction();
 
138
        if (SmartIndentEnabled()) // smart indent
 
139
        {
 
140
            int idx = stc->GetLine(currLine - 1).Find(wxT('>'), true);
 
141
            if (idx != wxNOT_FOUND)
 
142
            {
 
143
                wxString tag;
 
144
                for (int i = stc->PositionFromLine(currLine - 1) + idx - 1; i > 0; --i)
 
145
                {
 
146
                    if (stc->GetCharAt(i) == wxT('<'))
 
147
                    {
 
148
                        tag = stc->GetTextRange(i, pos);
 
149
                        break;
 
150
                    }
 
151
                }
 
152
                // tag found
 
153
                if (reTag.Matches(tag))
 
154
                {
 
155
                    indent = ed->GetLineIndentString(stc->LineFromPosition(pos - tag.Length()));
 
156
                    // is open tag
 
157
                    if (reTag.GetMatch(tag, 1).IsEmpty() && reTag.GetMatch(tag, 3).IsEmpty())
 
158
                    {
 
159
                        wxString tagId = reTag.GetMatch(tag, 2);
 
160
                        // is close-tag after cursor?
 
161
                        tag = stc->GetLine(currLine);
 
162
                        if (reTag.Matches(tag) && !reTag.GetMatch(tag, 1).IsEmpty() && reTag.GetMatch(tag, 2) == tagId)
 
163
                        {
 
164
                            if (wxIsspace(stc->GetCharAt(pos)))
 
165
                                stc->DelWordRight();
 
166
                            stc->InsertText(pos, indent);
 
167
                            stc->NewLine();
 
168
                        }
 
169
                        Indent(stc, indent);
 
170
                    }
 
171
                }
 
172
            }
 
173
            else if (stc->GetStyleAt(pos) >= wxSCI_HJ_START && stc->GetStyleAt(pos) <= wxSCI_HPHP_OPERATOR)
 
174
            {
 
175
                // embedded language, indent braces
 
176
                const wxString lineSuffix = stc->GetLine(currLine).Strip(wxString::both);
 
177
                if (lineSuffix == wxT('}') || lineSuffix == wxT(']'))
 
178
                {
 
179
                    stc->InsertText(pos, GetEOLStr(stc->GetEOLMode()) + indent);
 
180
                    Indent(stc, indent);
 
181
                }
 
182
                else if (GetLastNonWhitespaceChar(ed) == wxT('{'))
 
183
                    Indent(stc, indent);
 
184
            }
 
185
            else
 
186
            {
 
187
                // align attributes
 
188
                for (int i = stc->PositionFromLine(currLine - 1); i < stc->GetLineEndPosition(currLine - 1); ++i)
 
189
                {
 
190
                    if (stc->GetStyleAt(i) == wxSCI_H_ATTRIBUTE || stc->GetStyleAt(i) == wxSCI_H_ATTRIBUTEUNKNOWN)
 
191
                    {
 
192
                        Indent(stc, indent, i - stc->PositionFromLine(currLine - 1));
 
193
                        if (stc->GetLineEndPosition(currLine) > pos + 2 && wxIsspace(stc->GetCharAt(pos)))
 
194
                            stc->DelWordRight();
 
195
                        break;
 
196
                    }
 
197
                }
 
198
            }
 
199
        }
 
200
        stc->InsertText(pos, indent);
 
201
        stc->GotoPos(pos + indent.Length());
 
202
        stc->ChooseCaretX();
 
203
        stc->EndUndoAction();
 
204
    }
 
205
}