UNPKG

@freeword/meta

Version:

Meta package for Freeword: exports all core types, constants, and utilities from the src/ directory.

166 lines 6.38 kB
import _ /**/ from 'lodash'; import * as NodeUtil from 'node:util'; // import { nextTick } from 'node:process' import { AtoZlos } from "../lexicon/LexiconConsts.js"; import * as JSPrintf from 'sprintf-js'; // export * from "./BaseUtils.js"; export * from "../lib/Streaming.js"; export * from "../lib/Random.js"; export * from "../UtilityConsts.js"; export * from "../lib/Rot13.js"; export { badOutcome, throwable } from "./OutcomeUtils.js"; export * from "./CollectionUtils.js"; export * from "./Logging.js"; export * from "./PromiseUtils.js"; export const { sprintf, vsprintf } = JSPrintf; /** @returns a bag with keys a, b, ... z and values of type VT */ export function alphabetLookupBag(seed) { if (_.isFunction(seed)) { return objectify(AtoZlos, (ltr) => seed(ltr)); } return objectify(AtoZlos, () => (seed)); } function indentPaddingFor(indent) { if (!indent) { return ''; } if (_.isString(indent)) { return indent; } return _.repeat(' ', indent); } /** * Pretty-print an array of strings in chunks * * @param arr - The array to pretty-print * @param opts - The options for pretty-printing * @returns The pretty-printed array */ export function prettifyStrings(arr, { chunkSize = 20, colwd = 12, key, indent = 2, naked = false } = {}) { const indentPadding = indentPaddingFor(indent); const lines = _.chunk(arr, chunkSize).map((chunk) => chunk.map((val) => _.padEnd(val + ',', colwd)).join(' ')); const body = lines.join('\n' + indentPadding); const bracketed = naked ? body : '[\n ' + body + '\n]'; return (key ? kfy(key) : '') + bracketed; } /** * Pretty-print an array of strings in chunks * * @param arr - The array to pretty-print * @param opts - The options for pretty-printing * @returns The pretty-printed array */ export function prettifyInChunks(arr, { chunkSize = 20, colwd = 12, key, indent = 2, stringify = true } = {}) { const stringified = stringify ? _.map(arr, (val) => inspectify(val)) : arr; return prettifyStrings(stringified, { chunkSize, colwd, key, indent }); } export function prettifyArray(arr, opts = {}) { const inspected = inspectify(arr); if ((inspected.length < 180) && (!opts.chunkArrays)) { return opts.naked ? inspected.slice(1, -1).trim() : inspected; } return prettifyInChunks(arr, opts); } export function prettifySet(set, { key, ...opts } = {}) { const elements = prettifyArray(Array.from(set), opts); return (key ? kfy(key) : '') + 'new Set(' + elements + ')'; } export function inspectify(val, _opts = {}) { return NodeUtil.inspect(val, { depth: 10, colors: false, breakLength: Infinity, maxArrayLength: Infinity, maxStringLength: Infinity, compact: true, numericSeparator: true }); } const FieldnameRE = /^[a-zA-Z_]\w*$/; export function kfy(key, opts = {}) { const str = FieldnameRE.test(key) ? key : inspectify(key); return _.padEnd(str + ':', opts.keywd); } export function prettifyField(val, opts = {}) { if (_.isArray(val)) { return prettifyArray(val, opts); } if (_.isSet(val)) { return prettifySet(val, opts); } return inspectify(val); } export function prettify(obj, { key, naked = false, ...opts } = {}) { const firstkey = _.isNil(key) ? '' : (kfy(key) + ' '); const startBracket = naked ? '' : '{'; const endBracket = naked ? '' : '}'; const lines = []; const indentPadding = indentPaddingFor(opts.indent); _.each(obj, (val, key) => { const keypart = kfy(key, { keywd: 12, ...opts }); const valpart = prettifyField(val, opts); lines.push(indentPadding + keypart + ' ' + valpart); }); return firstkey + startBracket + '\n' + lines.join(',\n') + ',\n' + endBracket; } export function rebag(clxn, func) { let seq = 0; return Object.fromEntries(_.map(clxn, (val, key) => func(val, key, seq++, clxn))); } export function objectify(clxn, func) { return rebag(clxn, (val, key, seq, ...args) => [val, func(val, key, seq, ...args)]); } export function bagslice(bag, start, end) { const keys = _.keys(bag).slice(start, end); return _.pick(bag, keys); } export function sortOnKeys([key, _val]) { return key; } export function sortOnNumkeys([key, _val]) { return Number(key); } /** Sort a bag by a funtion -- by default, its keys. * @note **by default, keys that parse as positive integers (1, 2, 3, ...) will appear first in retrieval order**. * This is part of the spec for Object. * @example { '1': 1, '2': 2, '-1': -1, '0.9': 0.9, '1.1': 1.1 } * If you use the magic function `sortOnNumkeys`, * keys that stringify as integers will be reinserted as `x.0`: * @example { '-1.0': -1, '0.9': 0.9, '1.0': 1, '1.1': 1.1, '2.0': 2 } */ export function bagsort(bag, sortfn = sortOnKeys, { mungeNumKeys = true, sortdirs } = {}) { const result = {}; const sorted = _.orderBy(_.entries(bag), sortfn, sortdirs); if (!mungeNumKeys) { return _.fromPairs(sorted); } for (const [key, val] of sorted) { const mungedKey = (Number.isInteger(Number(key))) ? (String(key) + '.0') : key; result[mungedKey] = val; } return result; } const nextTicker = globalThis.nextTick ?? ((func) => (func())); /** * Sleep for one tick (i.e. let everyone else have a turn) * @returns true */ export async function sleepNextTick() { return new Promise((yay) => { nextTicker(() => yay(true)); }); } /** * Sleep for a given number of milliseconds * @param ms - The number of milliseconds to sleep * @param nextTick - Whether to sleep for one tick before starting the sleep * @note IMPORTANT: if nextTick is true, the sleep will be delayed by * the duration given PLUS an unknowable amount of time * @returns true */ export async function sleep(ms, awakeNextTick = false) { if (awakeNextTick) { await sleepNextTick(); } return new Promise((resolve) => setTimeout(resolve, ms)).then(() => true); } export async function* catiters(...iters) { for (const iter of iters) { yield* iter; } } export function isNode() { return (typeof process !== 'undefined' && process.release && process.release.name === 'node'); } export function isBrowser() { // if (isNode()) { return false } return (!!import.meta.client); } //# sourceMappingURL=UF.js.map