aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdwim.pl106
1 files changed, 76 insertions, 30 deletions
diff --git a/dwim.pl b/dwim.pl
index 6d2c445..de14ae5 100755
--- a/dwim.pl
+++ b/dwim.pl
@@ -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;
+}