Skip to content

Commit 4b1732f

Browse files
committed
toInclude, toEnd options. Prior to refactor
1 parent dd45fe9 commit 4b1732f

File tree

7 files changed

+290
-12
lines changed

7 files changed

+290
-12
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2014-24 Lloyd Brookes <[email protected]>
3+
Copyright (c) 2014-25 Lloyd Brookes <[email protected]>
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
# Rewrite in progress
2+
3+
Notes: https://3.basecamp.com/4457154/buckets/28765380/todos/5201126085

dist/index.cjs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,19 @@ var arrayBack = require('array-back');
1212
* - Find one or more items, return them, remove them from the input array
1313
*
1414
* arr {string[]} - Input array. Only mutated if `options.remove` is set.
15-
* [options.rtol] {boolean} - Enable right-to-left scans. Either that or pass in a custom iterator.
15+
* [options.rtol] {boolean} - Enable right-to-left scans. Either that or pass in a custom iterator. TODO.
1616
* [options.remove] {boolean} - Remove from source array
1717
* [options.inclusive] {boolean} - If `true` includes the to item.
18-
* [options.from] {function}
19-
* [options.to] {function}
18+
* [options.from] {string[]|function[]}
19+
* [options.to] {string[]|function[]} - A "Stop Here" function. Set one or more strings as the terminating arg. Or, from the function `fn(arg, index, argv, valueIndex)`, return true for the first arg that is out of range. Set `inclusive` to also include it.
20+
* [options.toInclude] {string[]|function[]} - From the function `fn(arg, index, argv, valueIndex)`, return true for the first arg that is out of range. Set `inclusive` to also include it.
2021
* [options.noFurtherThan] {function}
22+
* [options.toEnd] {boolean}
2123
* @returns string[]
2224
*/
2325
function fromTo (arr, options = {}) {
2426
let { from: fromFn, to: toFn, noFurtherThan, remove, inclusive, toEnd } = options;
27+
2528
if (inclusive === undefined && !noFurtherThan && toFn) {
2629
inclusive = true;
2730
}
@@ -33,9 +36,14 @@ function fromTo (arr, options = {}) {
3336
return fn
3437
}
3538
});
39+
40+
if (fromFn.length === 0) {
41+
throw new Error('from required')
42+
}
43+
3644
toFn = arrayBack(toFn).map(fn => {
3745
if (typeof fn === 'string') {
38-
return function (item, index, arr, valueIndex) { return item === fn }
46+
return function (item) { return item === fn }
3947
} else {
4048
return fn
4149
}

lib/from-to.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,19 @@ import arrayBack from 'array-back'
1010
* - Find one or more items, return them, remove them from the input array
1111
*
1212
* arr {string[]} - Input array. Only mutated if `options.remove` is set.
13-
* [options.rtol] {boolean} - Enable right-to-left scans. Either that or pass in a custom iterator.
13+
* [options.rtol] {boolean} - Enable right-to-left scans. Either that or pass in a custom iterator. TODO.
1414
* [options.remove] {boolean} - Remove from source array
1515
* [options.inclusive] {boolean} - If `true` includes the to item.
16-
* [options.from] {function}
17-
* [options.to] {function}
16+
* [options.from] {string[]|function[]}
17+
* [options.to] {string[]|function[]} - A "Stop Here" function. Set one or more strings as the terminating arg. Or, from the function `fn(arg, index, argv, valueIndex)`, return true for the first arg that is out of range. Set `inclusive` to also include it.
18+
* [options.toInclude] {string[]|function[]} - From the function `fn(arg, index, argv, valueIndex)`, return true for the first arg that is out of range. Set `inclusive` to also include it.
1819
* [options.noFurtherThan] {function}
20+
* [options.toEnd] {boolean}
1921
* @returns string[]
2022
*/
2123
function fromTo (arr, options = {}) {
2224
let { from: fromFn, to: toFn, noFurtherThan, remove, inclusive, toEnd } = options
25+
2326
if (inclusive === undefined && !noFurtherThan && toFn) {
2427
inclusive = true
2528
}
@@ -31,9 +34,14 @@ function fromTo (arr, options = {}) {
3134
return fn
3235
}
3336
})
37+
38+
if (fromFn.length === 0) {
39+
throw new Error('from required')
40+
}
41+
3442
toFn = arrayBack(toFn).map(fn => {
3543
if (typeof fn === 'string') {
36-
return function (item, index, arr, valueIndex) { return item === fn }
44+
return function (item) { return item === fn }
3745
} else {
3846
return fn
3947
}

package-lock.json

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/from-to-args.js

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
import { strict as a } from 'assert'
2+
import CommandLineArgs from 'command-line-args'
3+
import fromTo from 'command-line-args/fromTo'
4+
5+
const [test, only, skip] = [new Map(), new Map(), new Map()]
6+
7+
/* TODO: Rewrite this set of CLA tests to use from-to */
8+
/* Each element in optionDefinitions should be a from-to config set. The output of which can be cleaned and named separately, i.e. naming each result "file", "verbose" etc and fixing the type of each value. */
9+
10+
test.set('Input argv is not mutated', async function () {
11+
const argv = ['one', 'two', '--one', 'something', '--two']
12+
// const optionDefinitions = [
13+
// {
14+
// name: 'one',
15+
// from: arg => arg === '--one',
16+
// to: (valueIndex, arg) => valueIndex === 1 && !arg.startsWith('--'),
17+
// type: values => values[0]
18+
// }
19+
// ]
20+
// const cla = new CommandLineArgs(argv, optionDefinitions)
21+
// const result = cla.parse()
22+
// a.notEqual(cla.args, argv)
23+
// a.notEqual(cla.args.length, argv.length)
24+
25+
const result = fromTo(argv, {
26+
from: '--one',
27+
to: (arg, index, argv, valueIndex) => valueIndex > 1 || arg.startsWith('--'),
28+
remove: true
29+
})
30+
this.data = {argv, result}
31+
})
32+
33+
test.set('--option <no value>', async function () {
34+
const argv = ['one', 'two', '--one', '--two', 'three']
35+
// const optionDefinitions = [
36+
// {
37+
// name: 'one',
38+
// from: arg => arg === '--one',
39+
// to: (valueIndex, arg) => valueIndex === 1 && !arg.startsWith('--'),
40+
// type: values => values[0]
41+
// }
42+
// ]
43+
// const cla = new CommandLineArgs(argv, optionDefinitions)
44+
// const result = cla.parse()
45+
// // this.data = {result, cla}
46+
// a.deepEqual(result, { one: undefined })
47+
// a.deepEqual(cla.args, ['one', 'two', '--two'])
48+
49+
const result = fromTo(argv, {
50+
from: '--one',
51+
// to: console.log,
52+
to: (arg, index, argv, valueIndex) => {
53+
console.log(arg, index, valueIndex)
54+
return valueIndex === 1 && !arg.startsWith('--')
55+
},
56+
remove: true
57+
})
58+
this.data = { result, argv }
59+
})
60+
61+
skip.set('--option flag', async function () {
62+
const argv = ['one', 'two', '--one', '--two']
63+
const optionDefinitions = [
64+
{
65+
name: 'one',
66+
from: arg => arg === '--one',
67+
type: values => true
68+
}
69+
]
70+
const cla = new CommandLineArgs(argv, optionDefinitions)
71+
const result = cla.parse()
72+
a.deepEqual(result, { one: true })
73+
a.deepEqual(cla.args, ['one', 'two', '--two'])
74+
})
75+
76+
skip.set('--option flag not present', async function () {
77+
const argv = ['one', 'two', '--not-one', '--two']
78+
const optionDefinitions = [
79+
{
80+
name: 'one',
81+
from: arg => arg === '--one',
82+
type: values => true
83+
}
84+
]
85+
const cla = new CommandLineArgs(argv, optionDefinitions)
86+
const result = cla.parse()
87+
a.deepEqual(result, {})
88+
a.deepEqual(cla.args, ['one', 'two', '--not-one', '--two'])
89+
})
90+
91+
skip.set('--option <value>', async function () {
92+
const argv = ['one', 'two', '--one', 'something', '--two']
93+
const optionDefinitions = [
94+
{
95+
name: 'one',
96+
from: arg => arg === '--one',
97+
to: (valueIndex, arg) => valueIndex === 1 && !arg.startsWith('--'),
98+
type: values => values[0]
99+
}
100+
]
101+
const cla = new CommandLineArgs(argv, optionDefinitions)
102+
const result = cla.parse()
103+
a.deepEqual(result, { one: 'something' })
104+
a.deepEqual(cla.args, ['one', 'two', '--two'])
105+
})
106+
107+
skip.set('no name supplied: use the fromArg as the default', async function () {
108+
const argv = ['one', 'two', '--one', 'something', '--two']
109+
const optionDefinitions = [
110+
{
111+
from: arg => arg === '--one',
112+
to: (valueIndex, arg) => valueIndex === 1 && !arg.startsWith('--'),
113+
type: values => values[0]
114+
}
115+
]
116+
const cla = new CommandLineArgs(argv, optionDefinitions)
117+
const result = cla.parse()
118+
a.deepEqual(result, { '--one': 'something' })
119+
a.deepEqual(cla.args, ['one', 'two', '--two'])
120+
})
121+
122+
skip.set('Missing type: all args to the right of the fromArg returned', async function () {
123+
const argv = ['one', 'two', '--one', 'first', 'second', '--two']
124+
const optionDefinitions = [
125+
{
126+
from: arg => arg === '--one',
127+
to: (valueIndex, arg, index, argv) => argv[index + 1] && argv[index + 1].startsWith('--')
128+
}
129+
]
130+
const cla = new CommandLineArgs(argv, optionDefinitions)
131+
const result = cla.parse()
132+
a.deepEqual(result, { '--one': ['first', 'second'] })
133+
a.deepEqual(cla.args, ['one', 'two', '--two'])
134+
})
135+
136+
skip.set('name can be a function receiving the extraction matched by from and to', async function () {
137+
const argv = ['one', 'two', '--one', 'first', 'second', '--two']
138+
const optionDefinitions = [
139+
{
140+
from: arg => arg === '--one',
141+
to: (valueIndex, arg, index, argv) => argv[index + 1] && argv[index + 1].startsWith('--'),
142+
name: (extraction) => extraction.join('|')
143+
}
144+
]
145+
const cla = new CommandLineArgs(argv, optionDefinitions)
146+
const result = cla.parse()
147+
a.deepEqual(result, { '--one|first|second': ['first', 'second'] })
148+
})
149+
150+
skip.set('dynamic definition function receives fromArg', async function () {
151+
const argv = ['one', 'two', '--one', 'something', '--two']
152+
const optionDefinitions = [
153+
{
154+
from: arg => arg === '--one',
155+
def: fromArg => {
156+
a.equal(fromArg, '--one')
157+
return {
158+
to: (valueIndex, arg) => valueIndex === 1,
159+
name: 'one',
160+
type: values => values[0]
161+
}
162+
}
163+
}
164+
]
165+
const cla = new CommandLineArgs(argv, optionDefinitions)
166+
const result = cla.parse()
167+
a.deepEqual(result, { one: 'something' })
168+
a.deepEqual(cla.args, ['one', 'two', '--two'])
169+
})
170+
171+
skip.set('noFurtherThan', async function () {
172+
const argv = ['command1', 'arg', '--option', 'value', '--flag', 'command2', 'arg2']
173+
const commands = ['command1', 'command2']
174+
const optionDefinitions = [
175+
{
176+
from: arg => commands.includes(arg),
177+
noFurtherThan: (valueIndex, arg, index, argv) => commands.includes(arg)
178+
}
179+
]
180+
const cla = new CommandLineArgs(argv, optionDefinitions)
181+
const result = cla.parse()
182+
// this.data = result
183+
a.deepEqual(result, {
184+
command1: ['arg', '--option', 'value', '--flag'],
185+
command2: ['arg2']
186+
})
187+
})
188+
189+
skip.set('to not found: no args matched', async function () {
190+
const argv = ['command1', 'arg', '--option', 'value', '--flag']
191+
const optionDefinitions = [
192+
{
193+
from: arg => arg === 'command1',
194+
to: () => false
195+
}
196+
]
197+
const cla = new CommandLineArgs(argv, optionDefinitions)
198+
const result = cla.parse()
199+
// this.data = result
200+
a.deepEqual(result, {
201+
command1: []
202+
})
203+
})
204+
205+
skip.set('noFurtherThan not found: all args matched until the end', async function () {
206+
const argv = ['command1', 'arg', '--option', 'value', '--flag']
207+
const optionDefinitions = [
208+
{
209+
from: arg => arg === 'command1',
210+
noFurtherThan: () => false
211+
}
212+
]
213+
const cla = new CommandLineArgs(argv, optionDefinitions)
214+
const result = cla.parse()
215+
// this.data = result
216+
a.deepEqual(result, {
217+
command1: ['arg', '--option', 'value', '--flag']
218+
})
219+
})
220+
221+
export { test, only, skip }

test/from-to.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ skip.set('from second occurance', async function () {
7474
const arr = ['one', 'here', '--', '--', '--', 'here', '--', '--', '--', 'there']
7575
const result = fromTo(arr, {
7676
from: 'here',
77-
fromOccurance: 2,
77+
fromOccurance: 2, // DEPRECATED
7878
toEnd: true
7979
})
8080
a.deepEqual(result, ['here', '--', '--', '--', 'here', '--', '--', '--', 'there'])
@@ -91,14 +91,38 @@ test.set('flag', async function () {
9191
})
9292

9393
test.set('--option value', async function () {
94-
const arr = ['one', 'here', '--option', 'there']
94+
const arr = ['one', 'here', '--option', 'there', 'more']
9595
const result = fromTo(arr, {
9696
from: '--option',
97-
to: (val) => val.startsWith('--'),
97+
to: (val, i, a, valueIndex) => valueIndex > 1 || val.startsWith('--'),
9898
remove: true
9999
})
100100
a.deepEqual(result, ['--option', 'there'])
101+
a.deepEqual(arr, ['one', 'here', 'more'])
102+
})
103+
104+
/* TODO: GET RID of noFurtherThan and inclusive - too confusing to use and code. Stick with "stop here", "no further than here" behaviour which is not inclusive. (default behaviour used by array.slice) */
105+
only.set('--option value without remove', async function () {
106+
const arr = ['one', 'here', '--option', 'there', 'more']
107+
const result = fromTo(arr, {
108+
from: '--option',
109+
noFurtherThan: (val, i, a, valueIndex) => valueIndex > 1 || val.startsWith('--'),
110+
remove: false
111+
})
112+
a.deepEqual(result, ['--option', 'there'])
113+
a.deepEqual(arr, ['one', 'here', '--option', 'there', 'more'])
114+
})
115+
116+
test.set('--option value value ...', async function () {
117+
const arr = ['one', 'here', '--option', 'there', 'more']
118+
const result = fromTo(arr, {
119+
from: '--option',
120+
to: (val) => val.startsWith('--'),
121+
remove: true
122+
})
123+
a.deepEqual(result, ['--option', 'there', 'more'])
101124
a.deepEqual(arr, ['one', 'here'])
102125
})
103126

127+
104128
export { test, only, skip }

0 commit comments

Comments
 (0)