2012 0005 0018
While many an
dabbrev-expand for within-buffer completion, I’ve always wanted (purely for reasons of amusement) to take it further: completion via Google’s search suggestions. I was going to do this as a weekend project, but an ugly version was surprisingly simple.
curl is all we need to fetch the completions for a query string as
> echo -en $(curl -H "Accept: application/json" \ "http://suggestqueries.google.com/complete/search?client=firefox&q=query") ["query",["query","query xiv","query letter","query_posts","query shark","query access","query tracker","query string","query letter sample","queryperformancecounter"]]
using a (very platform dependent)
echo trick to convert the escaped unicode sequences to their proper characters.
With this, a quick hack in
elisp is all that’s necessary to parse the results into
emacs and insert it into the current buffer:
(defun google-request (query) (shell-command-to-string (format "echo -en $(curl -H \"Accept: application/json\" \"http://suggestqueries.google.com/complete/search?client=firefox&q=%s\" 2>/dev/null)" query))) (defun google-preprocess (query) (let ((l (split-string (apply 'string (removel '(?\" ?\[ ?\]) (string-to-list query))) ","))) (if (> (length (car (cdr l))) 0) (remove (car l) (cdr l)) nil))) (defun google-complete () (interactive) (end-of-thing 'word) (let ((s (thing-at-point 'word))) (when s (let ((q (google-preprocess (google-request s)))) (when q (insert (substring (car q) (length s)))))))) (defun removel (el l) (cond (el (removel (cdr el) (remove (car el) l))) (t l)))
Since it went more swiftly than anticipated, I generalized the code to parsing any delimited shell output and wrapped it in a minor mode with some key bindings and
customize variables. Right now, I’m uncreatively calling it
shell-parse-mode, it has support for scrolling through the list of completions forwards (
shell-parse-complete) and backwards (
shell-parse-complete-backwards) with the
C-Shift-Tab keys, respectively. Using
M-x customize-mode <Enter>
shell-parse-mode, you can swap out the
curl command with any shell snippet that will kick back completions, and change the delimiter as well.
You can grab
shell-parse.el on github. Simply
shell-parse.el script in
.emacs and it should be ready to go.
It has a few todos scattered through it yet, and is not very idiomatic
emacs or portable, but that’s what github’s issue tracker is for, after all.