ratpoisonwiki webjump removed
[conkeror.git] / modules / webjump.js
blob8772658d75e2b9375773f59c59f54f395d0d1635
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                 "$post_data");
14 function define_webjump (key, handler) {
15     keywords(arguments);
16     var argument = arguments.$argument;
17     let alternative = arguments.$alternative;
18     var post_data = arguments.$post_data;
20     // handler may be a function or a string.  An alternative url may
21     // be passed using the $alternative keyword; it is used in place
22     // of the handler when no arguments are supplied by the user when
23     // invoking the webjump (see get_webjump).  For string webjumps
24     // that contain %s and for which no alternative is provided, an
25     // alternative is autogenerated by trimming the path from the url.
26     // A webjump can thus function both as a way to invoke a search
27     // and as a bookmark.
28     //
29     // When the handler is a string and post_data is given the webjump
30     // will result in a POST.  A '%s' element in post_data will be
31     // replaced by the webjump argument and the alternative is the
32     // same as the handler (but as a GET).
33     //
34     // The argument property may be false (no arguments will be
35     // accepted for the webjump), true (arguments are required for the
36     // webjump) or 'optional' (arguments are accepted but not
37     // required).  If the property is not specified, a sensible default
38     // is chosen depending on the type of the handler and whether an
39     // alternative is specified.  If the property is false, then
40     // completing on the name of the webjump in the minibuffer will
41     // not result in a space being appended.
42     //
43     if (typeof(handler) == "function") {
44         if (argument == null && alternative == null)
45             argument = true;
46     } else if (typeof(handler) == "string") {
47         if (post_data && alternative == null)
48             alternative = handler;
49         else if (handler.indexOf('%s') == -1)
50             argument = false;
51         else if (alternative == null)
52             alternative = url_path_trim(handler);
53     }
54     if (alternative && argument == null)
55         argument = 'optional';
57     function make_string_handler (template) {
58         var b = template.indexOf('%s');
59         return function (arg) {
60             var a = b + 2;
61             // Just return the same string if it doesn't contain a %s
62             if (b == -1)
63                 return template;
64             return template.substr(0,b) + encodeURIComponent(arg) + template.substring(a);
65         };
66     }
68     function make_post_handler (uri, post_data) {
69         return function (arg) {
70             return load_spec({
71                 uri: uri,
72                 post_data: make_post_data(post_data.map(function (pair) {
73                     if (pair[1] == '%s')
74                         return [pair[0], arg];
75                     else
76                         return pair;
77                 }))
78             });
79         };
80     }
82     if (typeof(handler) == "string") {
83         if (post_data)
84             handler = make_post_handler(handler, post_data);
85         else
86             handler = make_string_handler(handler);
87     }
89     webjumps[key] = { key: key,
90                       handler: handler,
91                       completer: arguments.$completer,
92                       description: arguments.$description,
93                       argument: argument,
94                       alternative: alternative};
97 function clear_webjumps () {
98     webjumps = {};
101 define_variable("webjump_partial_match", true,
102     "When entering a url, if the input is not a webjump, " +
103     "but would uniquely complete to a webjump, then accept " +
104     "that webjump only if this is true.");
106 function match_webjump (str) {
107     var sp = str.indexOf(' ');
109     var key, arg;
110     if (sp == -1) {
111         key = str;
112         arg = null;
113     } else {
114         key = str.substring(0, sp);
115         arg = str.substring(sp + 1);
116         if (/^\s*$/.test(arg))
117             arg = null;
118     }
120     // Look for an exact match
121     var match = webjumps[key];
123     // Look for a partial match
124     if (!match && webjump_partial_match) {
125         for (let [k,v] in Iterator(webjumps)) {
126             if (String(k).substring(0, key.length) == key) {
127                 if (match) {
128                     // key is not a unique prefix, as there are multiple partial matches
129                     return null;
130                 }
131                 match = v;
132             }
133         }
134     }
136     if (match) {
137         if (arg == null && match.argument == true)
138             throw interactive_error('Webjump '+key+' requires an argument.');
139         return [match, key, arg];
140     }
141     return null;
145 function get_webjump (value) {
146     var res = match_webjump(value);
147     if (!res)
148         return null;
149     let [match,key,arg] = res;
150     if (arg == null && match.alternative)
151         return match.alternative;
152     return match.handler(arg);
155 function get_url_or_webjump (input) {
156     var url = get_webjump(input);
157     if (url != null)
158         return url;
159     else
160         return input;
163 function webjump_completer () {
164     let base_completer = prefix_completer(
165         $completions = [ v for ([k,v] in Iterator(webjumps)) ],
166         $get_string = function (x) { return x.key + (x.argument ? " " : ""); },
167         $get_description = function (x) { return x.description || ""; });
168     return function (input, pos, conservative) {
169         let str = input.substring(0,pos);
170         let res;
171         try { res = match_webjump(str); }
172         catch (e) { res = null; }
173         if (res) {
174             let [match, key, arg] = res;
175             if (arg != null) { // If there is no argument yet, we use the base completer
176                 if (match.completer) {
177                     let c = yield match.completer.call(null, arg, pos - key.length - 1, conservative);
178                     yield co_return(nest_completions(c, match.key + " "));
179                 }
180                 yield co_return(null);
181             }
182         }
183         yield co_return(base_completer(input, pos, conservative));
184     };
189  * Built-in webjumps
190  */
192 function define_delicious_webjumps (username) {
193     define_webjump("delicious", "http://www.delicious.com/" + username + "/%s",
194                    $alternative = "http://www.delicious.com/" + username);
195     define_webjump("adelicious", "javascript:location.href='http://www.delicious.com/save"+
196                    "?v=2&url='+encodeURIComponent(location.href)+'&title='+"+
197                    "encodeURIComponent(document.title);");
198     define_webjump("sdelicious", "http://www.delicious.com/search?p=%s&u="+username+
199                    "&chk=&context=userposts&fr=del_icio_us&lc=1");
200     define_webjump("sadelicious", "http://www.delicious.com/search/all?search=%s");
203 function define_lastfm_webjumps (username) {
204     if (! username) username = "";
205     define_webjump("lastfm", "http://www.last.fm/user/"+username);
206     define_webjump("lastfm-user", "http://www.last.fm/user/%s");
207     define_webjump("lastfm-music", "http://www.last.fm/search?m=all&q=%s");
208     define_webjump("lastfm-group", "http://www.last.fm/users/groups?s_bio=%s");
209     define_webjump("lastfm-tag", "http://www.last.fm/search?m=tag&q=%s");
210     define_webjump("lastfm-label", "http://www.last.fm/search?m=label&q=%s");
211     define_webjump("lastfm-event", "http://www.last.fm/events?by=artists&q=%s");
214 function define_default_webjumps () {
215     define_webjump("conkerorwiki",
216                    "http://conkeror.org/?action=fullsearch&context=60&value=%s&fullsearch=Text");
217     define_webjump("lucky",      "http://www.google.com/search?q=%s&btnI=I'm Feeling Lucky");
218     define_webjump("maps",       "http://maps.google.com/?q=%s");
219     define_webjump("scholar",    "http://scholar.google.com/scholar?q=%s");
220     define_webjump("slang",      "http://www.urbandictionary.com/define.php?term=%s");
221     define_webjump("dictionary", "http://dictionary.reference.com/search?q=%s");
222     define_webjump("image",      "http://images.google.com/images?q=%s");
223     define_webjump("clhs",
224                    "http://www.xach.com/clhs?q=%s",
225                    $alternative = "http://www.lispworks.com/documentation/HyperSpec/Front/index.htm");
226     define_webjump("cliki",      "http://www.cliki.net/admin/search?words=%s");
227     define_webjump("stumpwmwiki", "http://github.com/sabetts/stumpwm/search?q=%s");
228     define_webjump("savannah",
229                    "http://savannah.gnu.org/search/?words=%s&type_of_search=soft&Search=Search&exact=1");
230     define_webjump("sourceforge", "http://sourceforge.net/search/?words=%s");
231     define_webjump("freshmeat", "http://freshmeat.net/search/?q=%s");
232     define_webjump("slashdot", "http://slashdot.org/search.pl?query=%s");
233     define_webjump("kuro5hin", "http://www.kuro5hin.org/?op=search&string=%s");
236 define_default_webjumps();
238 provide("webjump");