root/lang/javascript/vimperator-plugins/trunk/gmperator.js

Revision 36129, 15.2 kB (checked in by teramako, 9 months ago)

fix autocommands.trigger arument

Line 
1var PLUGIN_INFO =
2<VimperatorPlugin>
3<name>{NAME}</name>
4<description>Vimperator plugin for Greasemonkey</description>
5<author mail="teramako@gmail.com" homepage="http://d.hatena.ne.jp/teramako/">teramako</author>
6<version>0.6c</version>
7<minVersion>2.0pre</minVersion>
8<maxVersion>2.0pre</maxVersion>
9<updateURL>http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/gmperator.js</updateURL>
10<detail><![CDATA[
11
12== Command ==
13
14=== gmlist ===
15:gmli[st] {filter}:
16    show user scripts matches {filter}
17:gmli[st]!:
18    show all user scripts
19:gmli[st] full:
20    same as :gmli[st]!
21
22=== gmload ===
23:gmlo[ad] {name|filename}:
24    load the user script to the current page
25    but, do not dispatch load event
26    so maybe you should edit the scripts before load
27:gmlo[ad]! {name|filename}:
28    force load the user script
29
30=== gmset ===
31:gmset!:
32    toggle enable/disable Greasemonkey
33:gmset! {filename}:
34    toggle enable/disable the script
35:gmset {filename} {options}:
36    change the {filename} script attributes.
37    {options}:
38        -n[name] {value}:  change name to {value}
39        -i[nclude] {expr[,expr,...]}: change includes to expr list ("," demiliter)
40        -e[xclude] {expr[,expr,...]}: change excludes to expr list ("," demiliter)
41    Caution:
42        This change is permanent, not only the session.
43        And cannot get back.
44
45
46==== example ====
47    :gmset! {filename} -n fooScriptName -i http://*,https://* -e http://example.com/*:
48         - toggle enable or disable,
49         - name to "fooScriptName",
50         - includes to "http://*" and "https://*",
51         - and excludes to "http://example.com/*"
52
53
54=== gmcommand ===
55:gmcommand {command name}:
56    run Greasemonkey Command
57
58== AutoCommand ==
59
60Available events
61
62GMInjectedScript:
63    when open either foreground or background
64GMActiveScript:
65    when TabSelect or open foreground
66    example:
67        autocmd GMActiveScript scriptName\.user\.js$ :echo "scriptName is executing"
68        when any URL and scriptName.user.js is executing
69
70
71== Dialog ==
72
73:dialog userscriptmanager:
74    open Greasemonkey UserScript Manager
75
76== for JavaScripter ==
77you can access to the sandbox of Greasemonkey !!!
78
79liberator.plugins.gmperator:
80    allItem:
81        return object of
82            key:
83                {panalID}
84            value:
85                {GmContainer}
86
87        {panelID}:
88            @see gBrowser.mTags[].linkedPanel
89
90    currentPanel:
91        currentContainer  :
92            return the current {GmContainer} object
93        currentSandbox    :
94            return the current sandbox object
95        gmScripts         :
96             return array of {userScripts}
97                              {userScripts} => (:
98                                 - filename   : {String}
99                                 - name       : {String}
100                                 - namespace  : {String}
101                                 - description: {String}
102                                 - enabled    : {Boolean}
103                                 - includes   : {String[]}
104                                 - encludes   : {String[]}
105                              )
106
107]]></detail>
108</VimperatorPlugin>;
109
110(function(){
111
112const Cc = Components.classes;
113const Ci = Components.interfaces;
114const gmID = '@greasemonkey.mozdev.org/greasemonkey-service;1';
115if (!Cc[gmID]){
116    liberator.log('Greasemonkey is not installed',0);
117    return;
118}
119
120liberator.plugins.gmperator = (function(){ //{{{
121    // -----------------------
122    // PUBLIC section
123    // -----------------------
124    // {{{
125    var manager = {
126        register: function (uri,sandbox,script){
127            var panelID = getPanelID(sandbox.window);
128            if (!panelID) return;
129            var gmCon;
130            if (containers[panelID] && containers[panelID].uri == uri){
131                gmCon = containers[panelID];
132            } else {
133                gmCon = new GmContainer(uri,sandbox);
134                containers[panelID] = gmCon;
135                this.__defineGetter__(panelID,function() gmCon);
136                //liberator.log('gmpeartor: Registered: ' + panelID + ' - ' + uri,8);
137            }
138            gmCon.sandbox = sandbox;
139            gmCon.addScript(script);
140            gmCon.uri = uri;
141            triggerGMEvent('GMInjectedScript',uri,script._filename);
142            if (panelID == this.currentPanel){
143                triggerGMEvent('GMActiveScript',uri,script._filename);
144            }
145        },
146        get gmScripts() GM_getConfig().scripts,
147        get allItem() containers,
148        get currentPanel() getBrowser().mCurrentTab.linkedPanel,
149        get currentContainer() containers[this.currentPanel] || null,
150        get currentSandbox(){
151            var id = this.currentPanel;
152            return containers[id] ? containers[id].sandbox : null;
153        },
154        getSandboxFromWindow: function(win){
155            for each (let c in containers){
156                if (c.sandbox.window == win) return sandbox;
157            }
158            return null;
159        },
160        getContainersFromURI: function(uri){
161            var list = [];
162            for each (let c in containers){
163                if (c.uri == uri) list.push(c);
164            }
165            return list.length > 0 ? list : null;
166        }
167    };
168    // }}}
169    // -----------------------
170    // PRIVATE section
171    // -----------------------
172    // {{{
173    var containers = {};
174    var gmSvc = Cc[gmID].getService().wrappedJSObject;
175
176    function appendCode(target,name,func){
177        var original = target[name];
178        target[name] = function(){
179            var tmp = original.apply(target,arguments);
180            func.apply(this,arguments);
181            return tmp;
182        };
183    }
184    appendCode(gmSvc,'evalInSandbox',function(code,uri,sandbox,script){
185        liberator.plugins.gmperator.register(uri,sandbox,script);
186    });
187    function getPanelID(win){
188        var tabs = getBrowser().mTabs;
189        for (let i=0,l=tabs.length; i<l; i++){
190            let tab = tabs.item(i);
191            if (tab.linkedBrowser.contentWindow == win){
192                return tab.linkedPanel;
193            }
194        }
195    }
196    function updateGmContainerList(event){
197        var t = event.target;
198        if (t && t.localName == 'tab' && t.linkedPanel){
199            delete containers[t.linkedPanel];
200            delete liberator.plugins.gmperator[t.linkedPanel];
201        }
202    }
203    function dispatchGMTabSelect(event){
204        var panelID = event.originalTarget.linkedPanel;
205        var container;
206        if (container = containers[panelID]){
207            liberator.log(panelID + '\n' + container.uri +'\n'+ container.scripts.length,8);
208            container.scripts.forEach(function(script){
209                triggerGMEvent('GMActiveScript',container.uri,script._filename);
210            });
211        }
212    }
213    /**
214     * trigger autocommand
215     * @param {String} name Event name
216     * @param {String} uri
217     * @param {String} filename script filename
218     */
219    function triggerGMEvent(name,uri,filename){
220        autocommands.trigger(name, {url: uri+'\n'+filename });
221        liberator.log('gmpeartor: '+ name + ' ' + uri+'\n'+filename,8);
222    }
223    getBrowser().mTabContainer.addEventListener('TabClose',updateGmContainerList,false);
224    getBrowser().mTabBox.addEventListener('TabSelect',dispatchGMTabSelect,false);
225
226    config.autocommands.push(['GMInjectedScript','Triggered when UserScript is injected']);
227    config.autocommands.push(['GMActiveScript','Triggered when location is changed and injected UserScripts are exist']);
228    config.dialogs.push(['userscriptmanager','Greasemonkey Manager',function(){GM_openUserScriptManager();}]);
229    // }}}
230    return manager;
231})(); //}}}
232
233// ---------------------------
234// User Command
235// ---------------------------
236commands.addUserCommand(['gmli[st]','lsgm'],'list Greasemonkey scripts', //{{{
237    function(args){
238        var xml = <></>;
239        var scripts = GM_getConfig().scripts;
240        var reg;
241        if (args.bang || args.string == 'full'){
242            reg = new RegExp();
243        } else if (args.string){
244            reg = new RegExp(args.string,'i');
245        }
246        if (reg){
247            for each (let s in scripts){
248                if (reg.test(s.name) || reg.test(s._filename)){
249                    xml += scriptToString(s);
250                }
251            }
252        } else {
253            let table = <table/>;
254            let tr;
255            for each (let script in scripts){
256                tr = <tr/>;
257                if (script.enabled){
258                    tr.* += <td style="font-weight:bold;">{script.name}</td>;
259                } else {
260                    tr.* += <td>{script.name}</td>;
261                }
262                tr.* += <td>({script._filename})</td>;
263                table.* += tr;
264            }
265            xml += table;
266        }
267        liberator.echo(xml,true);
268        function scriptToString(script){
269            var table = <table>
270                <caption class="hl-Title" style="text-align:left">{script.name}</caption>
271            </table>;
272            [['FileName','_filename'],['NameSpace','namespace'],['Description','description'],
273             ['Includes','includes'],['Excludes','excludes'],['Enabled','enabled']].forEach(function(prop){
274                let tr = <tr>
275                    <th style="font-weight:bold;text-align:left;vertical-align:top">{prop[0]}</th>
276                </tr>;
277                let contents = script[prop[1]];
278                if (typeof contents == 'string' || typeof contents == 'boolean'){
279                    tr.* += <td>{contents}</td>;
280                } else {
281                    let td = <td/>;
282                    for (let i=0,l=contents.length; i<l; i++){
283                        td.* += contents[i];
284                        if (contents[i+1]) td.* += <br/>;
285                    }
286                    tr.* += td;
287                }
288                table.* += tr;
289            });
290            return table;
291        }
292    },{
293        bang:true
294    }
295); //}}}
296commands.addUserCommand(['gmlo[ad]'],'load Greasemonkey scripts', //{{{
297    function(args){
298        if (!args.string){
299            liberator.echoerr('Usage: :gmlo[ad][!] {name|filename}');
300            return;
301        }
302        var scripts = GM_getConfig().scripts;
303        var script;
304        for (let i=0,l=scripts.length; i<l; i++){
305            if (scripts[i]._filename == args.string || scripts[i].name == args.string){
306                script = scripts[i];
307                break;
308            }
309        }
310        if (!script){
311            liberator.echoerr('no such a user script');
312            return;
313        } else if (liberator.plugins.gmperator.currentContainer.hasScript(script._filename) && !args.bang){
314            liberator.echoerr(script._filename + ' is already loaded!');
315            return;
316        } else {
317            liberator.echo('loading: ' +script._filename);
318        }
319        var href,unsafewin;
320        try {
321            href = buffer.URL;
322            unsafewin = window.content.document.defaultView.wrappedJSObject;
323            GM_BrowserUI.gmSvc.wrappedJSObject.injectScripts([script],href,unsafewin,window);
324        } catch (e){
325            liberator.log(e);
326            liberator.echoerr(e);
327        }
328        /*
329        // do you have idea how to dispatch load event to only the script ?
330        window.setTimeout(function(){
331            var loadEvent = document.createEvent('Event');
332            loadEvent.initEvent('load',true,true,window.content.document,1);
333            window.content.document.dispatchEvent(loadEvent);
334        },100);
335        */
336    },{
337        completer: function(context) scriptsCompleter(context.filter,true)
338    }
339); //}}}
340commands.addUserCommand(['gmset'],'change settings for Greasemonkey scripts', //{{{
341    function(args){
342        if (args.length == 0){
343            if (args.bang) GM_setEnabled(!GM_getEnabled()); // toggle enable/disable Greasemonkey
344            return;
345        }
346        var filename = args[0];
347        var config = GM_getConfig();
348        var script;
349        for (let i=0,l=config.scripts.length; i<l; i++){
350            if (config.scripts[i]._filename == filename){
351                script = config.scripts[i];
352                break;
353            }
354        }
355        if (!script) return;
356        if (args.bang){ // toggle enable/disable the script if {filename} is exist
357            script.enabled = !script.enabled;
358        }
359        if (args['-name']) script.name = args['-name'];
360        if (args['-include']) script.include = args['-include'];
361        if (args['-exclude']) script.exclude = args['-exclude'];
362        config._save();
363    },{
364        completer: function(context) scriptsCompleter(context.filter,false),
365        options: [
366            [['-name','-n'],    commands.OPTION_STRING],
367            [['-include','-i'], commands.OPTION_LIST],
368            [['-exclude','-e'], commands.OPTION_LIST]
369        ],
370        bang:true
371    }
372); //}}}
373commands.addUserCommand(['gmcommand','gmcmd'],'run Greasemonkey Command', //{{{
374    function(args){
375        var commander = GM_BrowserUI.getCommander(content);
376        var commandName = args[0];
377        for (let i=0,l=commander.menuItems.length; i<l; i++){
378            let menuItem = commander.menuItems[i];
379            if (menuItem.getAttribute('label') == commandName){
380                menuItem._commandFunc();
381                return;
382            }
383        }
384        liberator.echoerr(commandName + ' is not defined userscript command.');
385    },
386    {
387        completer: function(context){
388            var items = GM_BrowserUI.getCommander(content).menuItems;
389            var completions = [];
390            var exp = new RegExp(context.filter,'i');
391            context.title = ["UserScript's Commands"];
392            context.completions = [[items[i].getAttribute('label'),'-'] for (i in items)].filter(function(item){
393                return this.test(item[0]);
394            },exp);
395        },
396        argCount: "1"
397    }
398); //}}}
399
400// ---------------------------
401// Utils
402// ---------------------------
403/** Grasemonkey sandbox container {{{
404 * @param {String} uri
405 * @param {Sandbox} sandbox
406 * @param {Array} scripts
407 */
408function GmContainer(uri,sandbox){
409    this.uri = uri;
410    this.sandbox = sandbox;
411    this.scripts = [];
412}
413GmContainer.prototype = {
414    addScript : function(script){
415        if (!this.hasScript(script)){
416            return this.scripts.push(script);
417        }
418        return false;
419    },
420    hasScript : function(script){
421        var filename;
422        switch (typeof script){
423            case 'object': filename = script._filename; break;
424            case 'string': filename = script; break;
425            default: return null;
426        }
427        return this.scripts.some(function(s) s._filename == filename);
428    }
429}; // }}}
430function scriptsCompleter(filter,flag){ //{{{
431    var candidates = [];
432    var scripts = GM_getConfig().scripts;
433    var isAll = false;
434    if (!filter) isAll=true;
435    if (flag){
436        for each (let s in scripts){
437            if (isAll || s.name.toLowerCase().indexOf(filter) == 0 ||
438                s._filename.indexOf(filter) == 0)
439            {
440                candidates.push([s.name,s.description]);
441                candidates.push([s._filename,s.description]);
442            }
443        }
444    } else {
445        for each (let s in scripts){
446            if (isAll || s._filename.indexOf(filter) == 0)
447            {
448                candidates.push([s._filename,s.description]);
449            }
450        }
451    }
452    return [0,candidates];
453} //}}}
454
455})();
456
457// vim: fdm=marker sw=4 ts=4 et:
Note: See TracBrowser for help on using the browser.