2 * (C) Copyright 2004-2007 Shawn Betts
3 * (C) Copyright 2007-2008 John J. Foerch
4 * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
6 * Use, modification, and distribution are subject to the terms specified in the
10 var webjumps = new string_hashmap();
12 define_keywords("$completer", "$description", "$no_argument");
13 function define_webjump(key, handler) {
17 // handler may be a function, a string, or an array
18 // of a string and a "no args" alternate string.
20 // if the no_argument property is set on a webjump,
21 // completing on the name of the webjump will not
22 // result in a space being appended.
24 // we only pay attention to the no_argument keyword
25 // if the handler is a function. for string webjumps,
26 // we simply see if there is a "%s" in the string.
28 if (typeof(handler) == "function") {
29 no_argument = arguments.$no_argument;
30 } else if (typeof(handler) == "string") {
31 if (handler.indexOf('%s') == -1)
35 function make_handler (template, alternative) {
36 if (alternative == null)
37 alternative = url_path_trim(template);
38 var b = template.indexOf('%s');
39 return function (arg) {
41 if (arg == null && b > -1)
43 // Just return the same string if it doesn't contain a %s
46 return template.substr(0,b) + encodeURIComponent(arg) + template.substring(a);
50 if (typeof(handler) == "string")
51 handler = make_handler(handler);
52 if (typeof(handler) == "object")
53 // An array of a template and an alternative url (for no args)
54 handler = make_handler(handler[0], handler[1]);
58 handler: handler, completer: arguments.$completer,
59 description: arguments.$description,
60 no_argument: no_argument});
64 var add_webjump = define_webjump;
66 function add_delicious_webjumps (username)
68 define_webjump("delicious", "http://del.icio.us/" + username);
69 define_webjump("adelicious", "javascript:location.href='http://del.icio.us/"+username+
70 "?v=2&url='+encodeURIComponent(location.href)+'&title='+"+
71 "encodeURIComponent(document.title);");
72 define_webjump("sdelicious", "http://delicious.com/search?p=%s&u="+username+
73 "&chk=&context=userposts&fr=del_icio_us&lc=1");
74 define_webjump("sadelicious", "http://del.icio.us/search/all?search=%s");
77 function add_lastfm_webjumps(username)
79 if (! username) username = "";
80 define_webjump("lastfm", "http://www.last.fm/user/"+username);
81 define_webjump("lastfm-user", "http://www.last.fm/user/%s");
82 define_webjump("lastfm-music", "http://www.last.fm/search?m=all&q=%s");
83 define_webjump("lastfm-group", "http://www.last.fm/users/groups?s_bio=%s");
84 define_webjump("lastfm-tag", "http://www.last.fm/search?m=tag&q=%s");
85 define_webjump("lastfm-label", "http://www.last.fm/search?m=label&q=%s");
86 define_webjump("lastfm-event", "http://www.last.fm/events?by=artists&q=%s");
89 function clear_webjumps()
94 // Some built in web jumps
95 function define_default_webjumps()
97 define_webjump("conkerorwiki",
98 "http://conkeror.org/?action=fullsearch&context=60&value=%s&fullsearch=Text");
99 define_webjump("lucky", "http://www.google.com/search?q=%s&btnI=I'm Feeling Lucky");
100 define_webjump("maps", "http://maps.google.com/?q=%s");
101 define_webjump("scholar", "http://scholar.google.com/scholar?q=%s");
102 define_webjump("clusty", "http://www.clusty.com/search?query=%s");
103 define_webjump("slang", "http://www.urbandictionary.com/define.php?term=%s");
104 define_webjump("dictionary", "http://dictionary.reference.com/search?q=%s");
105 define_webjump("xulplanet", ["http://www.google.com/custom?q=%s&cof=S%3A"+
106 "http%3A%2F%2Fwww.xulplanet.com%3BAH%3Aleft%3BLH%3A65%3BLC"+
107 "%3A4682B4%3BL%3Ahttp%3A%2F%2Fwww.xulplanet.com%2Fimages%2F"+
108 "xulplanet.png%3BALC%3Ablue%3BLW%3A215%3BAWFID%3A0979f384d5"+
109 "181409%3B&domains=xulplanet.com&sitesearch=xulplanet.com&sa=Go",
110 "http://xulplanet.com"]);
111 define_webjump("image", "http://images.google.com/images?q=%s");
112 define_webjump("imdb", "http://www.imdb.com/find?s=all&q=%s&x=0&y=0");
113 define_webjump("clhs", ["http://www.xach.com/clhs?q=%s", "http://www.lispworks.com/documentation/HyperSpec/Front/index.htm"]);
114 define_webjump("emacswiki", "http://www.emacswiki.org/cgi-bin/wiki?search=%s");
115 define_webjump("cliki", "http://www.cliki.net/admin/search?words=%s");
116 define_webjump("ratpoisonwiki", "http://ratpoison.antidesktop.net/?search=%s");
117 define_webjump("stumpwmwiki", "http://stumpwm.antidesktop.net/wiki?search=%s");
118 define_webjump("savannah", "http://savannah.gnu.org/search/?words=%s&type_of_search=soft&Search=Search&exact=1");
119 define_webjump("sourceforge", "http://sourceforge.net/search/?words=%s");
120 define_webjump("freshmeat", "http://freshmeat.net/search/?q=%s");
121 define_webjump("slashdot", "http://slashdot.org/search.pl?query=%s");
122 define_webjump("kuro5hin", "http://www.kuro5hin.org/?op=search&string=%s");
123 define_webjump("sheldonbrown", "http://www.google.com/search?q=site:sheldonbrown.com %s");
124 define_webjump("youtube", "http://www.youtube.com/results?search_query=%s&search=Search");
127 function match_webjump(str) {
128 var sp = str.indexOf(' ');
135 key = str.substring(0, sp);
136 arg = str.substring(sp + 1);
137 if (/^\s*$/.test(arg))
141 // Look for an exact match
142 var match = webjumps.get(key);
144 // Look for a partial match
146 for (let [k,v] in webjumps.iterator()) {
147 if (k.substring(0, key.length) == key) {
149 // key is not a unique prefix, as there are multiple partial matches
158 if (arg == null && !match.no_argument) {
159 throw interactive_error('Webjump '+key+' requires an argument.');
161 return [match, key, arg];
167 function getWebJump(value)
169 var res = match_webjump(value);
172 let [match,key,arg] = res;
173 return match.handler(arg);
176 function get_url_or_webjump(input)
178 var url = getWebJump(input);
187 define_default_webjumps();
189 function webjump_completer()
191 let base_completer = prefix_completer(
192 $completions = [ v for ([k,v] in webjumps.iterator()) ],
193 $get_string = function (x) { return x.key + (x.no_argument==true ? "" : " "); },
194 $get_description = function (x) { return x.description || ""; });
196 return function(input, pos, conservative) {
197 let str = input.substring(0,pos);
199 try { res = match_webjump(str); }
200 catch (e) { res = null; }
202 let [match, key, arg] = res;
203 if (arg != null) { // If there is no argument yet, we use the base completer
204 if (match.completer) {
205 let c = yield match.completer.call(null, arg, pos - key.length - 1, conservative);
206 yield co_return(nest_completions(c, match.key + " "));
208 yield co_return(null);
211 yield co_return(base_completer(input, pos, conservative));