DuckDuckGo Bang Macro
Prompted by the recently released Bang On iOS app1, I decided to make a macro for Keyboard Maestro that could accomplish the same thing with Safari.
This macro is really just a series of scripts, so it could easily be converted to a LaunchBar plugin. The macro grabs the current URL and looks for a query string. It then converts the query string to one of several DuckDuckGo bang searches.
The first AppleScript just grabs the URL of the front Safari window and passes it into a KM variable.
property theURL : ""
tell application "Safari"
set theURL to URL of the current tab of window 1
end tell
The second Python script2 does most of the work. It uses the urllib module to dissect the URL. It returns the current query string if one exists. Since the macro is expecting to process a query string, it first looks for the common query parameter in the URL. If it doesn't find one, the macro does nothing.
#!/usr/bin/env python
import urllib
from urlparse import urlparse, parse_qs
import os
newQuery = "fail"
kmVarCurrentURL = os.getenv('KMVAR_temp')
o = urlparse(kmVarCurrentURL)
qs = parse_qs(o.query)
if 'q' in qs:
queryString = urllib.quote(parse_qs(o.query)['q'][0])
newQuery = "http://duckduckgo.com/?q=" + queryString + "+%21gi"
print newQuery
Here's the great thing about the DDG query syntax: To use a bang search, just add it to the end of the current query string. That's all I'm really doing in these scripts. I get the query string with python and then tack on the appropriate bang parameter.
The final AppleScript just redirects Safari to the new URL.
property theURL : ""
tell application "Keyboard Maestro Engine"
set theURL to (process tokens "%Variable%temp%")
end tell
tell application "Safari"
tell document 1 to set URL to theURL
end tell
I've tied all of these to a single Keyboard Maestro macro trigger group available in Safari. While viewing a DDG search result page I hit cmd-shift-/ to get the following selection panel:
I then just hit the number of the bang I would like.
Since the script is looking for any query string, if I decide to execute a different search, I can just trigger the macro again. For example, this Python doc query string:
http://docs.python.org/search.html?q=urllib&check_keywords=yes&area=default
Is converted to this query if I trigger the macro again and choose Github:
https://github.com/search?q=urllib&type=Everything&repo=&langOverride=&start_value=1
This is all made possible by the Python urllib library. Specifically, the urlparse() method and the parse_qs() method which extracts the query string from the url.