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();