Skip to content

Commit

Permalink
feat(args): support num_args range
Browse files Browse the repository at this point in the history
  • Loading branch information
fu050409 committed Aug 2, 2024
1 parent ea089ab commit 599e07f
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 0 deletions.
13 changes: 13 additions & 0 deletions __test__/num_args.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import test from 'ava'
import { spawnSync } from 'child_process'

test('num_args', (t) => {
const result = spawnSync('node', [`examples/num_args.cjs`, '--foo', '1', '2', '3'])
const more_than = spawnSync('node', [`examples/num_args.cjs`, '--foo', '1', '2', '3', '4'])
const less_than = spawnSync('node', [`examples/num_args.cjs`, '--foo', '1'])
t.is(result.error, undefined)
t.is(result.stderr.length, 0)
t.deepEqual(result.status ?? 0, 0)
t.not(more_than.stderr.length, 0)
t.not(less_than.stderr.length, 0)
})
17 changes: 17 additions & 0 deletions examples/num_args.cts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Context, defineCommand, run } from '..'

const main = defineCommand({
meta: {
name: 'test',
},
options: {
foo: {
type: 'option',
numArgs: '2..=3',
required: true,
},
},
callback: (_: Context) => {},
})

run(main)
16 changes: 16 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@

/* auto-generated by NAPI-RS */

/**
* Define a command functionally
*
* @param options Command options
* @returns {Command}
*/
export declare function defineCommand(options: Command): Command
/**
* Run command
Expand Down Expand Up @@ -173,6 +179,16 @@ export interface CommandOption {
* just add `--color` to the command line to produce the desired color output.
*/
defaultMissing?: string
/**
* Limit the count of values for the argument
*
* If the expected number of parameters required is a fixed value, pass in the
* number directly. If you want to limit the number of values to a range, for
* example, pass `1..5` or `1..=4` to specify a range from 1 to 4 inclusive.
*/
numArgs?: string
/** Requires that options use the `--option=val` syntax */
requiredEquals?: boolean
/**
* Hide argument in help output
*
Expand Down
4 changes: 4 additions & 0 deletions src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ use crate::resolver::{resolve_command, resolve_option_args};
use crate::types::Command;
use crate::utils::parse_arguments;

/// Define a command functionally
///
/// @param options Command options
/// @returns {Command}
#[napi]
pub fn define_command(options: Command) -> Command {
options
Expand Down
48 changes: 48 additions & 0 deletions src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,47 @@ pub(crate) fn resolve_value_hint(value_hint: &str) -> clap::builder::ValueHint {
}
}

pub(crate) fn resolve_num_args(num_args: &str) -> clap::builder::ValueRange {
if let Ok(n) = num_args.parse::<usize>() {
return n.into();
}
let (start, end) = num_args.split_once("..").expect("Invalid num_args");
match (start, end) {
("", "") => (..).into(),
("", end) => {
if end.starts_with("=") {
let end: usize = end
.strip_prefix("=")
.unwrap()
.parse()
.expect("Invalid end of range");
(..=end).into()
} else {
let end: usize = end.parse().expect("Invalid end of range");
(..end).into()
}
}
(start, "") => {
let start: usize = start.parse().expect("Invalid start of range");
(start..).into()
}
(start, end) => {
let start: usize = start.parse().expect("Invalid start of range");
if end.starts_with("=") {
let end: usize = end
.strip_prefix("=")
.unwrap()
.parse()
.expect("Invalid end of range");
(start..=end).into()
} else {
let end: usize = end.parse().expect("Invalid end of range");
(start..end).into()
}
}
}
}

pub(crate) fn resolve_command_options(
clap: clap::Command,
meta: &HashMap<String, CommandOption>,
Expand Down Expand Up @@ -161,6 +202,13 @@ pub(crate) fn resolve_command_options(
if let Some(default_missing) = opt.default_missing {
arg = arg.default_missing_value(default_missing);
}
if let Some(num_args) = opt.num_args {
let num_args = resolve_num_args(num_args);
arg = arg.num_args(num_args);
}
if let Some(required_equals) = opt.required_equals {
arg = arg.require_equals(required_equals);
}
if let Some(hidden) = opt.hidden {
arg = arg.hide(hidden);
}
Expand Down
8 changes: 8 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ pub struct CommandOption {
/// a default, such as `default_missing_value("always")`, the user can quickly
/// just add `--color` to the command line to produce the desired color output.
pub default_missing: Option<&'static str>,
/// Limit the count of values for the argument
///
/// If the expected number of parameters required is a fixed value, pass in the
/// number directly. If you want to limit the number of values to a range, for
/// example, pass `1..5` or `1..=4` to specify a range from 1 to 4 inclusive.
pub num_args: Option<&'static str>,
/// Requires that options use the `--option=val` syntax
pub required_equals: Option<bool>,
/// Hide argument in help output
///
/// Do not display the argument in the help message.
Expand Down

0 comments on commit 599e07f

Please sign in to comment.