Comparing version 1.0.1 to 1.1.0
@@ -0,1 +1,11 @@ | ||
# 1.1 | ||
- Cosmetic changes to help output | ||
- `implies` support | ||
- `valid` option value lists | ||
# 1.0 | ||
Multi-section parsing, environment variables | ||
# 0.1 | ||
@@ -2,0 +12,0 @@ |
95
index.js
'use strict' | ||
// XXX required options? or just attach a usage() method on result? | ||
// XXX Also aliases don't have defaults and shouldn't show up in the | ||
// results, so they feel like maybe a different kind of thing? | ||
const assert = require('assert') | ||
@@ -86,2 +81,4 @@ const cliui = require('cliui') | ||
const winWidth = process && process.stdout && process.stdout.columns || 80 | ||
const ui = cliui() | ||
@@ -97,6 +94,23 @@ | ||
let maxWidth = 0 | ||
let maxMax = 26 | ||
let maxWidth = 8 | ||
let prev = null | ||
j.help.forEach(row => { | ||
if (row.left) | ||
maxWidth = Math.min(30, Math.max(row.left.length + 4, maxWidth)) | ||
// find the max width of left-hand sides, and decide whether or not | ||
// to skip a line based on the length of the next option | ||
if (row.left) { | ||
if (row.text.length > winWidth - maxMax) { | ||
if (prev) | ||
prev.skipLine = true | ||
row.skipLine = true | ||
} | ||
prev = row | ||
const len = row.left.length + 4 | ||
if (len > maxWidth && len < maxMax) | ||
maxWidth = len | ||
} else { | ||
if (prev) | ||
prev.skipLine = true | ||
prev = null | ||
} | ||
}) | ||
@@ -106,8 +120,22 @@ | ||
if (row.left) { | ||
ui.div({ | ||
text: row.left, | ||
padding: [0, 2, 0, 2], | ||
width: maxWidth, | ||
}, { text: row.text }) | ||
ui.div() | ||
// If the row is too long, don't wrap it | ||
// Bump the right-hand side down a line to make room | ||
if (row.left.length >= maxWidth - 2) { | ||
ui.div({ | ||
text: row.left, | ||
padding: [ 0, 0, 0, 2 ] | ||
}) | ||
ui.div({ | ||
text: row.text, | ||
padding: [ 0, 0, 0, maxWidth ] | ||
}) | ||
} else { | ||
ui.div({ | ||
text: row.left, | ||
padding: [0, 1, 0, 2], | ||
width: maxWidth, | ||
}, { text: row.text }) | ||
} | ||
if (row.skipLine) | ||
ui.div() | ||
} else | ||
@@ -157,2 +185,4 @@ ui.div(row) | ||
const buildParser = (j, sections) => { | ||
let inHeader = true | ||
sections.forEach(section => { | ||
@@ -186,2 +216,3 @@ if (Array.isArray(section)) | ||
'description must be string') | ||
inHeader = false | ||
j.help.push({ | ||
@@ -195,3 +226,6 @@ text: trim(`${section.description}:`), | ||
typeof section.help === 'string' || assert(false, 'help must be a string') | ||
j.help.push({ text: trim(section.help) + '\n' }) | ||
j.help.push({ | ||
text: trim(section.help) + '\n', | ||
padding: inHeader ? null : [ 0, 0, 0, 2 ] | ||
}) | ||
} | ||
@@ -206,2 +240,3 @@ | ||
for (let n = 0; n < names.length; n++) { | ||
inHeader = false | ||
const name = names[n] | ||
@@ -361,10 +396,11 @@ const val = section[name] | ||
const hint = val.hint || name | ||
const shortEq = val.short && val.short.length > 1 ? '=' : '' | ||
const short = val.short ? ( | ||
isFlag(val) ? `, -${val.short}` | ||
: `, -${val.short}<${hint}>` | ||
isFlag(val) ? `-${val.short} ` | ||
: `-${val.short}${shortEq}<${hint}> ` | ||
) : '' | ||
const left = isEnv(val) ? name | ||
: isFlag(val) ? `--${name}${short}` | ||
: `--${name}=<${hint}>${short}` | ||
: isFlag(val) ? `${short}--${name}` | ||
: `${short}--${name}=<${hint}>` | ||
@@ -418,2 +454,15 @@ j.help.push({ text, left }) | ||
const wrap = (text, padding) => { | ||
const ui = cliui() | ||
ui.div({ text, padding }) | ||
return ui.toString() | ||
} | ||
const assertValid = (val, key, spec) => | ||
!isOpt(spec) || !spec.valid || | ||
spec.valid.indexOf(val) !== -1 || assert(false, | ||
`Invalid value ${val} provided for ${key}. | ||
Must be one of: | ||
${wrap(spec.valid.join(' '), [ 0, 2, 0, 8 ])}`) | ||
const parse_ = j => { | ||
@@ -499,2 +548,4 @@ const argv = getArgv(j) | ||
assertValid(val, key, spec) | ||
if (isList(spec)) { | ||
@@ -514,2 +565,8 @@ if (isOpt(spec)) { | ||
} | ||
if (spec.implies) { | ||
for (let i in spec.implies) { | ||
j.result[i] = spec.implies[i] | ||
} | ||
} | ||
} | ||
@@ -516,0 +573,0 @@ |
{ | ||
"name": "jackspeak", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "A very strict and proper argument parser.", | ||
"main": "index.js", | ||
"scripts": { | ||
"snap": "TAP_SNAPSHOT=1 tap test/*.js", | ||
"build-examples": "for i in examples/*.js ; do node $i -h > ${i/.js/.txt}; done", | ||
"snap": "TAP_SNAPSHOT=1 tap test/*.js && npm run build-examples", | ||
"test": "tap test/*.js --100", | ||
@@ -39,3 +40,6 @@ "preversion": "npm test", | ||
], | ||
"author": "Isaac Z. Schlueter <i@izs.me>" | ||
"author": "Isaac Z. Schlueter <i@izs.me>", | ||
"engines": { | ||
"node": ">=8" | ||
} | ||
} |
@@ -66,2 +66,7 @@ # jackspeak | ||
- `implies` - JavaScript object of values to set in the result | ||
objet when this flag or option is encountered in the arguments. | ||
This can be used to have one flag enable another by default, for | ||
example. | ||
The types are: | ||
@@ -104,2 +109,5 @@ | ||
- `valid` - An array of valid values. If the user provides a | ||
value outside this set, it will throw an error. | ||
- `alias` - A string or array of options that this option | ||
@@ -106,0 +114,0 @@ expands to when used. This works the same as flag aliases, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
28524
488
376