2 * (C) Copyright 2004-2007 Shawn Betts
3 * (C) Copyright 2007-2008,2012 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 define_keywords("$alternative", "$completer", "$doc", "$post_data",
12 function webjump (name, handler) {
15 $require_match = false);
17 this.alternative = arguments.$alternative;
18 this.completer = arguments.$completer;
19 this.doc = arguments.$doc;
20 this.post_data = arguments.$post_data;
21 this.require_match = arguments.$require_match;
22 if (typeof handler == "function") {
23 if (handler.length == 0)
24 this.argument = false;
25 else if (this.alternative == null)
27 this.handler = handler;
28 } else if (typeof handler == "string") {
29 if (handler.indexOf("%s") == -1 &&
30 (! this.post_data || this.post_data.every(function (x) x[1] != "%s")))
32 this.argument = false;
33 } else if (this.alternative == null) {
35 this.alternative = true; // use same handler
37 this.alternative = url_path_trim(handler);
40 this.handler = this._make_post_handler(handler);
42 this.handler = this._make_string_handler(handler);
44 throw Error("bad handler type");
48 toString: function () "#<webjump>",
54 argument: null, // null represents optional argument
56 _make_string_handler: function (template) {
57 var b = template.indexOf('%s');
58 return function (arg) {
60 // Just return the same string if it doesn't contain a %s
63 return template.substr(0,b) + encodeURIComponent(arg) + template.substring(a);
66 _make_post_handler: function (uri) {
68 return function (arg) {
71 post_data: make_post_data(w.post_data.map(function (pair) {
73 return [pair[0], arg];
80 call: function (arg) {
81 if (arg == null && this.argument == true)
82 throw interactive_error("Webjump "+this.name+" requires an argument.");
83 if (arg || this.alternative == true || this.argument == false)
84 return this.handler(arg);
85 return this.alternative
92 function define_webjump (name, handler) {
94 var w = new webjump(name, handler, forward_keywords(arguments));
98 function clear_webjumps () {
102 define_variable("webjump_partial_match", true,
103 "When entering a url, if the input is not a webjump, " +
104 "but would uniquely complete to a webjump, then accept " +
105 "that webjump only if this is true.");
107 function match_webjump (str) {
108 var sp = str.split(/(\s+)/, 2);
113 var arg = str.substr(key.length + sep.length);
115 // Look for an exact match
116 var match = webjumps[key];
118 // Look for a partial match
119 if (! match && webjump_partial_match) {
120 for (let [k, v] in Iterator(webjumps)) {
121 if (String(k).substring(0, key.length) == key) {
122 if (match) // prefix must be unique for a partial match
123 return [null, null, null, null];
129 return [match, key, sep, arg];
130 return [null, null, null, null];
134 function get_webjump (value) {
135 let [w, key, sep, arg] = match_webjump(value);
141 function get_url_or_webjump (input) {
142 return get_webjump(input) || input;
146 // a webjump completer is a nesting of two completers: one that completes
147 // on webjump names, and one specific to the individual webjump.
148 function webjump_name_completer () {
149 prefix_completer.call(this,
150 $completions = object_values(webjumps),
151 $get_string = function (x) x.name + (x.argument == false ? "" : " "),
152 $get_description = function (x) x.doc || "");
154 webjump_name_completer.prototype = {
155 constructor: webjump_name_completer,
156 __proto__: prefix_completer.prototype,
157 toString: function () "#<webjump_name_completer>"
161 function webjump_completer () {
162 completer.call(this);
163 this.webjump_name_completer = new webjump_name_completer();
165 webjump_completer.prototype = {
166 constructor: webjump_completer,
167 __proto__: completer.prototype,
168 toString: function () "#<webjump_completer>",
169 webjump_name_completer: null,
170 require_match: false,
171 complete: function (input, pos) {
172 this.require_match = false;
173 let [w, key, sep, arg] = match_webjump(input);
174 var current_part = position_in_strings([key, sep, arg], pos);
175 if (current_part % 2)
177 if (current_part) { // complete on the argument
179 this.require_match = w.require_match;
180 var c = yield w.completer.complete(arg, pos - key.length - sep.length);
181 yield co_return(nest_completions(c, w.name + " "));
183 yield co_return(null);
186 // complete on the webjump name
187 yield co_return(this.webjump_name_completer.complete(input, pos));
196 function define_delicious_webjumps (username) {
197 define_webjump("delicious", "http://www.delicious.com/" + username + "/%s",
198 $alternative = "http://www.delicious.com/" + username);
199 define_webjump("adelicious", "javascript:location.href='http://www.delicious.com/save"+
200 "?v=2&url='+encodeURIComponent(location.href)+'&title='+"+
201 "encodeURIComponent(document.title);");
202 define_webjump("sdelicious", "http://www.delicious.com/search?p=%s&u="+username+
203 "&chk=&context=userposts&fr=del_icio_us&lc=1");
204 define_webjump("sadelicious", "http://www.delicious.com/search/all?search=%s");
207 function define_lastfm_webjumps (username) {
208 if (! username) username = "";
209 define_webjump("lastfm", "http://www.last.fm/user/"+username);
210 define_webjump("lastfm-user", "http://www.last.fm/user/%s");
211 define_webjump("lastfm-music", "http://www.last.fm/search?m=all&q=%s");
212 define_webjump("lastfm-group", "http://www.last.fm/users/groups?s_bio=%s");
213 define_webjump("lastfm-tag", "http://www.last.fm/search?m=tag&q=%s");
214 define_webjump("lastfm-label", "http://www.last.fm/search?m=label&q=%s");
215 define_webjump("lastfm-event", "http://www.last.fm/events?by=artists&q=%s");
218 function define_default_webjumps () {
219 define_webjump("conkerorwiki",
220 "http://conkeror.org/?action=fullsearch&context=60&value=%s&fullsearch=Text");
221 define_webjump("lucky", "https://www.google.com/search?q=%s&btnI=I'm Feeling Lucky");
222 define_webjump("maps", "https://maps.google.com/?q=%s");
223 define_webjump("scholar", "https://scholar.google.com/scholar?q=%s");
224 define_webjump("slang", "https://www.urbandictionary.com/define.php?term=%s");
225 define_webjump("dictionary", "http://dictionary.reference.com/search?q=%s");
226 define_webjump("image", "https://www.google.com/images?q=%s");
229 define_default_webjumps();