From 48ed5168d477fe11fe4f21ae104e3750935b0943 Mon Sep 17 00:00:00 2001 From: Florrie Date: Sat, 15 Feb 2020 22:13:53 -0400 Subject: cli args (bass boost ur music) $ mtui --player sox --player-options bass +25 \; --- general-util.js | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) (limited to 'general-util.js') diff --git a/general-util.js b/general-util.js index 3aa4180..0a81cdc 100644 --- a/general-util.js +++ b/general-util.js @@ -192,3 +192,121 @@ module.exports.getTimeStrings = function({curHour, curMin, curSec, lenHour, lenM return module.exports.getTimeStringsFromSec(curSecTotal, lenSecTotal) } + +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 result = {} + 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) { + console.error(`Unknown option name: ${name}`) + process.exit(1) + } + 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) { + console.error(`Unknown option name: ${name}`) + process.exit(1) + } + 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() + +module.exports.parseOptions = parseOptions -- cgit 1.3.0-6-gf8a5