Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 'use strict'
- const OPTION_REGEXP = /^--(?:(no)-)?(\w{2,}(?:[\w-]+)?)$/
- const FLOAT_REGEXP = /^[+-]?(\d+)?(\.\d+)?$/
- const CAMEL_REGEXP = /[-_]+([A-z])/g
- const FLAG_REGEXP = /^-(\w+)$/
- const TYPE = {
- boolean: boolean,
- number: number,
- list: {
- append: true,
- transform: value
- },
- value: value,
- auto: auto
- }
- class Clint {
- constructor (options, argTransform = TYPE.auto) {
- this.aliases = {}
- this.transforms = {}
- this.appends = {}
- this.argTransform = argTransform
- options = Object.assign({
- '*': {
- transform: TYPE.auto
- },
- '--*': {
- transform: TYPE.auto
- },
- input: {
- transform: TYPE.auto,
- alias: 'i'
- },
- output: {
- transform: TYPE.auto,
- alias: 'o'
- },
- version: {
- transform: TYPE.boolean,
- alias: 'v'
- },
- help: {
- transform: TYPE.boolean,
- alias: 'h'
- },
- force: {
- transform: TYPE.boolean,
- alias: 'f'
- },
- add: {
- transform: TYPE.boolean,
- alias: 'a'
- },
- remove: {
- transform: TYPE.boolean,
- alias: 'r'
- }
- }, options)
- for (let name in options) {
- let option = options[name]
- let optionName = camelize(name)
- if (option == null || option === false) continue
- let aliases = []
- if (option === true) {
- this.transforms[optionName] = (v) => v
- } else if (typeof option === 'function') {
- this.transforms[optionName] = option
- } else {
- if (option.alias) aliases.push(option.alias)
- if (option.aliases) aliases.push(...option.aliases)
- this.transforms[optionName] = option.transform
- if (option.append) this.appends[optionName] = option.append
- }
- for (let alias of aliases) this.aliases[alias] = optionName
- }
- // check for aliases recursion
- for (let alias in this.aliases) {
- let value = this.aliases[alias]
- if (this.aliases[value] === alias) {
- let message = `recursive alias ${alias} > ${value}, ${value} > ${alias}`
- throw new Error(message)
- }
- }
- }
- parse (argv) {
- const args = []
- const opts = {}
- const aliases = this.aliases
- let prev = false
- // recursively resolve aliases
- const alias = function (key) {
- while (aliases[key]) key = aliases[key]
- return key
- }
- const setOpt = (key, value) => {
- let transform = this.transforms[key] || this.transforms['--*']
- if (!transform) return
- let list
- if (this.appends[key]) list = opts[key] || (opts[key] = [])
- value = transform(value)
- if (value == null) return
- if (list) {
- list.push(value)
- return true // special return true for successful append
- } else {
- opts[key] = value
- }
- }
- const setPrev = (value) => {
- if (prev) {
- let isList = setOpt(prev, value)
- if (!isList) prev = false
- }
- }
- for (let arg of argv) {
- const match = arg.match(OPTION_REGEXP)
- // IS NOT "--(no-)option"
- if (!match) {
- const match = arg.match(FLAG_REGEXP)
- // IS "-o"
- if (match) {
- setPrev(true)
- for (let f of match[1].split('')) setOpt(alias(f), true)
- // IS "value"
- } else {
- const transform = this.transforms['*']
- // set value for the previous waiting option
- if (prev) setPrev(arg)
- // otherwise push the value to the current list (def: args)
- else args.push(transform ? transform(arg) : arg)
- }
- // IS "--(no-)option"
- } else {
- // set true if last one was waiting
- setPrev(true)
- const tag = match[1]
- const option = alias(camelize(match[2]))
- // const ls = match[3]
- // IS "--no-option"
- if (tag === 'no') {
- setOpt(option, 'no')
- } else {
- // wait for value
- prev = option
- }
- }
- }
- // set true if last one was waiting
- setPrev(true)
- return { args, opts }
- }
- }
- function camelize (string) {
- return string.replace(CAMEL_REGEXP, (full, match) => match.toUpperCase())
- }
- function boolean (string) {
- if (/^(no|n|false)$/.test(string)) return false
- if (/^(yes|y|true)$/.test(string)) return true
- }
- function number (string) {
- let m = FLOAT_REGEXP.test(string)
- if (m) return parseFloat(string)
- }
- function auto (arg) {
- let value = boolean(arg)
- if (value == null) value = number(arg)
- if (value == null) value = arg
- return value
- }
- function value (arg) {
- if (typeof arg !== 'string') return
- let value = number(arg)
- if (value == null) value = arg
- return value
- }
- function clint (...args) {
- return new Clint(...args)
- }
- clint.parse = function () {
- return new Clint().parse(...arguments)
- }
- clint.TYPE = TYPE
- clint.Clint = Clint
- module.exports = clint
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement