args-tokens 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Argument token Kind
3
+ * - `option`: option token, support short option (e.g. `-x`) and long option (e.g. `--foo`)
4
+ * - `option-terminator`: option terminator (`--`) token, see guideline 10 in https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
5
+ * - `positional`: positional token
6
+ */
7
+ export type ArgTokenKind = 'option' | 'option-terminator' | 'positional';
8
+ /**
9
+ * Argument token
10
+ */
11
+ export interface ArgToken {
12
+ /**
13
+ * Argument token kind
14
+ */
15
+ kind: ArgTokenKind;
16
+ /**
17
+ * Argument token index, e.g `--foo bar` => `--foo` index is 0, `bar` index is 1
18
+ */
19
+ index: number;
20
+ /**
21
+ * Option name, e.g. `--foo` => `foo`, `-x` => `x`
22
+ */
23
+ name?: string;
24
+ /**
25
+ * Raw option name, e.g. `--foo` => `--foo`, `-x` => `-x`
26
+ */
27
+ rawName?: string;
28
+ /**
29
+ * Option value, e.g. `--foo=bar` => `bar`, `-x=bar` => `bar`.
30
+ * If the `allowCompatible` option is `true`, short option value will be same as Node.js `parseArgs` behavior.
31
+ */
32
+ value?: string;
33
+ /**
34
+ * Inline value, e.g. `--foo=bar` => `true`, `-x=bar` => `true`.
35
+ */
36
+ inlineValue?: boolean;
37
+ }
38
+ /**
39
+ * Parse Options
40
+ */
41
+ export interface ParseOptions {
42
+ /**
43
+ * [Node.js parseArgs](https://nodejs.org/api/util.html#parseargs-tokens) tokens compatible mode
44
+ * @default false
45
+ */
46
+ allowCompatible?: boolean;
47
+ }
48
+ /**
49
+ * Parse command line arguments
50
+ * @example
51
+ * ```js
52
+ * import { parseArgs } from 'args-tokens' // for Node.js and Bun
53
+ * // import { parseArgs } from 'jsr:@kazupon/args-tokens' // for Deno
54
+ *
55
+ * const tokens = parseArgs(['--foo', 'bar', '-x', '--bar=baz'])
56
+ * // do something with using tokens
57
+ * // ...
58
+ * console.log('tokens:', tokens)
59
+ * ```
60
+ * @param args command line arguments
61
+ * @param options parse options
62
+ * @returns argument tokens
63
+ */
64
+ export declare function parseArgs(args: string[], options?: ParseOptions): ArgToken[];
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: MIT
3
+ // Modifier: kazuya kawaguchi (a.k.a. kazupon)
4
+ // Forked from `nodejs/node` (`pkgjs/parseargs`)
5
+ // Repository url: https://github.com/nodejs/node (https://github.com/pkgjs/parseargs)
6
+ // Author: Node.js contributors
7
+ // Code url: https://github.com/nodejs/node/blob/main/lib/internal/util/parse_args/parse_args.js
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.parseArgs = parseArgs;
10
+ const HYPHEN_CHAR = '-';
11
+ const HYPHEN_CODE = HYPHEN_CHAR.codePointAt(0);
12
+ const EQUAL_CHAR = '=';
13
+ const EQUAL_CODE = EQUAL_CHAR.codePointAt(0);
14
+ const TERMINATOR = '--';
15
+ const SHORT_OPTION_PREFIX = HYPHEN_CHAR;
16
+ const LONG_OPTION_PREFIX = '--';
17
+ /**
18
+ * Parse command line arguments
19
+ * @example
20
+ * ```js
21
+ * import { parseArgs } from 'args-tokens' // for Node.js and Bun
22
+ * // import { parseArgs } from 'jsr:@kazupon/args-tokens' // for Deno
23
+ *
24
+ * const tokens = parseArgs(['--foo', 'bar', '-x', '--bar=baz'])
25
+ * // do something with using tokens
26
+ * // ...
27
+ * console.log('tokens:', tokens)
28
+ * ```
29
+ * @param args command line arguments
30
+ * @param options parse options
31
+ * @returns argument tokens
32
+ */
33
+ function parseArgs(args, options = {}) {
34
+ const { allowCompatible = false } = options;
35
+ const tokens = [];
36
+ const remainings = [...args];
37
+ let index = -1;
38
+ let groupCount = 0;
39
+ let hasShortValueSeparator = false;
40
+ while (remainings.length > 0) {
41
+ const arg = remainings.shift();
42
+ if (arg == undefined) {
43
+ break;
44
+ }
45
+ const nextArg = remainings[0];
46
+ if (groupCount > 0) {
47
+ groupCount--;
48
+ }
49
+ else {
50
+ index++;
51
+ }
52
+ // check if `arg` is an options terminator.
53
+ // guideline 10 in https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
54
+ if (arg === TERMINATOR) {
55
+ tokens.push({
56
+ kind: 'option-terminator',
57
+ index
58
+ });
59
+ const mapped = remainings.map(arg => {
60
+ return { kind: 'positional', index: ++index, value: arg };
61
+ });
62
+ tokens.push(...mapped);
63
+ break;
64
+ }
65
+ if (isShortOption(arg)) {
66
+ const shortOption = arg.charAt(1);
67
+ let value;
68
+ let inlineValue;
69
+ if (groupCount) {
70
+ // e.g. `-abc`
71
+ tokens.push({
72
+ kind: 'option',
73
+ name: shortOption,
74
+ rawName: arg,
75
+ index,
76
+ value,
77
+ inlineValue
78
+ });
79
+ if (groupCount === 1 && hasOptionValue(nextArg)) {
80
+ value = remainings.shift();
81
+ if (hasShortValueSeparator) {
82
+ inlineValue = true;
83
+ hasShortValueSeparator = false;
84
+ }
85
+ tokens.push({
86
+ kind: 'option',
87
+ index,
88
+ value,
89
+ inlineValue
90
+ });
91
+ }
92
+ }
93
+ else {
94
+ // e.g. `-a`
95
+ tokens.push({
96
+ kind: 'option',
97
+ name: shortOption,
98
+ rawName: arg,
99
+ index,
100
+ value,
101
+ inlineValue
102
+ });
103
+ }
104
+ // eslint-disable-next-line unicorn/no-null
105
+ if (value != null) {
106
+ ++index;
107
+ }
108
+ continue;
109
+ }
110
+ if (isShortOptionGroup(arg)) {
111
+ // expend short option group (e.g. `-abc` => `-a -b -c`, `-f=bar` => `-f bar`)
112
+ const expanded = [];
113
+ let shortValue = '';
114
+ for (let i = 1; i < arg.length; i++) {
115
+ const shortableOption = arg.charAt(i);
116
+ if (hasShortValueSeparator) {
117
+ shortValue += shortableOption;
118
+ }
119
+ else {
120
+ if (!allowCompatible && shortableOption.codePointAt(0) === EQUAL_CODE) {
121
+ hasShortValueSeparator = true;
122
+ }
123
+ else {
124
+ expanded.push(`${SHORT_OPTION_PREFIX}${shortableOption}`);
125
+ }
126
+ }
127
+ }
128
+ if (shortValue) {
129
+ expanded.push(shortValue);
130
+ }
131
+ remainings.unshift(...expanded);
132
+ groupCount = expanded.length;
133
+ continue;
134
+ }
135
+ if (isLongOption(arg)) {
136
+ // e.g. `--foo`
137
+ const longOption = arg.slice(2);
138
+ tokens.push({
139
+ kind: 'option',
140
+ name: longOption,
141
+ rawName: arg,
142
+ index,
143
+ value: undefined,
144
+ inlineValue: undefined
145
+ });
146
+ continue;
147
+ }
148
+ if (isLongOptionAndValue(arg)) {
149
+ // e.g. `--foo=bar`
150
+ const equalIndex = arg.indexOf(EQUAL_CHAR);
151
+ const longOption = arg.slice(2, equalIndex);
152
+ const value = arg.slice(equalIndex + 1);
153
+ tokens.push({
154
+ kind: 'option',
155
+ name: longOption,
156
+ rawName: `${LONG_OPTION_PREFIX}${longOption}`,
157
+ index,
158
+ value,
159
+ inlineValue: true
160
+ });
161
+ continue;
162
+ }
163
+ tokens.push({
164
+ kind: 'positional',
165
+ index,
166
+ value: arg
167
+ });
168
+ }
169
+ return tokens;
170
+ }
171
+ /**
172
+ * Check if `arg` is a short option (e.g. `-f`)
173
+ * @param arg the argument to check
174
+ * @returns whether `arg` is a short option
175
+ */
176
+ function isShortOption(arg) {
177
+ return (arg.length === 2 && arg.codePointAt(0) === HYPHEN_CODE && arg.codePointAt(1) !== HYPHEN_CODE);
178
+ }
179
+ /**
180
+ * Check if `arg` is a short option group (e.g. `-abc`)
181
+ * @param arg the argument to check
182
+ * @returns whether `arg` is a short option group
183
+ */
184
+ function isShortOptionGroup(arg) {
185
+ if (arg.length <= 2) {
186
+ return false;
187
+ }
188
+ if (arg.codePointAt(0) !== HYPHEN_CODE) {
189
+ return false;
190
+ }
191
+ if (arg.codePointAt(1) === HYPHEN_CODE) {
192
+ return false;
193
+ }
194
+ return true;
195
+ }
196
+ /**
197
+ * Check if `arg` is a long option (e.g. `--foo`)
198
+ * @param arg the argument to check
199
+ * @returns whether `arg` is a long option
200
+ */
201
+ function isLongOption(arg) {
202
+ return hasLongOptionPrefix(arg) && !arg.includes(EQUAL_CHAR, 3);
203
+ }
204
+ /**
205
+ * Check if `arg` is a long option with value (e.g. `--foo=bar`)
206
+ * @param arg the argument to check
207
+ * @returns whether `arg` is a long option
208
+ */
209
+ function isLongOptionAndValue(arg) {
210
+ return hasLongOptionPrefix(arg) && arg.includes(EQUAL_CHAR, 3);
211
+ }
212
+ /**
213
+ * Check if `arg` is a long option prefix (e.g. `--`)
214
+ * @param arg the argument to check
215
+ * @returns whether `arg` is a long option prefix
216
+ */
217
+ function hasLongOptionPrefix(arg) {
218
+ return arg.length > 2 && ~arg.indexOf(LONG_OPTION_PREFIX);
219
+ }
220
+ /**
221
+ * Check if a `value` is an option value
222
+ * @param value a value to check
223
+ * @returns whether a `value` is an option value
224
+ */
225
+ function hasOptionValue(value) {
226
+ // eslint-disable-next-line unicorn/no-null
227
+ return !(value == null) && value.codePointAt(0) !== HYPHEN_CODE;
228
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Argument token Kind
3
+ * - `option`: option token, support short option (e.g. `-x`) and long option (e.g. `--foo`)
4
+ * - `option-terminator`: option terminator (`--`) token, see guideline 10 in https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
5
+ * - `positional`: positional token
6
+ */
7
+ export type ArgTokenKind = 'option' | 'option-terminator' | 'positional';
8
+ /**
9
+ * Argument token
10
+ */
11
+ export interface ArgToken {
12
+ /**
13
+ * Argument token kind
14
+ */
15
+ kind: ArgTokenKind;
16
+ /**
17
+ * Argument token index, e.g `--foo bar` => `--foo` index is 0, `bar` index is 1
18
+ */
19
+ index: number;
20
+ /**
21
+ * Option name, e.g. `--foo` => `foo`, `-x` => `x`
22
+ */
23
+ name?: string;
24
+ /**
25
+ * Raw option name, e.g. `--foo` => `--foo`, `-x` => `-x`
26
+ */
27
+ rawName?: string;
28
+ /**
29
+ * Option value, e.g. `--foo=bar` => `bar`, `-x=bar` => `bar`.
30
+ * If the `allowCompatible` option is `true`, short option value will be same as Node.js `parseArgs` behavior.
31
+ */
32
+ value?: string;
33
+ /**
34
+ * Inline value, e.g. `--foo=bar` => `true`, `-x=bar` => `true`.
35
+ */
36
+ inlineValue?: boolean;
37
+ }
38
+ /**
39
+ * Parse Options
40
+ */
41
+ export interface ParseOptions {
42
+ /**
43
+ * [Node.js parseArgs](https://nodejs.org/api/util.html#parseargs-tokens) tokens compatible mode
44
+ * @default false
45
+ */
46
+ allowCompatible?: boolean;
47
+ }
48
+ /**
49
+ * Parse command line arguments
50
+ * @example
51
+ * ```js
52
+ * import { parseArgs } from 'args-tokens' // for Node.js and Bun
53
+ * // import { parseArgs } from 'jsr:@kazupon/args-tokens' // for Deno
54
+ *
55
+ * const tokens = parseArgs(['--foo', 'bar', '-x', '--bar=baz'])
56
+ * // do something with using tokens
57
+ * // ...
58
+ * console.log('tokens:', tokens)
59
+ * ```
60
+ * @param args command line arguments
61
+ * @param options parse options
62
+ * @returns argument tokens
63
+ */
64
+ export declare function parseArgs(args: string[], options?: ParseOptions): ArgToken[];
@@ -0,0 +1,225 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Modifier: kazuya kawaguchi (a.k.a. kazupon)
3
+ // Forked from `nodejs/node` (`pkgjs/parseargs`)
4
+ // Repository url: https://github.com/nodejs/node (https://github.com/pkgjs/parseargs)
5
+ // Author: Node.js contributors
6
+ // Code url: https://github.com/nodejs/node/blob/main/lib/internal/util/parse_args/parse_args.js
7
+ const HYPHEN_CHAR = '-';
8
+ const HYPHEN_CODE = HYPHEN_CHAR.codePointAt(0);
9
+ const EQUAL_CHAR = '=';
10
+ const EQUAL_CODE = EQUAL_CHAR.codePointAt(0);
11
+ const TERMINATOR = '--';
12
+ const SHORT_OPTION_PREFIX = HYPHEN_CHAR;
13
+ const LONG_OPTION_PREFIX = '--';
14
+ /**
15
+ * Parse command line arguments
16
+ * @example
17
+ * ```js
18
+ * import { parseArgs } from 'args-tokens' // for Node.js and Bun
19
+ * // import { parseArgs } from 'jsr:@kazupon/args-tokens' // for Deno
20
+ *
21
+ * const tokens = parseArgs(['--foo', 'bar', '-x', '--bar=baz'])
22
+ * // do something with using tokens
23
+ * // ...
24
+ * console.log('tokens:', tokens)
25
+ * ```
26
+ * @param args command line arguments
27
+ * @param options parse options
28
+ * @returns argument tokens
29
+ */
30
+ export function parseArgs(args, options = {}) {
31
+ const { allowCompatible = false } = options;
32
+ const tokens = [];
33
+ const remainings = [...args];
34
+ let index = -1;
35
+ let groupCount = 0;
36
+ let hasShortValueSeparator = false;
37
+ while (remainings.length > 0) {
38
+ const arg = remainings.shift();
39
+ if (arg == undefined) {
40
+ break;
41
+ }
42
+ const nextArg = remainings[0];
43
+ if (groupCount > 0) {
44
+ groupCount--;
45
+ }
46
+ else {
47
+ index++;
48
+ }
49
+ // check if `arg` is an options terminator.
50
+ // guideline 10 in https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
51
+ if (arg === TERMINATOR) {
52
+ tokens.push({
53
+ kind: 'option-terminator',
54
+ index
55
+ });
56
+ const mapped = remainings.map(arg => {
57
+ return { kind: 'positional', index: ++index, value: arg };
58
+ });
59
+ tokens.push(...mapped);
60
+ break;
61
+ }
62
+ if (isShortOption(arg)) {
63
+ const shortOption = arg.charAt(1);
64
+ let value;
65
+ let inlineValue;
66
+ if (groupCount) {
67
+ // e.g. `-abc`
68
+ tokens.push({
69
+ kind: 'option',
70
+ name: shortOption,
71
+ rawName: arg,
72
+ index,
73
+ value,
74
+ inlineValue
75
+ });
76
+ if (groupCount === 1 && hasOptionValue(nextArg)) {
77
+ value = remainings.shift();
78
+ if (hasShortValueSeparator) {
79
+ inlineValue = true;
80
+ hasShortValueSeparator = false;
81
+ }
82
+ tokens.push({
83
+ kind: 'option',
84
+ index,
85
+ value,
86
+ inlineValue
87
+ });
88
+ }
89
+ }
90
+ else {
91
+ // e.g. `-a`
92
+ tokens.push({
93
+ kind: 'option',
94
+ name: shortOption,
95
+ rawName: arg,
96
+ index,
97
+ value,
98
+ inlineValue
99
+ });
100
+ }
101
+ // eslint-disable-next-line unicorn/no-null
102
+ if (value != null) {
103
+ ++index;
104
+ }
105
+ continue;
106
+ }
107
+ if (isShortOptionGroup(arg)) {
108
+ // expend short option group (e.g. `-abc` => `-a -b -c`, `-f=bar` => `-f bar`)
109
+ const expanded = [];
110
+ let shortValue = '';
111
+ for (let i = 1; i < arg.length; i++) {
112
+ const shortableOption = arg.charAt(i);
113
+ if (hasShortValueSeparator) {
114
+ shortValue += shortableOption;
115
+ }
116
+ else {
117
+ if (!allowCompatible && shortableOption.codePointAt(0) === EQUAL_CODE) {
118
+ hasShortValueSeparator = true;
119
+ }
120
+ else {
121
+ expanded.push(`${SHORT_OPTION_PREFIX}${shortableOption}`);
122
+ }
123
+ }
124
+ }
125
+ if (shortValue) {
126
+ expanded.push(shortValue);
127
+ }
128
+ remainings.unshift(...expanded);
129
+ groupCount = expanded.length;
130
+ continue;
131
+ }
132
+ if (isLongOption(arg)) {
133
+ // e.g. `--foo`
134
+ const longOption = arg.slice(2);
135
+ tokens.push({
136
+ kind: 'option',
137
+ name: longOption,
138
+ rawName: arg,
139
+ index,
140
+ value: undefined,
141
+ inlineValue: undefined
142
+ });
143
+ continue;
144
+ }
145
+ if (isLongOptionAndValue(arg)) {
146
+ // e.g. `--foo=bar`
147
+ const equalIndex = arg.indexOf(EQUAL_CHAR);
148
+ const longOption = arg.slice(2, equalIndex);
149
+ const value = arg.slice(equalIndex + 1);
150
+ tokens.push({
151
+ kind: 'option',
152
+ name: longOption,
153
+ rawName: `${LONG_OPTION_PREFIX}${longOption}`,
154
+ index,
155
+ value,
156
+ inlineValue: true
157
+ });
158
+ continue;
159
+ }
160
+ tokens.push({
161
+ kind: 'positional',
162
+ index,
163
+ value: arg
164
+ });
165
+ }
166
+ return tokens;
167
+ }
168
+ /**
169
+ * Check if `arg` is a short option (e.g. `-f`)
170
+ * @param arg the argument to check
171
+ * @returns whether `arg` is a short option
172
+ */
173
+ function isShortOption(arg) {
174
+ return (arg.length === 2 && arg.codePointAt(0) === HYPHEN_CODE && arg.codePointAt(1) !== HYPHEN_CODE);
175
+ }
176
+ /**
177
+ * Check if `arg` is a short option group (e.g. `-abc`)
178
+ * @param arg the argument to check
179
+ * @returns whether `arg` is a short option group
180
+ */
181
+ function isShortOptionGroup(arg) {
182
+ if (arg.length <= 2) {
183
+ return false;
184
+ }
185
+ if (arg.codePointAt(0) !== HYPHEN_CODE) {
186
+ return false;
187
+ }
188
+ if (arg.codePointAt(1) === HYPHEN_CODE) {
189
+ return false;
190
+ }
191
+ return true;
192
+ }
193
+ /**
194
+ * Check if `arg` is a long option (e.g. `--foo`)
195
+ * @param arg the argument to check
196
+ * @returns whether `arg` is a long option
197
+ */
198
+ function isLongOption(arg) {
199
+ return hasLongOptionPrefix(arg) && !arg.includes(EQUAL_CHAR, 3);
200
+ }
201
+ /**
202
+ * Check if `arg` is a long option with value (e.g. `--foo=bar`)
203
+ * @param arg the argument to check
204
+ * @returns whether `arg` is a long option
205
+ */
206
+ function isLongOptionAndValue(arg) {
207
+ return hasLongOptionPrefix(arg) && arg.includes(EQUAL_CHAR, 3);
208
+ }
209
+ /**
210
+ * Check if `arg` is a long option prefix (e.g. `--`)
211
+ * @param arg the argument to check
212
+ * @returns whether `arg` is a long option prefix
213
+ */
214
+ function hasLongOptionPrefix(arg) {
215
+ return arg.length > 2 && ~arg.indexOf(LONG_OPTION_PREFIX);
216
+ }
217
+ /**
218
+ * Check if a `value` is an option value
219
+ * @param value a value to check
220
+ * @returns whether a `value` is an option value
221
+ */
222
+ function hasOptionValue(value) {
223
+ // eslint-disable-next-line unicorn/no-null
224
+ return !(value == null) && value.codePointAt(0) !== HYPHEN_CODE;
225
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "args-tokens",
3
3
  "description": "parseArgs tokens compatibility and more high-performance parser",
4
- "version": "0.2.3",
4
+ "version": "0.2.5",
5
5
  "author": {
6
6
  "name": "kazuya kawaguchi",
7
7
  "email": "kawakazu80@gmail.com"