Add facility to allow user functions to transform typed URLs.
[conkeror.git] / modules / webjump.js
blobef5906b7283cdf084cfc9a194587e1ff2aad861a
1 /**
2  * (C) Copyright 2004-2007 Shawn Betts
3  * (C) Copyright 2007-2008 John J. Foerch
4  * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
5  *
6  * Use, modification, and distribution are subject to the terms specified in the
7  * COPYING file.
8 **/
10 //// web jump stuff
12 var webjumps = new string_hashmap();
14 define_keywords("$completer", "$description", "$no_argument");
15 function define_webjump(key, handler) {
16     keywords(arguments);
18     var no_argument = arguments.$no_argument;
20     make_handler = function(template, alternative) {
21         let b = template.indexOf('%s');
22         if (b == -1)
23             no_argument = true;
24         if (alternative == null)
25             alternative = compute_url_pre_path(template);
26         if (alternative && !no_argument)
27             no_argument = "maybe";
28         return function (arg) {
29             var a = b + 2;
30             if (arg == null)
31                 return alternative;
32             // Just return the same string if it doesn't contain a %s
33             if (b == -1)
34                 return template;
35             return template.substr(0,b) + encodeURIComponent(arg) + template.substring(a);
36         };
37     }
39     if (typeof(handler) == "string")
40         handler = make_handler(handler);
41     if (typeof(handler) == "object")
42         // An array of a template and an alternative url (for no args)
43         handler = make_handler(handler[0], handler[1]);
45     webjumps.put(key,
46                  {key: key,
47                   handler: handler, completer: arguments.$completer,
48                   description: arguments.$description,
49                   no_argument: no_argument});
52 // Compatibility
53 var add_webjump = define_webjump;
55 function add_delicious_webjumps (username)
57     add_webjump("delicious", "http://del.icio.us/" + username);
58     add_webjump("adelicious", "javascript:location.href='http://del.icio.us/" + username + "?v=2&url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title);");
59     add_webjump("sdelicious", "http://delicious.com/search?p=%s&u=" + username + "&chk=&context=userposts&fr=del_icio_us&lc=1");
60     add_webjump("sadelicious", "http://del.icio.us/search/all?search=%s");
63 function clear_webjumps()
65     webjumps = {};
68 // Some built in web jumps
69 function define_default_webjumps()
71     add_webjump("conkerorwiki",
72                 "http://conkeror.org/?action=fullsearch&context=60&value=%s&fullsearch=Text");
73     add_webjump("lucky",      "http://www.google.com/search?q=%s&btnI=I'm Feeling Lucky");
74     add_webjump("maps",       "http://maps.google.com/?q=%s");
75     add_webjump("scholar",    "http://scholar.google.com/scholar?q=%s");
76     add_webjump("clusty",     "http://www.clusty.com/search?query=%s");
77     add_webjump("slang",      "http://www.urbandictionary.com/define.php?term=%s");
78     add_webjump("dictionary", "http://dictionary.reference.com/search?q=%s");
79     add_webjump("xulplanet",  ["http://www.google.com/custom?q=%s&cof=S%3A"+
80                 "http%3A%2F%2Fwww.xulplanet.com%3BAH%3Aleft%3BLH%3A65%3BLC"+
81                 "%3A4682B4%3BL%3Ahttp%3A%2F%2Fwww.xulplanet.com%2Fimages%2F"+
82                 "xulplanet.png%3BALC%3Ablue%3BLW%3A215%3BAWFID%3A0979f384d5"+
83                 "181409%3B&domains=xulplanet.com&sitesearch=xulplanet.com&sa=Go",
84                 "http://xulplanet.com"]);
85     add_webjump("image",      "http://images.google.com/images?q=%s");
86     add_webjump("imdb",       "http://www.imdb.com/find?s=all&q=%s&x=0&y=0");
87     add_webjump("clhs",       ["http://www.xach.com/clhs?q=%s", "http://www.lispworks.com/documentation/HyperSpec/Front/index.htm"]);
88     add_webjump("emacswiki",  "http://www.emacswiki.org/cgi-bin/wiki?search=%s");
89     add_webjump("cliki",      "http://www.cliki.net/admin/search?words=%s");
90     add_webjump("ratpoisonwiki", "http://ratpoison.antidesktop.net/?search=%s");
91     add_webjump("stumpwmwiki", "http://stumpwm.antidesktop.net/wiki?search=%s");
92     add_webjump("savannah", "http://savannah.gnu.org/search/?words=%s&type_of_search=soft&Search=Search&exact=1");
93     add_webjump("sourceforge", "http://sourceforge.net/search/?words=%s");
94     add_webjump("freshmeat", "http://freshmeat.net/search/?q=%s");
95     add_webjump("slashdot", "http://slashdot.org/search.pl?query=%s");
96     add_webjump("kuro5hin", "http://www.kuro5hin.org/?op=search&string=%s");
97     add_webjump("sheldonbrown",     "http://www.google.com/search?q=site:sheldonbrown.com %s");
98     add_webjump("youtube", "http://www.youtube.com/results?search_query=%s&search=Search");
101 function match_webjump(str) {
102     var sp = str.indexOf(' ');
104     var key, arg;
105     if (sp == -1) {
106         key = str;
107         arg = null;
108     } else {
109         key = str.substring(0, sp);
110         arg = str.substring(sp + 1);
111         if (/^\s*$/.test(arg))
112             arg = null;
113     }
115     // Look for an exact match
116     var match = webjumps.get(key);
118     // Look for a partial match
119     if (!match) {
120         for (let [k,v] in webjumps.iterator()) {
121             if (k.substring(0, key.length) == key) {
122                 if (match) {
123                     // key is not a unique prefix, as there are multiple partial matches
124                     return null;
125                 }
126                 match = v;
127             }
128         }
129     }
131     if (match) {
132         if (arg == null && !match.no_argument) {
133             throw interactive_error('Webjump '+key+' requires an argument.');
134         }
135         return [match, key, arg];
136     }
137     return null;
141 function getWebJump(value)
143     var res = match_webjump(value);
144     if (!res)
145         return null;
146     let [match,key,arg] = res;
147     return match.handler(arg);
150 function get_url_or_webjump(input)
152     var url = getWebJump(input);
154     if (url != null) {
155         return url;
156     } else {
157         return input;
158     }
161 define_default_webjumps();
163 function webjump_completer()
165     let base_completer = prefix_completer(
166         $completions = [ v for ([k,v] in webjumps.iterator()) ],
167         $get_string = function (x) x.key + (x.no_argument==true ? "" : " "),
168         $get_description = function (x) x.description || "");
170     return function(input, pos, conservative) {
171         let str = input.substring(0,pos);
172         let res;
173         try { res = match_webjump(str); }
174         catch (e) { res = null; }
175         if (res) {
176             let [match, key, arg] = res;
177             if (arg != null) { // If there is no argument yet, we use the base completer
178                 if (match.completer) {
179                     let c = yield match.completer.call(null, arg, pos - key.length - 1, conservative);
180                     yield co_return(nest_completions(c, match.key + " "));
181                 }
182                 yield co_return(null);
183             }
184         }
185         yield co_return(base_completer(input, pos, conservative));
186     };