@coldsmirk/inkstone-redis 0.22.0 → 0.24.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/dist/index.d.ts CHANGED
@@ -1,2 +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 };
1
+ import { C as REDIS_COMMANDS, S as createRedisVocabulary, T as RedisCommand, _ as RedisCompletionCandidate, a as LineRefusal, b as createRedisAssist, c as SplitLine, d as runnableLine, f as spellWord, g as RedisCatalog, h as RedisAssist, i as LineRead, l as lineBounds, m as CatalogKey, n as RedisMarkerCode, o as LineWord, p as splitLine, r as lineMarkers, s as RunnableLine, t as RedisMarker, u as readLine, v as RedisHoverCard, w as REDIS_VERSION, x as RedisVocabulary, y as RedisSignatureHelp } from "./markers-Bmqe2Tjf.js";
2
+ export { type CatalogKey, type LineRead, type LineRefusal, type LineWord, REDIS_COMMANDS, REDIS_VERSION, type RedisAssist, type RedisCatalog, type RedisCommand, type RedisCompletionCandidate, type RedisHoverCard, type RedisMarker, type RedisMarkerCode, type RedisSignatureHelp, type RedisVocabulary, type RunnableLine, type SplitLine, createRedisAssist, createRedisVocabulary, lineBounds, lineMarkers, readLine, runnableLine, spellWord, splitLine };
package/dist/index.js CHANGED
@@ -1,6 +1,12 @@
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";
1
+ import { a as runnableLine, i as readLine, n as createRedisVocabulary, o as spellWord, r as lineBounds, s as splitLine, t as lineMarkers } from "./markers-DFpfcLLE.js";
2
+ import { n as REDIS_VERSION, t as REDIS_COMMANDS } from "./commands-B2cgDRf7.js";
3
3
  //#region src/assist.ts
