diff options
author | John Ankarström <john@ankarstrom.se> | 2021-06-07 01:13:31 +0200 |
---|---|---|
committer | John Ankarström <john@ankarstrom.se> | 2021-06-07 01:13:41 +0200 |
commit | 10c638d1824950d80df52a691b562d772d6e25e2 (patch) | |
tree | 1e1c80329f7ed6a9b46b806484f1e014dedb27ff | |
parent | e3e38fab30514c3922b630ea1cb884fcc1e78e29 (diff) | |
download | dwim-10c638d1824950d80df52a691b562d772d6e25e2.tar.gz |
stuff
-rwxr-xr-x | dwim | 146 | ||||
-rw-r--r-- | dwim.1 | 102 |
2 files changed, 138 insertions, 110 deletions
@@ -5,71 +5,79 @@ use v5.24; use warnings; use strict; -use Path::ExpandTilde; use subs qw/path env handle fail run arguments/; -my ($phrase, %o) = arguments "usage: $0 parse\n", 1, d => 0; -$phrase = `xsel -o` if not defined $phrase; +my ($DEBUG, $handler, $phrase); -my @OPENER = ("xtopen"); -my @EDITOR = (@OPENER, "vi"); -my @PDF_VIEWER = ("xpdf"); -my @MAN_VIEWER = (@OPENER, "man"); -my @MAILER = (@OPENER, "mutt"); -my @BROWSER = (@OPENER, "w3m -title"); -my @FILE_BROWSER = (@OPENER, "noice"); -my @MAILDIR_VIEWER = (@OPENER, "mutt -f"); -my $MAILROOT = env MAILROOT => "/home/john/mail/"; +while ($_ = shift @ARGV) { + if (/^-d$/) { + $DEBUG = 1; + } elsif (/^-/) { + die "usage: $0 [-d] [phrase]\n"; + } else { + $phrase = $_; + } +} + +$phrase = `xsel -o` if not defined $phrase; -our $handler; +my @OPENER = ('xtopen'); +my @EDITOR = (@OPENER, 'vi'); +my @PDF_VIEWER = ('xpdf'); +my @MAN_VIEWER = (@OPENER, 'man'); +my @MAILER = (@OPENER, 'mutt'); +my @BROWSER = (@OPENER, 'w3m -title'); +my @FILE_BROWSER = (@OPENER, 'noice'); +my @MAILDIR_VIEWER = (@OPENER, 'mutt -f'); +my $MAILROOT = env MAILROOT => '/home/john/mail/'; for ($phrase) { if (/^(https?:\/?\/?\S+)$/) { - handle "web address"; - run @BROWSER, "$1" + handle 'web address'; + run @BROWSER, $1 } if (/^(mailto:\S+)$/ or /^(\S+@.+\.\w+)$/) { - handle "e-mail address"; - run @MAILER, "$1" + handle 'e-mail address'; + run @MAILER, $1 } if (/^(.+?):(\d+).*?$/) { - handle "file:line (like grep -n)"; + handle 'file:line (like grep -n)'; my $p = path $1; - run @EDITOR, "+$2", "$p" + run @EDITOR, "+$2", $p } if (/^(.+) line (\d+)\.?$/) { - handle "FILE line LINE (like perl)"; + handle 'FILE line LINE (like perl)'; my $p = path $1; - run @EDITOR, "+$2", "$p" + run @EDITOR, "+$2", $p } if (/^(.+):(.+)$/) { - handle "file:query (like grep)"; + handle 'file:query (like grep)'; my $p = path $1; - run @EDITOR, "+/$2", "$p" if -e $p; - fail "file not found" if $o{d}; + run @EDITOR, "+/$2", $p if -e $p; + fail 'file not found' if $DEBUG; # otherwise fall through } - if (/^(\S+)\((\S+)\)[,.]?/) { - handle "manpage(section)"; + if (/^(\S+)\((\d+)\)[):,.]*$/) { + handle 'manual(section)'; run @MAN_VIEWER, $2, $1; } - if (/^(\S+)\.([1-9])/) { - handle "manpage.section"; + if (/^([A-Za-z]+)\.([1-9])$/) { + handle 'manual.section'; my $p = path "$1.$2"; run @MAN_VIEWER, $p if -e $p; run @MAN_VIEWER, $2, $1; } if (/^<(\S+)>$/) { - handle "<header.h>"; + handle '<header.h>'; open my $h, 'find / -maxdepth 3 -type d -name include 2>&-|' - or fail "could not search include directories"; + or fail 'could not search include directories'; while (<$h>) { chomp; if (-e "$_/$1") { @@ -78,22 +86,17 @@ for ($phrase) { } } close $h; - fail "header file not found"; - } - - if (/^(\S+-[\d.]+_\d+)$/) { - handle "xbps package"; - run @OPENER, "in-shell", "sudo", "xbps-install", "-S", $1; + fail 'header file not found'; } if (/^(\S+)$/) { - handle "maildir / directory / file"; + handle 'maildir / directory / file'; my $p = path $1; - run @MAILDIR_VIEWER, "$p" if $p =~ /^$MAILROOT/; # maildir - run @FILE_BROWSER, "$p" if -d $p; # directory - run @PDF_VIEWER, "$p" if -e $p and $p =~ /\.pdf$/; # pdf - run @EDITOR, "$p" if -e $p; # file - fail "file not found" if $o{d}; + run @MAILDIR_VIEWER, $p if $p =~ /^$MAILROOT/; # maildir + run @FILE_BROWSER, $p if -d $p; # directory + run @PDF_VIEWER, $p if -e $p and $p =~ /\.pdf$/; # pdf + run @EDITOR, $p if -e $p; # file + fail 'file not found' if $DEBUG; # otherwise fall through } @@ -103,16 +106,19 @@ for ($phrase) { sub path { my $n = shift; - $n = expand_tilde($n); + $n =~ s,^~([^/]+),/home/$1,; + $n =~ s,^~,/home/$ENV{USER},; return $n if $n =~ /^\// or $n =~ /^~/; - my $d = `xtitle`; - chomp $d; - $d =~ s/.*\(([^(]+)\)$/$1/; - $d =~ s,^~([^/]+),/home/$1,; - $d =~ s,^~,/home/$ENV{USER},; - die "couldn't retrieve current directory\n" - if ! -d $d and ! -d ($d = dirname($d)); - return "$d/$n"; + for (`xtitle`) { + chomp; + s/.*\(([^(]+)\)$/$1/; + s,^~([^/]+),/home/$1,; + s,^~,/home/$ENV{USER},; + die "couldn't retrieve current directory\n" + if ! -d $_ and ! -d ($_ = dirname($_)); + return "$_/$n"; + } + die "couldn't retrieve current directory: xtitle not installed\n"; } # take K => V and return environment variable K if defined, otherwise V @@ -125,7 +131,7 @@ sub env { sub handle { $handler = shift; - print STDERR "$handler MATCHED\n" if $o{d}; + print STDERR "$handler MATCHED\n" if $DEBUG; } sub fail { @@ -134,12 +140,13 @@ sub fail { } sub run { - if ($o{d}) { + if ($DEBUG) { my @argv = @_; s/(\s)/\\$1/g for @argv; # escape whitespace print STDERR "@argv\n"; } - exec @_; + system "@_ &"; + exit; } sub dirname { @@ -147,34 +154,3 @@ sub dirname { $path =~ s,/[^/]+,,; return $path; } - -# 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; -} @@ -3,49 +3,101 @@ .Os .Sh NAME .Nm dwim -.Nd do what i mean with a given phrase (file, URL etc.) +.Nd do what I mean with a given phrase (file, URL etc.) . .Sh SYNOPSIS .Nm dwim -.Ar phrase +.Op Fl d +.Op Ar phrase . .Sh DESCRIPTION +.Pp .Nm dwim is a program similar to Plan 9's plumber. It takes a string .Ar ( phrase ) and matches it against a number of regular expressions, which are connected to handlers, specifying what to do with the phrase. -. +.Pp +If no +.Ar phrase +is given, the current X selection is retrieved from +.Xr xsel 1 . +This is surprisingly useful. +If you assign a shortcut key to invoke +.Nm dwim +in your window manager, +you can select a string of text, +press the shortcut key and +.Nm +will act on the selected text. +.Pp +If the +.Li xtitle +program is installed on the system, +.Nm +will try to figure out the current working directory +from the window title. +The following title formats are recognized: +.Bl -enum -offset indent -compact +.It +.Em path +.It +.Em program +.Em ( path ) +.El +.Pp +Tilde expansion is supported. .Sh EXAMPLES .Ss Without X selection Open -.Li message-window.lisp -on line 164 -in -.Li $EDITOR : -. +.Em Makefile +in the configured text editor: .Bd -literal -$ grep 'def.*indicator ' *.lisp -message-window.lisp:164:(defun show-frame-indicator (group &optional force) -$ dwim message-window.lisp:164 +$ ls +LICENSE Makefile README.md repl repl.1 repl.c +$ dwim Makefile .Ed -. .Ss With X selection -Open -.Li Makefile -in -.Li $EDITOR : -. +.Pp +If we represent the current X selection with bold text, +the following procedure opens +.Em message-window.lisp +on line 164 +in the configured text editor: .Bd -literal -$ ls -LICENSE Makefile README.md repl repl.1 repl.c -# (select Makefile) +$ grep -n 'def.*indicator ' *.lisp +\f(CBmessage-window.lisp:164:(defun\fP show-frame-indicator (group &optional force) $ dwim .Ed -. -.Sh EXTENDING -It is a simple Perl script that is easily extensible. -.Sh AUTHOR +.Sh CONFIGURATION +.Nm +is configured by editing the source code. +It is a simple Perl script, +which uses regular expressions to parse phrases. +Default programs are defined at the top of the script. +The following associations are defined by default: +.Bl -tag -width 18n -offset indent -compact +.It OPENER +.Li xtopen +(change this to +.Li xterm -e +or equivalent) +.It EDITOR +.Li OPENER vi +.It PDF_VIEWER +.Li xpdf +.It MAN_VIEWER +.Li OPENER man +.It MAILER +.Li OPENER mutt +.It BROWSER +.Li OPENER w3m -title +.It FILE_BROWSER +.Li OPENER noice +.It MAILDIR_VIEWER +.Li OPENER mutt -f +.El +.Sh AUTHORS .An -nosplit -.An John Ankarström Aq Mt john@ankarstrom.se +.An John Ankarström Aq Mt "john (at) ankarstrom.se" |