File: CSSCodeCompletion.cpp

package info (click to toggle)
codelite 17.0.0%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 136,244 kB
  • sloc: cpp: 491,547; ansic: 280,393; php: 10,259; sh: 8,930; lisp: 7,664; vhdl: 6,518; python: 6,020; lex: 4,920; yacc: 3,123; perl: 2,385; javascript: 1,715; cs: 1,193; xml: 1,110; makefile: 804; cobol: 741; sql: 709; ruby: 620; f90: 566; ada: 534; asm: 464; fortran: 350; objc: 289; tcl: 258; java: 157; erlang: 61; pascal: 51; ml: 49; awk: 44; haskell: 36
file content (153 lines) | stat: -rw-r--r-- 5,157 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "CSSCodeCompletion.h"
#include "JSON.h"
#include "codelite_events.h"
#include "css.json"
#include "globals.h"
#include "ieditor.h"
#include "webtools.h"
#include "wxCodeCompletionBox.h"
#include "wxCodeCompletionBoxEntry.hpp"
#include "wxCodeCompletionBoxManager.h"
#include <algorithm>
#include <set>
#include <wx/stc/stc.h>
#include <wx/tokenzr.h>
#include <wx/xrc/xmlres.h>

CSSCodeCompletion::CSSCodeCompletion(WebTools* plugin)
    : ServiceProvider("WebTools: CSS", eServiceType::kCodeCompletion)
    , m_isEnabled(true)
    , m_plugin(plugin)
{
    JSON root(CSS_JSON);
    JSONItem arr = root.toElement();
    int count = arr.arraySize();
    std::set<wxString> valuesSet;
    for(int i = 0; i < count; ++i) {
        JSONItem entry = arr.arrayItem(i);
        if(!entry.hasNamedObject("name"))
            continue;

        Entry e;
        e.property = entry.namedObject("name").toString();
        e.values = entry.namedObject("values").toArrayString();
        m_entries.push_back(e);

        // collect the values and make them a unique set
        for(size_t i = 0; i < e.values.size(); ++i) {
            valuesSet.insert(e.values.Item(i));
        }
    }

    std::for_each(valuesSet.begin(), valuesSet.end(), [&](const wxString& v) {
        Entry e;
        e.property = v;
        m_entries.push_back(e);
    });

    Bind(wxEVT_CC_CODE_COMPLETE, &CSSCodeCompletion::OnCodeComplete, this);
}

CSSCodeCompletion::~CSSCodeCompletion() { Unbind(wxEVT_CC_CODE_COMPLETE, &CSSCodeCompletion::OnCodeComplete, this); }

void CSSCodeCompletion::CssCodeComplete(IEditor* editor)
{
    if(!m_isEnabled)
        return;

    // Perform HTML code completion
    wxStyledTextCtrl* ctrl = editor->GetCtrl();
    int currentLine = ctrl->GetCurrentLine();
    int minPos = ctrl->PositionFromLine(currentLine);

    wxChar nonWhitespaceChar = 0;
    int nonWhitespaceCharPos = wxNOT_FOUND;
    int curpos = ctrl->GetCurrentPos();

    while((curpos > minPos)) {
        nonWhitespaceChar = ctrl->GetCharAt(curpos);
        switch(nonWhitespaceChar) {
        case '\n':
        case '\r':
        case '\t':
        case ' ':
            break;
        default:
            nonWhitespaceCharPos = curpos;
            break;
        }
        if(nonWhitespaceCharPos != wxNOT_FOUND)
            break;
        curpos = ctrl->PositionBefore(curpos);
    }

    if(nonWhitespaceCharPos != wxNOT_FOUND && nonWhitespaceChar == ':') {
        // Suggest values of the given properties
        wxString word = GetPreviousWord(editor, nonWhitespaceCharPos);
        if(word.IsEmpty())
            return;
        Entry::Vec_t::const_iterator iter =
            std::find_if(m_entries.begin(), m_entries.end(), [&](const Entry& e) { return (e.property == word); });
        if(iter != m_entries.end()) {
            wxCodeCompletionBox::BmpVec_t bitmaps;
            bitmaps.push_back(wxXmlResource::Get()->LoadBitmap("code-tags"));

            wxCodeCompletionBoxEntry::Vec_t entries;
            const wxArrayString& values = (*iter).values;

            for(size_t i = 0; i < values.size(); ++i) {
                wxCodeCompletionBoxEntry::Ptr_t entry = wxCodeCompletionBoxEntry::New(values.Item(i), 0);
                entries.push_back(entry);
            }
            wxCodeCompletionBoxManager::Get().ShowCompletionBox(editor->GetCtrl(), entries, bitmaps, 0,
                                                                editor->GetCurrentPosition(), this);
        }
    } else {
        wxCodeCompletionBox::BmpVec_t bitmaps;
        bitmaps.push_back(wxXmlResource::Get()->LoadBitmap("code-tags"));

        wxCodeCompletionBoxEntry::Vec_t entries;
        for(size_t i = 0; i < m_entries.size(); ++i) {
            wxCodeCompletionBoxEntry::Ptr_t entry = wxCodeCompletionBoxEntry::New(m_entries.at(i).property, 0);
            // entry->SetComment(m_entries.at(i).m_comment);
            entries.push_back(entry);
        }
        wxCodeCompletionBoxManager::Get().ShowCompletionBox(
            editor->GetCtrl(), entries, bitmaps, 0, editor->WordStartPos(editor->GetCurrentPosition(), false), this);
    }
}

wxString CSSCodeCompletion::GetPreviousWord(IEditor* editor, int pos)
{
    int lineStartPos = editor->GetCtrl()->PositionFromLine(editor->GetCtrl()->LineFromPosition(pos));

    // get the line from the start up until the ":"
    wxString line = editor->GetCtrl()->GetTextRange(lineStartPos, pos);
    if(line.IsEmpty())
        return "";

    wxArrayString words = ::wxStringTokenize(line, "\r\n \t", wxTOKEN_STRTOK);
    if(words.IsEmpty())
        return "";
    return words.Last();
}

void CSSCodeCompletion::OnCodeComplete(clCodeCompletionEvent& event)
{
    event.Skip();
    IEditor* editor = GetEditor(event.GetFileName());
    if(editor && m_plugin->IsCSSFile(editor)) {
        // CSS code completion
        event.Skip(false);
        CssCodeComplete(editor);
    }
}

IEditor* CSSCodeCompletion::GetEditor(const wxString& filename) const
{
    auto editor = clGetManager()->FindEditor(filename);
    if(editor && editor == clGetManager()->GetActiveEditor()) {
        return editor;
    }
    return nullptr;
}