moved some utility functions to "basic.js"
[guerillascript.git] / modules / concmd.js
blob4a2408e5e04bd88a9413093f3181d8a777e5b7aa
1 /* coded by Ketmar // Invisible Vector (psyc://ketmar.no-ip.org/~Ketmar)
2  * Understanding is not required. Only obedience.
3  *
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");
14 let latestUC = false;
15 let sclist;
18 function buildFileList (list) {
19   sclist = [];
20   for (let idx = 0; idx < list.length; ++idx) {
21     let xn = list[idx];
22     let it = {value:xn};
23     it.name = (xn.islib ? "/lib/"+xn.name : xn.name);
24     sclist.push(it);
25   }
29 function addjsext (fn) {
30   if (!/\.js$/.test(fn)) fn += ".js";
31   return fn;
35 function openEditor (fname, chromeWin, newfile) {
36   let fl = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
37   fl.followLinks = true;
38   fl.initWithPath(fname);
39   let lmtime = 0;
40   if (fl.exists()) {
41     if (fl.isDirectory()) return;
42     lmtime = fl.lastModifiedTime;
43   } else {
44     if (!newfile) return;
45   }
46   let text;
47   try {
48     text = fileReadText(fl);
49     newfile = false;
50   } catch (e) {
51     if (!newfile) {
52       logError("can't read file: "+fname);
53       return;
54     }
55     text =
56       "// ==UserScript==\n"+
57       "// @name        \n"+
58       "// @description \n"+
59       "// @version     1.0\n"+
60       "// @include     *\n"+
61       "// @run-at      document-end\n"+
62       "// @noframes\n"+
63       "// @libraries   \n"+
64       "// @require     \n"+
65       "// ==/UserScript==\n\n";
66   }
67   let spw = chromeWin.Scratchpad.ScratchpadManager.openScratchpad({
68     filename: fname,
69     text: text,
70     saved: !newfile,
71   });
72   // TODO: how can i observe file changes without timer?
73   let wasChange = false;
74   let checkFC = function () {
75     let fl = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
76     fl.followLinks = true;
77     fl.initWithPath(fname);
78     if (fl.exists() && !fl.isDirectory() && lmtime != fl.lastModifiedTime) {
79       lmtime = fl.lastModifiedTime;
80       return true;
81     }
82     return false;
83   };
84   let tm = intervalTimer(function () {
85     if (checkFC()) { scacheAPI.reset(); wasChange = true; }
86   }, 1500);
87   // kill timer on closing
88   spw.addEventListener("close", function sploaded() {
89     spw.removeEventListener("close", sploaded, false);
90     tm.cancel();
91     // just in case
92     if (wasChange || checkFC()) {
93       scacheAPI.reset();
94       scacheAPI.validate();
95       latestUC = scacheAPI.getUC();
96     }
97   }, false);
101 let gcliCommandSpecs = [
102   {
103     name: "guerilla",
104     description: "GuerillaJS control",
105   },
106   // subcommands
107   {
108     name: "guerilla about",
109     description: "show various info",
110     params: [
111       { name: "type",
112         description: "info to show",
113         type: { name: "selection", data: ["readme", "credits", "thanks", "licenses"] },
114         defaultValue: "readme",
115       }
116     ],
117     exec: function (args, context) {
118       let bro = context.environment.chromeWindow.gBrowser;
119       let list;
120       switch (args.type) {
121         case "credits": list = "CREDITS"; break;
122         case "thanks": list = "THANKS"; break;
123         case "licenses": list = ["LICENSE.bsd", "LICENSE.mit", "LICENSE.mpl", "LICENSE.wtfpl"]; break;
124         default: list = "README"; break;
125       }
126       if (typeof(list) == "string") {
127         bro.selectedTab = bro.addTab("chrome://guerilla/content/"+list);
128       } else {
129         for (let name of list) bro.selectedTab = bro.addTab("chrome://guerilla/content/"+name);
130       }
131     },
132   },
133   //
134   {
135     name: "guerilla reset",
136     description: "reset all internal caches",
137     exec: function (args, context) {
138       //conlog("clearing guerilla caches...");
139       scacheAPI.reset();
140     },
141   },
142   //
143   {
144     name: "guerilla debug",
145     description: "switch debug mode on/off",
146     params: [
147       { name: "flag",
148         description: "action to perform",
149         type: { name: "selection", data: ["show", "tan", "ona", "toggle"] },
150         defaultValue: "show",
151       }
152     ],
153     returnValue: "string",
154     exec: function (args, context) {
155       switch (args.flag) {
156         case "tan": guerillaOptions.debugMode = true; break;
157         case "ona": guerillaOptions.debugMode = false; break;
158         case "toggle": guerillaOptions.debugMode = !guerillaOptions.debugMode; break;
159       }
160       return "guerilla debug mode is "+(guerillaOptions.debugMode ? "on" : "off");
161     },
162   },
163   //
164   {
165     name: "guerilla log",
166     description: "switch logging on/off",
167     params: [
168       { name: "flag",
169         description: "action to perform",
170         type: { name: "selection", data: ["show", "tan", "ona", "toggle"] },
171         defaultValue: "show",
172       }
173     ],
174     returnValue: "string",
175     exec: function (args, context) {
176       switch (args.flag) {
177         case "tan": guerillaOptions.logEnabled = true; break;
178         case "ona": guerillaOptions.logEnabled = false; break;
179         case "toggle": guerillaOptions.logEnabled = !guerillaOptions.logEnabled; break;
180       }
181       return "guerilla logging is "+(guerillaOptions.logEnabled ? "on" : "off");
182     },
183   },
184   //
185   {
186     name: "guerilla state",
187     description: "switch guerilla state",
188     params: [
189       { name: "flag",
190         description: "action to perform",
191         type: { name: "selection", data: ["show", "active", "inactive", "toggle"] },
192         defaultValue: "show",
193       }
194     ],
195     returnValue: "string",
196     exec: function (args, context) {
197       switch (args.flag) {
198         case "active": guerillaOptions.active = true; break;
199         case "inactive": guerillaOptions.active = false; break;
200         case "toggle": guerillaOptions.active = !guerillaOptions.active; break;
201       }
202       return "guerilla is "+(guerillaOptions.active ? "" : "in")+"active";
203     },
204   },
205   //
206   {
207     name: "guerilla activate",
208     description: "activate guerilla",
209     returnValue: "string",
210     exec: function (args, context) {
211       guerillaOptions.active = true;
212       return "guerilla is active";
213     },
214   },
215   //
216   {
217     name: "guerilla deactivate",
218     description: "deactivate guerilla",
219     returnValue: "string",
220     exec: function (args, context) {
221       guerillaOptions.active = false;
222       return "guerilla is inactive";
223     },
224   },
225   //
226   {
227     name: "guerilla new",
228     description: "create new userscript",
229     params: [
230       { name: "filename",
231         description: "new script name",
232         type: "string",
233       }
234     ],
235     exec: function (args, context) {
236       let mt = args.filename.match(/^\/?lib\/([^\/]+)$/);
237       let dir;
238       if (mt) {
239         // new library
240         dir = getUserLibDir();
241         if (!dir.exists()) dir.create(res.DIRECTORY_TYPE, 0750);
242         dir.append(addjsext(mt[1]));
243       } else {
244         if (args.filename.length == 0 || args.filename.indexOf("/") >= 0) { alert("invalid file name: "+args.filename); return; }
245         dir = getUserJSDir();
246         dir.append(addjsext(args.filename));
247       }
248       conlog("trying to edit '"+dir.path+"'");
249       openEditor(dir.path, context.environment.chromeDocument.defaultView, true);
250     },
251   },
252   //
253   {
254     name: "guerilla edit",
255     description: "edit guerilla script",
256     //returnValue: "string",
257     params: [
258       { name: "filename",
259         description: "script name to edit",
260         type: {
261           name: "selection",
262           //cacheable: true,
263           lookup: function (context) {
264             // recache scripts if necessary
265             let uc = scacheAPI.getUC();
266             if (latestUC === false || latestUC != uc) {
267               scacheAPI.reset();
268               scacheAPI.validate();
269               latestUC = scacheAPI.getUC();
270               buildFileList(scacheAPI.getScripts());
271             }
272             return sclist;
273           },
274         }, // type
275       }
276     ],
277     exec: function (args, context) {
278       if (args.filename) openEditor(args.filename.path, context.environment.chromeDocument.defaultView);
279     },
280   },
284 exports.gcliInit = function () {
285   for (let f = 0; f < gcliCommandSpecs.length; ++f) {
286     if (gcliCommandSpecs[f].name) gcli.addCommand(gcliCommandSpecs[f]);
287   }
291 exports.gcliDeinit = function () {
292   for (let f = 0; f < gcliCommandSpecs.length; ++f) {
293     if (gcliCommandSpecs[f].name) gcli.removeCommand(gcliCommandSpecs[f]);
294   }