Merge remote-tracking branch 'origin/github/pr/45'
[grml.org.git] / scripts / google_correct.txt
1 #!/usr/bin/env python2.5
2 """
3 Filename:      google_correct.py
4 Purpose:       correct a keyword using google search
5 Authors:       (c) Michael Prokop <mika@grml.org>
6 Bug-Reports:   see http://grml.org/bugs/
7 License:       This file is licensed under the GPL v2 or any later version.
8 Latest change: Sun Mar 09 19:19:04 CET 2008 [mika]
9
10 Notice:
11
12 * requires xsel binary
13 * requires python >= 2.4 (for urllib2), version 2.5 suggested :)
14 * if python-notify is installed it's used as notification system
15
16 History:
17
18 * 2008-03-09: improve cmdline parsing logic [gregor herrmann]
19               include support for libnotify [mika]
20               usage information for -h/--help [mika]
21               provide output on stdout even when using xsel [mika]
22 * 2008-02-11: initial version [mika]
23
24 Whishlist:
25
26 * support multiple keywords in one single invocation
27 * use python-xlib instead of xsel,
28   like in http://kalvdans.no-ip.org/svn/saturnapps/selection.py ?
29 * support something like a search gateway for anonymous search requests
30 * support different backends (like fuzzy search in local dictionaries)
31 * provide small selection menu for X, vim,...
32 """
33
34 import os
35 import re
36 import urllib
37 import urllib2
38 import subprocess
39 import sys
40
41 _correction_re = re.compile(r'<font[^>]*>Did you mean: </font><a[^>]*>'
42                             r'<b><i>(.*?)</i></b></a>(?i)')
43
44 def usage():
45     print """
46 google_correct.py: correct a keyword using google's 'Did you mean' feature
47
48 Usage:
49
50       Either run:
51
52         google_correct.py <keyword>
53
54       or select keyword in X and execute the script to set new X selection:
55
56         google_correct.py
57
58 Send bug reports, feature requests and patches to Michael Prokop <mika@grml.org>
59 """
60
61 def which(filename):
62     """Check whether a given program can be executed"""
63     for path in (os.environ.get('PATH') or os.defpath).split(os.pathsep):
64         myfile = os.path.join(path, filename)
65         if os.access(myfile, os.X_OK):
66             return myfile
67
68 def correct_keyword(keyword):
69     """Correct spelling of a keyword using google's 'Did you mean' feature"""
70     req = urllib2.Request('http://www.google.com/search?%s' % urllib.urlencode({
71         'q':        keyword.encode('utf-8'),
72         'spell':    '1'
73     }))
74     req.add_header('User-Agent', 'Mikas-Keyword-Corrector/1.0 :-)')
75     resp = urllib2.urlopen(req)
76     match = _correction_re.search(resp.read())
77     return match and match.group(1) or keyword
78
79 # would be nice to support multiple keywords at once,
80 # needs work in _correction_re though:
81 #def cmdline():
82 #    for argument in sys.argv[1:]:
83 #        return ' '.join(arg for arg in sys.argv[1:])
84 #keyword = cmdline()
85
86 def get_x_selection():
87     """Get X selection"""
88     proc = subprocess.Popen(['xsel', ], stdout=subprocess.PIPE)
89     x_selection = proc.stdout.read()
90     proc.stdout.close()
91     proc.wait()
92     return x_selection
93
94 def set_x_selection(keyword):
95     """Set X selection to the given keyword"""
96     proc = subprocess.Popen(['xsel', '-i'], stdin=subprocess.PIPE)
97     proc.stdin.write(keyword)
98     proc.stdin.close()
99     proc.wait()
100
101 def default_cb(n, action):
102     assert action == "default"
103     print "You clicked the default action"
104     n.close()
105     gtk.main_quit()
106
107 def notify(new_keyword, old_keyword):
108     try:
109         import pynotify
110         if pynotify.init("google_correct"):
111             if new_keyword is not old_keyword:
112                 n = pynotify.Notification("New keyword for \"%s\":" % old_keyword, new_keyword)
113             else:
114                 n = pynotify.Notification("google_correct result:", "No new keyword for \"%s\" found" % old_keyword)
115
116             n.set_timeout(2000)
117             n.show()
118     except:
119         return 0 # don't print anything because someone might use the output :)
120
121 if __name__ == '__main__':
122     if '--help' in sys.argv or '-h' in sys.argv:
123         usage()
124         sys.exit(1);
125
126     if sys.argv[1:]:
127         # print it to stdout:
128         old_keyword = sys.argv[1]
129         new_keyword = correct_keyword(old_keyword)
130         print new_keyword
131         notify(new_keyword, old_keyword)
132         # or if you prefer to put it directly to X selection:
133         #set_x_selection(correct_keyword(sys.argv[1]))
134     else:
135        if which('xsel'):
136            old_keyword = get_x_selection()
137            new_keyword = correct_keyword(old_keyword)
138            print new_keyword
139            set_x_selection(new_keyword)
140            notify(new_keyword, old_keyword)
141        else:
142            sys.exit("Sorry, xsel not found. Exiting.")
143
144 ## END OF FILE #################################################################
145 # vim: ft=python tw=100 ai et