diff options
author | John <john@ankarstrom.se> | 2019-06-03 01:55:05 +0200 |
---|---|---|
committer | John <john@ankarstrom.se> | 2019-06-03 01:55:05 +0200 |
commit | 22d1803698b05203d2c4e5c0884a0572f5768c86 (patch) | |
tree | 688fc1b9358ca9b91cb9646c6ea30de3abbd87ad | |
parent | 351153eae7a319a25ef1365279257f7019b733cf (diff) | |
download | dwim-22d1803698b05203d2c4e5c0884a0572f5768c86.tar.gz |
argument support (-d for debug)
To facilitate debugging, I've reified the handler descriptions, which
were comments previously. Now, they've been made strings passed to
the `handle` subroutine, which sets `$handler`, which then (in case of
-d) can be read by `fail`, which notifies the user that a handler has
failed.
-rwxr-xr-x | dwim.pl | 106 |
1 files changed, 76 insertions, 30 deletions
@@ -6,66 +6,112 @@ use v5.24; use warnings; use strict; use Path::ExpandTilde; +use subs qw/path env handle fail arguments/; -die "usage: $0 phrase\n" if scalar @ARGV > 1; -my $p; -$p = $ARGV[0] if defined $ARGV[0]; -$p = `xsel -o` if not defined $ARGV[0]; +my ($phrase, %o) = arguments "usage: $0 parse\n", 1, d => 0; +$phrase = `xsel -o` if not defined $phrase; -my $OPENER = env (OPENER => "u"); -my $EDITOR = env (EDITOR => "vi"); -my $MAILER = env (MAILER => "mutt"); -my $MAILROOT = env (MAILROOT => "/home/john/mail/"); +my @LAUNCHER = split /\s/, env(OPENER => "urxvtc -e"); +my @EDITOR = split /\s/, env(EDITOR => "vi"); +my @MAILER = split /\s/, env(MAILER => "mutt"); +my @MAILDIR_VIEWER = split /\s/, env(MAILDIR_VIEWER => "mutt -f"); +my $MAILROOT = env(MAILROOT => "/home/john/mail/"); -for ($p) { - # web address +our $handler; + +for ($phrase) { if (/^(https?:\/\/.+)$/) { + handle "web address"; exec "firefox", "$1" } - # e-mail address if (/^(mailto:\/\/.+)$/ or /^(.+@.+\.\w+)$/) { - exec $MAILER, "$1" + handle "e-mail address"; + exec @MAILER, "$1" } - # file:line if (/^(.+):(\d+)(:.*?)?$/) { - my $f = path($1); - exec $OPENER, $EDITOR, "-c", ":$2", "$f" + handle "file:line"; + my $p = path($1); + exec @LAUNCHER, @EDITOR, "-c", ":$2", "$p" } - # file:query (if file exists) if (/^(.+):(.+)$/) { - my $f = path($1); - exec $OPENER, $EDITOR, "-c", "/$2", "$f" if -e $f; + handle "file:query (like grep)"; + my $p = path($1); + exec @LAUNCHER, @EDITOR, "-c", "/$2", "$p" if -e $p; + fail "file not found" if $o{d}; # otherwise fall through } - # maildir (if it matches) or file (if it exists) if (/^([^\s]+)$/) { - my $f = path($1); - exec $OPENER, $MAILER, "-f", "$f" if $f =~ /^$MAILROOT/; # maildir - exec $OPENER, $EDITOR, "$f" if -e $f; #file + handle "maildir / directory / file"; + my $p = path($1); + exec @LAUNCHER, @MAILDIR_VIEWER, "$p" if $p =~ /^$MAILROOT/; # maildir + exec @LAUNCHER, @EDITOR, "$p" if -e $p; #file + fail "file not found" if $o{d}; # otherwise fall through } # otherwise - die "no handler matched by: $p\n" + die "no handler matched by: $phrase\n" } sub path { - my $f = shift; - $f = expand_tilde($f); - return $f if $f =~ /^\// or $f =~ /^~/; - my $t = `xtitle`; - chomp $t; - die "couldn't retrieve directory\n" if ! -d $t and ! -d ($t = dirname $t); - return "$t/$f"; + my $n = shift; + $n = expand_tilde($n); + return $n if $n =~ /^\// or $n =~ /^~/; + my $d = `xtitle`; + chomp $d; + die "couldn't retrieve current directory\n" if ! -d $d and ! -d ($d = dirname $d); + return "$d/$n"; } +# take K => V and return environment variable K if defined, otherwise V sub env { my %h = @_; my $k = (keys %h)[0]; return $ENV{$k} if defined ${ENV}{$k}; return $h{$k}; } + +sub handle { + $handler = shift; + print STDERR "$handler MATCHED\n" if $o{d}; +} + +sub fail { + my $msg = shift; + print STDERR "$handler FAILED: $msg\n"; +} + +# parse ARGV and return list of positionals and hash of option values +sub arguments { + my $usage = shift; # usage string + my $n = shift; # number of positional arguments + my %options = @_; # option specification + + # parse options (end upon --) + + while ($_ = shift @ARGV) { + last if /^--$/; + unshift @ARGV, $_ and last if not /^-/; + + s/^-//; + if (defined $options{$_}) { $options{$_} = 1 } + else { die $usage; } + } + + # fill @positionals with $n strings (with undef upon empty ARGV) + + my @positionals; + my $i = 0; + while (++$i <= $n) { + if ($_ = shift @ARGV) { push @positionals, $_ } + else { push @positionals, undef } + } + + die $usage if @ARGV; # all processing should be done + + return @positionals, %options; +} |