Merge pull request #3292 from SillyTavern/macrosparser
Signed| @@ -26,6 +26,12 @@ Handlebars.registerHelper('helperMissing', function () { | |||
| 26 | * @typedef {(nonce: string) => string} MacroFunction | 26 | * @typedef {(nonce: string) => string} MacroFunction |
| 27 | */ | 27 | */ |
| 28 | 28 | ||
| 29 | /** | ||
| 30 | * @typedef {Object} CustomMacro | ||
| 31 | * @property {string} key - Macro name (key) | ||
| 32 | * @property {string} description - Optional description of the macro | ||
| 33 | */ | ||
| 34 | |||
| 29 | export class MacrosParser { | 35 | export class MacrosParser { |
| 30 | /** | 36 | /** |
| 31 | * A map of registered macros. | 37 | * A map of registered macros. |
| @@ -34,11 +40,28 @@ export class MacrosParser { | |||
| 34 | static #macros = new Map(); | 40 | static #macros = new Map(); |
| 35 | 41 | ||
| 36 | /** | 42 | /** |
| 43 | * A map of macro descriptions. | ||
| 44 | * @type {Map<string, string>} | ||
| 45 | */ | ||
| 46 | static #descriptions = new Map(); | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Returns an iterator over all registered macros. | ||
| 50 | * @returns {IterableIterator<CustomMacro>} | ||
| 51 | */ | ||
| 52 | static [Symbol.iterator] = function* () { | ||
| 53 | for (const macro of MacrosParser.#macros.keys()) { | ||
| 54 | yield { key: macro, description: MacrosParser.#descriptions.get(macro) }; | ||
| 55 | } | ||
| 56 | }; | ||
| 57 | |||
| 58 | /** | ||
| 37 | * Registers a global macro that can be used anywhere where substitution is allowed. | 59 | * Registers a global macro that can be used anywhere where substitution is allowed. |
| 38 | * @param {string} key Macro name (key) | 60 | * @param {string} key Macro name (key) |
| 39 | * @param {string|MacroFunction} value A string or a function that returns a string | 61 | * @param {string|MacroFunction} value A string or a function that returns a string |
| 62 | * @param {string} [description] Optional description of the macro | ||
| 40 | */ | 63 | */ |
| 41 | static registerMacro(key, value) { | 64 | static registerMacro(key, value, description = '') { |
| 42 | if (typeof key !== 'string') { | 65 | if (typeof key !== 'string') { |
| 43 | throw new Error('Macro key must be a string'); | 66 | throw new Error('Macro key must be a string'); |
| 44 | } | 67 | } |
| @@ -64,6 +87,10 @@ export class MacrosParser { | |||
| 64 | } | 87 | } |
| 65 | 88 | ||
| 66 | this.#macros.set(key, value); | 89 | this.#macros.set(key, value); |
| 90 | |||
| 91 | if (typeof description === 'string' && description) { | ||
| 92 | this.#descriptions.set(key, description); | ||
| 93 | } | ||
| 67 | } | 94 | } |
| 68 | 95 | ||
| 69 | /** | 96 | /** |
| @@ -88,6 +115,8 @@ export class MacrosParser { | |||
| 88 | if (!deleted) { | 115 | if (!deleted) { |
| 89 | console.warn(`Macro ${key} was not registered`); | 116 | console.warn(`Macro ${key} was not registered`); |
| 90 | } | 117 | } |
| 118 | |||
| 119 | this.#descriptions.delete(key); | ||
| 91 | } | 120 | } |
| 92 | 121 | ||
| 93 | /** | 122 | /** |
| @@ -22,6 +22,8 @@ import { SlashCommandBreakPoint } from './SlashCommandBreakPoint.js'; | |||
| 22 | import { SlashCommandDebugController } from './SlashCommandDebugController.js'; | 22 | import { SlashCommandDebugController } from './SlashCommandDebugController.js'; |
| 23 | import { commonEnumProviders } from './SlashCommandCommonEnumsProvider.js'; | 23 | import { commonEnumProviders } from './SlashCommandCommonEnumsProvider.js'; |
| 24 | import { SlashCommandBreak } from './SlashCommandBreak.js'; | 24 | import { SlashCommandBreak } from './SlashCommandBreak.js'; |
| 25 | import { MacrosParser } from '../macros.js'; | ||
| 26 | import { t } from '../i18n.js'; | ||
| 25 | 27 | ||
| 26 | /** @typedef {import('./SlashCommand.js').NamedArgumentsCapture} NamedArgumentsCapture */ | 28 | /** @typedef {import('./SlashCommand.js').NamedArgumentsCapture} NamedArgumentsCapture */ |
| 27 | /** @typedef {import('./SlashCommand.js').NamedArguments} NamedArguments */ | 29 | /** @typedef {import('./SlashCommand.js').NamedArguments} NamedArguments */ |
| @@ -494,6 +496,10 @@ export class SlashCommandParser { | |||
| 494 | li.querySelector('tt').textContent, | 496 | li.querySelector('tt').textContent, |
| 495 | (li.querySelector('tt').remove(),li.innerHTML), | 497 | (li.querySelector('tt').remove(),li.innerHTML), |
| 496 | )); | 498 | )); |
| 499 | for (const macro of MacrosParser) { | ||
| 500 | if (options.find(it => it.name === macro.key)) continue; | ||
| 501 | options.push(new MacroAutoCompleteOption(macro.key, `{{${macro.key}}}`, macro.description || t`No description provided`)); | ||
| 502 | } | ||
| 497 | const result = new AutoCompleteNameResult( | 503 | const result = new AutoCompleteNameResult( |
| 498 | macro.name, | 504 | macro.name, |
| 499 | macro.start + 2, | 505 | macro.start + 2, |