diff options
Diffstat (limited to 'nixos/gui/chrome/content/nixos.js')
-rw-r--r-- | nixos/gui/chrome/content/nixos.js | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/nixos/gui/chrome/content/nixos.js b/nixos/gui/chrome/content/nixos.js new file mode 100644 index 000000000000..63a3c16a573f --- /dev/null +++ b/nixos/gui/chrome/content/nixos.js @@ -0,0 +1,255 @@ + +function NixOS () { + var env = Components.classes["@mozilla.org/process/environment;1"]. + getService(Components.interfaces.nsIEnvironment); + + if (env.exists("NIXOS")) + this.nixos = env.get("NIXOS"); + if (env.exists("NIXOS_CONFIG")) + this.config = env.get("NIXOS_CONFIG"); + if (env.exists("NIXPKGS")) + this.nixpkgs = env.get("NIXPKGS"); + if (env.exists("mountPoint")) + this.root = env.get("mountPoint"); + if (env.exists("NIXOS_OPTION")) + this.optionBin = env.get("NIXOS_OPTION"); + this.option = new Option("options", this, null); +}; + +NixOS.prototype = { + root: "", + nixos: "/etc/nixos/nixos", + nixpkgs: "/etc/nixos/nixpkgs", + config: "/etc/nixos/configuration.nix", + instantiateBin: "/run/current-system/sw/bin/nix-instantiate", + optionBin: "/run/current-system/sw/bin/nixos-option", + tmpFile: "nixos-gui", + option: null +}; + +function Option (name, context, parent) { + this.name = name; + this.context_ = context; + if (parent == null) + this.path = ""; + else if (parent.path == "") + this.path = name; + else + this.path = parent.path + "." + name; +}; + +Option.prototype = { + load: function () { + var env = ""; + env += "'NIXOS=" + this.context_.root + this.context_.nixos + "' "; + env += "'NIXOS_PKGS=" + this.context_.root + this.context_.nixpkgs + "' "; + env += "'NIXOS_CONFIG=" + this.context_.config + "' "; + var out = makeTempFile(this.context_.tmpFile); + var prog = this.context_.optionBin + " 2>&1 >" + out.path + " "; + var args = " --xml " + this.path; + + runProgram(/*env + */ prog + args); + var xml = readFromFile(out); + out.remove(false); + + // jQuery does a stack overflow when converting a huge XML to a DOM. + var dom = DOMParser().parseFromString(xml, "text/xml"); + var xmlAttrs = $("expr > attrs > attr", dom); + + this.isOption = xmlAttrs.first().attr("name") == "_isOption"; + + if (!this.isOption) + this.loadSubOptions(xmlAttrs); + else + this.loadOption(xmlAttrs); + this.isLoaded = true; + }, + + loadSubOptions: function (xmlAttrs) { + var cur = this; + var attrs = new Array(); + + xmlAttrs.each( + function (index) { + var name = $(this).attr("name"); + var attr = new Option(name, cur.context_, cur); + attrs.push(attr); + } + ); + + this.subOptions = attrs; + }, + + optionAttributeMap: { + _isOption: function (cur, v) { }, + value: function (cur, v) { cur.value = xml2nix($(v).children().first()); }, + default: function (cur, v) { cur.defaultValue = xml2nix($(v).children().first()); }, + example: function (cur, v) { cur.example = xml2nix($(v).children().first()); }, + description: function (cur, v) { cur.description = this.string(v); }, + typename: function (cur, v) { cur.typename = this.string(v); }, + options: function (cur, v) { cur.loadSubOptions($("attrs", v).children()); }, + declarations: function (cur, v) { cur.declarations = this.pathList(v); }, + definitions: function (cur, v) { cur.definitions = this.pathList(v); }, + + string: function (v) { + return $(v).children("string").first().attr("value"); + }, + + pathList: function (v) { + var list = []; + $(v).children("list").first().children().each( + function (idx) { + list.push($(this).attr("value")); + } + ); + return list; + } + }, + + + loadOption: function (attrs) { + var cur = this; + + attrs.each( + function (index) { + var name = $(this).attr("name"); + log("loadOption: " + name); + cur.optionAttributeMap[name](cur, this); + } + ); + }, + + // keep the context under which this option has been used. + context_: null, + // name of the option. + name: "", + // result of nixos-option. + value: null, + typename: null, + defaultValue: null, + example: null, + description: "", + declarations: [], + definitions: [], + // path to reach this option + path: "", + + // list of options accessible from here. + isLoaded: false, + isOption: false, + subOptions: [] +}; + +var xml2nix_pptable = { + attrs: function (node, depth, pp) { + var children = node.children().not( + function () { + var name = $(this).attr("name"); + return name.charAt(0) == "_"; + } + ); + var c = 0; + var out = ""; + out += "{"; + depth += 1; + children.each( + function (idx) { + c += 1; + out += pp.indent(depth); + out += pp.dispatch($(this), depth, pp); + } + ); + depth -= 1; + if (c > 0) + out += this.indent(depth); + else + out += " "; + out += "}"; + return out; + }, + list: function (node, depth, pp) { + var children = node.children(); + var c = 0; + var out = ""; + out += "["; + depth += 1; + children.each( + function (idx) { + c += 1; + out += pp.indent(depth); + out += pp.dispatch($(this), depth, pp); + } + ); + depth -= 1; + if (c > 0) + out += this.indent(depth); + else + out += " "; + out += "]"; + return out; + }, + attr: function (node, depth, pp) { + var name = node.attr("name"); + var out = ""; + var val = ""; + out += name + " = "; + depth += 1; + val = pp.dispatch(node.children().first(), depth, pp); + out += val; + depth -= 1; + out += ";"; + return out; + }, + string: function (node, depth, pp) { + return "\"" + node.attr("value") + "\""; + }, + path: function (node, depth, pp) { + return node.attr("value"); + }, + bool: function (node, depth, pp) { + return node.attr("value"); + }, + "int": function (node, depth, pp) { + return node.attr("value"); + }, + null: function (node, depth, pp) { + return "null"; + }, + derivation: function (node, depth, pp) { + return "<derivation>"; + }, + function: function (node, depth, pp) { + return "<function>"; + }, + unevaluated: function (node, depth, pp) { + return "<unevaluated>"; + }, + + dispatch: function (node, depth, pp) { + for (var key in pp) + { + if(node.is(key)) + { + // log(this.indent(depth) + "dispatch: " + key); + var out = pp[key](node, depth, pp); + // log(this.indent(depth) + "dispatch: => " + out); + return out; + } + } + return "<dispatch-error>"; + }, + indent: function (depth) { + var ret = "\n"; + while (depth--) + ret += " "; + return ret; + } +}; + +function xml2nix(node) { + var depth = 0; + var pp = xml2nix_pptable; + var out = pp.dispatch(node, depth, pp); + // log("pretty:\n" + out); + return out; +} |