4
+ const NO_CATALOG = { keys: () => [] };
5
+ function keyAt(command, index) {
6
+ if (command.keys === void 0) return false;
7
+ const [first, last, step] = command.keys;
8
+ return index >= first && (index - first) % step === 0 && (last < 0 || index <= last);
9
+ }
4
10
  function argumentsOf(command) {
5
11
  const rest = command.syntax.slice(command.name.length).trim();
6
12
  return rest === "" ? void 0 : rest;
@@ -11,7 +17,7 @@ function documentationOf(command) {
11
17
  const text = parts.filter((part) => part !== "").join("\n\n");
12
18
  return text === "" ? void 0 : text;
13
19
  }
14
- function createRedisAssist(vocabulary = createRedisVocabulary()) {
20
+ function createRedisAssist(catalog = NO_CATALOG, vocabulary = createRedisVocabulary()) {
15
21
  const top = vocabulary.commands.filter((command) => !command.name.includes(" "));
16
22
  return {
17
23
  complete: (text, offset) => {
@@ -42,15 +48,26 @@ function createRedisAssist(vocabulary = createRedisVocabulary()) {
42
48
  });
43
49
  const resolved = vocabulary.resolve(names);
44
50
  if (resolved === null || read.index < resolved.consumed) return [];
45
- return resolved.command.tokens.map((token) => {
51
+ const { command } = resolved;
52
+ const tokens = command.tokens.map((token) => {
46
53
  return {
47
54
  label: token,
48
55
  kind: "token",
49
56
  insertText: token,
50
- detail: resolved.command.name,
51
- sortGroup: 2
57
+ detail: command.name,
58
+ sortGroup: 3
52
59
  };
53
60
  });
61
+ if (!keyAt(command, read.index)) return tokens;
62
+ return [...catalog.keys().map((key) => {
63
+ return {
64
+ label: key.name,
65
+ kind: "key",
66
+ insertText: spellWord(key.name),
67
+ ...key.type !== "" && { detail: key.type },
68
+ sortGroup: 2
69
+ };
70
+ }), ...tokens];
54
71
  },
55
72
  hover: (text, offset) => {
56
73
  const read = readLine(text, offset);
@@ -82,4 +99,4 @@ function createRedisAssist(vocabulary = createRedisVocabulary()) {
82
99
  };
83
100
  }
84
101
  //#endregion
85
- export { REDIS_COMMANDS, REDIS_VERSION, createRedisAssist, createRedisVocabulary, lineBounds, lineMarkers, readLine, runnableLine, splitLine };
102
+ export { REDIS_COMMANDS, REDIS_VERSION, createRedisAssist, createRedisVocabulary, lineBounds, lineMarkers, readLine, runnableLine, spellWord, splitLine };
@@ -27,6 +27,14 @@ interface RedisCommand {
27
27
  * Every fixed word the arguments take (`NX`, `EX`, `WITHSCORES`), uppercased, sorted.
28
28
  */
29
29
  tokens: string[];
30
+ /**
31
+ * Where the call's keys stand, as `COMMAND` states it: the first key's word (the name is
32
+ * word 0), the last's — negative counts back from the call's end — and the step from one
33
+ * key to the next. `[1, 1, 1]` for `GET key`, `[1, -1, 1]` for `DEL key [key ...]`,
34
+ * `[1, -1, 2]` for `MSET key value [key value ...]`. Absent where the call takes no key,
35
+ * and where only its own arguments can say which words are keys (`EVAL`, `GEORADIUS`).
36
+ */
37
+ keys?: [first: number, last: number, step: number];
30
38
  /**
31
39
  * The version that deprecated it, where one did.
32
40
  */
@@ -65,12 +73,30 @@ declare function createRedisVocabulary(commands?: readonly RedisCommand[]): Redi
65
73
  //#endregion
66
74
  //#region src/assist.d.ts
67
75
  /**
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.
76
+ * One key as the catalog lists it, with the type the keyspace answered for it.
77
+ */
78
+ interface CatalogKey {
79
+ name: string;
80
+ /**
81
+ * `string`, `hash`, `list`, … as `TYPE` answers; `""` where the catalog read none.
82
+ */
83
+ type: string;
84
+ }
85
+ /**
86
+ * The keyspace as the host lists it — and it MUST be a cache-backed read (the tree's own
87
+ * list), never a fresh one: completion reads it on every keystroke in a key.
88
+ */
89
+ interface RedisCatalog {
90
+ keys: () => readonly CatalogKey[];
91
+ }
92
+ /**
93
+ * One suggestion: a command's name at the line's start, a container's subcommand after it, a
94
+ * key of the keyspace where the command takes one, or a fixed word of the command's own syntax
95
+ * (`NX`, `WITHSCORES`) anywhere after.
70
96
  */
71
97
  interface RedisCompletionCandidate {
72
98
  label: string;
73
- kind: "command" | "subcommand" | "token";
99
+ kind: "command" | "subcommand" | "key" | "token";
74
100
  insertText: string;
75
101
  detail?: string;
76
102
  documentation?: string;
@@ -124,7 +150,7 @@ interface RedisAssist {
124
150
  * `readLine` — redis-cli's own splitting — so they can never disagree about which word the
125
151
  * caret is on.
126
152
  */
127
- declare function createRedisAssist(vocabulary?: RedisVocabulary): RedisAssist;
153
+ declare function createRedisAssist(catalog?: RedisCatalog, vocabulary?: RedisVocabulary): RedisAssist;
128
154
  //#endregion
129
155
  //#region src/line.d.ts
130
156
  /**
@@ -169,6 +195,14 @@ interface SplitLine {
169
195
  * The words of one line, redis-cli's way.
170
196
  */
171
197
  declare function splitLine(line: string): SplitLine;
198
+ /**
199
+ * One word spelled as a line this reader splits back into exactly it: bare where every
200
+ * character of it stands on its own, and double-quoted with that form's own escapes where one
201
+ * does not — a blank, either quote, a backslash or a character below the printable range. The
202
+ * inverse of [`splitLine`], for a word something other than the reader puts on a line: a key a
203
+ * completion inserts, a name a tool writes.
204
+ */
205
+ declare function spellWord(word: string): string;
172
206
  /**
173
207
  * The line the caret is on, read: its bounds in the whole text, its words, and where among
174
208
  * them the caret stands.
@@ -241,4 +275,4 @@ interface RedisMarker {
241
275
  */
242
276
  declare function lineMarkers(text: string, vocabulary?: RedisVocabulary): RedisMarker[];
243
277
  //#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 };
278
+ export { REDIS_COMMANDS as C, createRedisVocabulary as S, RedisCommand as T, RedisCompletionCandidate as _, LineRefusal as a, createRedisAssist as b, SplitLine as c, runnableLine as d, spellWord as f, RedisCatalog as g, RedisAssist as h, LineRead as i, lineBounds as l, CatalogKey as m, RedisMarkerCode as n, LineWord as o, splitLine as p, lineMarkers as r, RunnableLine as s, RedisMarker as t, readLine as u, RedisHoverCard as v, REDIS_VERSION as w, RedisVocabulary as x, RedisSignatureHelp as y };
@@ -1,4 +1,4 @@
1
- import { t as REDIS_COMMANDS } from "./commands-BMa2ec02.js";
1
+ import { t as REDIS_COMMANDS } from "./commands-B2cgDRf7.js";
2
2
  //#region src/line.ts
3
3
  const ESCAPES = {
4
4
  n: "\n",
@@ -7,6 +7,11 @@ const ESCAPES = {
7
7
  b: "\b",
8
8
  a: String.fromCodePoint(7)
9
9
  };
10
+ const NAMED = new Map([
11
+ ...Object.entries(ESCAPES).map(([escape, character]) => [character, escape]),
12
+ ["\"", "\""],
13
+ ["\\", "\\"]
14
+ ]);
10
15
  function blank(character) {
11
16
  return /\s/u.test(character);
12
17
  }
@@ -111,6 +116,14 @@ function splitLine(line) {
111
116
  refusal: null
112
117
  };
113
118
  }
119
+ function spellWord(word) {
120
+ if (word !== "" && !/["'\\\s\p{Cc}]/u.test(word)) return word;
121
+ return `"${[...word].map((character) => {
122
+ const escape = NAMED.get(character);
123
+ if (escape !== void 0) return `\\${escape}`;
124
+ return /\p{Cc}/u.test(character) ? String.raw`\x${character.codePointAt(0).toString(16).padStart(2, "0")}` : character;
125
+ }).join("")}"`;
126
+ }
114
127
  function lineBounds(text, offset) {
115
128
  const lineStart = text.lastIndexOf("\n", offset - 1) + 1;
116
129
  const next = text.indexOf("\n", offset);
@@ -247,4 +260,4 @@ function lineMarkers(text, vocabulary = DEFAULT_VOCABULARY) {
247
260
  return markers;
248
261
  }
249
262
  //#endregion
250
- export { runnableLine as a, readLine as i, createRedisVocabulary as n, splitLine as o, lineBounds as r, lineMarkers as t };
263
+ export { runnableLine as a, readLine as i, createRedisVocabulary as n, spellWord as o, lineBounds as r, splitLine as s, lineMarkers as t };
package/dist/monaco.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { S as RedisCommand, p as RedisAssist, t as RedisMarker } from "./markers-gZmuOyuR.js";
1
+ import { T as RedisCommand, h as RedisAssist, t as RedisMarker } from "./markers-Bmqe2Tjf.js";
2
2
  import * as monacoEditor from "monaco-editor";
3
3
  import { IDisposable, editor } from "monaco-editor";
4
4
  //#region src/monaco.d.ts
package/dist/monaco.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as REDIS_COMMANDS } from "./commands-BMa2ec02.js";
1
+ import { t as REDIS_COMMANDS } from "./commands-B2cgDRf7.js";
2
2
  //#region src/monaco.ts
3
3
  const REDIS_LANGUAGE_ID = "redis";
4
4
  const LANGUAGES_KEY = Symbol.for("coldsmirk.inkstone.redis.languages");
@@ -98,6 +98,7 @@ function itemKinds(monaco) {
98
98
  return {
99
99
  command: kinds.Function,
100
100
  subcommand: kinds.Method,
101
+ key: kinds.Struct,
101
102
  token: kinds.Keyword
102
103
  };
103
104
  }
package/dist/react.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { p as RedisAssist, t as RedisMarker } from "./markers-gZmuOyuR.js";
1
+ import { h as RedisAssist, t as RedisMarker } from "./markers-Bmqe2Tjf.js";
2
2
  import { MonacoModule } from "./monaco.js";
3
3
  import { ReactNode } from "react";
4
4
  import { editor } from "monaco-editor";
@@ -83,6 +83,13 @@ interface RedisEditorProps {
83
83
  * markers are drawn without it.
84
84
  */
85
85
  markerWording?: (marker: RedisMarker) => string;
86
+ /**
87
+ * Extra construction options, merged under this editor's own (`ariaLabel`): the escape hatch
88
+ * a host reaches for a construction option no prop names — `overflowWidgetsDomNode`, where
89
+ * the page's own layers would otherwise stand over the editor's floating widgets (hover,
90
+ * completion, parameter hints) left inside it.
91
+ */
92
+ options?: editor.IStandaloneEditorConstructionOptions;
86
93
  }
87
94
  /**
88
95
  * The command-line editing surface: Monaco under the `redis` grammar, one command a line, the
@@ -90,6 +97,6 @@ interface RedisEditorProps {
90
97
  * through `registerRedisLanguage`, and each line's markers refreshed on every change (they are
91
98
  * one split per line, cheap enough to run synchronously).
92
99
  */
93
- declare function RedisEditor({ value, onChange, dark, height, fontSize, locale, placeholder, ariaLabel, languageId, loading, failure, onRun, runActionLabel, onCaret, onReady, onMount, assist, markerWording }: RedisEditorProps): import("react").JSX.Element;
100
+ declare function RedisEditor({ value, onChange, dark, height, fontSize, locale, placeholder, ariaLabel, languageId, loading, failure, onRun, runActionLabel, onCaret, onReady, onMount, assist, markerWording, options }: RedisEditorProps): import("react").JSX.Element;
94
101
  //#endregion
95
102
  export { RedisCaret, RedisEditor, RedisEditorHandle, RedisEditorProps };
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as lineMarkers } from "./markers-BlM8eKCj.js";
1
+ import { t as lineMarkers } from "./markers-DFpfcLLE.js";
2
2
  import { REDIS_LANGUAGE_ID, defineRedisLanguage, registerRedisLanguage, setRedisMarkers } from "./monaco.js";
3
3
  import { MonacoEditor } from "@coldsmirk/inkstone-react/monaco";
4
4
  import { useEffect, useInsertionEffect, useRef, useState } from "react";
@@ -32,7 +32,7 @@ function caretOf(instance) {
32
32
  to: model.getOffsetAt(selection.getEndPosition())
33
33
  };
34
34
  }
35
- function RedisEditor({ value, onChange, dark = false, height = 200, fontSize, locale, placeholder, ariaLabel, languageId = REDIS_LANGUAGE_ID, loading, failure, onRun, runActionLabel = "Run command", onCaret, onReady, onMount, assist, markerWording }) {
35
+ function RedisEditor({ value, onChange, dark = false, height = 200, fontSize, locale, placeholder, ariaLabel, languageId = REDIS_LANGUAGE_ID, loading, failure, onRun, runActionLabel = "Run command", onCaret, onReady, onMount, assist, markerWording, options }) {
36
36
  const [modelPath] = useState(() => `file:///inkstone-redis/${String(nextEditorId())}.redis`);
37
37
  const bindings = useRef([]);
38
38
  const assistRef = useLatest(assist ?? null);
@@ -60,7 +60,10 @@ function RedisEditor({ value, onChange, dark = false, height = 200, fontSize, lo
60
60
  language: languageId,
61
61
  loading,
62
62
  locale,
63
- options: { ariaLabel },
63
+ options: {
64
+ ...options,
65
+ ariaLabel
66
+ },
64
67
  path: modelPath,
65
68
  placeholder,
66
69
  value,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coldsmirk/inkstone-redis",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "description": "Redis command-line editing intelligence for Monaco: the command table of Redis 7.2 (names, syntax, arity), redis-cli's own line splitting, completion / hover / signature help, line markers, and a drop-in React command editor.",
5
5
  "keywords": [
6
6
  "redis",
@@ -45,12 +45,12 @@
45
45
  "monaco-editor": "^0.56.0",
46
46
  "react": "^19.2.8",
47
47
  "react-dom": "^19.2.8",
48
- "@coldsmirk/inkstone-react": "^0.22.0"
48
+ "@coldsmirk/inkstone-react": "^0.24.0"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "monaco-editor": "^0.56.0",
52
52
  "react": ">=19",
53
- "@coldsmirk/inkstone-react": "^0.22.0"
53
+ "@coldsmirk/inkstone-react": "^0.24.0"
54
54
  },
55
55
  "peerDependenciesMeta": {
56
56
  "@coldsmirk/inkstone-react": {