interface the web using zsh
This has been lingering on my laptop for some time now. For about a year,
actually. If you know surfraw, you know the idea.
If you don't, then imagine you'd like to search something via google real
quick from the command line like this:
lookup google that-thing-i-want-to-know-about
If you think, that's worth having, read on.
"This" is called `zsh-lookup', or `lookup' for short (or `lu' for really
short). It's implemented in zsh and does not share any code with surfraw.
It's licenced under the same terms as zsh is - which is BSD-ish.
Why reinvent the wheel if surfraw exists? Well, since lookup is written
in zsh and not in POSIX shell, it can take advantage of all those features zsh
has to offer. That means, really flexible configuration via `zstyle',
completion based on compsys - context sensitive correctly working for all
shipped backends - and, in my opinion, cleaner code because zsh knows about
arrays and associative arrays (read: hashes). Lookup also has support for
creating aliases for its backends (similar to git aliases); and completion for
those aliases just works. Out of the box.
Surfraw does support more web services than lookup does. A lot more. Something
like 100 vs. 20. I don't care for most of the services that lookup doesn't
implement - which is the reason they aren't implemented in the first place.
Feel free to implement new backends for lookup. The `LOOKUP_be_leo' file should
walk you through most of the questions that may arise during the process. Read
it beforehand. Really. If you'd like to look at a very simple backend, take a
look at the one for `cpan'. More complex backends would be `gmane' and `rfc'.
Now, after a year of using the thing, I'm pretty confident that it works well
enough. I am thinking about submitting it to zsh upstream for inclusion - if
the maintainers think that it's worth it.
For now, you can get the latest code from github:
git clone git://github.com/ft/zsh-lookup.git
To get it working you may use the `import_into_fpath.sh' script. After that you
need to load and initialise the system:
autoload -Uz lookupinit; lookupinit
The backends all document themselves, so if you'd like to know how the `gmane'
backend works, do:
lu -h gmane
Here's the documentation that would be available via "man zshcontrib" if lookup
ever gets included in zsh:
WORLD WIDE WEB SERVICES FOR ZSH
Loading this subsystem enables the user to access useful webservices
(such as google, gmane, wikipedia and many more) via the command line.
In order to load and initialize the system, you need a issue the fol
lowing command:
autoload -Uz lookupinit && lookupinit
After that, a function called lookup is available. Its basic syntax is
as follows:
lookup [GLOBAL-OPTION(s)...] <backend> OPTION(s)...
<backend> is a string describing the service that will be accessed.
Backends are self-documenting. To access a backends documentation, use
lookups -h global-option as described below.
-h [backend]
Print a help message.
If [backend] is defined, it will display the self-documentation
of the named backend.
-i (Re)initialize the lookup subsystem.
This is usually not required (unless you add new backends at
runtime).
-a <alias-definition>
Add a backend alias.
<alias-definition> has this format: alias-identifier="back
end-name -options".
-d <alias-identifier>
Remove the backend alias named <alias-identifier>.
-Q Let a handler function create the QUERY string.
See Query Handlers below.
-q <argument>
same as -Q, but lets you give an argument for the handler func
tion, too.
-l List available backends.
-L List defined backend aliases.
-P Print which browser command would be used instead of actually
executing it.
-R Send url to remote (GUI) browser (like firefox).
Quickstart
This section is for people who do not want to setup the lookup system
on their own:
zstyle ':lookup:*' txt-browser w3m
zstyle ':lookup:*' txt-formats "%s"
zstyle ':lookup:*' gui-browser firefox
zstyle ':lookup:*' gui-formats -remote "openurl(%s)"
zstyle ':lookup:*' use-pager true
zstyle ':lookup:*' pager-auto true
zstyle ':lookup:*' pager less -M
If you want to use other browsers, youll figure it out from here.
Now to find out what backends there are, do:
lookup -l
To get documentation for a backend do (the gmane backend here):
lookup -h gmane
Feel free to use lu instead of lookup to avoid a lot of typing. So, if
you want to search the web via google.com for zsh, do:
lu google zsh
Configuration
The lookup feature is primarily configured via zstyle. For additional
convenience the user can define and remove aliases for backends via the
-a and -d options of the lookup function (see examples below).
The context used for zstyle is:
:lookup:<execution-ident>:<backend>:<local-part>
<executing-ident>
Is an identifier for the code region in which a style is looked up.
Valid strings are: -main-, -backend-, -queryhandler-, -hook- and
-browser-. These are provided for maximum control of the con
text. Usually using * for this field will be good enough.
<backend>
Is the backend in question. Find out about valid strings via:
lookup -l.
<local-part>
Usually, this is set to -default-. Backends may set this to
another value, though (the rfc backend does, for example). See
the backends documentation for details.
This is a description of all styles that are looked up by the main sys
tem itself. Backends do look up other styles as well; they are
described in the backends self-documentation.
debug When set, lookup will print some debugging information to stdout
and it only prints out what command if would run instead o actu
ally running it (the latter has the same effect as the -P
option). [Type: boolean; Default: false]
txt-browser
This sets up the text based browser, which lookup will call to
access a web service. [Type: string; Default: $BROWSER, if that
is unset: w3m]
txt-formats
A list of arguments that is passed to the text based browser.
Within these arguments the string %s is replaced by the URL that
the browser should open. [Type: string; Default: %s]
gui-browser
This is the "remote" GUI browser, which is called when the -R
option of lookup is used. The default is the same as for the
text based browser.
Thus, for making use of the -R option you will have to set up
this style and possibly the txt-formats style (See below, and
Examples). [Type: string; Default: see txt-browser]
gui-formats
A list of arguments that is passed to the "remote" GUI browser.
Within these arguments the string %s is replaced by the URL that
the browser should open. [Type: string; Default: see txt-for
mats]
use-pager
When displaying a backends self-documentation, you may want to
read that text in a pager because the text may be too long for
your terminal.
Setting this style will always put the help text into a pager
(unless pager-auto is set, too). [Type: boolean; Default: false]
pager-auto
If set, a pager is only used to display help-texts if the text
would not fit on the screen (see prompt-height below). This has
no effect if use-pager is not set to true. [Type: boolean;
Default: false]
pager The pager to use for displaying help texts. [Type: string;
Default: $PAGER, if that is unset: more]
prompt-height
This is the height of the prompt assumed when calculating
whether to use a pager when pager-auto is set. [Type: integer;
Default: 1]
query-handlers
A list of handlers, that may be used to alter (and possibly gen
erate) a query for a web service. See Query Handlers and Exam
ples below. [Type: list; Default: empty]
hooks A list of functions to run at a certain time. There is one hook
type directly before a backend is run; and one that is run
directly after a backend ran and a browser is to be spawned. (If
a backend runs other hooks, it will document those itself). See
Hooks below. [Type: list; Default: empty]
Query Handlers
Query Handlers can be used to automate the generation and changing of
queries. Usually, after all option parsing is done, the remaining argu
ments to a backend are copied into the QUERY variable, concatenating
them by single spaces.
This QUERY variable is a global parameter to the lookup system, so that
you may change it in query handlers and the caller will used the
changed variable.
Such a handler itself is just a shell function named LOOKUP_qh_name,
where name is the name of the handler which you use in the query-han
dlers style.
The <execution-identifier> part of the zstyle context used in such han
dlers is -queryhandler- (this is only important if you want to make
your handlers configurable by zstyle).
The Examples section below has an example of how to automate queries
using such a handler.
Hooks
The basic lookup system (backends may run their own hooks, which they
will document themselves if they do) runs two hooks: One before a back
end is run, the other after a backend was run, before the browser is
spawned.
The hook list for the former is looked up in the :lookup:-main-:<back
end>:-default- context, for the latter in the :lookup:-browser-:<back
end>:-default- context.
In contrast to query handlers the name of a hook in the zstyle list is
the same as the functions that is called. The following arguments are
provided to these functions: In the -main- context: the same arguments
that are passed to the backend. In the -browser- context: the same URL
that is handed over to the browser.
There is a special variable unencQUERY that is available in hooks in
the -browser- context. It contains the unencoded query string. With
that the -browser- hooks can be used to set xterm or GNU screen titles.
The <execution-identifier> part of the zstyle context used in hooks is
-hook- (this is only important if you want to make your hooks config
urable by zstyle).
Examples
Basic calls:
lookup google zsh
lookup deb_bts -p zsh
Calls using the shorter lu:
lu google zsh
lu usenet zsh
Example backend aliases:
lu -a s=google
lu -a d=leo
lu -a z=zsh_mla
lu -a wd="wikipedia -l de"
And use those aliases:
lu s zsh compsys
lu d sugar
lu z -w 12345
lu wd zsh
Setup firefox as your "remote" GUI browser:
zstyle ':lookup:*' gui-browser firefox
zstyle ':lookup:*' gui-formats -remote "openurl(%s)"
Do the same for opera:
zstyle ':lookup:*' gui-browser opera
zstyle ':lookup:*' gui-formats -newtab -remote "openURL(%s)"
And finally an example for Query Handlers:
Lets assume, you have a command that queries your music player as to
which Song is currently playing, in one of the following formats:
np: Artist - Album - Track
np: Artist - Track
Lets further assume such a program is called audio-stat. If the player
is stopped is displays: -stopped-
Now wouldnt it be convenient if we could use such information in order
to make queries with the letssingit backend (which queries www.letssin
git.com)? It would and the following does:
zstyle ':lookup:*:letssingit:*' query-handlers letssingit
function LOOKUP_qh_letssingit() {
local mode=${lookup_communicate[mode]}
local np
case ${mode} in
(artist|album|song)
np="$(audio-stat)"
np=${np/np: /}
if [[ ${np} == -stopped- ]] ; then
printf \n Currently not playing anything!\n\n
return 3
fi
;;
esac
case ${mode} in
(artist)
QUERY=${np%% - *}
;;
(album)
np=${np% - *}
if [[ ${np} == *\ -\ * ]] ; then
QUERY=${np#* - }
else
printf \n Could not get album (%s)!\n\n "$(audio-stat)"
return 3
fi
;;
(song)
QUERY=${np##* - }
;;
esac
return 0
}
Now, to search for the lyrics of the currently running song, you can do
this:
lu -Q letssingit -m song
You can use -m artist or -m album in order to search for lyrics of the
currently playing artist or album, too.
(Comments: 0)