« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/upd8-util.js
diff options
context:
space:
mode:
Diffstat (limited to 'upd8-util.js')
-rw-r--r--upd8-util.js423
1 files changed, 0 insertions, 423 deletions
diff --git a/upd8-util.js b/upd8-util.js
deleted file mode 100644
index 4c4186f7..00000000
--- a/upd8-util.js
+++ /dev/null
@@ -1,423 +0,0 @@
-// This is used by upd8.js! It's part of the 8ackend. Read the notes there if
-// you're curious.
-//
-// Friendly(!) disclaimer: these utility functions haven't 8een tested all that
-// much. Do not assume it will do exactly what you want it to do in all cases.
-// It will likely only do exactly what I want it to, and only in the cases I
-// decided were relevant enough to 8other handling.
-
-'use strict';
-
-// Apparently JavaScript doesn't come with a function to split an array into
-// chunks! Weird. Anyway, this is an awesome place to use a generator, even
-// though we don't really make use of the 8enefits of generators any time we
-// actually use this. 8ut it's still awesome, 8ecause I say so.
-module.exports.splitArray = function*(array, fn) {
-    let lastIndex = 0;
-    while (lastIndex < array.length) {
-        let nextIndex = array.findIndex((item, index) => index >= lastIndex && fn(item));
-        if (nextIndex === -1) {
-            nextIndex = array.length;
-        }
-        yield array.slice(lastIndex, nextIndex);
-        // Plus one because we don't want to include the dividing line in the
-        // next array we yield.
-        lastIndex = nextIndex + 1;
-    }
-};
-
-// This function's name is a joke. Jokes! Hahahahahahahaha. Funny.
-module.exports.joinNoOxford = function(array, plural = 'and') {
-    array = array.filter(Boolean);
-
-    if (array.length === 0) {
-        // ????????
-        return '';
-    }
-
-    if (array.length === 1) {
-        return array[0];
-    }
-
-    if (array.length === 2) {
-        return `${array[0]} ${plural} ${array[1]}`;
-    }
-
-    return `${array.slice(0, -1).join(', ')} ${plural} ${array[array.length - 1]}`;
-};
-
-module.exports.progressPromiseAll = function (msgOrMsgFn, array) {
-    if (!array.length) {
-        return Promise.resolve([]);
-    }
-
-    const msgFn = (typeof msgOrMsgFn === 'function'
-        ? msgOrMsgFn
-        : () => msgOrMsgFn);
-
-    let done = 0, total = array.length;
-    process.stdout.write(`\r${msgFn()} [0/${total}]`);
-    const start = Date.now();
-    return Promise.all(array.map(promise => promise.then(val => {
-        done++;
-        // const pc = `${done}/${total}`;
-        const pc = (Math.round(done / total * 1000) / 10 + '%').padEnd('99.9%'.length, ' ');
-        if (done === total) {
-            const time = Date.now() - start;
-            process.stdout.write(`\r\x1b[2m${msgFn()} [${pc}] \x1b[0;32mDone! \x1b[0;2m(${time} ms) \x1b[0m\n`)
-        } else {
-            process.stdout.write(`\r${msgFn()} [${pc}] `);
-        }
-        return val;
-    })));
-};
-
-module.exports.queue = function (array, max = 50) {
-    if (max === 0) {
-        return array.map(fn => fn());
-    }
-
-    const begin = [];
-    let current = 0;
-    const ret = array.map(fn => new Promise((resolve, reject) => {
-        begin.push(() => {
-            current++;
-            Promise.resolve(fn()).then(value => {
-                current--;
-                if (current < max && begin.length) {
-                    begin.shift()();
-                }
-                resolve(value);
-            }, reject);
-        });
-    }));
-
-    for (let i = 0; i < max && begin.length; i++) {
-        begin.shift()();
-    }
-
-    return ret;
-};
-
-module.exports.delay = ms => new Promise(res => setTimeout(res, ms));
-
-module.exports.th = function (n) {
-    if (n % 10 === 1 && n !== 11) {
-        return n + 'st';
-    } else if (n % 10 === 2 && n !== 12) {
-        return n + 'nd';
-    } else if (n % 10 === 3 && n !== 13) {
-        return n + 'rd';
-    } else {
-        return n + 'th';
-    }
-};
-
-// My function names just keep getting 8etter.
-module.exports.s = function (n, word) {
-    return `${n} ${word}` + (n === 1 ? '' : 's');
-};
-
-// Hey, did you know I apparently put a space 8efore the parameters in function
-// names? 8ut only in function expressions, not declar8tions? I mean, I guess
-// you did. You're pro8a8ly more familiar with my code than I am 8y this
-// point. I haven't messed with any of this code in ages. Yay!!!!!!!!
-//
-// This function only does anything on o8jects you're going to 8e reusing.
-// Argua8ly I could use a WeakMap here, 8ut since the o8ject needs to 8e
-// reused to 8e useful anyway, I just store the result with a symbol.
-// Sorry if it's 8een frozen I guess??
-module.exports.cacheOneArg = function (fn) {
-    const symbol = Symbol('Cache');
-    return arg => {
-        if (!arg[symbol]) {
-            arg[symbol] = fn(arg);
-        }
-        return arg[symbol];
-    };
-};
-
-const decorateTime = function (functionToBeWrapped) {
-    const fn = function(...args) {
-        const start = Date.now();
-        const ret = functionToBeWrapped(...args);
-        const end = Date.now();
-        fn.timeSpent += end - start;
-        fn.timesCalled++;
-        return ret;
-    };
-
-    fn.wrappedName = functionToBeWrapped.name;
-    fn.timeSpent = 0;
-    fn.timesCalled = 0;
-    fn.displayTime = function() {
-        const averageTime = fn.timeSpent / fn.timesCalled;
-        console.log(`\x1b[1m${fn.wrappedName}(...):\x1b[0m ${fn.timeSpent} ms / ${fn.timesCalled} calls \x1b[2m(avg: ${averageTime} ms)\x1b[0m`);
-    };
-
-    decorateTime.decoratedFunctions.push(fn);
-
-    return fn;
-};
-
-decorateTime.decoratedFunctions = [];
-decorateTime.displayTime = function() {
-    if (decorateTime.decoratedFunctions.length) {
-        console.log(`\x1b[1mdecorateTime results: ` + '-'.repeat(40) + '\x1b[0m');
-        for (const fn of decorateTime.decoratedFunctions) {
-            fn.displayTime();
-        }
-    }
-};
-
-module.exports.decorateTime = decorateTime;
-
-// Stolen as #@CK from mtui!
-const parseOptions = async function(options, optionDescriptorMap) {
-    // This function is sorely lacking in comments, but the basic usage is
-    // as such:
-    //
-    // options is the array of options you want to process;
-    // optionDescriptorMap is a mapping of option names to objects that describe
-    // the expected value for their corresponding options.
-    // Returned is a mapping of any specified option names to their values, or
-    // a process.exit(1) and error message if there were any issues.
-    //
-    // Here are examples of optionDescriptorMap to cover all the things you can
-    // do with it:
-    //
-    // optionDescriptorMap: {
-    //   'telnet-server': {type: 'flag'},
-    //   't': {alias: 'telnet-server'}
-    // }
-    //
-    // options: ['t'] -> result: {'telnet-server': true}
-    //
-    // optionDescriptorMap: {
-    //   'directory': {
-    //     type: 'value',
-    //     validate(name) {
-    //       // const whitelistedDirectories = ['apple', 'banana']
-    //       if (whitelistedDirectories.includes(name)) {
-    //         return true
-    //       } else {
-    //         return 'a whitelisted directory'
-    //       }
-    //     }
-    //   },
-    //   'files': {type: 'series'}
-    // }
-    //
-    // ['--directory', 'apple'] -> {'directory': 'apple'}
-    // ['--directory', 'artichoke'] -> (error)
-    // ['--files', 'a', 'b', 'c', ';'] -> {'files': ['a', 'b', 'c']}
-    //
-    // TODO: Be able to validate the values in a series option.
-
-    const handleDashless = optionDescriptorMap[parseOptions.handleDashless];
-    const handleUnknown = optionDescriptorMap[parseOptions.handleUnknown];
-    const result = Object.create(null);
-    for (let i = 0; i < options.length; i++) {
-        const option = options[i];
-        if (option.startsWith('--')) {
-            // --x can be a flag or expect a value or series of values
-            let name = option.slice(2).split('=')[0]; // '--x'.split('=') = ['--x']
-            let descriptor = optionDescriptorMap[name];
-            if (!descriptor) {
-                if (handleUnknown) {
-                    handleUnknown(option);
-                } else {
-                    console.error(`Unknown option name: ${name}`);
-                    process.exit(1);
-                }
-                continue;
-            }
-            if (descriptor.alias) {
-                name = descriptor.alias;
-                descriptor = optionDescriptorMap[name];
-            }
-            if (descriptor.type === 'flag') {
-                result[name] = true;
-            } else if (descriptor.type === 'value') {
-                let value = option.slice(2).split('=')[1];
-                if (!value) {
-                    value = options[++i];
-                    if (!value || value.startsWith('-')) {
-                        value = null;
-                    }
-                }
-                if (!value) {
-                    console.error(`Expected a value for --${name}`);
-                    process.exit(1);
-                }
-                result[name] = value;
-            } else if (descriptor.type === 'series') {
-                if (!options.slice(i).includes(';')) {
-                    console.error(`Expected a series of values concluding with ; (\\;) for --${name}`);
-                    process.exit(1);
-                }
-                const endIndex = i + options.slice(i).indexOf(';');
-                result[name] = options.slice(i + 1, endIndex);
-                i = endIndex;
-            }
-            if (descriptor.validate) {
-                const validation = await descriptor.validate(result[name]);
-                if (validation !== true) {
-                    console.error(`Expected ${validation} for --${name}`);
-                    process.exit(1);
-                }
-            }
-        } else if (option.startsWith('-')) {
-            // mtui doesn't use any -x=y or -x y format optionuments
-            // -x will always just be a flag
-            let name = option.slice(1);
-            let descriptor = optionDescriptorMap[name];
-            if (!descriptor) {
-                if (handleUnknown) {
-                    handleUnknown(option);
-                } else {
-                    console.error(`Unknown option name: ${name}`);
-                    process.exit(1);
-                }
-                continue;
-            }
-            if (descriptor.alias) {
-                name = descriptor.alias;
-                descriptor = optionDescriptorMap[name];
-            }
-            if (descriptor.type === 'flag') {
-                result[name] = true;
-            } else {
-                console.error(`Use --${name} (value) to specify ${name}`);
-                process.exit(1);
-            }
-        } else if (handleDashless) {
-            handleDashless(option);
-        }
-    }
-    return result;
-}
-
-parseOptions.handleDashless = Symbol();
-parseOptions.handleUnknown = Symbol();
-
-module.exports.parseOptions = parseOptions;
-
-// Cheap FP for a cheap dyke!
-// I have no idea if this is what curry actually means.
-module.exports.curry = f => x => (...args) => f(x, ...args);
-
-module.exports.mapInPlace = (array, fn) => array.splice(0, array.length, ...array.map(fn));
-
-module.exports.filterEmptyLines = string => string.split('\n').filter(line => line.trim()).join('\n');
-
-module.exports.unique = arr => Array.from(new Set(arr));
-
-const logColor = color => (literals, ...values) => {
-    const w = s => process.stdout.write(s);
-    w(`\x1b[${color}m`);
-    for (let i = 0; i < literals.length; i++) {
-        w(literals[i]);
-        if (values[i] !== undefined) {
-            w(`\x1b[1m`);
-            w(String(values[i]));
-            w(`\x1b[0;${color}m`);
-        }
-    }
-    w(`\x1b[0m\n`);
-};
-
-module.exports.logInfo = logColor(2);
-module.exports.logWarn = logColor(33);
-module.exports.logError = logColor(31);
-
-module.exports.sortByName = (a, b) => {
-    let an = a.name.toLowerCase();
-    let bn = b.name.toLowerCase();
-    if (an.startsWith('the ')) an = an.slice(4);
-    if (bn.startsWith('the ')) bn = bn.slice(4);
-    return an < bn ? -1 : an > bn ? 1 : 0;
-};
-
-module.exports.chunkByConditions = function(array, conditions) {
-    if (array.length === 0) {
-        return [];
-    } else if (conditions.length === 0) {
-        return [array];
-    }
-
-    const out = [];
-    let cur = [array[0]];
-    for (let i = 1; i < array.length; i++) {
-        const item = array[i];
-        const prev = array[i - 1];
-        let chunk = false;
-        for (const condition of conditions) {
-            if (condition(item, prev)) {
-                chunk = true;
-                break;
-            }
-        }
-        if (chunk) {
-            out.push(cur);
-            cur = [item];
-        } else {
-            cur.push(item);
-        }
-    }
-    out.push(cur);
-    return out;
-};
-
-module.exports.chunkByProperties = function(array, properties) {
-    return module.exports.chunkByConditions(array, properties.map(p => (a, b) => {
-        if (a[p] instanceof Date && b[p] instanceof Date)
-            return +a[p] !== +b[p];
-
-        if (a[p] !== b[p]) return true;
-
-        // Not sure if this line is still necessary with the specific check for
-        // d8tes a8ove, 8ut, uh, keeping it anyway, just in case....?
-        if (a[p] != b[p]) return true;
-
-        return false;
-    }))
-        .map(chunk => ({
-            ...Object.fromEntries(properties.map(p => [p, chunk[0][p]])),
-            chunk
-        }));
-};
-
-// Very cool function origin8ting in... http-music pro8a8ly!
-// Sorry if we happen to 8e violating past-us's copyright, lmao.
-module.exports.promisifyProcess = function(proc, showLogging = true) {
-    // Takes a process (from the child_process module) and returns a promise
-    // that resolves when the process exits (or rejects, if the exit code is
-    // non-zero).
-    //
-    // Ayy look, no alpha8etical second letter! Couldn't tell this was written
-    // like three years ago 8efore I was me. 8888)
-
-    return new Promise((resolve, reject) => {
-        if (showLogging) {
-            proc.stdout.pipe(process.stdout);
-            proc.stderr.pipe(process.stderr);
-        }
-
-        proc.on('exit', code => {
-            if (code === 0) {
-                resolve();
-            } else {
-                reject(code);
-            }
-        })
-    })
-};
-
-// Stolen from jq! Which pro8a8ly stole the concept from other places. Nice.
-module.exports.withEntries = (obj, fn) => Object.fromEntries(fn(Object.entries(obj)));
-
-// Nothin' more to it than what it says. Runs a function in-place. Provides an
-// altern8tive syntax to the usual IIFEs (e.g. (() => {})()) when you want to
-// open a scope and run some statements while inside an existing expression.
-module.exports.call = fn => fn();