File: neovimapi.cpp

package info (click to toggle)
neovim-qt 0.2.19-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,808 kB
  • sloc: cpp: 45,441; python: 234; makefile: 24; sh: 19; xml: 5
file content (167 lines) | stat: -rw-r--r-- 4,587 bytes parent folder | download
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Auto generated {{date}} from nvim API level:{{api_level}}
#include "auto/neovimapi{{api_level}}.h"
#include "neovimconnector.h"
#include "msgpackrequest.h"
#include "msgpackiodevice.h"
#include "util.h"

namespace NeovimQt {
/* Unpack Neovim EXT types Window, Buffer Tabpage which are all
 * uint64_t see Neovim:msgpack_rpc_to_
 */
QVariant unpackBufferApi{{api_level}}(MsgpackIODevice *dev, const char* in, quint32 size)
{
	msgpack_unpacked result;
	msgpack_unpacked_init(&result);
	msgpack_unpack_return ret = msgpack_unpack_next(&result, in, size, NULL);

	QVariant variant;

	if (ret == MSGPACK_UNPACK_SUCCESS) {
		switch (result.data.type) {
			case MSGPACK_OBJECT_NEGATIVE_INTEGER:
				variant = (qint64)result.data.via.i64;
				break;
			case MSGPACK_OBJECT_POSITIVE_INTEGER:
				variant = (quint64)result.data.via.u64;
				break;
			default:
				// TODO it would be nice if we could call back MsgpackIoDevice method or primitive types here
				qWarning() << "Unsupported type found for EXT type" << result.data.type << result.data;
		}
	}

	msgpack_unpacked_destroy(&result);
	return variant;
}
#define unpackWindowApi{{api_level}} unpackBufferApi{{api_level}}
#define unpackTabpageApi{{api_level}} unpackBufferApi{{api_level}}

NeovimApi{{api_level}}::NeovimApi{{api_level}}(NeovimConnector *c)
:m_c(c)
{
	// EXT types
	{% for typename in exttypes %}
	m_c->m_dev->registerExtType({{exttypes[typename]}}, unpack{{typename}}Api{{api_level}});
	{% endfor %}
	connect(m_c->m_dev, &MsgpackIODevice::notification,
			this, &NeovimApi{{api_level}}::neovimNotification);
}

// Slots
{% for f in functions %}
MsgpackRequest* NeovimApi{{api_level}}::{{f.name}}({{f.argstring}})
{
	MsgpackRequest *r = m_c->m_dev->startRequestUnchecked("{{f.name}}", {{f.argcount}});
	r->setFunction(NeovimApi{{api_level}}::NEOVIM_FN_{{f.name.upper()}});
	connect(r, &MsgpackRequest::finished, this, &NeovimApi{{api_level}}::handleResponse);
	connect(r, &MsgpackRequest::error, this, &NeovimApi{{api_level}}::handleResponseError);
{% for param in f.parameters %}
	m_c->m_dev->{{param.sendmethod}}({{param.name}});
{% endfor %}
	return r;
}
{% endfor %}

// Handlers

void NeovimApi{{api_level}}::handleResponseError(quint32 msgid, quint64 fun, const QVariant& res)
{

	// TODO: support Neovim error types Exception/Validation/etc
	QString errMsg;
	const QVariantList asList = res.toList();
	if (asList.size() >= 2) {
		if (asList.at(1).canConvert<QByteArray>()) {
			errMsg = m_c->m_dev->decode(asList.at(1).toByteArray());
		} else {
			errMsg = tr("Received unsupported Neovim error type");
		}
	}

	switch(fun) {
{% for f in functions %}
	case NeovimApi{{api_level}}::NEOVIM_FN_{{f.name.upper()}}:
		emit err_{{f.name}}(errMsg, res);
		break;
{% endfor %}
	default:
		m_c->setError(NeovimConnector::RuntimeMsgpackError, QStringLiteral("Received error for function that should not fail: %s").arg(fun));
	}
}

void NeovimApi{{api_level}}::handleResponse(quint32 msgid, quint64 fun, const QVariant& res)
{
	switch(fun) {
{% for f in functions %}
	case NeovimApi{{api_level}}::NEOVIM_FN_{{f.name.upper()}}:
		{
{% if f.return_type.native_type != 'void' %}
			{{f.return_type.native_type}} data;
			if (decode(res, data)) {
				m_c->setError(NeovimConnector::RuntimeMsgpackError, "Error unpacking return type for {{f.name}}");
				return;
			} else {
				emit on_{{f.name}}(data);
			}
{% else %}
			emit on_{{f.name}}();
{% endif %}

		}
		break;
{% endfor %}
	default:
		qWarning() << "Received unexpected response";
	}
}

/**
 * Check function table from api_metadata[1]
 *
 * This checks the API metadata build from the bindings against the metadata
 * passed as argument.
 *
 * Returns false if there is an API mismatch
 */
bool NeovimApi{{api_level}}::checkFunctions(const QVariantList& ftable)
{

	QList<Function> required;
	required
	{% for f in functions %}
	<< Function("{{f.return_type.neovim_type}}", "{{f.name}}",
			QList<QString>()
			{% for param in f.parameters %}
			<< QStringLiteral("{{param.neovim_type}}")
			{% endfor %}
			, false)
	{% endfor %}
	;


	QList<Function> supported;
	foreach(const QVariant& val, ftable) {
		auto f = Function::fromVariant(val);
		if (!f.isValid()) {
			qDebug() << "Invalid function in metadata" << f;
			continue;
		}
		supported.append(f);

		if (!required.contains(f)) {
			qDebug() << "Unknown function(api {{api_level}})" << f;
		}
	}

	bool ok = true;
	foreach(const Function& f, required) {
		if (!supported.contains(f)) {
			qDebug() << "- instance DOES NOT support API{{api_level}}:" << f;
			ok = false;
		}
	}
	return ok;
}

} // Namespace