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
|
// SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
// SPDX-License-Identifier: BSD-3-Clause
#include "pqPythonCompleter.h"
QString pqPythonCompleter::getVariableToComplete(const QString& prompt)
{
// Search backward through the string for usable characters
QString textToComplete{};
for (int i = prompt.length() - 1; i >= 0; --i)
{
QChar c = prompt.at(i);
if (c.isLetterOrNumber() || c == '.' || c == '_' || c == '[' || c == ']')
{
textToComplete.prepend(c);
}
else
{
break;
}
}
return textToComplete;
}
//-----------------------------------------------------------------------------
QStringList pqPythonCompleter::getCompletions(const QString& prompt)
{
QString textToComplete = this->getVariableToComplete(prompt);
// Variable to lookup is the name before the last dot if there is one.
QString lookup{};
int dot = textToComplete.lastIndexOf('.');
if (dot != -1)
{
lookup = textToComplete.mid(0, dot);
}
// Lookup python names
if (this->getCompleteEmptyPrompts() || !lookup.isEmpty() ||
!this->getCompletionPrefix(prompt).isEmpty())
{
return this->getPythonCompletions(lookup);
}
return QStringList{};
};
//-----------------------------------------------------------------------------
QString pqPythonCompleter::getCompletionPrefix(const QString& prompt)
{
// Search backward through the string for usable characters
QString compareText = this->getVariableToComplete(prompt);
int dot = compareText.lastIndexOf('.');
if (dot != -1)
{
compareText = compareText.mid(dot + 1);
}
return compareText;
};
//-----------------------------------------------------------------------------
void pqPythonCompleter::appendPyObjectAttributes(PyObject* object, QStringList& results)
{
if (!object)
{
return;
}
PyObject* keys = nullptr;
bool is_dict = PyDict_Check(object);
if (is_dict)
{
keys = PyDict_Keys(object); // returns *new* reference.
}
else
{
keys = PyObject_Dir(object); // returns *new* reference.
}
if (keys)
{
PyObject* key;
PyObject* value;
QString keystr;
int nKeys = PyList_Size(keys);
for (int i = 0; i < nKeys; ++i)
{
key = PyList_GetItem(keys, i);
if (is_dict)
{
value = PyDict_GetItem(object, key); // Return value: Borrowed reference.
Py_XINCREF(value); // so we can use Py_DECREF later.
}
else
{
value = PyObject_GetAttr(object, key); // Return value: New reference.
}
if (!value)
{
continue;
}
results << PyUnicode_AsUTF8(key);
Py_DECREF(value);
// Clear out any errors that may have occurred.
PyErr_Clear();
}
Py_DECREF(keys);
}
Py_DECREF(object);
}
//-----------------------------------------------------------------------------
PyObject* pqPythonCompleter::derivePyObject(const QString& pythonObjectName, PyObject* locals)
{
PyObject* derivedObject = locals;
QStringList tmpNames = pythonObjectName.split('.');
for (int i = 0; i < tmpNames.size() && derivedObject; ++i)
{
QByteArray tmpName = tmpNames.at(i).toUtf8();
PyObject* prevObj = derivedObject;
if (PyDict_Check(derivedObject))
{
derivedObject = PyDict_GetItemString(derivedObject, tmpName.data());
Py_XINCREF(derivedObject);
}
else
{
derivedObject = PyObject_GetAttrString(derivedObject, tmpName.data());
}
Py_DECREF(prevObj);
}
PyErr_Clear();
return derivedObject;
}
|