/req

gawk und dmenu powered plumberlike

Primary LanguageAwkMIT LicenseMIT

= req - a gawk and dmenu powered plumberlike =

[...plumber?] I seem to remember thinking that it was sort of awk inspired
(Aharon Robbins on comp.lang.awk)

Rob Pike's paper[1] does a good job at explaining what plumber does.
With req you further get a scripting language for rules, a menu api,
and lots of examples to get you started.

req homepage:
https://github.com/robert-figura/req

[1] "Plumbing and Other Utilities", Rob Pike
http://doc.cat-v.org/plan_9/4th_edition/papers/plumb


= SYNOPSIS =

  req [-OPTIONS...] DATA

  -p          port (-a port=<port>)
  -f          triggering application (-a from=<client>)
  -menu       always display menu
  -select     select from menu, -select <number>
  -d          print menu and exit (-menu -a menu_type=print)
  -a          assign attribute, -a <name>=<value>
  -A          assign attribute, -A <name> <value>
  -m          import header file, -m <file>
  -e|--       rest of commandline is a single data record
  -alias      alias mode (-a format=alias)
  -stdin      read from stdin, ignore rest of commandline
  -file       read files, -file <file1>...
  -rfile      reverse read files, -rfile <file1>...
  -percent    substitute e.g. %ctx.xwin in data
  -t|-test    don't run but print command (-a run_hook=print)
  -v          be verbose
  -V|-version show version
  -h|-help    display this usage info


= SHOW CASES =

Usually you'd bind a hotkey to run req on clipboard contents. Or set
up applications to let those run req, e.g. your filemanager to run req
on the currently selected file. In the following you see the
commandline interface in action:

  # note: -t shows the command instead of executing it

  # mimetype based file launcher
  $ mv trivium1.pdf z.doc
  $ req -t z.doc
  xpdf -cont -z width '/home/rfigura/z.doc'
  # note that it isn't fooled by the "wrong" file name extension

  # it's an url launcher, too
  $ req -t http://localhost/
  surf -n 'http://localhost/'

  # for some urls scripting is turned off:
  $ req -t http://w3c.org/
  surf -p -s 'http://w3c.org/'

  # some urls get downloaded:
  $ req -t http://localhost/test.pdf
  [...]
  curl -f -J -L -O -b '/home/rfigura/.surf/cookies.txt' 'http://localhost/test.pdf'
  # sorry, i lied. the actual -t facilities can't yet _show_ the above,
  # because of a download wrapper. But it works, and you get the idea

If there is no "auto" action it'll open a menu. You can also
explicitly request a choice using the -menu switch. In the following
i'll use -d, to get the menu printed to the console instead. The
asterisk "*" indicates that the auto flag is set, allowing to launch
those when interaction isn't requested.

  # -d dumps the menu and quits

  # search & translate
  $ req -d foobar
  1 - google.com
  2 - translate
  3 - en.wikipedia.org
  [...]

  # calculator, i do enter formulas in dmenu, or find them on the web
  $ req -d '37864 / 3600'
  1 - * bc
  2 - * pari/gp
  3 - * gnuplot
  [...]

  # it knows about various date formats, too
  $ req -t '21. Nov 2011'
  1 - cal


= EXAMPLE CODE =

Your rules should go to port.*.awk files. It can be as simple as the
following two-liner suggests:

  # a temporary rule i'd put in port.open.awk...
  get("file.mimetype") ~ /^video\// && tolower(get("file.name")) ~ /simon.templar/ {
      export("mplayer_args", "-vf crop=526:400:98:4 ")
  }

  # ...so simon templar gets cropped properly in mplayer
  $ req -t simon-templar-12726.mp4
  mplayer -quiet -vf crop=526:400:98:4 '/home/rfigura/simon-templar-12726.mp4'

In case you want to add new data types, or new patterns for existing
data types, you should add code to some class*.awk. Look, req can be a
powerful front-end for unix commands:

  # a minimalistic process manager:
  # class.awk:
  match($0, /^([0-9]+)$/, m) {
      set("decimal", "" (0 + m[1]))
  }
  (d = get("decimal")) &&
  (c = readFile("/proc/" decimal "/cmdline")) {
      set("pid", d)
  }
  # port.open.awk:
  get("pid") {
      label("SIGTERM"); menu("kill -TERM " Q(get("pid")))
  }

Using req with other scripting languages. There are many ways to do
this. Here's an easy one to think of, others are more fun to look at:

  # open tk's colorpicker, allowing it to run without choice
  # port.open.awk:
  func wish(script) {
       return "echo " Q(script) " | wish"
  }
  match($0, /^(#[0-9a-fA-F]{6,6})/, m) {
      c =   "wm withdraw .\n"
      c = c "puts [tk_chooseColor -parent . -initialcolor \"" m[1] "\" -title \"Tk color picker\"]\n"
      c = c "exit\n"
      label("colorpicker"); run(wish(c))
  }

You can call internal functions instead of shell scripts and read all
remaining data when that happens to be the user's choice:

  func mysql(s) {
      s = collapse(s)
      # todo: is that hinting at a problem in req?:
      s = gensub(/\n/, " ", "g", s)
      runHook(pager("mysql test -e " Q(s)))
  }
  /^(SELECT|INSERT|UPDATE|DELETE)/ {
      label("mysql"); menu("@mysql " $0)
  }

Suggestion: If you have a comfy working ruleset do `git commit` to back
it up!

Suggestion: Read the source. First try some src/port.*.awk files,
maybe start here:
https://github.com/robert-figura/req/blob/master/src/port.open.awk

Suggestion: Grep the source for menu labels, commands, or namespace
elements.


= INSTALL =

  $ git clone https://github.com/robert-figura/req ~/.req
  $ cd ~/.req
  # test it:
  $ ./req -d foobar
  # copy front-end to someplace in your path:
  $ cp req ~/bin

You could stop here.

  ### build exec.so
  $ cp config.mk.sample config.mk
  # fetch or locate awk extension header, edit config.mk:
  $ make
  # edit src/main.head.awk, change the default for run_hook:
  #   defAttr("run_hook", "exec")

  ### xterm colorization
  $ alias xterm='req -p xterm -alias'

  ### bash completion
  $ complete -o default -C 'req -p bash-completion -alias' -D

  ### hotkey daemon
  $ ~/.req/bin/xbindkeys-hotkeyd.sh &

  ### hook req into environment variables
  $ export BROWSER='req -p dispatch -f BROWSER'
  # same for EDITOR, TERMINAL, ...

  ### replace xdg_open by req (or req -menu)

  ### set up your filemanager to let req open all files

  ...


== Dependencies ==

- gawk >= 4.1:
  http://www.gnu.org/software/gawk/gawk.html
- bash:
  http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html

== Other suggested software ==

- file (file type recognition)
  http://www.darwinsys.com/file/
- dmenu (fast x11 menu)
  http://suckless.org/dmenu
- xclip (x11 clipboard support)
  http://xclip.sourceforge.net/
- xprop (x11 window context detection)
  http://xorg.freedesktop.org/wiki
- xbindkeys (for hotkey daemon)
  http://hocwp.free.fr/xbindkeys/xbindkeys.html
- xterm (auto-set xterm background examples)
  http://invisible-island.net/xterm
- gawkapi.h headers, gnu make, and some c compiler (for exec.so support)
  http://www.gnu.org/software/gawk/gawk.html
- less (the default pager)
  http://www.greenwoodsoftware.com/less
- dwm (fast tiling windowmanager)
  http://suckless.org/dwm
- surf (minimalist browser)
  http://surf.suckless.org/
- git (to back up your rules)
  http://git-scm.com/