carcass changes
[guerillascript.git] / main / modules / concmd.js
blob391dd1c29be9005a8cc100eff5e2ecd521f2d86a
1 /* coded by Ketmar // Invisible Vector (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * This program is free software. It comes without any warranty, to
5 * the extent permitted by applicable law. You can redistribute it
6 * and/or modify it under the terms of the Do What The Fuck You Want
7 * To Public License, Version 2, as published by Sam Hocevar. See
8 * http://www.wtfpl.net/txt/copying/ for more details.
9 */
10 ////////////////////////////////////////////////////////////////////////////////
11 uses("resource://gre/modules/devtools/gcli.jsm");
13 require("utils/utils");
14 let {oneShotTimer, intervalTimer} = require("utils/timer");
17 ////////////////////////////////////////////////////////////////////////////////
18 let editList = {lmod:-1};
19 let editNames;
22 function getEditList () {
23 let cur = scacheAPI.getScriptsForEdit();
24 if (cur.lmod != editList.lmod) {
25 editList = {lmod:cur.lmod, list:cur.list};
26 editNames = new Array();
27 for (let xnfo of editList.list) editNames.push({name:xnfo.name, value:xnfo.path});
29 return editNames;
33 ////////////////////////////////////////////////////////////////////////////////
34 let pkgList = {lmod:-1};
35 let pkgNames;
38 function getPkgList () {
39 let cur = pkgman.getPackageList();
40 //conlog("getPkgList: pkgList.lmod=", pkgList.lmod, "; cur.lmod=", cur.lmod);
41 if (cur.lmod != pkgList.lmod) {
42 pkgList = {lmod:cur.lmod, list:cur.list};
43 pkgNames = new Array();
44 for (let pi of pkgList.list) pkgNames.push({name:pi.name, value:pi});
46 return pkgNames;
50 ////////////////////////////////////////////////////////////////////////////////
51 function addjsext (fn) {
52 if (!/\.js$/.test(fn)) fn += ".js";
53 return fn;
57 ////////////////////////////////////////////////////////////////////////////////
58 function openEditor (fname, chromeWin, newfile) {
59 let fl = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
60 fl.followLinks = true;
61 fl.initWithPath(fname);
62 let lmtime = 0;
63 if (fl.exists()) {
64 if (fl.isDirectory()) return;
65 lmtime = fl.lastModifiedTime;
66 } else {
67 if (!newfile) return;
69 let text;
70 try {
71 text = fileReadText(fl);
72 newfile = false;
73 } catch (e) {
74 if (!newfile) {
75 logError("can't read file: "+fname);
76 return;
78 text =
79 "// ==UserScript==\n"+
80 "// @name \n"+
81 "// @description \n"+
82 "// @version 1.0\n"+
83 "// @include *\n"+
84 "// @run-at document-end\n"+
85 "// @noframes\n"+
86 "// @nowrap\n"+
87 "// @libraries \n"+
88 "// @require \n"+
89 "// ==/UserScript==\n\n";
91 let spw = chromeWin.Scratchpad.ScratchpadManager.openScratchpad({
92 filename: fname,
93 text: text,
94 saved: !newfile,
95 });
96 // TODO: how can i observe file changes without timer?
97 let wasChange = false;
98 let checkFC = function () {
99 let fl = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
100 fl.followLinks = true;
101 fl.initWithPath(fname);
102 if (fl.exists() && !fl.isDirectory() && lmtime != fl.lastModifiedTime) {
103 lmtime = fl.lastModifiedTime;
104 return true;
106 return false;
108 let tm = intervalTimer(function () {
109 if (checkFC()) { scacheAPI.reset(); wasChange = true; }
110 }, 1500);
111 // kill timer on closing
112 spw.addEventListener("close", function sploaded() {
113 spw.removeEventListener("close", sploaded, false);
114 tm.cancel();
115 // just in case
116 if (wasChange || checkFC()) {
117 scacheAPI.reset();
118 scacheAPI.validate();
119 latestUC = scacheAPI.getUC();
121 }, false);
125 ////////////////////////////////////////////////////////////////////////////////
126 let gcliCommandSpecs = [
128 name: "guerilla",
129 description: "GuerillaJS control",
131 // subcommands
133 name: "guerilla about",
134 description: "show various info",
135 params: [
137 name: "type",
138 description: "info to show",
139 type: { name: "selection", data: ["readme", "credits", "thanks", "licenses"] },
140 defaultValue: "readme",
143 exec: function (args, context) {
144 let bro = context.environment.chromeWindow.gBrowser;
145 let list;
146 switch (args.type) {
147 case "credits": list = "CREDITS.txt"; break;
148 case "thanks": list = "THANKS.txt"; break;
149 case "licenses": list = ["LICENSE.bsd.txt", "LICENSE.mit.txt", "LICENSE.mpl.txt", "LICENSE.wtfpl.txt"]; break;
150 default: list = "README.txt"; break;
152 if (typeof(list) == "string") {
153 bro.selectedTab = bro.addTab(gsdoxUrl+list);
154 } else {
155 for (let name of list) bro.selectedTab = bro.addTab(gsdoxUrl+name);
161 name: "guerilla reset",
162 description: "reset all internal caches",
163 exec: function (args, context) {
164 //conlog("clearing guerilla caches...");
165 scacheAPI.reset();
170 name: "guerilla debug",
171 description: "switch debug mode on/off",
172 params: [
174 name: "flag",
175 description: "action to perform",
176 type: { name: "selection", data: ["show", "tan", "ona", "toggle"] },
177 defaultValue: "show",
180 returnValue: "string",
181 exec: function (args, context) {
182 switch (args.flag) {
183 case "tan": addonOptions.debugMode = true; break;
184 case "ona": addonOptions.debugMode = false; break;
185 case "toggle": addonOptions.debugMode = !addonOptions.debugMode; break;
187 return "guerilla debug mode is "+(addonOptions.debugMode ? "on" : "off");
192 name: "guerilla log",
193 description: "switch logging on/off",
194 params: [
196 name: "flag",
197 description: "action to perform",
198 type: { name: "selection", data: ["show", "tan", "ona", "toggle"] },
199 defaultValue: "show",
202 returnValue: "string",
203 exec: function (args, context) {
204 switch (args.flag) {
205 case "tan": addonOptions.logEnabled = true; break;
206 case "ona": addonOptions.logEnabled = false; break;
207 case "toggle": addonOptions.logEnabled = !addonOptions.logEnabled; break;
209 return "guerilla logging is "+(addonOptions.logEnabled ? "on" : "off");
214 name: "guerilla state",
215 description: "switch guerilla state",
216 params: [
218 name: "flag",
219 description: "action to perform",
220 type: { name: "selection", data: ["show", "active", "inactive", "toggle"] },
221 defaultValue: "show",
224 returnValue: "string",
225 exec: function (args, context) {
226 switch (args.flag) {
227 case "active": addonOptions.active = true; break;
228 case "inactive": addonOptions.active = false; break;
229 case "toggle": addonOptions.active = !addonOptions.active; break;
231 return "guerilla is "+(addonOptions.active ? "" : "in")+"active";
236 name: "guerilla activate",
237 description: "activate guerilla",
238 returnValue: "string",
239 exec: function (args, context) {
240 addonOptions.active = true;
241 return "guerilla is active";
246 name: "guerilla deactivate",
247 description: "deactivate guerilla",
248 returnValue: "string",
249 exec: function (args, context) {
250 addonOptions.active = false;
251 return "guerilla is inactive";
256 name: "guerilla new",
257 description: "create new userscript",
258 params: [
260 name: "filename",
261 description: "new script name",
262 type: "string",
265 exec: function (args, context) {
266 let fname = args.filename;
267 let mt = fname.match(/^\/?libs\/([^\/]+)$/);
268 if (mt) fname = mt[1];
269 if (fname.length == 0 || fname.indexOf("/") >= 0) return;
270 fname = addjsext(fname);
271 let dir;
272 if (mt) {
273 // new library
274 dir = getUserLibDir();
275 dir.append(fname);
276 } else {
277 //if (args.filename.length == 0 || args.filename.indexOf("/") >= 0) { alert("invalid file name: "+args.filename); return; }
278 dir = getUserJSDir();
279 dir.append(fname);
281 conlog("trying to edit '"+dir.path+"'");
282 openEditor(dir.path, context.environment.chromeDocument.defaultView, true);
287 name: "guerilla edit",
288 description: "edit guerilla script",
289 //returnValue: "string",
290 params: [
292 name: "filename",
293 description: "script name to edit",
294 type: {
295 name: "selection",
296 cacheable: false,
297 lookup: function (context) getEditList(),
298 }, // type
301 exec: function (args, context) {
302 if (args.filename) openEditor(args.filename, context.environment.chromeDocument.defaultView);
305 // package backend
307 name: "guerilla package",
308 description: "GuerillaJS package control",
311 name: "guerilla package abort",
312 description: "abort all operations",
313 exec: function (args, context) { pkgman.cancel(); },
316 name: "guerilla package list",
317 description: "list installed packages",
318 returnValue: "string",
319 params: [
321 name: "mask",
322 description: "mask",
323 defaultValue: "*",
324 type: "string",
327 exec: function (args, context) {
328 let mask = args.mask||"*";
329 let re = wild2re(mask);
330 let res = "=== package list ===";
331 let count = 0;
332 for (let pi of pkgDB.getActivePackages()) {
333 if (re.test(pi.name)) {
334 res += "\n"+pi.name;
335 if (pi.version) res += "\t"+pi.version;
336 ++count;
339 //return (count ? res : "no packages found");
340 //TODO: special output
341 logError(count ? res : "no packages found");
342 return "find result in error console";
346 name: "guerilla package update",
347 description: "update package(s)",
348 params: [
350 name: "mask",
351 description: "mask",
352 defaultValue: "",
353 type: "string",
356 exec: function (args, context) {
357 if (!args.mask) return;
358 let mask = args.mask||"*";
359 let re = wild2re(mask);
360 for (let pi of pkgDB.getActivePackages()) {
361 if (re.test(pi.name)) {
362 try {
363 pkgman.update(pi.name);
364 } catch (e) {
365 logError("ERROR: ", e.message);
372 name: "guerilla package install",
373 description: "install package",
374 params: [
376 name: "name",
377 description: "package name",
378 type: "string",
381 name: "url",
382 description: "package install url",
383 type: "string",
386 exec: function (args, context) {
387 if (!args.name || !args.url) return;
388 try {
389 pkgman.install(args.name, args.url);
390 } catch (e) {
391 logError("ERROR: ", e.message);
396 name: "guerilla package remove",
397 description: "remove package",
398 params: [
400 name: "name",
401 description: "package name",
402 type: {
403 name: "selection",
404 cacheable: false,
405 lookup: function (context) getPkgList(),
406 }, // type
409 exec: function (args, context) {
410 //if (!args.name.name) return;
411 try {
412 pkgman.remove(args.name.name);
413 } catch (e) {
414 logError("ERROR: ", e.message);
418 // wtf
420 name: "guerilla wtf",
421 description: "wtf",
422 params: [
424 name: "filename",
425 description: "file name",
426 //defaultValue: "",
427 type: "string",
430 exec: function (args, context) {
431 if (!args.filename) return;
432 try {
433 let h = calcFileSha512(args.filename);
434 logError("h="+h+"; "+args.filename);
435 } catch (e) {
436 logError("ERROR: ", e.message);
443 ////////////////////////////////////////////////////////////////////////////////
444 registerStartupHook("gcli", function () {
445 for (let cmd of gcliCommandSpecs) {
446 if (cmd && typeof(cmd) === "object" && cmd.name) gcli.addCommand(cmd);
451 registerShutdownHook("gcli", function () {
452 for (let cmd of gcliCommandSpecs) {
453 if (cmd && typeof(cmd) === "object" && cmd.name) gcli.removeCommand(cmd);