Skip to content

Instantly share code, notes, and snippets.

@Digital39999
Last active January 25, 2024 15:45
Show Gist options
  • Save Digital39999/df84aaacd40c62f07f18f636907e0d8b to your computer and use it in GitHub Desktop.
Save Digital39999/df84aaacd40c62f07f18f636907e0d8b to your computer and use it in GitHub Desktop.
export type RecursiveStringArray = (RecursiveStringArray | string)[];
export type DeconstructedFunction = { args: (string | string[])[], body: string, wrapScope: boolean, wrapArgs: boolean; isAsync: boolean; };
export function guildEvalParser<R, A extends never[]>(func: string | ((...args: A) => R)): string {
if (typeof func === 'function') func = func.toString();
const type: 'function' | 'arrow' = (func.startsWith('function') || func.startsWith('async function')) ? 'function' : 'arrow';
if (type === 'function') func = func.replace(/function\s+\w+\s*/, 'function ');
const data = getStuff({ func, type });
return reconstruct({ ...data, ...insertBodyCheck(data) });
function getStuff({ func, type }: { func: string, type: 'function' | 'arrow' }) {
switch (type) {
case 'arrow': {
let [wrapScope, wrapArgs, isAsync] = [false, false, false];
func = func.startsWith('async') ? func.replace(/async\s*/, () => { isAsync = true; return ''; }) : func;
const stuff = func.split('=>').map((x) => x.trim());
const body = stuff.slice(1);
let args = stuff[0];
let actualBody = body.join(' => ').trim();
if (args.startsWith('(')) { args = args.slice(1, -1); wrapArgs = true; }
if (actualBody.match(/^\{[\s\S]*\}$/)) {
wrapScope = false;
actualBody = actualBody.slice(1, -1).trim();
if (actualBody.endsWith(';')) actualBody = actualBody.slice(0, -1).trim();
}
return {
args: args.split(',').map((x) => {
x = x.trim();
if (x.includes('{')) {
const destructured = x.slice(x.indexOf('{') + 1, x.indexOf('}')).split(',').map((x) => x.trim().split(' ').pop() || '').filter((x) => x);
return destructured.length ? destructured : x;
} else return x.split(' ').pop() || '';
}).filter((x) => x),
body: actualBody.trim(),
isAsync,
wrapScope,
wrapArgs,
};
}
case 'function': {
let [wrapScope, isAsync] = [true, false];
func = func.startsWith('async') ? func.replace(/async\s*/, () => { isAsync = true; return ''; }) : func;
const stuff = func.split(') {').map((x, i) => { x = x.trim(); return i === 0 ? x.slice(x.indexOf('(') + 1) : `{ ${x}`; });
const body = stuff.slice(1);
let args = stuff[0];
let actualBody = body.join(') {').trim();
if (args.startsWith('(')) { args = args.slice(1, -1); }
if (actualBody.match(/^\{[\s\S]*\}$/)) {
wrapScope = false;
actualBody = actualBody.slice(1, -1).trim();
if (actualBody.endsWith(';')) actualBody = actualBody.slice(0, -1).trim();
}
return {
args: args.split(',').map((x) => {
x = x.trim();
if (x.includes('{')) {
const destructured = x.slice(x.indexOf('{') + 1, x.indexOf('}')).split(',').map((x) => x.trim().split(' ').pop() || '').filter((x) => x);
return destructured.length ? destructured : x;
} else return x.split(' ').pop() || '';
}).filter((x) => x),
body: actualBody.trim(),
wrapScope,
wrapArgs: true,
isAsync,
};
}
}
}
function reconstruct({ args, body, wrapScope, wrapArgs, isAsync }: DeconstructedFunction) {
let argsStr = makeArgs(args);
switch (type) {
case 'arrow': {
if (wrapArgs) argsStr = `(${argsStr})`;
if (wrapScope) body = `{ ${body} }`;
if (isAsync) argsStr = `async ${argsStr}`;
return `${argsStr} => ${body}`;
}
case 'function': {
if (wrapArgs) argsStr = `(${argsStr})`;
if (wrapScope) body = `{ ${body} }`;
return `function ${argsStr} ${body}`;
}
}
}
function makeArgs(args: RecursiveStringArray): string {
return args.map((x) => {
if (typeof x === 'string') return x;
else return `{ ${makeArgs(x)} }`;
}).join(', ');
}
function insertBodyCheck({ args, body, wrapScope }: Omit<DeconstructedFunction, 'wrapArgs'>) {
if (args.length < 3) return { body: body };
return {
wrapScope: true,
body: !body.match(new RegExp(`if\\s*\\(\\s*!\\s*${args[2]}\\s*\\)\\s*return`, 'g'))
? `if (!${args[2]}) return;\n ${wrapScope ? body : `return ${body};`}`
: body,
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment