Skip to content

Commit d0f7bd4

Browse files
committed
Implement "limit-last" mode for multipleOptions
We're flipping the order of the arguments array before and after running through it in order to retroactively inject stuff into result.argv. This is a SERIOUSLY suboptimal approach, but because I don't predict that the "limit-last" option will be used that often, a sloppy approach is better than blowing days of effort over a "clean" approach.
1 parent 995efb1 commit d0f7bd4

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

index.js

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -219,19 +219,14 @@ function getOpts(input, optdef, config){
219219
break;
220220
}
221221

222-
/** Use the first option; treat any following duplicates as items of argv */
223-
case "limit-first":{
222+
/** Use the first/last options; treat any following/preceding duplicates as argv items respectively */
223+
case "limit-first":
224+
case "limit-last":{
224225
let values = Array.isArray(value) ? value : [value];
225226
result.argv.push(option.prevMatchedName, ...values);
226227
break;
227228
}
228229

229-
/** Use only the last option; treat any preceding duplicates as items of argv */
230-
case "limit-last":{
231-
232-
break;
233-
}
234-
235230

236231
/** Chuck a hissy-fit if that's what the author wants */
237232
case "error":{
@@ -322,6 +317,26 @@ function getOpts(input, optdef, config){
322317
};
323318

324319

320+
/** Reverses the argument order of the given array, keeping options and their parameter lists intact */
321+
let flip = function(input){
322+
input = input.reverse();
323+
324+
/** Flip any options back into the right order */
325+
for(let i = 0, l = input.length; i < l; ++i){
326+
let arg = input[i];
327+
let opt = shortNames[arg] || longNames[arg];
328+
329+
if(opt){
330+
let from = Math.max(0, i - opt.arity);
331+
let to = i + 1;
332+
let extract = input.slice(from, to).reverse();
333+
input.splice(from, extract.length, ...extract);
334+
}
335+
}
336+
337+
return input;
338+
};
339+
325340

326341
/** Tackle bundling: make sure there's at least one option with a short name to work with */
327342
let nameKeys = Object.keys(shortNames);
@@ -379,6 +394,11 @@ function getOpts(input, optdef, config){
379394
}
380395

381396

397+
/** If we're handling duplicate options with "limit-last", flip the input order */
398+
if("limit-last" === multipleOptions)
399+
input = flip(input);
400+
401+
382402
/** Start processing the arguments we were given to handle */
383403
for(let i = 0, l = input.length; i < l; ++i){
384404
let arg = input[i];
@@ -428,6 +448,11 @@ function getOpts(input, optdef, config){
428448
/** Ended abruptly? */
429449
if(currentOption) wrapItUp();
430450

451+
452+
/** Check if we need to flip the returned .argv array back into the right order again */
453+
if("limit-last" === multipleOptions)
454+
result.argv = flip(result.argv);
455+
431456
return result;
432457
}
433458

test/tests.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,17 @@
7474
}
7575
},
7676

77+
{
78+
"name": "Duplicate-option handling: limit-last",
79+
"input": "alpha --set-size 640 480 beta --set-size 800 600 gamma --set-size 1024 768",
80+
"config": {"noAliasPropagation": "first-only", "multipleOptions": "limit-last"},
81+
"optdef": {"-s, --set-size": "<width=\\d+> <height=\\d+>"},
82+
"expected": {
83+
"options": {"setSize": ["1024", "768"]},
84+
"argv": ["alpha", "--set-size", "640", "480", "beta", "--set-size", "800", "600", "gamma"]
85+
}
86+
},
87+
7788
{
7889
"name": "Duplicate-option handling: error",
7990
"input": "--arg 1 alpha --arg 2",

0 commit comments

Comments
 (0)