Add the base of a highly experimental gui for NixOS.
svn path=/nixos/trunk/; revision=17455
This commit is contained in:
parent
a701637f94
commit
5bf3abba14
|
@ -0,0 +1,19 @@
|
|||
This file should become a nix expression.
|
||||
|
||||
you need to:
|
||||
- download the latest jQuery from:
|
||||
http://jqueryjs.googlecode.com/files/jquery-1.3.2.js
|
||||
SHA1 Checksum: f0b95e99225f314fbe37ccf6b74ce2f916c517de
|
||||
|
||||
- install 'xulrunner' with nix:
|
||||
nix-env -i xulrunner
|
||||
|
||||
- install and add nix-intantiate in your path
|
||||
|
||||
- have /etc/nixos/nixpkgs
|
||||
- have /etc/nixos/nixos
|
||||
|
||||
|
||||
to run it, either:
|
||||
- cd /etc/nixos/nixos/gui; ./nixos-gui
|
||||
- xulrunner /etc/nixos/nixos/gui/application.ini
|
|
@ -0,0 +1,35 @@
|
|||
[App]
|
||||
;
|
||||
; This field specifies your organization's name. This field is recommended,
|
||||
; but optional.
|
||||
Vendor=NixOS
|
||||
;
|
||||
; This field specifies your application's name. This field is required.
|
||||
Name=NixOS-gui
|
||||
;
|
||||
; This field specifies your application's version. This field is optional.
|
||||
Version=0.0
|
||||
;
|
||||
; This field specifies your application's build ID (timestamp). This field is
|
||||
; required.
|
||||
BuildID=20090925
|
||||
;
|
||||
; This field specifies a compact copyright notice for your application. This
|
||||
; field is optional.
|
||||
;Copyright=
|
||||
;
|
||||
; This ID is just an example. Every XUL app ought to have it's own unique ID.
|
||||
; You can use the microsoft "guidgen" or "uuidgen" tools, or go on
|
||||
; irc.mozilla.org and /msg botbot uuid. This field is optional.
|
||||
;ID=
|
||||
|
||||
[Gecko]
|
||||
;
|
||||
; This field is required. It specifies the minimum Gecko version that this
|
||||
; application requires.
|
||||
MinVersion=1.9a5
|
||||
;
|
||||
; This field is optional. It specifies the maximum Gecko version that this
|
||||
; application requires. It should be specified if your application uses
|
||||
; unfrozen interfaces.
|
||||
;MaxVersion=1.9.0.*
|
|
@ -0,0 +1 @@
|
|||
content nixos-gui content/nixos-gui/
|
|
@ -0,0 +1,74 @@
|
|||
function makeTempFile(prefix)
|
||||
{
|
||||
var file = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties)
|
||||
.get("TmpD", Components.interfaces.nsIFile);
|
||||
file.append(prefix || "xulrunner");
|
||||
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0664);
|
||||
return file;
|
||||
}
|
||||
|
||||
function writeToFile(file, data)
|
||||
{
|
||||
// file is nsIFile, data is a string
|
||||
var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIFileOutputStream);
|
||||
|
||||
// use 0x02 | 0x10 to open file for appending.
|
||||
foStream.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
|
||||
foStream.write(data, data.length);
|
||||
foStream.close();
|
||||
}
|
||||
|
||||
function readFromFile(file)
|
||||
{
|
||||
// |file| is nsIFile
|
||||
var data = "";
|
||||
var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Components.interfaces.nsIFileInputStream);
|
||||
var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Components.interfaces.nsIScriptableInputStream);
|
||||
fstream.init(file, -1, 0, 0);
|
||||
sstream.init(fstream);
|
||||
|
||||
var str = sstream.read(4096);
|
||||
while (str.length > 0) {
|
||||
data += str;
|
||||
str = sstream.read(4096);
|
||||
}
|
||||
|
||||
sstream.close();
|
||||
fstream.close();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function runProgram(commandLine)
|
||||
{
|
||||
// create an nsILocalFile for the executable
|
||||
var file = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
file.initWithPath("/bin/sh");
|
||||
|
||||
// create an nsIProcess
|
||||
var process = Components.classes["@mozilla.org/process/util;1"]
|
||||
.createInstance(Components.interfaces.nsIProcess);
|
||||
process.init(file);
|
||||
|
||||
// Run the process.
|
||||
// If first param is true, calling thread will be blocked until
|
||||
// called process terminates.
|
||||
// Second and third params are used to pass command-line arguments
|
||||
// to the process.
|
||||
var args = ["-c", commandLine];
|
||||
process.run(true, args, args.length);
|
||||
}
|
||||
|
||||
// only for testing...
|
||||
function testIO()
|
||||
{
|
||||
var f = makeTempFile();
|
||||
writeToFile(f, "essai\ntest");
|
||||
alert(readFromFile(f));
|
||||
runProgram("zenity --info");
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
var COPYCOL = 2;
|
||||
var gOptionListView = new treeView(["opt-success","opt-name","opt-desc"],
|
||||
COPYCOL);
|
||||
|
||||
// Run xulrunner application.ini -jsconsole -console, to see messages.
|
||||
function log(str)
|
||||
{
|
||||
Components.classes['@mozilla.org/consoleservice;1']
|
||||
.getService(Components.interfaces.nsIConsoleService)
|
||||
.logStringMessage(str);
|
||||
}
|
||||
|
||||
|
||||
// return the DOM of the value returned by nix-instantiate
|
||||
function dumpOptions(path)
|
||||
{
|
||||
var nixInstantiate = "nix-instantiate"; // "@nix@/bin/nix-instantiate";
|
||||
var nixos = "/etc/nixos/nixos/default.nix"; // "@nixos@/default.nix";
|
||||
|
||||
var o = makeTempFile("nixos-options");
|
||||
|
||||
path = "eval.options" + (path? "." + path : "");
|
||||
log("retrieve options from: " + path);
|
||||
|
||||
runProgram(nixInstantiate+" "+nixos+" -A "+path+" --eval-only --strict --xml 2>/dev/null | tr -d '' >" + o.path);
|
||||
|
||||
var xml = readFromFile(o);
|
||||
o.remove(false);
|
||||
|
||||
// jQuery does a stack overflow when converting the XML to a DOM.
|
||||
var dom = DOMParser().parseFromString(xml, "text/xml");
|
||||
|
||||
log("return dom");
|
||||
return dom;
|
||||
}
|
||||
|
||||
|
||||
// Pretty print Nix values.
|
||||
function nixPP(value, level)
|
||||
{
|
||||
function indent(level) { ret = ""; while (level--) ret+= " "; return ret; }
|
||||
|
||||
if (!level) level = 0;
|
||||
var ret = "<no match>";
|
||||
if (value.is("attrs")) {
|
||||
var content = "";
|
||||
value.children().each(function (){
|
||||
var name = $(this).attr("name");
|
||||
var value = nixPP($(this).children(), level + 1);
|
||||
content += indent(level + 1) + name + " = " + value + ";\n";
|
||||
});
|
||||
ret = "{\n" + content + indent(level) + "}";
|
||||
}
|
||||
else if (value.is("list")) {
|
||||
var content = "";
|
||||
value.children().each(function (){
|
||||
content += indent(level + 1) + "(" + nixPP($(this), level + 1) + ")\n";
|
||||
});
|
||||
ret = "[\n" + content + indent(level) + "]";
|
||||
}
|
||||
else if (value.is("bool"))
|
||||
ret = (value.attr("value") == "true");
|
||||
else if (value.is("string"))
|
||||
ret = '"' + value.attr("value") + '"';
|
||||
else if (value.is("path"))
|
||||
ret = value.attr("value");
|
||||
else if (value.is("int"))
|
||||
ret = parseInt(value.attr("value"));
|
||||
else if (value.is("derivation"))
|
||||
ret = value.attr("outPath");
|
||||
else if (value.is("function"))
|
||||
ret = "<function>";
|
||||
else {
|
||||
var content = "";
|
||||
value.children().each(function (){
|
||||
content += indent(level + 1) + "(" + nixPP($(this), level + 1) + ")\n";
|
||||
});
|
||||
ret = "<!--" + value.selector + "--><!--\n" + content + indent(level) + "-->";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Function used to reproduce the select operator on the XML DOM.
|
||||
// It return the value contained in the targeted attribute.
|
||||
function nixSelect(attrs, selector)
|
||||
{
|
||||
var names = selector.split(".");
|
||||
var value = $(attrs);
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
log(nixPP(value) + "." + names[i]);
|
||||
if (value.is("attrs"))
|
||||
value = value.children("attr[name='" + names[i] + "']").children();
|
||||
else {
|
||||
log("Cannot do an attribute selection.");
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
log("nixSelect return: " + nixPP(value));
|
||||
|
||||
var ret;
|
||||
if (value.is("attrs") || value.is("list"))
|
||||
ret = value;
|
||||
else if (value.is("bool"))
|
||||
ret = value.attr("value") == "true";
|
||||
else if (value.is("string"))
|
||||
ret = value.attr("value");
|
||||
else if (value.is("int"))
|
||||
ret = parseInt(value.attr("value"));
|
||||
else if (value.is("derivation"))
|
||||
ret = value.attr("outPath");
|
||||
else if (value.is("function"))
|
||||
ret = "<function>";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
var gProgressBar;
|
||||
function setProgress(current, max)
|
||||
{
|
||||
if (gProgressBar) {
|
||||
gProgressBar.value = 100 * current / max;
|
||||
log("progress: " + gProgressBar.value + "%");
|
||||
}
|
||||
else
|
||||
log("unknow progress bar");
|
||||
}
|
||||
|
||||
// fill the list of options
|
||||
function setOptionList(optionDOM)
|
||||
{
|
||||
var options = $("attrs", optionDOM).filter(function () {
|
||||
return $(this)
|
||||
.children("attr[name='_type']")
|
||||
.children("string[value='option']")
|
||||
.length != 0;
|
||||
});
|
||||
|
||||
var max = options.length;
|
||||
|
||||
log("Number of options: " + max);
|
||||
|
||||
setProgress(0, max);
|
||||
gOptionListView.clear();
|
||||
options.each(function (index){
|
||||
var success = nixSelect(this, "config.success");
|
||||
var name = nixSelect(this, "name");
|
||||
var desc = nixSelect(this, "description");
|
||||
if (success && name && desc) {
|
||||
log("Add option '" + name + "' in the list.");
|
||||
gOptionListView.addRow([success, name, desc]);
|
||||
}
|
||||
else
|
||||
log("A problem occur while scanning an option.");
|
||||
setProgress(index + 1, max);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function onload()
|
||||
{
|
||||
var optionList = document.getElementById("option-list");
|
||||
gProgressBar = document.getElementById("progress-bar");
|
||||
setProgress(0, 1);
|
||||
optionList.view = gOptionListView;
|
||||
|
||||
// try to avoid blocking the rendering, unfortunately this is not perfect.
|
||||
setTimeout(function (){
|
||||
setOptionList(dumpOptions("hardware"));}
|
||||
, 100);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window>
|
||||
|
||||
<!-- To edit this file I recommend you to use:
|
||||
http://xulfr.org/outils/xulediteur.xul
|
||||
-->
|
||||
|
||||
<window
|
||||
id = "nixos-gui"
|
||||
title = "NixOS gui"
|
||||
xmlns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="jquery-1.3.2.js"/>
|
||||
<script src="treeView.js"/>
|
||||
<script src="main.js"/>
|
||||
<script src="io.js"/>
|
||||
<tree flex="1" id="option-list" persist="height">
|
||||
<treecols>
|
||||
<treecol persist="hidden width" flex="1" id="opt-success" label="Success"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol persist="hidden width" flex="30" id="opt-name" label="Option"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol persist="hidden width" flex="50" id="opt-desc" label="Description"
|
||||
primary="true"/>
|
||||
</treecols>
|
||||
<treechildren id="first-child" flex="1"/>
|
||||
</tree>
|
||||
<progressmeter id="progress-bar" value="0%"/>
|
||||
</window>
|
|
@ -0,0 +1,117 @@
|
|||
// Taken from pageInfo.js
|
||||
|
||||
//******** define a js object to implement nsITreeView
|
||||
function treeView(columnids, copycol)
|
||||
{
|
||||
// columnids is an array of strings indicating the names of the columns, in order
|
||||
this.columnids = columnids;
|
||||
this.colcount = columnids.length;
|
||||
|
||||
// copycol is the index number for the column that we want to add to
|
||||
// the copy-n-paste buffer when the user hits accel-c
|
||||
this.copycol = copycol;
|
||||
this.rows = 0;
|
||||
this.tree = null;
|
||||
this.data = [ ];
|
||||
this.selection = null;
|
||||
this.sortcol = null;
|
||||
this.sortdir = 0;
|
||||
}
|
||||
|
||||
treeView.prototype = {
|
||||
set rowCount(c) { throw "rowCount is a readonly property"; },
|
||||
get rowCount() { return this.rows; },
|
||||
|
||||
setTree: function(tree)
|
||||
{
|
||||
this.tree = tree;
|
||||
},
|
||||
|
||||
getCellText: function(row, column)
|
||||
{
|
||||
// row can be null, but js arrays are 0-indexed.
|
||||
// colidx cannot be null, but can be larger than the number
|
||||
// of columns in the array (when column is a string not in
|
||||
// this.columnids.) In this case it's the fault of
|
||||
// whoever typoed while calling this function.
|
||||
return this.data[row][column.index] || "";
|
||||
},
|
||||
|
||||
setCellValue: function(row, column, value)
|
||||
{
|
||||
},
|
||||
|
||||
setCellText: function(row, column, value)
|
||||
{
|
||||
this.data[row][column.index] = value;
|
||||
},
|
||||
|
||||
addRow: function(row)
|
||||
{
|
||||
this.rows = this.data.push(row);
|
||||
this.rowCountChanged(this.rows - 1, 1);
|
||||
},
|
||||
|
||||
addRows: function(rows)
|
||||
{
|
||||
var length = rows.length;
|
||||
for(var i = 0; i < length; i++)
|
||||
this.rows = this.data.push(rows[i]);
|
||||
this.rowCountChanged(this.rows - length, length);
|
||||
},
|
||||
|
||||
rowCountChanged: function(index, count)
|
||||
{
|
||||
this.tree.rowCountChanged(index, count);
|
||||
},
|
||||
|
||||
invalidate: function()
|
||||
{
|
||||
this.tree.invalidate();
|
||||
},
|
||||
|
||||
clear: function()
|
||||
{
|
||||
if (this.tree)
|
||||
this.tree.rowCountChanged(0, -this.rows);
|
||||
this.rows = 0;
|
||||
this.data = [ ];
|
||||
},
|
||||
|
||||
handleCopy: function(row)
|
||||
{
|
||||
return (row < 0 || this.copycol < 0) ? "" : (this.data[row][this.copycol] || "");
|
||||
},
|
||||
|
||||
performActionOnRow: function(action, row)
|
||||
{
|
||||
if (action == "copy") {
|
||||
var data = this.handleCopy(row)
|
||||
this.tree.treeBody.parentNode.setAttribute("copybuffer", data);
|
||||
}
|
||||
},
|
||||
|
||||
getRowProperties: function(row, prop) { },
|
||||
getCellProperties: function(row, column, prop) { },
|
||||
getColumnProperties: function(column, prop) { },
|
||||
isContainer: function(index) { return false; },
|
||||
isContainerOpen: function(index) { return false; },
|
||||
isSeparator: function(index) { return false; },
|
||||
isSorted: function() { },
|
||||
canDrop: function(index, orientation) { return false; },
|
||||
drop: function(row, orientation) { return false; },
|
||||
getParentIndex: function(index) { return 0; },
|
||||
hasNextSibling: function(index, after) { return false; },
|
||||
getLevel: function(index) { return 0; },
|
||||
getImageSrc: function(row, column) { },
|
||||
getProgressMode: function(row, column) { },
|
||||
getCellValue: function(row, column) { },
|
||||
toggleOpenState: function(index) { },
|
||||
cycleHeader: function(col) { },
|
||||
selectionChanged: function() { },
|
||||
cycleCell: function(row, column) { },
|
||||
isEditable: function(row, column) { return false; },
|
||||
isSelectable: function(row, column) { return false; },
|
||||
performAction: function(action) { },
|
||||
performActionOnCell: function(action, row, column) { }
|
||||
};
|
|
@ -0,0 +1,154 @@
|
|||
const nsIAppShellService = Components.interfaces.nsIAppShellService;
|
||||
const nsISupports = Components.interfaces.nsISupports;
|
||||
const nsICategoryManager = Components.interfaces.nsICategoryManager;
|
||||
const nsIComponentRegistrar = Components.interfaces.nsIComponentRegistrar;
|
||||
const nsICommandLine = Components.interfaces.nsICommandLine;
|
||||
const nsICommandLineHandler = Components.interfaces.nsICommandLineHandler;
|
||||
const nsIFactory = Components.interfaces.nsIFactory;
|
||||
const nsIModule = Components.interfaces.nsIModule;
|
||||
const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
|
||||
|
||||
// CHANGEME: to the chrome URI of your extension or application
|
||||
const CHROME_URI = "chrome://nixos-gui/content/myviewer.xul";
|
||||
|
||||
// CHANGEME: change the contract id, CID, and category to be unique
|
||||
// to your application.
|
||||
const clh_contractID = "@mozilla.org/commandlinehandler/general-startup;1?type=myapp";
|
||||
|
||||
// use uuidgen to generate a unique ID
|
||||
const clh_CID = Components.ID("{2991c315-b871-42cd-b33f-bfee4fcbf682}");
|
||||
|
||||
// category names are sorted alphabetically. Typical command-line handlers use a
|
||||
// category that begins with the letter "m".
|
||||
const clh_category = "m-myapp";
|
||||
|
||||
/**
|
||||
* Utility functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Opens a chrome window.
|
||||
* @param aChromeURISpec a string specifying the URI of the window to open.
|
||||
* @param aArgument an argument to pass to the window (may be null)
|
||||
*/
|
||||
function openWindow(aChromeURISpec, aArgument)
|
||||
{
|
||||
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Components.interfaces.nsIWindowWatcher);
|
||||
ww.openWindow(null, aChromeURISpec, "_blank",
|
||||
"chrome,menubar,toolbar,status,resizable,dialog=no",
|
||||
aArgument);
|
||||
}
|
||||
|
||||
/**
|
||||
* The XPCOM component that implements nsICommandLineHandler.
|
||||
* It also implements nsIFactory to serve as its own singleton factory.
|
||||
*/
|
||||
const myAppHandler = {
|
||||
/* nsISupports */
|
||||
QueryInterface : function clh_QI(iid)
|
||||
{
|
||||
if (iid.equals(nsICommandLineHandler) ||
|
||||
iid.equals(nsIFactory) ||
|
||||
iid.equals(nsISupports))
|
||||
return this;
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
/* nsICommandLineHandler */
|
||||
|
||||
handle : function clh_handle(cmdLine)
|
||||
{
|
||||
openWindow(CHROME_URI, cmdLine);
|
||||
cmdLine.preventDefault = true;
|
||||
},
|
||||
|
||||
// CHANGEME: change the help info as appropriate, but
|
||||
// follow the guidelines in nsICommandLineHandler.idl
|
||||
// specifically, flag descriptions should start at
|
||||
// character 24, and lines should be wrapped at
|
||||
// 72 characters with embedded newlines,
|
||||
// and finally, the string should end with a newline
|
||||
helpInfo : " <filename> Open the file in the viewer\n",
|
||||
|
||||
/* nsIFactory */
|
||||
|
||||
createInstance : function clh_CI(outer, iid)
|
||||
{
|
||||
if (outer != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
|
||||
lockFactory : function clh_lock(lock)
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The XPCOM glue that implements nsIModule
|
||||
*/
|
||||
const myAppHandlerModule = {
|
||||
/* nsISupports */
|
||||
QueryInterface : function mod_QI(iid)
|
||||
{
|
||||
if (iid.equals(nsIModule) ||
|
||||
iid.equals(nsISupports))
|
||||
return this;
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
/* nsIModule */
|
||||
getClassObject : function mod_gch(compMgr, cid, iid)
|
||||
{
|
||||
if (cid.equals(clh_CID))
|
||||
return myAppHandler.QueryInterface(iid);
|
||||
|
||||
throw Components.results.NS_ERROR_NOT_REGISTERED;
|
||||
},
|
||||
|
||||
registerSelf : function mod_regself(compMgr, fileSpec, location, type)
|
||||
{
|
||||
compMgr.QueryInterface(nsIComponentRegistrar);
|
||||
|
||||
compMgr.registerFactoryLocation(clh_CID,
|
||||
"myAppHandler",
|
||||
clh_contractID,
|
||||
fileSpec,
|
||||
location,
|
||||
type);
|
||||
|
||||
var catMan = Components.classes["@mozilla.org/categorymanager;1"].
|
||||
getService(nsICategoryManager);
|
||||
catMan.addCategoryEntry("command-line-handler",
|
||||
clh_category,
|
||||
clh_contractID, true, true);
|
||||
},
|
||||
|
||||
unregisterSelf : function mod_unreg(compMgr, location, type)
|
||||
{
|
||||
compMgr.QueryInterface(nsIComponentRegistrar);
|
||||
compMgr.unregisterFactoryLocation(clh_CID, location);
|
||||
|
||||
var catMan = Components.classes["@mozilla.org/categorymanager;1"].
|
||||
getService(nsICategoryManager);
|
||||
catMan.deleteCategoryEntry("command-line-handler", clh_category);
|
||||
},
|
||||
|
||||
canUnload : function (compMgr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/* The NSGetModule function is the magic entry point that XPCOM uses to find what XPCOM objects
|
||||
* this component provides
|
||||
*/
|
||||
function NSGetModule(comMgr, fileSpec)
|
||||
{
|
||||
return myAppHandlerModule;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
pref("toolkit.defaultChromeURI", "chrome://nixos-gui/content/myviewer.xul");
|
||||
pref("general.useragent.extra.myviewer", "NixOS gui/0.0");
|
||||
|
||||
/* debugging prefs */
|
||||
pref("browser.dom.window.dump.enabled", true); // enable output to stderr
|
||||
pref("javascript.options.showInConsole", true); // show javascript errors from chrome: files in the jsconsole
|
||||
pref("javascript.options.strict", true); // show javascript strict warnings in the jsconsole
|
||||
|
||||
/* disable xul cache so that modifications to chrome: files apply without restarting xulrunner */
|
||||
pref("nglayout.debug.disable_xul_cache", true);
|
||||
pref("nglayout.debug.disable_xul_fastload", true);
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
exec xulrunner "./application.ini"
|
Loading…
Reference in New Issue