Skip to content

Commit

Permalink
Added the 'excluded_short_opts' field to the FromConfig for Commands
Browse files Browse the repository at this point in the history
- Added the `excluded_short_opts` field to Command's `FromConfig` to make it easier for library users to exclude certain Short Options when parsing converting from Zig Types.
  • Loading branch information
00JCIV00 committed Sep 17, 2024
1 parent 6f0372d commit a871c56
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 6 deletions.
3 changes: 2 additions & 1 deletion examples/covademo.zig
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ pub const DemoStruct = struct{
pub const InnerStruct = struct{
in_bool: bool = false,
in_float: f32 = 0,
h_string: []const u8 = "Just a test for fields starting with 'h'",
};
pub const InnerEnum = enum(u2){
red,
Expand Down Expand Up @@ -351,7 +352,7 @@ pub const setup_cmd: CommandT = .{
CommandT.from(DemoStruct, .{
.cmd_name = "struct-cmd",
.cmd_description = "A demo sub command made from a struct.",
.attempt_short_opts = false,
.attempt_short_opts = true,
//.cmd_hidden = true,
.cmd_group = "STRUCT-BASED",
.sub_cmds_mandatory = false,
Expand Down
37 changes: 32 additions & 5 deletions src/Command.zig
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,8 @@ pub fn Custom(comptime config: Config) type {
/// sequentially working through each next letter if the previous one has already been used.
/// (Note, user must deconflict for 'u' and 'h' if using auto-generated Usage/Help Options.)
attempt_short_opts: bool = true,
/// A list of Option Short Names to Exclude if attempting to create Short Options.
excluded_short_opts: []const u8 = &.{ 'u', 'h' },
/// Convert Fields with default values to Options instead of Values.
/// There's a corresponding field in the `ToConfig`.
default_val_opts: bool = false,
Expand Down Expand Up @@ -1051,7 +1053,12 @@ pub fn Custom(comptime config: Config) type {
.Optional => {
from_opts[opts_idx] = (OptionT.from(field, .{
.name = arg_name,
.short_name = if (from_config.attempt_short_opts) optShortName(arg_name, short_names, &short_idx) else null,
.short_name = if (from_config.attempt_short_opts) optShortName(
arg_name,
short_names,
&short_idx,
from_config.excluded_short_opts,
) else null,
.long_name = arg_name,
.ignore_incompatible = from_config.ignore_incompatible,
.opt_description = arg_description,
Expand All @@ -1063,7 +1070,12 @@ pub fn Custom(comptime config: Config) type {
if (from_config.default_val_opts and field.default_value != null) {
from_opts[opts_idx] = (OptionT.from(field, .{
.name = arg_name,
.short_name = if (from_config.attempt_short_opts) optShortName(arg_name, short_names, &short_idx) else null,
.short_name = if (from_config.attempt_short_opts) optShortName(
arg_name,
short_names,
&short_idx,
from_config.excluded_short_opts,
) else null,
.long_name = arg_name,
.ignore_incompatible = from_config.ignore_incompatible,
.opt_description = arg_description,
Expand All @@ -1086,7 +1098,12 @@ pub fn Custom(comptime config: Config) type {
.Optional => {
from_opts[opts_idx] = OptionT.from(field, .{
.name = arg_name,
.short_name = if (from_config.attempt_short_opts) optShortName(arg_name, short_names, &short_idx) else null,
.short_name = if (from_config.attempt_short_opts) optShortName(
arg_name,
short_names,
&short_idx,
from_config.excluded_short_opts,
) else null,
.long_name = arg_name,
.ignore_incompatible = from_config.ignore_incompatible,
.opt_description = arg_description
Expand Down Expand Up @@ -1140,12 +1157,22 @@ pub fn Custom(comptime config: Config) type {
};
}
/// Create a deconflicted Option short name from the provided `arg_name` and existing `short_names`.
fn optShortName(arg_name: []const u8, short_names: []u8, short_idx: *u8) ?u8 {
fn optShortName(
arg_name: []const u8,
short_names: []u8,
short_idx: *u8,
excluded_short_opts: []const u8,
) ?u8 {
return shortName: {
for (arg_name) |char| {
const ul_chars: [2]u8 = .{ toLower(char), toUpper(char) };
for (ul_chars) |ul| {
if (short_idx.* > 0 and utils.indexOfEql(u8, short_names[0..short_idx.*], ul) != null) continue;
if (
short_idx.* > 0 and (
utils.indexOfEql(u8, short_names[0..short_idx.*], ul) != null or
utils.indexOfEql(u8, excluded_short_opts[0..], ul) != null
)
) continue;
short_names[short_idx.*] = ul;
short_idx.* += 1;
break :shortName ul;
Expand Down

0 comments on commit a871c56

Please sign in to comment.