@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.
@@ -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 };
@@ -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 };