aboutsummaryrefslogtreecommitdiffstats
path: root/google-search.js
blob: 9be5cea77cf02734cd4550561ccf5e11ee19dc98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
var PLUGIN_INFO =
<VimperatorPlugin>
<name>{NAME}</name>
<description>Google Search, and AutoComplete.</description>
<description lang="ja">Google 検索し候補をよしなに補完します</description>
<minVersion>2.0</minVersion>
<maxVersion>2.0pre</maxVersion>
<updateURL>https://github.com/vimpr/vimperator-plugins/raw/master/google-search.js</updateURL>
<author mail="hotchpotch@gmail.com" homepage="http://tako3.net/http://d.hatena.ne.jp/secondlife/">Yuichi Tateno</author>
<license>MPL 1.1/GPL 2.0/LGPL 2.1</license>
<version>0.1</version>
<detail><![CDATA[
>||
:gsearch[!] のと[tab]
||<

google suggest での飛び先はあくまで google ですがこのプラグインは google の検索結果先に飛びます
この plugin を作ってから multi_requester.js の存在をしってあっちを使えば・・・、と思いましたいちおう favicon が表示されたりします
]]></detail>
</VimperatorPlugin>;

(function() {

var p = function (arg) {
    Application.console.log(arg);
    // liberator.log(arg);
}

// Simple $X. os0x version
function $X (exp, context, resolver) {
    context || (context = document);
    var Doc = context.ownerDocument || context;
    var result = Doc.evaluate(exp, context, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (var i = 0, len = result.snapshotLength, res = []; i < len; i++) {
        res.push(result.snapshotItem(i));
    }
    return res;
}

function getGoogleElements (word) {
     var [lang] = Cc['@mozilla.org/network/protocol;1?name=http']
                            .getService(Ci.nsIHttpProtocolHandler)
                            .language.split('-', 1);
     var xhr = new XMLHttpRequest();
     var endpoint = 'http://www.google.co.jp/search';
     var reqURL = endpoint + '?hl=' + lang + '&q=' + encodeURIComponent(word);
     xhr.open('GET', reqURL, false);
     xhr.send(null);

     var div = window.content.document.createElement('div');
     div.innerHTML = xhr.responseText;

     return $X('//div/ol/li/h3/a', div);
}

commands.addUserCommand(['gsearch'],
    'GoogleSearch, and AutoComplete',
    function (args) {
        var url = args.string;
        if (url.indexOf('http') != 0) {
            url = 'http://www.google.co.jp/search?q=' + encodeURIComponent(args.string);
        }
        liberator.open(url, args.bang? liberator.NEW_TAB : null);
    }, {
        completer: function (context) {
            context.filters = [function() true];
            context.keys = {text: "url", description: "title", icon: "icon"};
            context.title = ['URL', 'TITLE'];

            var regex = new RegExp('/url\\?q=([^&]+)');
            context.completions = getGoogleElements(context.filter).map(function(e) {
                var url = e.href.match(regex) ? decodeURIComponent(RegExp.$1) : e.href;
                return {
                    url:   url, 
                    icon:  bookmarks.getFavicon(url), 
                    title: e.textContent
                };
            });
        },
        argCount: '*',
        bang: true,
    },
    true
);

})();
ratorrc) using inline JavaScript. >|| // hatena sample javascript <<EOM liberator.globalVariables.userScenario = { DOMContentLoaded: [ { // good by hatena keyword pattern: 'http://d.hatena.ne.jp/keyword/', action: [ {sleep: 1000}, {follow: '//a[contains(@href,"http://ja.wikipedia.org/wiki")]'}, ], }, { // auto paging hatena in 5 seconds pattern: 'hatena.ne.jp', action: {and: [ {sleep: 5000}, {follow: '//a[@rel="prev"]'}, ]} }, { // recent vector site is confusing pattern: 'http://www.vector.co.jp/soft/', action: {or: [ {follow: ['//a[not(starts-with(@href,"http")) and contains(@href,"/soft/dl/")]', liberator.NEW_TAB]}, {follow: '//a[not(starts-with(@href,"http")) and contains(@href,"/download/file/")]'}, ]} }, ], load: [ { // auto hatena star pattern: 'hatena.ne.jp/', action: {follow: '//img[@class="hatena-star-add-button"]'}, }, ], }; EOM ||< Action expressions like >|| action: {and: [ {sleep: 5000}, {follow: '//a[@rel="prev"]'}, ]} ||< is syntax-sugar of >|| action: [{and: [ {sleep: [5000]}, {follow: ['//a[@rel="prev"]']}, ]}] ||< and action expressions are quoted by {begin: ...}. == TODO == - write more examples. - add more functions. - fix bugs. - a lot. ]]></detail> </VimperatorPlugin>; //}}} (function() { const debugMode = true; const VariablesName = 'ScenarioActorVariables'; const VariablesLabelID = 'ScenarioActorVariablesLabelID'; let SCENARIO_DIR = liberator.globalVariables.scenarioDir || 'scenario'; var libly = liberator.plugins.libly; var $U = libly.$U; var logger = $U.getLogger('scenario-actor'); function ScenarioActor () { //{{{ let variables = storage.newMap('scenarioactor', true); function ScenarioContext(event) { //{{{ let triggeredEvent = event; let win = (event.target.contentDocument||event.target).defaultView; let self = { glet: function (name, value) { if((typeof name)!='string') throw [name, value]; variables.set(name, self.eval(value)); return value; }, gvar: function (name) { if((typeof name)!='string') throw [name, value]; return variables.get(name); }, begin: function () { let lastValue; for(let i=0,len=arguments.length;i<len;++i) { lastValue = self.eval(arguments[i]); } return lastValue; }, and: function () { let lastValue; for(let i=0,len=arguments.length;i<len;++i) { if(!(lastValue = self.eval(arguments[i]))) break; } return lastValue; }, or: function () { let lastValue; for(let i=0,len=arguments.length;i<len;++i) { if(lastValue = self.eval(arguments[i])) break; } return lastValue; }, loop: function (cond, exp) { let mainThread = services.get('threadManager').mainThread; let f = function() { if(!self.eval(cond)) return; self.eval(exp); mainThread.processNextEvent(true); f(); }; setTimeout(f, 1); }, get: function (dst, prop) { let edst = self.eval({xpath: self.eval(dst)}); if(!edst) throw [dst, prop]; return edst[prop]; }, set: function (dst, src, prop) { let edst = self.eval({xpath: self.eval(dst)}); if(!edst) throw [dst, src, prop]; edst[prop] = self.eval(src); return edst[prop]; }, xpath: function (xpath) { if((typeof xpath)!='string'||!win.document) throw [name, value]; return buffer.evaluateXPath(xpath, win.document).snapshotItem(0); }, value: function (dst, src) { let edst = self.eval({xpath: self.eval(dst)}); if(!edst) throw [dst, src]; if(src!=undefined) { // set edst.value = self.eval(src); } return edst.value; }, click: function (dst) { let edst = self.eval({xpath: self.eval(dst)}); if(!edst) throw [dst]; edst.click(); return edst; }, follow: function(dst, where) { let edst = self.eval({xpath: self.eval(dst)}); if(!edst) throw [dst, where]; buffer.followLink(edst, where?where:liberator.CURRENT_TAB) return edst; }, remove: function (dst) { let edst = self.eval({xpath: self.eval(dst)}); if(!edst) throw [dst]; edst.parentNode.removeChild(edst); return edst; }, saveLink: function (dst, skipPrompt) { let edst = self.eval({xpath: self.eval(dst)}); if(!edst) throw [dst, skipPrompt]; buffer.saveLink(edst, skipPrompt); return edst; }, innerText: function (dst, src) { let edst = self.eval({xpath: self.eval(dst)}); if(!edst) throw [dst, src]; if(src==undefined) { // get return edst.innerText; } let esrc = self.eval(src); edst.innerText = esrc; return esrc; }, innerHTML: function (dst, src) { let edst = self.eval({xpath: self.eval(dst)}); if(!edst) throw [dst, src]; if(src==undefined) { // get return edst.innerHTML; } let esrc = self.eval(src); edst.innerHTML = esrc; return esrc; }, url: function() { if(!win.document) throw []; return win.document.location.href; }, prompt: function(message, init) { if(!win) throw [message, init]; return win.prompt(message||'', init||''); }, sleep: function(delay) { return liberator.sleep(delay); }, close: function() { if(!win) throw []; return win.close(); }, jseval: function() { let f = arguments[0]; let args = Array.prototype.slice.call(arguments); args.shift(); if(typeof f!='function') throw [f].concat(args); return f.apply(this, args); }, showVariables: function (names) { if(!win.document) throw [names]; actor.showVariables(win.document, names); }, eval: function(exp) { switch(typeof exp) { default: case 'bolean': case 'number': case 'string': case 'function': return exp; case 'object': for(let sym in exp) { let args = exp[sym]; if(debugMode) logger.log('{'+sym+': '+args+'}'); try { if(args instanceof Array) { return self[sym].apply(this, args); } return self[sym](args); } catch(args if args instanceof Array) { let msg = '{'+sym+': ['+args.join(',')+']}'; liberator.reportError(msg); return false; } } } }, }; return self; } //}}} function createLabel(doc, labelID) { let label; if(!(label = doc.getElementById(labelID))) { label = doc.createElement('pre'); label.id = VariablesLabelID; label.style.position = 'absolute'; label.style.top = '0px'; label.style.left = '0px'; label.style.margin = '0px'; label.style.padding = '0px'; label.style.fontSize = '80%'; label.style.border = '1px solid #ccc'; label.style.backgroundColor = '#fff'; label.style.textAlign = 'left'; label.style.zIndex = '100'; doc.body.appendChild(label); } return label; } function urlmatcher(url) { return function(scenario) { if(scenario.pattern) { let pattern = scenario.pattern; switch(typeof pattern) { case 'string': if(url.indexOf(pattern)==-1) return false; break; case 'object': if(!pattern.test(url)) return false; break; } } if(scenario.ignore) { let ignore = scenario.ignore; switch(typeof ignore) { case 'string': if(url.indexOf(ignore)!=-1) return false; break; case 'object': if(ignore.test(url)) return false; break; } } return true; } } let self = { enabled: true, readScenarioDirectory: function(name, fun) { io.getRuntimeDirectories(SCENARIO_DIR).forEach(function(dir) { $U.readDirectory(dir.path, name, fun); }); }, loadLocalScenario: function(name) { if(!name) name = '\.js$'; if(liberator.globalVariables.userScenario) loadedScenarioList.push(liberator.globalVariables.userScenario); self.readScenarioDirectory(name, function(file) { logger.log('load scenario '+file.path); io.source(file.path); }); loadedScenarioList.forEach(function(list) { for(let event in list) { self.addListener(event, list[event]); } }); }, showVariables: function(doc, names) { if(!doc) doc = window.content.document; if(!names) { names = [name for([name, value] in variables)]; } let label = createLabel(doc, VariablesLabelID); label.innerHTML = [arg+': '+variables.get(arg) for each(arg in names)].join("\n"); }, clear: function () { variables.clear(); }, addListener: function (eventType, scenarioList) { if(!scenarioList || scenarioList.length==0) return scenarioList; getBrowser().addEventListener(eventType, function (event) { if (!self.enabled) return; let context = ScenarioContext(event); let url = context.url(); if(!url) return false; let matchfun = urlmatcher(url); scenarioList.forEach(function(scenario) { if(matchfun(scenario)) { context.eval({begin: scenario.action}); } }); }, true); }, }; return self; }; //}}} let actor = plugins.scenarioActor = ScenarioActor(); let loadedScenarioList = plugins.scenarioActor.loadedScenarioList = []; actor.enabled = !/^(?:false|0)$/i.test(liberator.globalVariables.scenario_actor_enabled); actor.loadLocalScenario(); commands.addUserCommand(['scenarioclear'], 'clear scenario-actor variables', actor.clear, { argCount: '0', }); commands.addUserCommand(['scenariovars'], 'show scenario-actor variables', function(args) { actor.showVariables(window.content.document); }, { argCount: '0', }); commands.addUserCommand(['scenarioload'], 'load local scenario', function(args) { if(args.length) { args.forEach(actor.loadLocalScenario); } else { actor.loadLocalScenario(); } }, { argCount: '*', completer: function (context, args) { let completions = []; actor.readScenarioDirectory(name, function(file) { completions.push([file.leafName, '']); }); context.completions = completions; } }); commands.addUserCommand(['scenario'], 'turn on/off scenario-actor', function(args) { if (args.length) { switch (args[0].toLowerCase()) { case 'on': actor.enabled = true; break; case 'off': actor.enabled = false; break; default: liberator.echoerr('Invalid argument: ' + args[0]); return; } } else { actor.enabled = !actor.enabled; } liberator.echo('scenario-actor was ' + (actor.enabled ? 'enabled' : 'disabled')); }, { argCount: '*', completer: function (context, args) { context.completions = [['on', 'enable scenario-actor'], ['off', 'disable scenario-actor']]; } }); })(); // vim: set fdm=marker sw=4 ts=4 et: