@coldsmirk/inkstone-redis 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -0
- package/dist/commands-BMa2ec02.js +4610 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +85 -0
- package/dist/markers-BlM8eKCj.js +250 -0
- package/dist/markers-gZmuOyuR.d.ts +244 -0
- package/dist/monaco.d.ts +42 -0
- package/dist/monaco.js +184 -0
- package/dist/react.d.ts +95 -0
- package/dist/react.js +104 -0
- package/package.json +77 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { S as RedisCommand, _ as createRedisAssist, a as LineRefusal, b as REDIS_COMMANDS, c as SplitLine, d as runnableLine, f as splitLine, g as RedisSignatureHelp, h as RedisHoverCard, i as LineRead, l as lineBounds, m as RedisCompletionCandidate, n as RedisMarkerCode, o as LineWord, p as RedisAssist, r as lineMarkers, s as RunnableLine, t as RedisMarker, u as readLine, v as RedisVocabulary, x as REDIS_VERSION, y as createRedisVocabulary } from "./markers-gZmuOyuR.js";
|
|
2
|
+
export { type LineRead, type LineRefusal, type LineWord, REDIS_COMMANDS, REDIS_VERSION, type RedisAssist, type RedisCommand, type RedisCompletionCandidate, type RedisHoverCard, type RedisMarker, type RedisMarkerCode, type RedisSignatureHelp, type RedisVocabulary, type RunnableLine, type SplitLine, createRedisAssist, createRedisVocabulary, lineBounds, lineMarkers, readLine, runnableLine, splitLine };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { a as runnableLine, i as readLine, n as createRedisVocabulary, o as splitLine, r as lineBounds, t as lineMarkers } from "./markers-BlM8eKCj.js";
|
|
2
|
+
import { n as REDIS_VERSION, t as REDIS_COMMANDS } from "./commands-BMa2ec02.js";
|
|
3
|
+
//#region src/assist.ts
|
|
4
|
+
function argumentsOf(command) {
|
|
5
|
+
const rest = command.syntax.slice(command.name.length).trim();
|
|
6
|
+
return rest === "" ? void 0 : rest;
|
|
7
|
+
}
|
|
8
|
+
function documentationOf(command) {
|
|
9
|
+
const parts = [command.summary];
|
|
10
|
+
if (command.since !== "") parts.push(`Since ${command.since}${command.deprecated === void 0 ? "" : `, deprecated since ${command.deprecated}`}.`);
|
|
11
|
+
const text = parts.filter((part) => part !== "").join("\n\n");
|
|
12
|
+
return text === "" ? void 0 : text;
|
|
13
|
+
}
|
|
14
|
+
function createRedisAssist(vocabulary = createRedisVocabulary()) {
|
|
15
|
+
const top = vocabulary.commands.filter((command) => !command.name.includes(" "));
|
|
16
|
+
return {
|
|
17
|
+
complete: (text, offset) => {
|
|
18
|
+
const read = readLine(text, offset);
|
|
19
|
+
const names = read.words.map((word) => word.text);
|
|
20
|
+
if (read.index === 0) return top.map((command) => {
|
|
21
|
+
return {
|
|
22
|
+
label: command.name,
|
|
23
|
+
kind: "command",
|
|
24
|
+
insertText: command.name,
|
|
25
|
+
detail: argumentsOf(command),
|
|
26
|
+
documentation: documentationOf(command),
|
|
27
|
+
sortGroup: command.deprecated === void 0 ? 0 : 1
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
const container = names[0].toUpperCase();
|
|
31
|
+
const subs = vocabulary.subcommands.get(container);
|
|
32
|
+
if (read.index === 1 && subs !== void 0) return subs.map((sub) => {
|
|
33
|
+
const name = sub.name.slice(container.length + 1);
|
|
34
|
+
return {
|
|
35
|
+
label: name,
|
|
36
|
+
kind: "subcommand",
|
|
37
|
+
insertText: name,
|
|
38
|
+
detail: argumentsOf(sub),
|
|
39
|
+
documentation: documentationOf(sub),
|
|
40
|
+
sortGroup: sub.deprecated === void 0 ? 0 : 1
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
const resolved = vocabulary.resolve(names);
|
|
44
|
+
if (resolved === null || read.index < resolved.consumed) return [];
|
|
45
|
+
return resolved.command.tokens.map((token) => {
|
|
46
|
+
return {
|
|
47
|
+
label: token,
|
|
48
|
+
kind: "token",
|
|
49
|
+
insertText: token,
|
|
50
|
+
detail: resolved.command.name,
|
|
51
|
+
sortGroup: 2
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
hover: (text, offset) => {
|
|
56
|
+
const read = readLine(text, offset);
|
|
57
|
+
if (read.word === null) return null;
|
|
58
|
+
const resolved = vocabulary.resolve(read.words.map((word) => word.text));
|
|
59
|
+
if (resolved === null || read.index >= resolved.consumed) return null;
|
|
60
|
+
const { command } = resolved;
|
|
61
|
+
const markdown = [`\`${command.syntax}\``];
|
|
62
|
+
const documentation = documentationOf(command);
|
|
63
|
+
if (documentation !== void 0) markdown.push(documentation);
|
|
64
|
+
return {
|
|
65
|
+
from: read.lineStart + read.words[0].from,
|
|
66
|
+
to: read.lineStart + read.words[resolved.consumed - 1].to,
|
|
67
|
+
markdown
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
signature: (text, offset) => {
|
|
71
|
+
const read = readLine(text, offset);
|
|
72
|
+
const resolved = vocabulary.resolve(read.words.map((word) => word.text));
|
|
73
|
+
if (resolved === null || read.index < resolved.consumed || resolved.command.parameters.length === 0) return null;
|
|
74
|
+
const { command } = resolved;
|
|
75
|
+
return {
|
|
76
|
+
label: command.syntax,
|
|
77
|
+
parameters: command.parameters,
|
|
78
|
+
active: Math.min(read.index - resolved.consumed, command.parameters.length - 1),
|
|
79
|
+
documentation: command.summary === "" ? void 0 : command.summary
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
export { REDIS_COMMANDS, REDIS_VERSION, createRedisAssist, createRedisVocabulary, lineBounds, lineMarkers, readLine, runnableLine, splitLine };
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { t as REDIS_COMMANDS } from "./commands-BMa2ec02.js";
|
|
2
|
+
//#region src/line.ts
|
|
3
|
+
const ESCAPES = {
|
|
4
|
+
n: "\n",
|
|
5
|
+
r: "\r",
|
|
6
|
+
t: " ",
|
|
7
|
+
b: "\b",
|
|
8
|
+
a: String.fromCodePoint(7)
|
|
9
|
+
};
|
|
10
|
+
function blank(character) {
|
|
11
|
+
return /\s/u.test(character);
|
|
12
|
+
}
|
|
13
|
+
function hex(character) {
|
|
14
|
+
return /[0-9a-f]/iu.test(character);
|
|
15
|
+
}
|
|
16
|
+
function splitLine(line) {
|
|
17
|
+
const words = [];
|
|
18
|
+
const { length } = line;
|
|
19
|
+
let i = 0;
|
|
20
|
+
while (true) {
|
|
21
|
+
while (i < length && blank(line[i])) i++;
|
|
22
|
+
if (i >= length) break;
|
|
23
|
+
const from = i;
|
|
24
|
+
let text = "";
|
|
25
|
+
let inDouble = false;
|
|
26
|
+
let inSingle = false;
|
|
27
|
+
let done = false;
|
|
28
|
+
while (!done) {
|
|
29
|
+
const c = i < length ? line[i] : "";
|
|
30
|
+
if (inDouble) {
|
|
31
|
+
if (i >= length) return {
|
|
32
|
+
words,
|
|
33
|
+
refusal: {
|
|
34
|
+
code: "unbalanced-double-quote",
|
|
35
|
+
at: from
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
if (c === "\\" && i + 3 < length && line[i + 1] === "x" && hex(line[i + 2]) && hex(line[i + 3])) {
|
|
39
|
+
text += String.fromCodePoint(Number.parseInt(line.slice(i + 2, i + 4), 16));
|
|
40
|
+
i += 4;
|
|
41
|
+
} else if (c === "\\" && i + 1 < length) {
|
|
42
|
+
const escaped = line[i + 1];
|
|
43
|
+
text += ESCAPES[escaped] ?? escaped;
|
|
44
|
+
i += 2;
|
|
45
|
+
} else if (c === "\"") {
|
|
46
|
+
if (i + 1 < length && !blank(line[i + 1])) return {
|
|
47
|
+
words,
|
|
48
|
+
refusal: {
|
|
49
|
+
code: "quote-not-followed-by-blank",
|
|
50
|
+
at: i + 1
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
i++;
|
|
54
|
+
done = true;
|
|
55
|
+
} else {
|
|
56
|
+
text += c;
|
|
57
|
+
i++;
|
|
58
|
+
}
|
|
59
|
+
} else if (inSingle) {
|
|
60
|
+
if (i >= length) return {
|
|
61
|
+
words,
|
|
62
|
+
refusal: {
|
|
63
|
+
code: "unbalanced-single-quote",
|
|
64
|
+
at: from
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
if (c === "\\" && line[i + 1] === "'") {
|
|
68
|
+
text += "'";
|
|
69
|
+
i += 2;
|
|
70
|
+
} else if (c === "'") {
|
|
71
|
+
if (i + 1 < length && !blank(line[i + 1])) return {
|
|
72
|
+
words,
|
|
73
|
+
refusal: {
|
|
74
|
+
code: "quote-not-followed-by-blank",
|
|
75
|
+
at: i + 1
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
i++;
|
|
79
|
+
done = true;
|
|
80
|
+
} else {
|
|
81
|
+
text += c;
|
|
82
|
+
i++;
|
|
83
|
+
}
|
|
84
|
+
} else if (i >= length || blank(c)) done = true;
|
|
85
|
+
else if (c === "\"") {
|
|
86
|
+
inDouble = true;
|
|
87
|
+
i++;
|
|
88
|
+
} else if (c === "'") {
|
|
89
|
+
inSingle = true;
|
|
90
|
+
i++;
|
|
91
|
+
} else {
|
|
92
|
+
text += c;
|
|
93
|
+
i++;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
words.push({
|
|
97
|
+
text,
|
|
98
|
+
from,
|
|
99
|
+
to: i
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (words.length === 0) return {
|
|
103
|
+
words,
|
|
104
|
+
refusal: {
|
|
105
|
+
code: "empty",
|
|
106
|
+
at: 0
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
return {
|
|
110
|
+
words,
|
|
111
|
+
refusal: null
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function lineBounds(text, offset) {
|
|
115
|
+
const lineStart = text.lastIndexOf("\n", offset - 1) + 1;
|
|
116
|
+
const next = text.indexOf("\n", offset);
|
|
117
|
+
let lineEnd = next === -1 ? text.length : next;
|
|
118
|
+
if (lineEnd > lineStart && text[lineEnd - 1] === "\r") lineEnd--;
|
|
119
|
+
return {
|
|
120
|
+
lineStart,
|
|
121
|
+
lineEnd
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function readLine(text, offset) {
|
|
125
|
+
const { lineStart, lineEnd } = lineBounds(text, offset);
|
|
126
|
+
const line = text.slice(lineStart, lineEnd);
|
|
127
|
+
const split = splitLine(line);
|
|
128
|
+
const caret = Math.min(Math.max(offset - lineStart, 0), line.length);
|
|
129
|
+
const inside = split.words.findIndex((word) => word.from <= caret && caret <= word.to);
|
|
130
|
+
if (inside !== -1) return {
|
|
131
|
+
...split,
|
|
132
|
+
line,
|
|
133
|
+
lineStart,
|
|
134
|
+
lineEnd,
|
|
135
|
+
index: inside,
|
|
136
|
+
word: split.words[inside]
|
|
137
|
+
};
|
|
138
|
+
return {
|
|
139
|
+
...split,
|
|
140
|
+
line,
|
|
141
|
+
lineStart,
|
|
142
|
+
lineEnd,
|
|
143
|
+
index: split.words.filter((word) => word.to < caret).length,
|
|
144
|
+
word: null
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function runnableLine(text, from, to) {
|
|
148
|
+
if (from < to) {
|
|
149
|
+
const lines = text.slice(from, to).split(/\r?\n/u).filter((line) => line.trim() !== "");
|
|
150
|
+
if (lines.length === 0) return { kind: "none" };
|
|
151
|
+
if (lines.length > 1) return { kind: "several" };
|
|
152
|
+
return trimmed(text, from, to);
|
|
153
|
+
}
|
|
154
|
+
const { lineStart, lineEnd } = lineBounds(text, from);
|
|
155
|
+
return trimmed(text, lineStart, lineEnd);
|
|
156
|
+
}
|
|
157
|
+
function trimmed(text, from, to) {
|
|
158
|
+
const span = text.slice(from, to);
|
|
159
|
+
const start = from + (span.length - span.trimStart().length);
|
|
160
|
+
const end = to - (span.length - span.trimEnd().length);
|
|
161
|
+
return start >= end ? { kind: "none" } : {
|
|
162
|
+
kind: "one",
|
|
163
|
+
text: text.slice(start, end),
|
|
164
|
+
from: start,
|
|
165
|
+
to: end
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/vocabulary.ts
|
|
170
|
+
function createRedisVocabulary(commands = REDIS_COMMANDS) {
|
|
171
|
+
const byName = /* @__PURE__ */ new Map();
|
|
172
|
+
const subcommands = /* @__PURE__ */ new Map();
|
|
173
|
+
for (const command of commands) {
|
|
174
|
+
byName.set(command.name, command);
|
|
175
|
+
const space = command.name.indexOf(" ");
|
|
176
|
+
if (space !== -1) {
|
|
177
|
+
const container = command.name.slice(0, space);
|
|
178
|
+
const listed = subcommands.get(container) ?? [];
|
|
179
|
+
listed.push(command);
|
|
180
|
+
subcommands.set(container, listed);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
commands,
|
|
185
|
+
byName,
|
|
186
|
+
subcommands,
|
|
187
|
+
resolve: (words) => {
|
|
188
|
+
const first = words[0]?.toUpperCase();
|
|
189
|
+
if (first === void 0) return null;
|
|
190
|
+
const second = words[1]?.toUpperCase();
|
|
191
|
+
if (subcommands.has(first) && second !== void 0) {
|
|
192
|
+
const sub = byName.get(`${first} ${second}`);
|
|
193
|
+
if (sub !== void 0) return {
|
|
194
|
+
command: sub,
|
|
195
|
+
consumed: 2
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
const command = byName.get(first);
|
|
199
|
+
return command === void 0 ? null : {
|
|
200
|
+
command,
|
|
201
|
+
consumed: 1
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/markers.ts
|
|
208
|
+
const DEFAULT_VOCABULARY = createRedisVocabulary();
|
|
209
|
+
function lineMarkers(text, vocabulary = DEFAULT_VOCABULARY) {
|
|
210
|
+
const markers = [];
|
|
211
|
+
let lineStart = 0;
|
|
212
|
+
for (const raw of text.split("\n")) {
|
|
213
|
+
const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
|
|
214
|
+
const { words, refusal } = splitLine(line);
|
|
215
|
+
if (refusal === null) {
|
|
216
|
+
const names = words.map((word) => word.text);
|
|
217
|
+
const resolved = vocabulary.resolve(names);
|
|
218
|
+
if (resolved === null) markers.push({
|
|
219
|
+
from: lineStart + words[0].from,
|
|
220
|
+
to: lineStart + words[0].to,
|
|
221
|
+
code: "unknown-command",
|
|
222
|
+
severity: "hint"
|
|
223
|
+
});
|
|
224
|
+
else {
|
|
225
|
+
const { command, consumed } = resolved;
|
|
226
|
+
if (consumed === 1 && vocabulary.subcommands.has(command.name) && words.length > 1) markers.push({
|
|
227
|
+
from: lineStart + words[1].from,
|
|
228
|
+
to: lineStart + words[1].to,
|
|
229
|
+
code: "unknown-command",
|
|
230
|
+
severity: "hint"
|
|
231
|
+
});
|
|
232
|
+
else if (command.arity >= 0 ? words.length !== command.arity : words.length < -command.arity) markers.push({
|
|
233
|
+
from: lineStart + words[0].from,
|
|
234
|
+
to: lineStart + words.at(-1).to,
|
|
235
|
+
code: "wrong-arity",
|
|
236
|
+
severity: "warning"
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
} else if (refusal.code !== "empty") markers.push({
|
|
240
|
+
from: lineStart + refusal.at,
|
|
241
|
+
to: lineStart + line.length,
|
|
242
|
+
code: refusal.code,
|
|
243
|
+
severity: "error"
|
|
244
|
+
});
|
|
245
|
+
lineStart += raw.length + 1;
|
|
246
|
+
}
|
|
247
|
+
return markers;
|
|
248
|
+
}
|
|
249
|
+
//#endregion
|
|
250
|
+
export { runnableLine as a, readLine as i, createRedisVocabulary as n, splitLine as o, lineBounds as r, lineMarkers as t };
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
//#region src/commands.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* One command as the server describes it.
|
|
4
|
+
*/
|
|
5
|
+
interface RedisCommand {
|
|
6
|
+
/**
|
|
7
|
+
* `SET`; a container's subcommand as `CLIENT LIST`.
|
|
8
|
+
*/
|
|
9
|
+
name: string;
|
|
10
|
+
/**
|
|
11
|
+
* `COMMAND`'s arity: how many words the call takes, the name (and the subcommand) counted;
|
|
12
|
+
* negative for at least that many.
|
|
13
|
+
*/
|
|
14
|
+
arity: number;
|
|
15
|
+
group: string;
|
|
16
|
+
since: string;
|
|
17
|
+
summary: string;
|
|
18
|
+
/**
|
|
19
|
+
* The call as redis.io spells it: `SET key value [NX | XX] [GET] …`.
|
|
20
|
+
*/
|
|
21
|
+
syntax: string;
|
|
22
|
+
/**
|
|
23
|
+
* Each top-level argument's `[start, end)` within `syntax`, for signature help.
|
|
24
|
+
*/
|
|
25
|
+
parameters: Array<[number, number]>;
|
|
26
|
+
/**
|
|
27
|
+
* Every fixed word the arguments take (`NX`, `EX`, `WITHSCORES`), uppercased, sorted.
|
|
28
|
+
*/
|
|
29
|
+
tokens: string[];
|
|
30
|
+
/**
|
|
31
|
+
* The version that deprecated it, where one did.
|
|
32
|
+
*/
|
|
33
|
+
deprecated?: string;
|
|
34
|
+
}
|
|
35
|
+
declare const REDIS_VERSION = "7.2.16";
|
|
36
|
+
declare const REDIS_COMMANDS: readonly RedisCommand[];
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/vocabulary.d.ts
|
|
39
|
+
/**
|
|
40
|
+
* The command table indexed for the questions the editor asks of it: a name to its command, a
|
|
41
|
+
* container (`CLIENT`, `CONFIG`, `XINFO` …) to its subcommands, and a line's first words to the
|
|
42
|
+
* command they name — the subcommand where the first word is a container and the second is one
|
|
43
|
+
* of its own, the container itself otherwise.
|
|
44
|
+
*/
|
|
45
|
+
interface RedisVocabulary {
|
|
46
|
+
commands: readonly RedisCommand[];
|
|
47
|
+
/**
|
|
48
|
+
* Every command by its uppercased name, subcommands under `CONTAINER SUB`.
|
|
49
|
+
*/
|
|
50
|
+
byName: ReadonlyMap<string, RedisCommand>;
|
|
51
|
+
/**
|
|
52
|
+
* Each container's subcommands, by the container's name.
|
|
53
|
+
*/
|
|
54
|
+
subcommands: ReadonlyMap<string, readonly RedisCommand[]>;
|
|
55
|
+
/**
|
|
56
|
+
* The command a line's words name, and how many of them name it (two for a subcommand); null
|
|
57
|
+
* for a word the table does not know — a module's command, or a typo.
|
|
58
|
+
*/
|
|
59
|
+
resolve: (words: readonly string[]) => {
|
|
60
|
+
command: RedisCommand;
|
|
61
|
+
consumed: number;
|
|
62
|
+
} | null;
|
|
63
|
+
}
|
|
64
|
+
declare function createRedisVocabulary(commands?: readonly RedisCommand[]): RedisVocabulary;
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/assist.d.ts
|
|
67
|
+
/**
|
|
68
|
+
* One suggestion: a command's name at the line's start, a container's subcommand after it, or
|
|
69
|
+
* a fixed word of the command's own syntax (`NX`, `WITHSCORES`) anywhere after.
|
|
70
|
+
*/
|
|
71
|
+
interface RedisCompletionCandidate {
|
|
72
|
+
label: string;
|
|
73
|
+
kind: "command" | "subcommand" | "token";
|
|
74
|
+
insertText: string;
|
|
75
|
+
detail?: string;
|
|
76
|
+
documentation?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Rank band, lower first; within a band the table's own order stands.
|
|
79
|
+
*/
|
|
80
|
+
sortGroup: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* What hovering the command's name says about it. Offsets are into the text handed to
|
|
84
|
+
* `hover`, so the editor turns them into its own range without re-reading the line.
|
|
85
|
+
*/
|
|
86
|
+
interface RedisHoverCard {
|
|
87
|
+
from: number;
|
|
88
|
+
to: number;
|
|
89
|
+
/**
|
|
90
|
+
* Markdown blocks, rendered in order.
|
|
91
|
+
*/
|
|
92
|
+
markdown: string[];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The command's syntax while the caret is among its arguments.
|
|
96
|
+
*/
|
|
97
|
+
interface RedisSignatureHelp {
|
|
98
|
+
/**
|
|
99
|
+
* The syntax line whole: `SET key value [NX | XX] …`.
|
|
100
|
+
*/
|
|
101
|
+
label: string;
|
|
102
|
+
/**
|
|
103
|
+
* Each argument's `[start, end)` within `label`.
|
|
104
|
+
*/
|
|
105
|
+
parameters: Array<[number, number]>;
|
|
106
|
+
/**
|
|
107
|
+
* The argument the caret's word stands at, clamped onto the last: the syntax's tail is the
|
|
108
|
+
* optional and repeated part, and every word past the fixed ones is in it.
|
|
109
|
+
*/
|
|
110
|
+
active: number;
|
|
111
|
+
documentation?: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The editor's assist over one command table: everything the surface can ask that needs to
|
|
115
|
+
* know Redis. Synchronous, since the table is in memory and nothing is fetched.
|
|
116
|
+
*/
|
|
117
|
+
interface RedisAssist {
|
|
118
|
+
complete: (text: string, offset: number) => RedisCompletionCandidate[];
|
|
119
|
+
hover: (text: string, offset: number) => RedisHoverCard | null;
|
|
120
|
+
signature: (text: string, offset: number) => RedisSignatureHelp | null;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Completion, hover and signature help over the table, all reading the caret's line through
|
|
124
|
+
* `readLine` — redis-cli's own splitting — so they can never disagree about which word the
|
|
125
|
+
* caret is on.
|
|
126
|
+
*/
|
|
127
|
+
declare function createRedisAssist(vocabulary?: RedisVocabulary): RedisAssist;
|
|
128
|
+
//#endregion
|
|
129
|
+
//#region src/line.d.ts
|
|
130
|
+
/**
|
|
131
|
+
* A Redis command is one line, split into words the way redis-cli splits one — and the way the
|
|
132
|
+
* polyglot sidecar's `RedisLine` splits it before the words go on the wire: bare words on
|
|
133
|
+
* blanks, double quotes with `\xHH`, `\n`, `\r`, `\t`, `\b`, `\a` and `\<c>` escapes, single
|
|
134
|
+
* quotes with `\'` alone, and a closing quote that must be followed by a blank. The two are
|
|
135
|
+
* mirrors: a line this reader refuses is a line the engine refuses, for the same reason, so
|
|
136
|
+
* the editor can say so before the round trip does.
|
|
137
|
+
*/
|
|
138
|
+
/**
|
|
139
|
+
* Why a line could not be read whole — a code, never a sentence; the host owns the wording.
|
|
140
|
+
* `"empty"` is a line of blanks alone.
|
|
141
|
+
*/
|
|
142
|
+
type LineRefusal = "unbalanced-double-quote" | "unbalanced-single-quote" | "quote-not-followed-by-blank" | "empty";
|
|
143
|
+
/**
|
|
144
|
+
* One word of the line: its text with the quoting resolved, and its `[from, to)` in the line
|
|
145
|
+
* as written, quotes included.
|
|
146
|
+
*/
|
|
147
|
+
interface LineWord {
|
|
148
|
+
text: string;
|
|
149
|
+
from: number;
|
|
150
|
+
to: number;
|
|
151
|
+
}
|
|
152
|
+
interface SplitLine {
|
|
153
|
+
/**
|
|
154
|
+
* The words read, in order — every one of them where `refusal` is null, those before the
|
|
155
|
+
* fault where it is not.
|
|
156
|
+
*/
|
|
157
|
+
words: LineWord[];
|
|
158
|
+
/**
|
|
159
|
+
* Where reading stopped, or null where the line read whole: `at` is the offset in the line
|
|
160
|
+
* the fault is at (the opening quote of an unbalanced pair, the character after a closing
|
|
161
|
+
* quote that should have been a blank).
|
|
162
|
+
*/
|
|
163
|
+
refusal: {
|
|
164
|
+
code: LineRefusal;
|
|
165
|
+
at: number;
|
|
166
|
+
} | null;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* The words of one line, redis-cli's way.
|
|
170
|
+
*/
|
|
171
|
+
declare function splitLine(line: string): SplitLine;
|
|
172
|
+
/**
|
|
173
|
+
* The line the caret is on, read: its bounds in the whole text, its words, and where among
|
|
174
|
+
* them the caret stands.
|
|
175
|
+
*/
|
|
176
|
+
interface LineRead extends SplitLine {
|
|
177
|
+
line: string;
|
|
178
|
+
/**
|
|
179
|
+
* The line's `[lineStart, lineEnd)` in the text; a `\r` before the break is outside it.
|
|
180
|
+
*/
|
|
181
|
+
lineStart: number;
|
|
182
|
+
lineEnd: number;
|
|
183
|
+
/**
|
|
184
|
+
* The word the caret is in or at the end of, or the number of words before the caret where
|
|
185
|
+
* it stands on a blank — the position a word typed now would take.
|
|
186
|
+
*/
|
|
187
|
+
index: number;
|
|
188
|
+
/**
|
|
189
|
+
* The word the caret is in, or null on a blank.
|
|
190
|
+
*/
|
|
191
|
+
word: LineWord | null;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Bounds of the line holding `offset`: from the character after the previous break to the
|
|
195
|
+
* next break, a `\r` before it left out.
|
|
196
|
+
*/
|
|
197
|
+
declare function lineBounds(text: string, offset: number): {
|
|
198
|
+
lineStart: number;
|
|
199
|
+
lineEnd: number;
|
|
200
|
+
};
|
|
201
|
+
declare function readLine(text: string, offset: number): LineRead;
|
|
202
|
+
/**
|
|
203
|
+
* What one run should send: the selection where there is one, else the caret's line — one
|
|
204
|
+
* command, since the engine takes one; a selection over several lines is `several`, and a
|
|
205
|
+
* selection or a line of blanks is `none`.
|
|
206
|
+
*/
|
|
207
|
+
type RunnableLine = {
|
|
208
|
+
kind: "one";
|
|
209
|
+
text: string;
|
|
210
|
+
from: number;
|
|
211
|
+
to: number;
|
|
212
|
+
} | {
|
|
213
|
+
kind: "none";
|
|
214
|
+
} | {
|
|
215
|
+
kind: "several";
|
|
216
|
+
};
|
|
217
|
+
declare function runnableLine(text: string, from: number, to: number): RunnableLine;
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/markers.d.ts
|
|
220
|
+
/**
|
|
221
|
+
* What a line marker says — a code, never a sentence; the host owns the wording:
|
|
222
|
+
*
|
|
223
|
+
* - the three quoting faults `splitLine` refuses, which the engine refuses too (`error`);
|
|
224
|
+
* - `"unknown-command"` — a first word the table does not know, or a container's second word
|
|
225
|
+
* that is none of its subcommands (`hint`: a module's command is unknown here and runs fine);
|
|
226
|
+
* - `"wrong-arity"` — fewer words than the command takes, or, for a command of a fixed count,
|
|
227
|
+
* more (`warning`: the server answers `wrong number of arguments`).
|
|
228
|
+
*/
|
|
229
|
+
type RedisMarkerCode = Exclude<LineRefusal, "empty"> | "unknown-command" | "wrong-arity";
|
|
230
|
+
interface RedisMarker {
|
|
231
|
+
/**
|
|
232
|
+
* The span marked, as offsets into the text handed to `lineMarkers`.
|
|
233
|
+
*/
|
|
234
|
+
from: number;
|
|
235
|
+
to: number;
|
|
236
|
+
code: RedisMarkerCode;
|
|
237
|
+
severity: "error" | "warning" | "hint";
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* The markers of every line of the text, a line of blanks marked with nothing.
|
|
241
|
+
*/
|
|
242
|
+
declare function lineMarkers(text: string, vocabulary?: RedisVocabulary): RedisMarker[];
|
|
243
|
+
//#endregion
|
|
244
|
+
export { RedisCommand as S, createRedisAssist as _, LineRefusal as a, REDIS_COMMANDS as b, SplitLine as c, runnableLine as d, splitLine as f, RedisSignatureHelp as g, RedisHoverCard as h, LineRead as i, lineBounds as l, RedisCompletionCandidate as m, RedisMarkerCode as n, LineWord as o, RedisAssist as p, lineMarkers as r, RunnableLine as s, RedisMarker as t, readLine as u, RedisVocabulary as v, REDIS_VERSION as x, createRedisVocabulary as y };
|
package/dist/monaco.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { S as RedisCommand, p as RedisAssist, t as RedisMarker } from "./markers-gZmuOyuR.js";
|
|
2
|
+
import * as monacoEditor from "monaco-editor";
|
|
3
|
+
import { IDisposable, editor } from "monaco-editor";
|
|
4
|
+
//#region src/monaco.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* The monaco module itself, as `onMount` hands it over.
|
|
7
|
+
*/
|
|
8
|
+
type MonacoModule = typeof monacoEditor;
|
|
9
|
+
/**
|
|
10
|
+
* The language id the editor registers a command line under.
|
|
11
|
+
*/
|
|
12
|
+
declare const REDIS_LANGUAGE_ID = "redis";
|
|
13
|
+
/**
|
|
14
|
+
* Register the language — the id, its Monarch grammar and its bracket configuration — once per
|
|
15
|
+
* monaco module. Call it before the first model of the language is created (`beforeMount`);
|
|
16
|
+
* a model created under an id Monaco does not know yet is plain text until it is.
|
|
17
|
+
*/
|
|
18
|
+
declare function defineRedisLanguage(monaco: MonacoModule, languageId?: string, commands?: readonly RedisCommand[]): void;
|
|
19
|
+
interface RedisLanguageHooks {
|
|
20
|
+
/**
|
|
21
|
+
* The assist as it stands right now — read per request rather than captured, so the host
|
|
22
|
+
* can swap it without touching Monaco's registry; null answers nothing.
|
|
23
|
+
*/
|
|
24
|
+
assist: () => RedisAssist | null;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Register completion, hover and signature help for one model. The disposables are the
|
|
28
|
+
* caller's to hold: Monaco's registry outlives any editor, and a provider left behind would
|
|
29
|
+
* answer for a model that no longer exists.
|
|
30
|
+
*/
|
|
31
|
+
declare function registerRedisLanguage(monaco: MonacoModule, modelPath: string, hooks: RedisLanguageHooks, languageId?: string): IDisposable[];
|
|
32
|
+
/**
|
|
33
|
+
* The owner Monaco files this package's markers under.
|
|
34
|
+
*/
|
|
35
|
+
declare const REDIS_MARKER_OWNER = "inkstone-redis";
|
|
36
|
+
/**
|
|
37
|
+
* Put `markers` on the model as Monaco's own, replacing this package's last set; the words
|
|
38
|
+
* beside each code are the host's, handed in per code.
|
|
39
|
+
*/
|
|
40
|
+
declare function setRedisMarkers(monaco: MonacoModule, model: editor.ITextModel, markers: readonly RedisMarker[], wording: (marker: RedisMarker) => string): void;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { MonacoModule, REDIS_LANGUAGE_ID, REDIS_MARKER_OWNER, RedisLanguageHooks, defineRedisLanguage, registerRedisLanguage, setRedisMarkers };
|