/** * ==VimperatorPlugin== * @name gmperator * @description Vimperator plugin for Greasemonkey * @author teramako teramako@gmail.com * @namespace http://d.hatena.ne.jp/teramako/ * @version 0.3a * ==/VimperatorPlugin== * * --------------------------- * Usage: * --------------------------- * {{{ * * :gmli[st] {filter} -> show user scripts matches {filter} * :gmli[st]! -> show all user scripts * :gmli[st] full -> same as :gmli[st]! * * :gmlo[ad] {name|filename} -> load the user script to the current page * but, don't dispatch load event * so maybe you should edit the scripts before load * :gmlo[ad]! {name|filename} -> force load the user script * * :gmset! -> toggle enable/disable Greasemonkey * :gmset! {filename} -> toogle enable/disable the script * :gmset {filename} {options} * {options}: * -n[ame] {value} -> change name to {value} * -i[nclude] {expr[,expr,...]} -> change includes to expr list ("," demiliter) * -e[xclude] {expr[,expr,...]} -> change excludes to expr list ("," demiliter) * * Caution: * The change is permanent, not only the session. * And cannot get back. * * e.g.) * :gmset! {filename} -n fooScriptName -i http://*,https://* -e http://example.com/* * toggle enable or disable, * name to "fooScriptName", * includes to "http://*" and "https://*", * and excludes to "http://example.com/*" * * }}} * --------------------------- * For plugin developer: * --------------------------- * {{{ * * 1). you can access to the sandbox of Greasemonkey !!! * 2). you can register commands to execute * when the user script is executed on the URI * @see liberator.plugins.gmperator.addAutoCommand * * liberator.plugins.gmperator => ( * allItem : return object of key : {panalID}, * value : {GmContainer} * {panelID} => @see gBrowser.mTags[].linkedPanel * currentPanel * currentContainer : return the current {GmContainer} object * currentSandbox : return the current sandbox object * gmScripts : return array of {userScripts} * {userScripts} => ( * filename : {String} * name : {String} * namespace : {String} * description: {String} * enabled : {Boolean} * includes : {String[]} * encludes : {String[]} * ) * addAutoCommand : function( uri, script, cmd ) * If both of uri and script are matched * * ) * }}} */ (function(){ const Cc = Components.classes; const Ci = Components.interfaces; const gmID = '@greasemonkey.mozdev.org/greasemonkey-service;1'; if (!Cc[gmID]) { log('Greasemonkey is not installed'); return; } if(!liberator.plugins) liberator.plugins = {}; liberator.plugins.gmperator = (function(){ //{{{ // ----------------------- // PUBLIC section // ----------------------- // {{{ var manager = { register: function (uri,sandbox,script){ var panelID = getPanelID(sandbox.window); var gmCon; if (containers[panelID]){ gmCon = containers[panelID]; } else { gmCon = new GmContainer(uri,sandbox); containers[panelID] = gmCon; this.__defineGetter__(panelID,function() gmCon); //log('gmpeartor: Registered: ' + panelID + ' - ' + uri); } gmCon.sandbox = sandbox; gmCon.addScript(script); gmCon.uri = uri; autocommands.trigger('GMInjectedScript',uri+'\n'+script.filename); }, get gmScripts() getScripts(), get allItem() containers, get currentPanel() getBrowser().mCurrentTab.linkedPanel, get currentContainer() containers[this.currentPanel] || null, get currentSandbox(){ var id = this.currentPanel; return containers[id] ? containers[id].sandbox : null; }, getSandboxFromWindow: function(win){ for each(var c in containers){ if(c.sandbox.window == win) return sandbox; } return null; }, getContainersFromURI: function(uri){ var list = []; for each(var c in containers){ if (c.uri == uri) list.push(c); } return list.length > 0 ? list : null; }, addAutoCommand: function(uri, script, cmd){ var reg = uri+'.*\n'+script+'\.user\.js'; autocommands.add('GMInjectedScript', reg, cmd); }, removeAutoCommand: function(uri, script){ var reg = uri+'.*\n'+script+'\.user\.js'; autocommands.remove('GMInjectedScript', reg); }, }; // }}} // ----------------------- // PRIVATE section // ----------------------- // {{{ var containers = {}; var gmSvc = Cc[gmID].getService().wrappedJSObject; function appendCode(target,name,func){ var original = target[name]; target[name] = function(){ var tmp = original.apply(target,arguments); func.apply(this,arguments); return tmp; }; } appendCode(gmSvc, 'evalInSandbox', function(code,uri,sandbox,script){ liberator.plugins.gmperator.register(uri,sandbox,script); }); function getPanelID(win){ var tabs = getBrowser().mTabs; for (var i=0; tabs.length; i++){ var tab = tabs.item(i); if (tab.linkedBrowser.contentWindow == win){ return tab.linkedPanel; } } //liberator.log(win + 'is not found'); } function updateGmContainerList(e){ var t = e.target; if (t && t.localName == 'tab' && t.linkedPanel){ delete containers[t.linkedPanel]; delete plugins.gmperator[t.linkedPanel]; } } getBrowser().mTabContainer.addEventListener('TabClose',updateGmContainerList,false); // }}} return manager; })(); //}}} // --------------------------- // User Command // --------------------------- commands.addUserCommand(['gmli[st]','lsgm'], 'list Greasemonkey scripts', //{{{ function(arg,special){ var str = ''; var scripts = getScripts(); var reg; if (special || arg == 'full'){ reg = new RegExp('.*'); } else if( arg ){ reg = new RegExp(arg,'i'); } if (reg){ for each(var s in scripts){ if ( reg.test(s.name) || reg.test(s.filename) ) { str += scriptToString(s) + '\n\n'; } } } else { var table = ; var tr; for each(var script in scripts){ tr = ; if (script.enabled){ tr.* += ; } else { tr.* += ; } tr.* += ; table.* += tr; } str += table.toSource(); } echo(str,true); function scriptToString(script){ var table =
{script.name}{script.name}({script.filename})
{script.name}
; ['FileName', 'NameSpace', 'Description', 'Includes', 'Excludes', 'Enabled'].forEach(function(prop){ var tr = {prop} ; var contents = script[prop.toLowerCase()]; if (typeof contents == "string"){ tr.* += {contents}; } else { var td = ; contents.forEach(function(c,i,a){ td.* += c; if (a[i+1]) td.* +=
; }); tr.* += td; } table.* += tr; }); return table.toSource(); } } ); //}}} commands.addUserCommand(['gmlo[ad]'], 'load Greasemonkey scripts', //{{{ function(arg, special){ if (!arg) { echoerr('Usage: :gmlo[ad][!] {name|filename}'); return; } var scripts = getScripts(); var script; for (var i=0; i 0){ script.name = commands.getOption(res.opts, '-name', script.name); script.includes = commands.getOption(res.opts, '-include', script.includes); script.excludes = commands.getOption(res.opts, '-exclude', script.excludes); } config.save(); },{ args: [ [['-name','-n'], commands.OPTION_STRING], [['-include','-i'], commands.OPTION_LIST], [['-exclude','-e'], commands.OPTION_LIST] ], shortHelp: 'change settings for Greasemonkey scripts', help: [ 'toggle enable/disable with "!", if {filename} is exist, if not toggle Greasemonkey', '
-n
-name
change the name
', '
-i
-include
change the includes list ("," delimiter)
', '
-e
-exclude
change the excludes list ("," delimiter)
', 'Caution: the change is permanent, not the only session.
And cannot get back.' ].join(''), completer: function(filter) scriptsCompleter(filter, false) } ); //}}} // --------------------------- // Utils // --------------------------- /** Grasemonkey sandbox container {{{ * @param {String} uri * @param {Sandbox} sandbox * @param {Array} scripts */ function GmContainer(uri,sandbox){ this.uri = uri; this.sandbox = sandbox; this.scripts = []; } GmContainer.prototype = { addScript : function(script) !this.hasScript(script) && this.scripts.push(script) || false, hasScript : function(script){ var filename; switch( typeof(script) ){ case 'object': filename = script.filename; break; case 'string': filename = script; break; default: return null; } return this.scripts.some(function(s) s.filename == filename); } }; // }}} function getScripts(){ //{{{ var config = new Config(); config.load(); return config.scripts; } //}}} function scriptsCompleter(filter,flag){ //{{{ var candidates = []; var scripts = getScripts(); var isAll = false; if (!filter) isAll=true; if (flag){ for each(var s in scripts){ if (isAll || s.name.toLowerCase().indexOf(filter) == 0 || s.filename.indexOf(filter) == 0) { candidates.push([s.name, s.description]); candidates.push([s.filename, s.description]); } } } else { for each(var s in scripts){ if (isAll || s.filename.indexOf(filter) == 0) { candidates.push([s.filename, s.description]); } } } return [0,candidates]; } //}}} })(); // vim: fdm=marker sw=4 ts=4 et: