root/lang/javascript/vimperator-plugins/trunk/extension-manager.js

Revision 36638, 12.8 kB (checked in by anekos, 7 months ago)

ヘルプ嫁追加

  • Property svn:executable set to *
Line 
1/* NEW BSD LICENSE {{{
2Copyright (c) 2010, anekos.
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without modification,
6are 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
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25THE 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 {{{
36let 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 {{{
62let 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:
Note: See TracBrowser for help on using the browser.