diff options
author | anekos | 2008-08-22 18:15:07 +0000 |
---|---|---|
committer | anekos | 2008-08-22 18:15:07 +0000 |
commit | a257e8195f2656692749ae294971c691deabb9dc (patch) | |
tree | 68cf1ba720812e6431daca71c03a48b11e88a2a5 | |
parent | 41378fc2905a841425e09effc6616f4fc25982f4 (diff) | |
download | vimperator-plugins-a257e8195f2656692749ae294971c691deabb9dc.tar.bz2 |
検索結果の強調表示追加。コードをほぼ全部書き換えた。色々改善された気がする。
git-svn-id: http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk@18090 d0d07461-0603-4401-acd4-de1884942a52
-rw-r--r-- | migemized_find.js | 212 |
1 files changed, 151 insertions, 61 deletions
diff --git a/migemized_find.js b/migemized_find.js index 2709576..ebad31e 100644 --- a/migemized_find.js +++ b/migemized_find.js @@ -2,7 +2,7 @@ // @name Migemized Find // @description-ja デフォルトのドキュメント内検索をミゲマイズする。 // @license Creative Commons 2.1 (Attribution + Share Alike) -// @version 0.3 +// @version 1.0 // ==/VimperatorPlugin== // // Usage: @@ -11,90 +11,180 @@ // '?' => Migemo検索 // 以外 => Migemo検索 // -// Setting: -// let g:migemized_find_delay = "0" -// 検索開始の遅延時間 -// // Author: // anekos // // Link: // http://d.hatena.ne.jp/nokturnalmortum/20080805#1217941126 -// -// TODO: -// FIND_MODE_NATIVE のときうまく動かない。XUL/Migemoの問題? -// 検索時に取りこぼさないようにする。 -// (とりあえず検索開始を遅延することで取りこぼしにくくした) -(function () { +(function () { try { - // findMode := FIND_MODE_NATIVE | FIND_MODE_MIGEMO | FIND_MODE_REGEXP + let XMigemoCore = Components.classes['@piro.sakura.ne.jp/xmigemo/factory;1'] + .getService(Components.interfaces.pIXMigemoFactory) + .getService('ja'); - const FindToolbar = document.getElementById('FindToolbar') - const FindbarTextbox = FindToolbar.getElement('findbar-textbox'); - const DOMUtils = Components.classes["@mozilla.org/inspector/dom-utils;1"]. - getService(Components.interfaces["inIDOMUtils"]); + function getPosition (elem) { + if (!elem) + return {x: 0, y: 0}; + let parent = getPosition(elem.offsetParent); + return { x: (elem.offsetLeft || 0) + parent.x, + y: (elem.offsetTop || 0) + parent.y } + } - let previousKeyword = null; - let lastKeyword = null; - let original = {}; + let delayCallTimer = null; + let MF = { + lastSearchText: null, + previousSearchText: null, + lastDirection: null, - // とりあえず、アレな方法で not found を検出 - function isNotFound () { - let rules = DOMUtils.getCSSStyleRules(FindbarTextbox); - for (let i = 0; i < rules.Count(); i++) { - if (rules.GetElementAt(i).selectorText.indexOf('notfound') >= 0) - return true; - } - } + get buffer function () liberator.buffer, - // 検索文字列から検索モードと検索文字列を得る。 - function getFindMode (str) { - let [head, tail] = [str[0], str.slice(1)]; - switch (head) { - case '/': - return [tail, XMigemoFind.FIND_MODE_REGEXP]; - case '?': - return [tail, XMigemoFind.FIND_MODE_MIGEMO]; - // case '-': - // return [tail, XMigemoFind.FIND_MODE_NATIVE]; - } - return [str, XMigemoFind.FIND_MODE_MIGEMO]; - } + get document function () content.document, - let timer = null; + get storage function () (this.buffer.__migemized_find_storage || (this.buffer.__migemized_find_storage = {})), - let migemized = { - find: function find (str, backwards) { + get defaultRange function () { + let range = this.document.createRange(); + range.selectNodeContents(this.document.body); + return range; + }, + + get highlightRemover function () (this.storage.highlightRemover || function () void(0)), + set highlightRemover function (fun) (this.storage.highlightRemover = fun), + + MODE_NORMAL: 0, + MODE_REGEXP: 1, + MODE_MIGEMO: 2, + + // 検索文字列から検索モードと検索文字列を得る。 + searchTextToRegExpString: function (str) { + let [head, tail] = [str[0], str.slice(1)]; + switch (head) { + case '/': + return tail; + case '?': + return XMigemoCore.getRegExp(tail); + } + return XMigemoCore.getRegExp(str); + }, + + removeHighlight: function () { + this.highlightRemover() + this.highlightRemover = null; + }, + + highlightRange: function (range, setRemover) { + let span = this.document.createElement('span'); + let spanStyle = 'background-color: lightblue; color: black; border: dotted 3px blue;'; + + span.setAttribute('style', spanStyle); + range.surroundContents(span); + + let scroll = function () { + let pos = getPosition(span); + content.scroll(pos.x - (content.innerWidth / 2), + pos.y - (content.innerHeight / 2)); + }; + setTimeout(scroll, 0); + + let remover = function () { + let range = this.document.createRange(); + range.selectNodeContents(span); + let content = range.extractContents(); + range.setStartBefore(span); + range.insertNode(content); + range.selectNode(span); + range.deleteContents(); + }; + + if (setRemover) + this.highlightRemover = remover; + + return remover; + }, + + find: function (str, backwards, range, start, end) { + if (!range) + range = this.defaultRange; + try { + return XMigemoCore.regExpFind(str, 'i', range, start, end, backwards); + } catch (e) { + return false; + } + }, + + findFirst: function (str, backwards) { let f = function () { - liberator.log('called '); - let [word, mode] = getFindMode(str); - if (!word) - return; - XMigemoFind.findMode = mode; - XMigemoFind.find(backwards, lastKeyword = word, true); + this.lastDirection = backwards; + this.lastSearchText = str = this.searchTextToRegExpString(str); + + let result = this.storage.lastResult = this.find(str, backwards); + + this.removeHighlight(); + if (result) + this.highlightRange(result, true); + + return result; }; - if (timer) - clearTimeout(timer); - timer = setTimeout(f, parseInt(liberator.globalVariables.migemized_find_delay || '300')); + + if (delayCallTimer) + clearTimeout(delayCallTimer); + + delayCallTimer = setTimeout(function () f.call(MF), 300); + }, + + findAgain: function (reverse) { + this.removeHighlight(); + + let str = this.lastSearchText; + let range = this.defaultRange; + let last = this.storage.lastResult; + let backwards = !!(!this.lastDirection ^ !reverse); + let start, end; + + if (last) { + if (backwards) { + end = last.cloneRange(); + end.setStart(last.endContainer, last.endOffset); + } else { + start = last.cloneRange(); + start.setStart(last.endContainer, last.endOffset); + } + } + + let result = this.storage.lastResult = this.find(str, backwards, range, start, end); + if (!result) + result = this.storage.lastResult = this.find(str, backwards, range); + + if (result) + this.highlightRange(result, true); + else + liberator.echoerr('not found: ' + str); + + return result; + }, + }; + + let original = {}; + + let migemized = { + find: function find (str, backwards) { + MF.findFirst(str, backwards); }, findAgain: function findAgain (reverse) { - XMigemoFind.find(reverse, lastKeyword || previousKeyword, true); + MF.findAgain(reverse); }, searchSubmitted: function searchSubmitted (command, forcedBackward) { - previousKeyword = lastKeyword; - XMigemoFind.clear(false); - liberator.modes.reset(); - if (isNotFound()) - setTimeout(function () { liberator.echoerr("E486: Pattern not found: " + command); }, 0); + if (!MF.storage.lastResult) + liberator.echoerr('not found: ' + MF.lastSearchText); + MF.previousSearchText = MF.lastSearchText; }, searchCanceled: function searchCanceled () { - lastKeyword = null; - XMigemoFind.clear(false); + MF.lastSearchText = MF.previousSearchText; }, }; @@ -113,4 +203,4 @@ uninstall: function () set(original), }; -})(); +}catch(e){liberator.log(e);}})(); |