| 1 | /* NEW BSD LICENSE {{{ |
|---|
| 2 | Copyright (c) 2010, anekos. |
|---|
| 3 | All rights reserved. |
|---|
| 4 | |
|---|
| 5 | Redistribution and use in source and binary forms, with or without modification, |
|---|
| 6 | are permitted provided that the following conditions are met: |
|---|
| 7 | |
|---|
| 8 | 1. Redistributions of source code must retain the above copyright notice, |
|---|
| 9 | this list of conditions and the following disclaimer. |
|---|
| 10 | 2. Redistributions in binary form must reproduce the above copyright notice, |
|---|
| 11 | this list of conditions and the following disclaimer in the documentation |
|---|
| 12 | and/or other materials provided with the distribution. |
|---|
| 13 | 3. The names of the authors may not be used to endorse or promote products |
|---|
| 14 | derived from this software without specific prior written permission. |
|---|
| 15 | |
|---|
| 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
|---|
| 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|---|
| 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
|---|
| 19 | IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
|---|
| 20 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
|---|
| 21 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|---|
| 22 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|---|
| 23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
|---|
| 24 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
|---|
| 25 | THE POSSIBILITY OF SUCH DAMAGE. |
|---|
| 26 | |
|---|
| 27 | |
|---|
| 28 | ################################################################################### |
|---|
| 29 | # http://sourceforge.jp/projects/opensource/wiki/licenses%2Fnew_BSD_license # |
|---|
| 30 | # に参考になる日本語訳がありますが、有効なのは上記英文となります。 # |
|---|
| 31 | ################################################################################### |
|---|
| 32 | |
|---|
| 33 | }}} */ |
|---|
| 34 | |
|---|
| 35 | // PLUGIN_INFO {{{ |
|---|
| 36 | let PLUGIN_INFO = |
|---|
| 37 | <VimperatorPlugin> |
|---|
| 38 | <name>extension manager</name> |
|---|
| 39 | <name lang="ja">アドオン管理</name> |
|---|
| 40 | <description>extension manager</description> |
|---|
| 41 | <description lang="ja">アドオンを管理します。</description> |
|---|
| 42 | <version>1.1.0</version> |
|---|
| 43 | <author mail="anekos@snca.net" homepage="http://d.hatena.ne.jp/nokturnalmortum/">anekos</author> |
|---|
| 44 | <license>new BSD License (Please read the source code comments of this plugin)</license> |
|---|
| 45 | <license lang="ja">修正BSDライセンス (ソースコードのコメントを参照してください)</license> |
|---|
| 46 | <updateURL>http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/extensions-manager.js</updateURL> |
|---|
| 47 | <minVersion>2.3</minVersion> |
|---|
| 48 | <maxVersion>2.3</maxVersion> |
|---|
| 49 | <detail><![CDATA[ |
|---|
| 50 | アドオンの有効無効状態を保存&復帰できるプラギン |
|---|
| 51 | 詳しくはヘルプを読んでくれよ。 |
|---|
| 52 | :help extension-manager-plugin |
|---|
| 53 | ]]></detail> |
|---|
| 54 | <detail lang="ja"><![CDATA[ |
|---|
| 55 | Store / Restore current extensions state. |
|---|
| 56 | read the help with the below command. |
|---|
| 57 | ":help extension-manager-plugin" |
|---|
| 58 | ]]></detail> |
|---|
| 59 | </VimperatorPlugin>; |
|---|
| 60 | // }}} |
|---|
| 61 | // INFO {{{ |
|---|
| 62 | let INFO = |
|---|
| 63 | <> |
|---|
| 64 | <plugin name="extension-manager" version="1.1.0" |
|---|
| 65 | href="http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/extension-manager.js" |
|---|
| 66 | summary="extension manager" |
|---|
| 67 | lang="en-US" |
|---|
| 68 | xmlns="http://vimperator.org/namespaces/liberator"> |
|---|
| 69 | <author email="anekos@snca.net">anekos</author> |
|---|
| 70 | <license>New BSD License</license> |
|---|
| 71 | <project name="Vimperator" minVersion="2.3"/> |
|---|
| 72 | <p> |
|---|
| 73 | Extention manager death yohooo |
|---|
| 74 | </p> |
|---|
| 75 | <item> |
|---|
| 76 | <tags>:extstate</tags> |
|---|
| 77 | <spec>:exts<oa>tate</oa> <a>sub-command</a> <a>name</a> <oa>extension-names...</oa></spec> |
|---|
| 78 | <description> |
|---|
| 79 | <p> |
|---|
| 80 | Store or restore current extensions state with <a>name</a>. |
|---|
| 81 | <p>The following <a>sub-commands</a> are interpreted.</p> |
|---|
| 82 | if the <oa>extension-names</oa> arguments are specified, |
|---|
| 83 | this command is only for these extensions. |
|---|
| 84 | <ul> |
|---|
| 85 | <li>store</li> |
|---|
| 86 | <li>restore</li> |
|---|
| 87 | </ul> |
|---|
| 88 | </p> |
|---|
| 89 | </description> |
|---|
| 90 | </item> |
|---|
| 91 | </plugin> |
|---|
| 92 | <plugin name="extension-manager" version="1.1.0" |
|---|
| 93 | href="http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/extension-manager.js" |
|---|
| 94 | summary="extension manager" |
|---|
| 95 | lang="ja" |
|---|
| 96 | xmlns="http://vimperator.org/namespaces/liberator"> |
|---|
| 97 | <author email="anekos@snca.net">anekos</author> |
|---|
| 98 | <license>New BSD License</license> |
|---|
| 99 | <project name="Vimperator" minVersion="2.3"/> |
|---|
| 100 | <p> |
|---|
| 101 | extention manager |
|---|
| 102 | </p> |
|---|
| 103 | <item> |
|---|
| 104 | <tags>:extstate</tags> |
|---|
| 105 | <spec>:exts<oa>tate</oa> <a>sub-command</a> <a>name</a> <oa>extension-names...</oa></spec> |
|---|
| 106 | <description> |
|---|
| 107 | <p> |
|---|
| 108 | 拡張の有効無効状態を <a>name</a> で保存復帰します。 |
|---|
| 109 | <oa>extension-names</oa> で拡張名を指定しておくと、指定された拡張のみが保存復帰の対象になります。 |
|---|
| 110 | <p>以下の <a>sub-commands</a> があります。</p> |
|---|
| 111 | <dl> |
|---|
| 112 | <dt>store</dt><dd>保存</dd> |
|---|
| 113 | <dt>restore</dt><dd>復帰</dd> |
|---|
| 114 | </dl> |
|---|
| 115 | </p> |
|---|
| 116 | </description> |
|---|
| 117 | </item> |
|---|
| 118 | <item> |
|---|
| 119 | <tags>:extbisect</tags> |
|---|
| 120 | <spec>:extbisect <a>sub-command</a></spec> |
|---|
| 121 | <description> |
|---|
| 122 | <p> |
|---|
| 123 | 問題のある拡張などをあぶり出すためのコマンドです。 |
|---|
| 124 | 二分探索ぽい方法よって、効率的に困った拡張を探し出します。 |
|---|
| 125 | 自動的に拡張の有効無効を切り替えていくので、かなり楽が出来ると思います。 |
|---|
| 126 | </p> |
|---|
| 127 | <p> |
|---|
| 128 | 作業手順。 |
|---|
| 129 | (ok fail start を実行すると自動的に再起動します) |
|---|
| 130 | <ol> |
|---|
| 131 | <li>":extbisect start" で開始</li> |
|---|
| 132 | <li>問題が起きていないかテスト</li> |
|---|
| 133 | <li>起きていなければ":extbisect ok"、起きていれば":extbisect fail"を実行</li> |
|---|
| 134 | <li>再起動するので、2 を再び繰り返す。</li> |
|---|
| 135 | </ol> |
|---|
| 136 | <p> |
|---|
| 137 | 問題のある拡張がなんであるか、確定したら ok/fail したときにメッセージが出ます。 |
|---|
| 138 | メッセージを確認したら、":extbisect reset" で拡張の状態を元に戻してください。 |
|---|
| 139 | </p> |
|---|
| 140 | <p> |
|---|
| 141 | テストを行うことで、エラーで Firefox が終了してしまう場合は、再起動後に ok / fail を実行してください。 |
|---|
| 142 | </p> |
|---|
| 143 | </p> |
|---|
| 144 | </description> |
|---|
| 145 | </item> |
|---|
| 146 | </plugin> |
|---|
| 147 | </>; |
|---|
| 148 | // }}} |
|---|
| 149 | |
|---|
| 150 | |
|---|
| 151 | (function () { |
|---|
| 152 | |
|---|
| 153 | let states = storage.newMap('plugins-extman-states', {store: true}); |
|---|
| 154 | let bisect = storage.newMap('plugins-extman-bisect', {store: true}); |
|---|
| 155 | |
|---|
| 156 | states.modify = bisect.modify = function (name, func) this.set(name, func(this.get(name))); |
|---|
| 157 | |
|---|
| 158 | function xabled (id, enable) |
|---|
| 159 | services.get("extensionManager")[enable ? 'enableItem' : 'disableItem'](id); |
|---|
| 160 | |
|---|
| 161 | function xabledWithName (name, enable) |
|---|
| 162 | xabled(liberator.getExtension(name), enable); |
|---|
| 163 | |
|---|
| 164 | function cmp (s1, s2) |
|---|
| 165 | (s1.toLowerCase() == s2.toLowerCase()); |
|---|
| 166 | |
|---|
| 167 | function extFilter (exts, names) |
|---|
| 168 | (names && names.length) ? exts.filter(function (ext) names.some(function (name) cmp(name, ext.name))) |
|---|
| 169 | : exts; |
|---|
| 170 | |
|---|
| 171 | function store (name, targets) { |
|---|
| 172 | let es = extFilter(liberator.extensions, targets); |
|---|
| 173 | states.set(name, {extensions: es, date: new Date()}); |
|---|
| 174 | } |
|---|
| 175 | |
|---|
| 176 | function slash (ary, index) |
|---|
| 177 | [ary.slice(0, index), ary.slice(index)]; |
|---|
| 178 | |
|---|
| 179 | function isVimp (ext) |
|---|
| 180 | (ext.name == 'Vimperator'); |
|---|
| 181 | |
|---|
| 182 | store('last'); |
|---|
| 183 | |
|---|
| 184 | let extState = { |
|---|
| 185 | store: function (name, targets) { |
|---|
| 186 | function done () |
|---|
| 187 | liberator.echo('extensions state was stored to "' + name + '".'); |
|---|
| 188 | |
|---|
| 189 | if (!name) |
|---|
| 190 | return liberator.echoerr('too few arguments'); |
|---|
| 191 | |
|---|
| 192 | if (states.get(name)) { |
|---|
| 193 | commandline.input( |
|---|
| 194 | 'overwrite? [y/n]', |
|---|
| 195 | function (answer) |
|---|
| 196 | (answer.toLowerCase() == 'y' ? (store(name, targets, true), done()) : liberator.echo('canceled')) |
|---|
| 197 | ); |
|---|
| 198 | } else { |
|---|
| 199 | store(name, targets, true); |
|---|
| 200 | done(); |
|---|
| 201 | } |
|---|
| 202 | }, |
|---|
| 203 | |
|---|
| 204 | restore: function (name, targets) { |
|---|
| 205 | if (!name) |
|---|
| 206 | return liberator.echoerr('too few arguments'); |
|---|
| 207 | |
|---|
| 208 | let state = states.get(name); |
|---|
| 209 | if (!state) |
|---|
| 210 | return liberator.echoerr('"' + name + '" has not been stored.'); |
|---|
| 211 | |
|---|
| 212 | let es = state.extensions; |
|---|
| 213 | if (targets.length) |
|---|
| 214 | es = es.filter(function (ext) targets.some(function (t) t == ext.name)); |
|---|
| 215 | es.forEach(function (ext) xabled(ext.id, ext.enabled)); |
|---|
| 216 | |
|---|
| 217 | liberator.echo('extensions state was restored from "' + name + '".'); |
|---|
| 218 | }, |
|---|
| 219 | |
|---|
| 220 | flush: function () { |
|---|
| 221 | states.save(); |
|---|
| 222 | }, |
|---|
| 223 | |
|---|
| 224 | __noSuchMethod__: function (name) { |
|---|
| 225 | liberator.echoerr(name + ' is not valid sub-command'); |
|---|
| 226 | } |
|---|
| 227 | }; |
|---|
| 228 | |
|---|
| 229 | let extBisect = { |
|---|
| 230 | start: function () { |
|---|
| 231 | if (this.__notReady(false)) |
|---|
| 232 | return; |
|---|
| 233 | let targets = liberator.extensions.filter(function (ext) !isVimp(ext) && ext.enabled); |
|---|
| 234 | bisect.set('store', liberator.extensions); |
|---|
| 235 | bisect.set('state', 'started'); |
|---|
| 236 | let ([a, b] = slash(targets, targets.length / 2)) { |
|---|
| 237 | bisect.set('yet', a); |
|---|
| 238 | bisect.set('current', b); |
|---|
| 239 | } |
|---|
| 240 | bisect.save(); |
|---|
| 241 | this.__reflectCurrent(); |
|---|
| 242 | liberator.restart(); |
|---|
| 243 | }, |
|---|
| 244 | |
|---|
| 245 | ok: function () { |
|---|
| 246 | if (this.__notReady(true)) |
|---|
| 247 | return; |
|---|
| 248 | if (this.__finished(true)) |
|---|
| 249 | return; |
|---|
| 250 | bisect.modify('yet', function (value) { |
|---|
| 251 | let [a, b] = slash(value, value.length / 2); |
|---|
| 252 | bisect.set('current', a); |
|---|
| 253 | return b; |
|---|
| 254 | }); |
|---|
| 255 | this.__reflectCurrent(); |
|---|
| 256 | liberator.restart(); |
|---|
| 257 | }, |
|---|
| 258 | |
|---|
| 259 | fail: function () { |
|---|
| 260 | if (this.__notReady(true)) |
|---|
| 261 | return; |
|---|
| 262 | if (this.__finished(false)) |
|---|
| 263 | return; |
|---|
| 264 | bisect.modify('current', function (value) { |
|---|
| 265 | let [a, b] = slash(value, value.length / 2); |
|---|
| 266 | bisect.set('yet', a); |
|---|
| 267 | return b; |
|---|
| 268 | }); |
|---|
| 269 | this.__reflectCurrent(); |
|---|
| 270 | liberator.restart(); |
|---|
| 271 | }, |
|---|
| 272 | |
|---|
| 273 | show: function () { |
|---|
| 274 | function f (ext) liberator.echo(' ' + ext.name); |
|---|
| 275 | liberator.echo('<<current>>'); |
|---|
| 276 | bisect.get('current').forEach(f) |
|---|
| 277 | liberator.echo('<<yet>>'); |
|---|
| 278 | bisect.get('yet').forEach(f) |
|---|
| 279 | }, |
|---|
| 280 | |
|---|
| 281 | reset: function () { |
|---|
| 282 | if (this.__notReady(true)) |
|---|
| 283 | return; |
|---|
| 284 | bisect.set('state', ''); |
|---|
| 285 | bisect.get('store').forEach(function (ext) xabled(ext.id, ext.enabled)); |
|---|
| 286 | bisect.save(); |
|---|
| 287 | liberator.echo('extensions were reset'); |
|---|
| 288 | liberator.restart(); |
|---|
| 289 | }, |
|---|
| 290 | |
|---|
| 291 | __notReady: function (started) { |
|---|
| 292 | if (!!(bisect.get('state') == 'started') == !!started) |
|---|
| 293 | return false; |
|---|
| 294 | liberator.echoerr('extbisect has ' + (started ? 'not ' : '') + 'been started.'); |
|---|
| 295 | return true; |
|---|
| 296 | }, |
|---|
| 297 | |
|---|
| 298 | __finished: function (ok) { |
|---|
| 299 | function answer (ext) { |
|---|
| 300 | liberator.echo(util.escapeString(ext.name) + ' is the criminal!!'); |
|---|
| 301 | return true; |
|---|
| 302 | } |
|---|
| 303 | |
|---|
| 304 | let current = bisect.get('current'); |
|---|
| 305 | let yet = bisect.get('yet'); |
|---|
| 306 | |
|---|
| 307 | if (ok && yet.length <= 1) |
|---|
| 308 | return answer(yet[0]); |
|---|
| 309 | |
|---|
| 310 | if (!ok && current.length <= 1) |
|---|
| 311 | return answer(current[0]); |
|---|
| 312 | |
|---|
| 313 | return false; |
|---|
| 314 | }, |
|---|
| 315 | |
|---|
| 316 | __reflectCurrent: function () { |
|---|
| 317 | let current = bisect.get('current'); |
|---|
| 318 | liberator.extensions.forEach( |
|---|
| 319 | function (ext) |
|---|
| 320 | (xabled(ext.id, isVimp(ext) || current.some(function (e) e.id == ext.id))) |
|---|
| 321 | ); |
|---|
| 322 | }, |
|---|
| 323 | |
|---|
| 324 | __noSuchMethod__: function (name) { |
|---|
| 325 | liberator.echoerr(name + ' is not valid sub-command'); |
|---|
| 326 | } |
|---|
| 327 | }; |
|---|
| 328 | |
|---|
| 329 | commands.addUserCommand( |
|---|
| 330 | ['exts[tate]'], |
|---|
| 331 | 'store / restore extensions state (enabled / disabled).', |
|---|
| 332 | function (args) { |
|---|
| 333 | let [cmd,] = args; |
|---|
| 334 | extState[cmd](args[1], args.slice(2)); |
|---|
| 335 | }, |
|---|
| 336 | { |
|---|
| 337 | completer: function (context, args) { |
|---|
| 338 | if (args.length == 1) { |
|---|
| 339 | context.title = ['sub command', 'description']; |
|---|
| 340 | context.completions = [ |
|---|
| 341 | ['store', 'store current state'], |
|---|
| 342 | ['restore', 'restore current state'], |
|---|
| 343 | ['flush', 'flush'] |
|---|
| 344 | ]; |
|---|
| 345 | } else if (args.length == 2) { |
|---|
| 346 | context.title = ['name']; |
|---|
| 347 | context.completions = [[name, state.date] for ([name, state] in states)]; |
|---|
| 348 | } else if (args.length >= 3) { |
|---|
| 349 | let exts = liberator.extensions; |
|---|
| 350 | context.title = ['name']; |
|---|
| 351 | context.quote = ['', util.escapeString, '']; |
|---|
| 352 | context.completions = [[ext.name, ext.description] for each (ext in exts)]; |
|---|
| 353 | } |
|---|
| 354 | } |
|---|
| 355 | }, |
|---|
| 356 | true |
|---|
| 357 | ); |
|---|
| 358 | |
|---|
| 359 | commands.addUserCommand( |
|---|
| 360 | ['extbisect'], |
|---|
| 361 | 'bisectrrrrrrrrrrr', |
|---|
| 362 | function (args) { |
|---|
| 363 | let [cmd,] = args; |
|---|
| 364 | extBisect[cmd](); |
|---|
| 365 | }, |
|---|
| 366 | { |
|---|
| 367 | completer: function (context, args) { |
|---|
| 368 | if (args.length == 1) { |
|---|
| 369 | context.title = ['sub command', 'description']; |
|---|
| 370 | context.completions = [ |
|---|
| 371 | ['start', 'start bisect'], |
|---|
| 372 | ['ok', ''], |
|---|
| 373 | ['fail', ''], |
|---|
| 374 | ['reset', ''], |
|---|
| 375 | ['show', ''] |
|---|
| 376 | ]; |
|---|
| 377 | } |
|---|
| 378 | } |
|---|
| 379 | }, |
|---|
| 380 | true |
|---|
| 381 | ); |
|---|
| 382 | |
|---|
| 383 | |
|---|
| 384 | |
|---|
| 385 | states.save(); |
|---|
| 386 | |
|---|
| 387 | })(); |
|---|
| 388 | |
|---|
| 389 | // vim:sw=2 ts=2 et si fdm=marker: |
|---|