Refactored the options parsing to be less bad. Now time to implement actual functionalitygit add .

This commit is contained in:
random 2025-01-20 04:41:08 -05:00
parent 99fc573b3c
commit f75fff9c98

View file

@ -1,137 +1,148 @@
#!/usr/bin/perl #!/usr/bin/perl
use strict; use strict;
use warnings; use warnings;
use Carp; use Carp;
#use HTML::Template; #use HTML::Template;
$SIG{__WARN__} = sub { die @_; }; $SIG{__WARN__} = sub { die @_; };
sub DisplayUsage my $PRG = $0;
{ $PRG =~ s!.*/!!;
my $options_ref = shift;
my @options = @$options_ref; #-----------------------------------------------------------------------
# Command line argument processing routines
print "Usage:\n"; #-----------------------------------------------------------------------
for my $opt (@options)
{ sub DisplayUsage
my $opt_str = " " . (defined $opt->{sopt} ? "-$opt->{sopt}, " : " "); {
$opt_str .= (defined $opt->{lopt} ? "--$opt->{lopt}" : ""); my $options_ref = shift;
my @options = @$options_ref;
if (lc $opt->{arg} eq "required")
{ print "Usage: $PRG [OPTIONS]\n";
$opt_str .= "=<value>"; for my $opt (@options)
} {
elsif (lc $opt->{arg} eq "optional") my $opt_str = " " . (defined $opt->{sopt} ? "-$opt->{sopt}, " : " ");
{ $opt_str .= (defined $opt->{lopt} ? "--$opt->{lopt}" : "");
$opt_str .= "[=<value>]";
} if (lc $opt->{arg} eq "required")
{
print $opt_str . "\n " . ($opt->{desc} // "") . "\n\n"; $opt_str .= "=<value>";
} }
elsif (lc $opt->{arg} eq "optional")
exit 0; {
} $opt_str .= "[=<value>]";
}
sub HandleArgs
{ print $opt_str . "\n " . ($opt->{desc} // "") . "\n\n";
my ($args_ref, $options_ref) = @_; }
my @args = @$args_ref; exit 0;
my @options = @$options_ref; }
for my $arg (@args) sub HandleArgs
{ {
if ($arg =~ m@^(-(?<sopts>\w{2,})|-(?<sopt>\w)|-+(?<lopt>[\w-]+))(=(?<optarg>.+))?\z@i) my ($args_ref, $options_ref) = @_;
{
my @soptlist; my @args = @$args_ref;
@soptlist = split //, $+{sopts} if defined $+{sopts}; my @options = @$options_ref;
my $optarg; for my $arg (@args)
my $handled = 1; {
if ($arg =~ m@^(-(?<sopts>\w{2,})|-(?<sopt>\w)|-+(?<lopt>[\w-]+))(=(?<optarg>.+))?\z@i)
DisplayUsage($options_ref) {
if ((defined $+{sopt} and $+{sopt} eq "h") or my @soptlist;
(defined $+{lopt} and $+{lopt} eq "help")); @soptlist = split //, $+{sopts} if defined $+{sopts};
@soptlist = do { my %sn; grep { !$sn{$_}++ } @soptlist };
for my $opt (@options)
{ my $optarg;
die "No option name to handle!"
unless defined $opt->{lopt} or defined $opt->{sopt}; DisplayUsage($options_ref)
if ((defined $+{sopt} and $+{sopt} eq "h") or
if (defined $opt->{sopt}) (defined $+{lopt} and $+{lopt} eq "help"));
{
if (grep { $_ eq $opt->{sopt} // () } @soptlist) for my $lsopt (@soptlist)
{ {
die "Option -$opt->{sopt} cannot be in a list as it requires an argument!\n" if (my @i = grep { $options[$_]->{sopt} eq $lsopt } 0..$#options)
if $opt->{arg} eq "required"; {
die "Option -$lsopt cannot be in a list as it requires an argument!\n"
$opt->{handler}(); if $options[$i[0]]->{arg} eq "required";
}
# will make these look better later $options[$i[0]]->{handler}();
elsif (defined $+{sopt} and defined $+{sopt} }
and $+{sopt} eq $opt->{sopt}) else { warn "Unknown option -$lsopt!\n"; }
{ }
$optarg = $+{optarg} // ();
$opt->{handler}($optarg); for my $k (qw(sopt lopt))
} {
} next if !defined $+{$k};
my $h = $k eq "lopt" ? '--':'-';
if (defined $opt->{lopt} and defined $+{lopt}
and $+{lopt} eq $opt->{lopt}) if (my @j = grep { $options[$_]->{$k} eq $+{$k} } 0..$#options)
{ {
$optarg = $+{optarg} // (); $optarg = $+{optarg} // ();
$opt->{handler}($optarg);
} die "Option $h$+{$k} requires an argument!\n"
} if !defined $optarg and $options[$j[0]]->{arg} eq "required";
die "Unrecognized option: $arg\n" $options[$j[0]]->{handler}($optarg);
unless $handled; }
} else { warn "Unknown option $h$+{$k}!\n"; }
} }
} }
}
sub HandleConf }
{
my $filename = shift; # TODO: Perhaps add precedence for different options.
print "Loading configuration from: $filename\n"; # For example, if you pass -pb to the program, you probably want to
} # build before publishing.
my @optArray = ( sub HandleConf
{ {
lopt => "config", my $filename = shift // "none";
sopt => "c", print "Loading configuration from: $filename\n";
desc => "Loads a custom config file at a specified path.", }
arg => "required",
handler => \&HandleConf #-----------------------------------------------------------------------
}, # Main routine
{ #-----------------------------------------------------------------------
lopt => "new-post",
sopt => "n", my @optArray = (
desc => "Create a new post.", {
arg => "none", lopt => "config",
handler => sub { print "do something\n"; } sopt => "c",
}, desc => "Loads a custom config file at a specified path.",
{ arg => "required",
lopt => "build", handler => \&HandleConf
sopt => "b", },
desc => "Build all posts and templates into HTML.", {
arg => "optional", lopt => "new-post",
handler => sub { print "do something\n"; } sopt => "n",
}, desc => "Create a new post.",
{ arg => "none",
lopt => "publish", handler => sub { print "do something\n"; }
sopt => "p", },
desc => "Publish built files.", {
arg => "none", lopt => "build",
handler => sub { print "do something\n"; } sopt => "b",
}, desc => "Build all posts and templates into HTML.",
); arg => "optional",
handler => sub { print "do something\n"; }
sub Main },
{ {
HandleArgs(\@ARGV, \@optArray); lopt => "publish",
} sopt => "p",
desc => "Publish built files.",
&Main(); arg => "none",
exit 0; handler => sub { print "do something\n"; }
},
);
sub Main
{
DisplayUsage(\@optArray) if (!@ARGV);
HandleArgs(\@ARGV, \@optArray);
}
&Main();
exit 0;