KTextEditor

katekeywordcompletion.cpp
1/*
2 SPDX-FileCopyrightText: 2014 Sven Brauch <svenbrauch@gmail.com>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "katekeywordcompletion.h"
8
9#include "katedocument.h"
10#include "katehighlight.h"
11#include "katetextline.h"
12
13#include <ktexteditor/view.h>
14
15#include <KLocalizedString>
16#include <QString>
17
18KateKeywordCompletionModel::KateKeywordCompletionModel(QObject *parent)
19 : CodeCompletionModel(parent)
20{
21 setHasGroups(false);
22}
23
25 const KTextEditor::Range &range,
26 KTextEditor::CodeCompletionModel::InvocationType /*invocationType*/)
27{
28 KTextEditor::DocumentPrivate *doc = static_cast<KTextEditor::DocumentPrivate *>(view->document());
29 if (!doc->highlight() || doc->highlight()->noHighlighting()) {
30 return;
31 }
32 m_items = doc->highlight()->keywordsForLocation(doc, range.end());
33 std::sort(m_items.begin(), m_items.end());
34}
35
37{
38 if (index.internalId()) {
39 return createIndex(0, 0);
40 } else {
41 return QModelIndex();
42 }
43}
44
45QModelIndex KateKeywordCompletionModel::index(int row, int column, const QModelIndex &parent) const
46{
47 if (!parent.isValid()) {
48 if (row == 0) {
49 return createIndex(row, column);
50 } else {
51 return QModelIndex();
52 }
53 } else if (parent.parent().isValid()) {
54 return QModelIndex();
55 }
56
57 if (row < 0 || row >= m_items.count() || column < 0 || column >= ColumnCount) {
58 return QModelIndex();
59 }
60
61 return createIndex(row, column, 1);
62}
63
65{
66 if (!parent.isValid() && !m_items.isEmpty()) {
67 return 1; // One root node to define the custom group
68 } else if (parent.parent().isValid()) {
69 return 0; // Completion-items have no children
70 } else {
71 return m_items.count();
72 }
73}
74
75static bool isInWord(const KTextEditor::View *view, const KTextEditor::Cursor &position, QChar c)
76{
77 KTextEditor::DocumentPrivate *document = static_cast<KTextEditor::DocumentPrivate *>(view->document());
78 KateHighlighting *highlight = document->highlight();
79 Kate::TextLine line = document->kateTextLine(position.line());
80 return highlight->isInWord(c, line.attribute(position.column() - 1));
81}
82
84{
85 const QString &text = view->document()->text(KTextEditor::Range(position, KTextEditor::Cursor(position.line(), 0)));
86 int pos;
87 for (pos = text.size() - 1; pos >= 0; pos--) {
88 if (isInWord(view, position, text.at(pos))) {
89 // This needs to be aware of what characters are word-characters in the
90 // active language, so that languages which prefix commands with e.g. @
91 // or \ have properly working completion.
92 continue;
93 }
94 break;
95 }
96 return KTextEditor::Range(KTextEditor::Cursor(position.line(), pos + 1), position);
97}
98
100{
101 if (view->cursorPosition() < range.start() || view->cursorPosition() > range.end()) {
102 return true; // Always abort when the completion-range has been left
103 }
104 // Do not abort completions when the text has been empty already before and a newline has been entered
105
106 for (QChar c : currentCompletion) {
107 if (!isInWord(view, range.start(), c)) {
108 return true;
109 }
110 }
111 return false;
112}
113
115 const QString &insertedText,
116 bool userInsertion,
117 const KTextEditor::Cursor & /*position*/)
118{
119 if (userInsertion && insertedText.size() > 3 && !insertedText.contains(QLatin1Char(' ')) && insertedText.at(insertedText.size() - 1).isLetter()) {
120 return true;
121 }
122 return false;
123}
124
126{
127 return true;
128}
129
130QVariant KateKeywordCompletionModel::data(const QModelIndex &index, int role) const
131{
132 if (role == UnimportantItemRole) {
133 return QVariant(true);
134 }
135 if (role == InheritanceDepth) {
136 return 9000;
137 }
138
139 if (!index.parent().isValid()) {
140 // group header
141 switch (role) {
142 case Qt::DisplayRole:
143 return i18n("Language keywords");
144 case GroupRole:
145 return Qt::DisplayRole;
146 }
147 }
148
149 if (index.column() == KTextEditor::CodeCompletionModel::Name && role == Qt::DisplayRole) {
150 return m_items.at(index.row());
151 }
152
154 static const QIcon icon(QIcon::fromTheme(QStringLiteral("code-variable")).pixmap(QSize(16, 16)));
155 return icon;
156 }
157
158 return QVariant();
159}
160
162{
163 return KTextEditor::CodeCompletionModelControllerInterface::HideListIfAutomaticInvocation;
164}
165
166#include "moc_katekeywordcompletion.cpp"
167
168// kate: indent-width 4; replace-tabs on
@ Icon
Icon representing the type of completion.
@ InheritanceDepth
Returns the inheritance depth of the completion.
@ GroupRole
Using this Role, it is possible to greatly optimize the time needed to process very long completion-l...
@ UnimportantItemRole
Return a nonzero value here to enforce sorting the item at the end of the list.
The Cursor represents a position in a Document.
Definition cursor.h:75
constexpr int column() const noexcept
Retrieve the column on which this cursor is situated.
Definition cursor.h:192
constexpr int line() const noexcept
Retrieve the line on which this cursor is situated.
Definition cursor.h:174
virtual QString text() const =0
Get the document content.
An object representing a section of text, from one Cursor to another.
constexpr Cursor end() const noexcept
Get the end position of this range.
constexpr Cursor start() const noexcept
Get the start position of this range.
A text widget with KXMLGUIClient that represents a Document.
Definition view.h:244
virtual Document * document() const =0
Get the view's document, that means the view is a view of the returned document.
virtual Cursor cursorPosition() const =0
Get the view's current cursor position.
void completionInvoked(KTextEditor::View *view, const KTextEditor::Range &range, InvocationType invocationType) override
This function is responsible to generating / updating the list of current completions.
bool shouldStartCompletion(KTextEditor::View *view, const QString &insertedText, bool userInsertion, const KTextEditor::Cursor &position) override
This function decides if the automatic completion should be started when the user entered some text.
bool shouldAbortCompletion(KTextEditor::View *view, const KTextEditor::Range &range, const QString &currentCompletion) override
This function decides if the completion should be aborted.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Reimplemented from QAbstractItemModel::index().
KTextEditor::Range completionRange(KTextEditor::View *view, const KTextEditor::Cursor &position) override
This function returns the completion range that will be used for the current completion.
MatchReaction matchingItem(const QModelIndex &matched) override
Called whenever an item in the completion-list perfectly matches the current filter text.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Reimplemented from QAbstractItemModel::rowCount().
bool shouldHideItemsWithEqualNames() const override
When multiple completion models are used at the same time, it may happen that multiple models add ite...
Class representing a single text line.
int attribute(int pos) const
Gets the attribute at the given position use KRenderer::attributes to get the KTextAttribute for this...
QString i18n(const char *text, const TYPE &arg...)
QModelIndex createIndex(int row, int column, void *ptr) const const
bool isLetter() const const
QIcon fromTheme(const QString &name)
const T & at(int i) const const
QList::iterator begin()
int count(const T &value) const const
QList::iterator end()
bool isEmpty() const const
int column() const const
quintptr internalId() const const
bool isValid() const const
QModelIndex parent() const const
int row() const const
QObject * parent() const const
const QChar at(int position) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
int size() const const
DisplayRole
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Feb 24 2024 20:00:58 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.