dynamic keymaps
[conkeror.git] / modules / labels.js
blob2ce4f99fd6366ca99237a563f888ff767b6f90fb
1 /**
2  * (C) Copyright 2008 Jeremy Maitin-Shepard
3  *
4  * Use, modification, and distribution are subject to the terms specified in the
5  * COPYING file.
6 **/
8 require_later("help.js"); // for pretty_print_value
10 /**
11  * @param name specifies the name of the label to be defined
12  *
13  * The remaining arguments should be strings, specifying the names of
14  * required arguments. Additionally, the last additional argument can
15  * be `null', which indicates that unlimited optional arguments can
16  * follow. If `null' is not specified as the last argument, then it is
17  * assumed that all optional arguments are keyword arguments. The
18  * optional arguments are stored as an array in a member called $.
19  */
20 function define_label (name) {
21     var allow_optional = false;
22     var required_args = [];
23     for (let i = 1; i < arguments.length; ++i) {
24         if (arguments[i] === null) {
25             allow_optional = true;
26             if (i + 1 != arguments.length)
27                 throw new Error("null must be the last argument");
28         } else {
29             required_args.push(arguments[i]);
30         }
31     }
32     function toString () {
33         let optional = this.$;
34         if (optional == null)
35             optional = [];
36         let printed_args = [];
37         let seen_defined_yet = false;
38         for (let i = required_args.length - 1; i >= 0; --i) {
39             let arg = required_args[i];
40             if (seen_defined_yet || this[arg] !== undefined) {
41                 printed_args.unshift(arg + " = " + pretty_print_value(this[arg]));
42                 seen_defined_yet = true;
43             }
44         }
45         printed_args.push.apply(null, optional.map(pretty_print_value));
46         for (let i in this) {
47             if (i.length > 1 && i[0] == "$")
48                 printed_args.push(i + " = " + this[i]);
49         }
50         if (printed_args.length > 0)
51             printed_args = "(" + printed_args.join(", ") + ")";
52         else
53             printed_args = "";
54         return this._name + printed_args;
55     }
56     var result;
57     result = function () {
58         var o = { _name: name, toString: toString, _id: result, __is_label: true, toSource: toString };
59         let max_req_arg = arguments.length;
60         if (max_req_arg > required_args.length)
61             max_req_arg = required_args.length;
62         for (let i = 0; i < max_req_arg; ++i)
63             o[required_args[i]] = arguments[i];
64         if (allow_optional)
65             o.$ = Array.prototype.slice.call(arguments, required_args.length);
66         else
67             write_keywords(o, arguments, required_args.length);
68         return o;
69     };
70     result._name = name;
71     result._id = result;
72     result.$ = [];
73     for (let i in required_args)
74         result[i] = undefined;
75     result.toString = toString;
76     result.__is_label = true;
77     conkeror[name] = result;
80 function label_id (value) {
81     if (value == null)
82         return null;
83     return value._id;