qwgit / lib / args.js
http{/,s} git server
git clone http://git.nthia.dev/qwgit

module.exports = function argparse(list, opts) {
  if (!opts) opts = {}
  let booleans = opts.boolean ?? {}
  let args = []
  let argv = new Map
  let stop = false
  for (var i = 0; i < list.length; i++) {
    let m, a = list[i]
    if (stop) {
      args.push(a)
    } if (a === '--') {
      stop = true
    } else if (m = /^-([^-]+)$/.exec(a)) {
      let flags = m[1].split('')
      let v = ''
      for (var j = 0; j < flags.length-1; j++) {
        if (flags[j+1] === '=') {
          set(argv, booleans, flags[j], flags.slice(j+2).join(''))
          v = null
          break
        }
        set(argv, booleans, flags[j], '')
      }
      if (v !== null && !/^-/.test(list[i+1]) && !has(booleans, m[1])) {
        v = list[i+1] ?? ''
        i++
      }
      if (v !== null) set(argv, booleans, flags[j], v)
    } else if (m = /^--?([^=]+)=(.*)$/.exec(a)) {
      set(argv, booleans, m[1], m[2])
    } else if ((m = /^--?([^=]+)$/.exec(a)) && !/^-/.test(list[i+1])) {
      if (has(booleans, m[1])) {
        set(argv, booleans, m[1], list[i+1] ?? '')
      } else {
        set(argv, booleans, m[1], list[i+1] ?? '')
        i++
      }
    } else if (m = /^--?([^=]+)$/.exec(a)) {
      set(argv, booleans, m[1], '')
    } else {
      args.push(a)
    }
  }
  return [args,argv]
}

function has(x, key) {
  if (typeof x.has === 'function') return x.has(key)
  else if (Array.isArray(x)) return x.includes(key)
  else return false
}

function parseBool(x) {
  if (x === 'true') return true
  if (x === 'false') return false
  if (x === '') return true
  return false
}

function set(argv, booleans, k, v) {
  if (has(booleans,k)) {
    argv.set(k, (argv.get(k) ?? []).concat(parseBool(v)))
  } else {
    argv.set(k, (argv.get(k) ?? []).concat(v === '' ? [] : v))
  }
}