From 4f0d935f1dec0cece23ac661b02486f095b5ee94 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Sat, 18 Mar 2023 19:41:32 -0300 Subject: data steps: annotate content function names --- src/content-function.js | 16 ++++++++--- src/util/sugar.js | 76 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/src/content-function.js b/src/content-function.js index 5138379..654a294 100644 --- a/src/content-function.js +++ b/src/content-function.js @@ -1,4 +1,4 @@ -import {empty} from './util/sugar.js'; +import {annotateFunction, empty} from './util/sugar.js'; export default function contentFunction({ contentDependencies = [], @@ -54,6 +54,7 @@ export function expectDependencies({ throw new Error(`Generate invalidated because unfulfilled dependencies provided: ${invalidatingDependencyKeys.join(', ')}`); }; + annotateFunction(wrappedGenerate, {name: generate, trait: 'invalidated'}); wrappedGenerate.fulfilled ??= false; } @@ -62,17 +63,19 @@ export function expectDependencies({ return generate(data, fulfilledDependencies); }; + annotateFunction(wrappedGenerate, {name: generate, trait: 'fulfilled'}); + wrappedGenerate.fulfilled ??= true; + wrappedGenerate.fulfill = function() { throw new Error(`All dependencies already fulfilled`); }; - - wrappedGenerate.fulfilled ??= true; } wrappedGenerate ??= function() { throw new Error(`Dependencies still needed: ${missingContentDependencyKeys.concat(missingExtraDependencyKeys).join(', ')}`); }; + annotateFunction(wrappedGenerate, {name: generate, trait: 'unfulfilled'}); wrappedGenerate.fulfilled ??= false; wrappedGenerate[contentFunction.identifyingSymbol] = true; @@ -84,6 +87,7 @@ export function expectDependencies({ throw new Error(`Expected call to this dependency's .data()`); }; + annotateFunction(wrappedGenerate, {name: fulfilledDependencies[key], description: 'data only'}); wrappedDependency.data = fulfilledDependencies[key].data; dataDependencies[key] = wrappedDependency; } @@ -91,13 +95,17 @@ export function expectDependencies({ wrappedGenerate.data = function(...args) { return data(...args, dataDependencies); }; + + annotateFunction(wrappedGenerate.data, {name: data, trait: 'fulfilled'}); } wrappedGenerate.data ??= function() { throw new Error(`Dependencies still needed: ${missingContentDependencyKeys.join(', ')}`); }; - wrappedGenerate.fulfill ??= function(dependencies) { + annotateFunction(wrappedGenerate.data, {name: data, trait: 'unfulfilled'}); + + wrappedGenerate.fulfill ??= function fulfill(dependencies) { return expectDependencies({ generate, data, diff --git a/src/util/sugar.js b/src/util/sugar.js index c60bddb..ad36d16 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -146,8 +146,9 @@ export function bindOpts(fn, bind) { ]); }; - Object.defineProperty(bound, 'name', { - value: fn.name ? `(options-bound) ${fn.name}` : `(options-bound)`, + annotateFunction(bound, { + name: fn, + trait: 'options-bound', }); for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(fn))) { @@ -487,3 +488,74 @@ export function decorateErrorWithIndex(fn) { } }; } + +// Delicious function annotations, such as: +// +// (*bound) soWeAreBackInTheMine +// (data *unfulfilled) generateShrekTwo +// +export function annotateFunction(fn, { + name: nameOrFunction = null, + description: newDescription, + trait: newTrait, +}) { + let name; + + if (typeof nameOrFunction === 'function') { + name = nameOrFunction.name; + } else if (typeof nameOrFunction === 'string') { + name = nameOrFunction; + } + + name ??= fn.name ?? 'anonymous'; + + const match = name.match(/^ *(?.*?) *\((?.*)( #(?.*))?\) *(?.*) *$/); + + let prefix, suffix, description, trait; + if (match) { + ({prefix, suffix, description, trait} = match.groups); + } + + prefix ??= ''; + suffix ??= name; + description ??= ''; + trait ??= ''; + + if (newDescription) { + if (description) { + description += '; ' + newDescription; + } else { + description = newDescription; + } + } + + if (newTrait) { + if (trait) { + trait += ' #' + newTrait; + } else { + trait = '#' + newTrait; + } + } + + let parenthesesPart; + + if (description && trait) { + parenthesesPart = `${description} ${trait}`; + } else if (description || trait) { + parenthesesPart = description || trait; + } else { + parenthesesPart = ''; + } + + let finalName; + + if (prefix && parenthesesPart) { + finalName = `${prefix} (${parenthesesPart}) ${suffix}`; + } else if (parenthesesPart) { + finalName = `(${parenthesesPart}) ${suffix}`; + } else { + finalName = suffix; + } + + Object.defineProperty(fn, 'name', {value: finalName}); +} -- cgit 1.3.0-6-gf8a5