2 * (C) Copyright 2004-2007 Shawn Betts
3 * (C) Copyright 2007-2009,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
11 * trim_whitespace removes whitespace from the beginning and end of the
14 function trim_whitespace (str
) {
15 return (new String(str
)).replace(/^\s+|\s+$/g, "");
19 function shell_quote (str
) {
20 var s
= str
.replace(/"/g, "\\\"");
21 s = s.replace(/\$/g, "\\$");
27 * Like perl's quotemeta. Backslash all non-alphanumerics.
29 function quotemeta (str) {
30 return str.replace(/([^a-zA-Z0-9])/g, "\\$1");
35 * Given a list of choices (strings), return a regexp which matches any
38 function choice_regexp (choices) {
39 return ("(?:" + choices.map(quotemeta).join("|") + ")");
44 * get_shortdoc_string, given a docstring, returns the portion of the
45 * docstring up to the first newline, or the whole docstring.
47 function get_shortdoc_string (doc) {
50 var idx = doc.indexOf("\n");
52 shortdoc = doc.substring(0,idx);
61 * string_format takes a format-string containing %X style format codes,
62 * and an object mapping the code-letters to replacement text. It
63 * returns a string with the formatting codes replaced by the replacement
66 function string_format (spec, substitutions) {
67 return spec.replace(/%(.)/g, function (a, b) substitutions[b]);
72 * html_escape replaces characters which are special in html with character
73 * entities, safe for inserting as text into an html document.
75 function html_escape (str) {
76 return str.replace(/&/g, '&')
77 .replace(/</g, '<')
78 .replace(/>/g, '>')
79 .replace(/\"/g, '"');
84 * get_spaces returns a string of n spaces.
86 function get_spaces (n) {
95 * word_wrap wraps str to line_length.
97 function word_wrap (str, line_length, line_prefix_first, line_prefix) {
98 if (line_prefix === undefined)
99 line_prefix = line_prefix_first;
100 else if (line_prefix.length < line_prefix_first.length) {
101 line_prefix += get_spaces(line_prefix_first.length - line_prefix.length);
104 line_length -= line_prefix_first.length;
109 let cur_prefix = line_prefix_first;
112 while (line_length < str.length) {
113 let i = str.lastIndexOf(" ", line_length);
115 i = str.indexOf(" ", line_length);
117 out += cur_prefix + str + "\n";
121 out += cur_prefix + str.substr(0, i) + "\n";
122 while (i < str.length && str.charAt(i) == " ")
126 cur_prefix = line_prefix;
129 out += cur_prefix + str + "\n";
135 * or_string joins an array of strings on commas, except for the last
136 * pair, which it joins with the word "or
".
138 function or_string (options) {
139 return options.slice(0,options.length-1)
140 .join(", ") + " or
" + options[options.length - 1];
145 * build_url_regexp builds a regular expression to match URLs for a given
148 * Both the $domain and $path arguments can be either regexps, in
149 * which case they will be matched as is, or strings, in which case
150 * they will be matched literally.
152 * $tlds specifies a list of valid top-level-domains to match, and
153 * defaults to .com. Useful for when e.g. foo.org and foo.com are the
156 * If $allow_www is true, www.domain.tld will also be allowed.
158 define_keywords("$domain
", "$path
", "$tlds
", "$allow_www
");
159 function build_url_regexp () {
160 function regexp_to_string (obj) {
161 if (typeof obj == "object
" && "source
" in obj)
163 return quotemeta(obj);
166 keywords(arguments, $path = "", $tlds = ["com
"], $allow_www = false);
167 var domain = regexp_to_string(arguments.$domain);
168 if (arguments.$allow_www) {
169 domain = "(?:www
\.)?" + domain;
171 var path = regexp_to_string(arguments.$path);
172 var tlds = arguments.$tlds;
173 var regexp = "^https
?://" + domain + "\\." + choice_regexp(tlds) + "/" + path;
174 return new RegExp(regexp
);
179 * position_in_strings takes a position and an array of strings, and
180 * returns the index of the string in the array that the position is in.
181 * At any position which is on the boundary between two strings, the lower
182 * string is the one that the position is considered to be in. This
183 * counts also for the first string, so a position of 0 always returns the
184 * index -1, that is, "before the first string".
186 function position_in_strings (strings
, pos
) {
187 for (var i
= 0, t
= 0, n
= strings
.length
;
191 if (strings
[i
] == null || pos
<= t
)
193 t
+= strings
[i
].length
;
200 * version_compare: compare two version strings with nsIVersionComparator.
201 * If a == b, returns 0; if a < b, returns <0; if a > b, returns >0.
203 function version_compare (a
, b
) {
204 var vc
= Cc
["@mozilla.org/xpcom/version-comparator;1"]
205 .getService(Ci
.nsIVersionComparator
);
206 return vc
.compare(a
, b
);
211 * common_prefix_length returns the length of the portions at the start of
212 * strings A and B that are the same, up to optional LIMIT.
214 function common_prefix_length (a
, b
, limit
) {
217 if (limit
== null || alen
< limit
)
221 for (var i
= 0; i
< limit
&& a
[i
] == b
[i
]; ++i
);