gmane page-mode: binding for browser-object-links
[conkeror.git] / modules / webjump.js
blobdcc570c6a14f819778eff3a98803452bbb9b1924
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 var webjumps = {};
12 define_keywords("$completer", "$description", "$argument", "$alternative");
13 function define_webjump(key, handler) {
14     keywords(arguments);
15     var argument = arguments.$argument;
16     let alternative = arguments.$alternative;
18     // handler may be a function or a string.  An alternative url may
19     // be passed using the $alternative keyword; it is used in place
20     // of the handler when no arguments are supplied by the user when
21     // invoking the webjump (see getWebJump).  For string webjumps
22     // that contain %s and for which no alternative is provided, an
23     // alternative is autogenerated by trimming the path from the url.
24     // A webjump can thus function both as a way to invoke a search
25     // and as a bookmark.
26     //
27     // The argument property may be false (no arguments will be
28     // accepted for the webjump), true (arguments are required for the
29     // webjump) or 'optional' (arguments are accepted but not
30     // required).  If the property is not specified, a sensible default
31     // is chosen depending on the type of the handler and whether an
32     // alternative is specified.  If the property is false, then
33     // completing on the name of the webjump in the minibuffer will
34     // not result in a space being appended.
35     //
36     if (typeof(handler) == "function") {
37         if (argument == null && alternative == null)
38             argument = true;
39     } else if (typeof(handler) == "string") {
40         if (handler.indexOf('%s') == -1)
41             argument = false;
42         else if (alternative == null)
43             alternative = url_path_trim(handler);
44     }
45     if (alternative && argument == null)
46         argument = 'optional';
48     function make_handler (template) {
49         var b = template.indexOf('%s');
50         return function (arg) {
51             var a = b + 2;
52             // Just return the same string if it doesn't contain a %s
53             if (b == -1)
54                 return template;
55             return template.substr(0,b) + encodeURIComponent(arg) + template.substring(a);
56         };
57     }
59     if (typeof(handler) == "string")
60         handler = make_handler(handler);
62     webjumps[key] = { key: key,
63                       handler: handler,
64                       completer: arguments.$completer,
65                       description: arguments.$description,
66                       argument: argument,
67                       alternative: alternative};
71 function define_delicious_webjumps (username)
73     define_webjump("delicious", "http://del.icio.us/" + username);
74     define_webjump("adelicious", "javascript:location.href='http://del.icio.us/"+username+
75                    "?v=2&url='+encodeURIComponent(location.href)+'&title='+"+
76                    "encodeURIComponent(document.title);");
77     define_webjump("sdelicious", "http://delicious.com/search?p=%s&u="+username+
78                    "&chk=&context=userposts&fr=del_icio_us&lc=1");
79     define_webjump("sadelicious", "http://del.icio.us/search/all?search=%s");
82 add_delicious_webjumps = define_delicious_webjumps;
84 function define_lastfm_webjumps(username)
86     if (! username) username = "";
87     define_webjump("lastfm", "http://www.last.fm/user/"+username);
88     define_webjump("lastfm-user", "http://www.last.fm/user/%s");
89     define_webjump("lastfm-music", "http://www.last.fm/search?m=all&q=%s");
90     define_webjump("lastfm-group", "http://www.last.fm/users/groups?s_bio=%s");
91     define_webjump("lastfm-tag", "http://www.last.fm/search?m=tag&q=%s");
92     define_webjump("lastfm-label", "http://www.last.fm/search?m=label&q=%s");
93     define_webjump("lastfm-event", "http://www.last.fm/events?by=artists&q=%s");
96 add_lastfm_webjumps = define_lastfm_webjumps;
98 function clear_webjumps()
100     webjumps = {};
103 // Some built in web jumps
104 function define_default_webjumps()
106     define_webjump("conkerorwiki",
107                    "http://conkeror.org/?action=fullsearch&context=60&value=%s&fullsearch=Text");
108     define_webjump("lucky",      "http://www.google.com/search?q=%s&btnI=I'm Feeling Lucky");
109     define_webjump("maps",       "http://maps.google.com/?q=%s");
110     define_webjump("scholar",    "http://scholar.google.com/scholar?q=%s");
111     define_webjump("clusty",     "http://www.clusty.com/search?query=%s");
112     define_webjump("slang",      "http://www.urbandictionary.com/define.php?term=%s");
113     define_webjump("dictionary", "http://dictionary.reference.com/search?q=%s");
114     define_webjump("xulplanet",
115                    "http://www.google.com/custom?q=%s&cof=S%3A"+
116                    "http%3A%2F%2Fwww.xulplanet.com%3BAH%3Aleft%3BLH%3A65%3BLC"+
117                    "%3A4682B4%3BL%3Ahttp%3A%2F%2Fwww.xulplanet.com%2Fimages%2F"+
118                    "xulplanet.png%3BALC%3Ablue%3BLW%3A215%3BAWFID%3A0979f384d5"+
119                    "181409%3B&domains=xulplanet.com&sitesearch=xulplanet.com&sa=Go",
120                    $alternative = "http://xulplanet.com");
121     define_webjump("image",      "http://images.google.com/images?q=%s");
122     define_webjump("clhs",
123                    "http://www.xach.com/clhs?q=%s",
124                    $alternative = "http://www.lispworks.com/documentation/HyperSpec/Front/index.htm");
125     define_webjump("emacswiki",  "http://www.emacswiki.org/cgi-bin/wiki?search=%s");
126     define_webjump("cliki",      "http://www.cliki.net/admin/search?words=%s");
127     define_webjump("ratpoisonwiki", "http://ratpoison.antidesktop.net/?search=%s");
128     define_webjump("stumpwmwiki", "http://stumpwm.antidesktop.net/wiki?search=%s");
129     define_webjump("savannah",
130                    "http://savannah.gnu.org/search/?words=%s&type_of_search=soft&Search=Search&exact=1");
131     define_webjump("sourceforge", "http://sourceforge.net/search/?words=%s");
132     define_webjump("freshmeat", "http://freshmeat.net/search/?q=%s");
133     define_webjump("slashdot", "http://slashdot.org/search.pl?query=%s");
134     define_webjump("kuro5hin", "http://www.kuro5hin.org/?op=search&string=%s");
137 define_variable("webjump_partial_match", true,
138                 "When entering a url, if the input is not a webjump, " +
139                 "but would uniquely complete to a webjump, then accept " +
140                 "that webjump only if this is true.");
142 function match_webjump(str) {
143     var sp = str.indexOf(' ');
145     var key, arg;
146     if (sp == -1) {
147         key = str;
148         arg = null;
149     } else {
150         key = str.substring(0, sp);
151         arg = str.substring(sp + 1);
152         if (/^\s*$/.test(arg))
153             arg = null;
154     }
156     // Look for an exact match
157     var match = webjumps[key];
159     // Look for a partial match
160     if (!match && webjump_partial_match) {
161         for (let [k,v] in Iterator(webjumps)) {
162             if (k.substring(0, key.length) == key) {
163                 if (match) {
164                     // key is not a unique prefix, as there are multiple partial matches
165                     return null;
166                 }
167                 match = v;
168             }
169         }
170     }
172     if (match) {
173         if (arg == null && match.argument == true) {
174             throw interactive_error('Webjump '+key+' requires an argument.');
175         }
176         return [match, key, arg];
177     }
178     return null;
182 function getWebJump(value)
184     var res = match_webjump(value);
185     if (!res)
186         return null;
187     let [match,key,arg] = res;
188     if (arg == null && match.alternative)
189         return match.alternative;
190     return match.handler(arg);
193 function get_url_or_webjump(input)
195     var url = getWebJump(input);
197     if (url != null) {
198         return url;
199     } else {
200         return input;
201     }
204 define_default_webjumps();
206 function webjump_completer()
208     let base_completer = prefix_completer(
209         $completions = [ v for ([k,v] in Iterator(webjumps)) ],
210         $get_string = function (x) { return x.key + (x.argument ? " " : ""); },
211         $get_description = function (x) { return x.description || ""; });
213     return function(input, pos, conservative) {
214         let str = input.substring(0,pos);
215         let res;
216         try { res = match_webjump(str); }
217         catch (e) { res = null; }
218         if (res) {
219             let [match, key, arg] = res;
220             if (arg != null) { // If there is no argument yet, we use the base completer
221                 if (match.completer) {
222                     let c = yield match.completer.call(null, arg, pos - key.length - 1, conservative);
223                     yield co_return(nest_completions(c, match.key + " "));
224                 }
225                 yield co_return(null);
226             }
227         }
228         yield co_return(base_completer(input, pos, conservative));
229     };