Changeset 18090

Show
Ignore:
Timestamp:
08/23/08 03:15:07 (5 months ago)
Author:
anekos
Message:

検索結果の強調表示追加。コードをほぼ全部書き換えた。色々改善された気がする。

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • lang/javascript/vimperator-plugins/trunk/migemized_find.js

    r17953 r18090  
    33// @description-ja デフォルトのドキュメント内検索をミゲマイズする。 
    44// @license        Creative Commons 2.1 (Attribution + Share Alike) 
    5 // @version        0.3 
     5// @version        1.0 
    66// ==/VimperatorPlugin== 
    77// 
     
    1212//      以外 => Migemo検索 
    1313// 
    14 // Setting: 
    15 //    let g:migemized_find_delay = "0" 
    16 //      検索開始の遅延時間 
    17 // 
    1814// Author: 
    1915//    anekos 
     
    2117// Link: 
    2218//    http://d.hatena.ne.jp/nokturnalmortum/20080805#1217941126 
    23 // 
    24 // TODO: 
    25 //    FIND_MODE_NATIVE のときうまく動かない。XUL/Migemoの問題? 
    26 //    検索時に取りこぼさないようにする。 
    27 //    (とりあえず検索開始を遅延することで取りこぼしにくくした) 
    28  
    29 (function () { 
    30  
    31   // findMode := FIND_MODE_NATIVE | FIND_MODE_MIGEMO | FIND_MODE_REGEXP  
    32  
    33   const FindToolbar = document.getElementById('FindToolbar') 
    34   const FindbarTextbox = FindToolbar.getElement('findbar-textbox'); 
    35   const DOMUtils = Components.classes["@mozilla.org/inspector/dom-utils;1"]. 
    36                       getService(Components.interfaces["inIDOMUtils"]); 
    37  
    38   let previousKeyword = null; 
    39   let lastKeyword = null; 
     19 
     20(function () { try { 
     21 
     22  let XMigemoCore = Components.classes['@piro.sakura.ne.jp/xmigemo/factory;1'] 
     23                     .getService(Components.interfaces.pIXMigemoFactory) 
     24                     .getService('ja'); 
     25 
     26  function getPosition (elem) { 
     27    if (!elem) 
     28      return {x: 0, y: 0}; 
     29    let parent = getPosition(elem.offsetParent); 
     30    return { x: (elem.offsetLeft || 0) + parent.x, 
     31             y: (elem.offsetTop  || 0) + parent.y  } 
     32  } 
     33 
     34  let delayCallTimer = null; 
     35 
     36  let MF = { 
     37    lastSearchText: null, 
     38    previousSearchText: null, 
     39    lastDirection: null, 
     40 
     41    get buffer function () liberator.buffer, 
     42 
     43    get document function () content.document, 
     44 
     45    get storage function () (this.buffer.__migemized_find_storage || (this.buffer.__migemized_find_storage = {})), 
     46 
     47    get defaultRange function () { 
     48      let range = this.document.createRange(); 
     49      range.selectNodeContents(this.document.body); 
     50      return range; 
     51    }, 
     52 
     53    get highlightRemover function () (this.storage.highlightRemover || function () void(0)), 
     54    set highlightRemover function (fun) (this.storage.highlightRemover = fun), 
     55 
     56    MODE_NORMAL: 0, 
     57    MODE_REGEXP: 1, 
     58    MODE_MIGEMO: 2, 
     59 
     60    // 検索文字列から検索モードと検索文字列を得る。 
     61    searchTextToRegExpString: function (str) { 
     62      let [head, tail] = [str[0], str.slice(1)]; 
     63      switch (head) { 
     64        case '/': 
     65          return tail; 
     66        case '?': 
     67          return XMigemoCore.getRegExp(tail); 
     68      } 
     69      return XMigemoCore.getRegExp(str); 
     70    }, 
     71 
     72    removeHighlight: function () { 
     73      this.highlightRemover() 
     74      this.highlightRemover = null; 
     75    }, 
     76 
     77    highlightRange: function (range, setRemover) { 
     78      let span = this.document.createElement('span'); 
     79      let spanStyle = 'background-color: lightblue; color: black; border: dotted 3px blue;'; 
     80 
     81      span.setAttribute('style', spanStyle); 
     82      range.surroundContents(span); 
     83 
     84      let scroll = function () { 
     85        let pos = getPosition(span); 
     86        content.scroll(pos.x - (content.innerWidth / 2), 
     87                       pos.y - (content.innerHeight / 2)); 
     88      }; 
     89      setTimeout(scroll, 0); 
     90 
     91      let remover = function () { 
     92        let range = this.document.createRange(); 
     93        range.selectNodeContents(span); 
     94        let content = range.extractContents(); 
     95        range.setStartBefore(span); 
     96        range.insertNode(content); 
     97        range.selectNode(span);  
     98        range.deleteContents();  
     99      }; 
     100 
     101      if (setRemover) 
     102        this.highlightRemover = remover; 
     103 
     104      return remover; 
     105    }, 
     106 
     107    find: function (str, backwards, range, start, end) { 
     108        if (!range) 
     109          range = this.defaultRange; 
     110        try { 
     111          return XMigemoCore.regExpFind(str, 'i', range, start, end, backwards); 
     112        } catch (e) { 
     113          return false; 
     114        } 
     115    }, 
     116 
     117    findFirst: function (str, backwards) { 
     118      let f = function () { 
     119        this.lastDirection = backwards; 
     120        this.lastSearchText = str = this.searchTextToRegExpString(str); 
     121 
     122        let result = this.storage.lastResult = this.find(str, backwards); 
     123 
     124        this.removeHighlight(); 
     125        if (result) 
     126          this.highlightRange(result, true); 
     127 
     128        return result; 
     129      }; 
     130 
     131      if (delayCallTimer) 
     132        clearTimeout(delayCallTimer); 
     133 
     134      delayCallTimer = setTimeout(function () f.call(MF), 300); 
     135    }, 
     136 
     137    findAgain: function (reverse) { 
     138      this.removeHighlight(); 
     139 
     140      let str = this.lastSearchText; 
     141      let range = this.defaultRange; 
     142      let last = this.storage.lastResult; 
     143      let backwards = !!(!this.lastDirection ^ !reverse); 
     144      let start, end; 
     145 
     146      if (last) { 
     147        if (backwards) { 
     148          end = last.cloneRange(); 
     149          end.setStart(last.endContainer, last.endOffset); 
     150        } else { 
     151          start = last.cloneRange(); 
     152          start.setStart(last.endContainer, last.endOffset); 
     153        } 
     154      } 
     155 
     156      let result = this.storage.lastResult = this.find(str, backwards, range, start, end); 
     157      if (!result) 
     158        result = this.storage.lastResult = this.find(str, backwards, range); 
     159 
     160      if (result) 
     161        this.highlightRange(result, true); 
     162      else 
     163        liberator.echoerr('not found: ' + str); 
     164 
     165      return result; 
     166    }, 
     167  }; 
     168 
    40169  let original = {}; 
    41  
    42  
    43   // とりあえず、アレな方法で not found を検出 
    44   function isNotFound () { 
    45     let rules = DOMUtils.getCSSStyleRules(FindbarTextbox); 
    46     for (let i = 0; i < rules.Count(); i++) { 
    47       if (rules.GetElementAt(i).selectorText.indexOf('notfound') >= 0) 
    48         return true; 
    49     } 
    50   } 
    51  
    52   // 検索文字列から検索モードと検索文字列を得る。 
    53   function getFindMode (str) { 
    54     let [head, tail] = [str[0], str.slice(1)]; 
    55     switch (head) { 
    56       case '/': 
    57         return [tail, XMigemoFind.FIND_MODE_REGEXP]; 
    58       case '?': 
    59         return [tail, XMigemoFind.FIND_MODE_MIGEMO]; 
    60       //  case '-': 
    61       //    return [tail, XMigemoFind.FIND_MODE_NATIVE]; 
    62     } 
    63     return [str, XMigemoFind.FIND_MODE_MIGEMO]; 
    64   } 
    65  
    66   let timer = null; 
    67170 
    68171  let migemized = { 
    69172    find: function find (str, backwards) { 
    70       let f = function () { 
    71         liberator.log('called '); 
    72         let [word, mode] = getFindMode(str); 
    73         if (!word) 
    74           return; 
    75         XMigemoFind.findMode = mode; 
    76         XMigemoFind.find(backwards, lastKeyword = word, true); 
    77       }; 
    78       if (timer) 
    79         clearTimeout(timer); 
    80       timer = setTimeout(f, parseInt(liberator.globalVariables.migemized_find_delay || '300')); 
     173      MF.findFirst(str, backwards); 
    81174    }, 
    82175 
    83176    findAgain: function findAgain (reverse) { 
    84       XMigemoFind.find(reverse, lastKeyword || previousKeyword, true); 
     177      MF.findAgain(reverse); 
    85178    }, 
    86179 
    87180    searchSubmitted: function searchSubmitted (command, forcedBackward) { 
    88       previousKeyword = lastKeyword; 
    89       XMigemoFind.clear(false); 
    90       liberator.modes.reset(); 
    91       if (isNotFound()) 
    92         setTimeout(function () { liberator.echoerr("E486: Pattern not found: " + command); }, 0); 
     181      if (!MF.storage.lastResult) 
     182        liberator.echoerr('not found: ' + MF.lastSearchText); 
     183      MF.previousSearchText = MF.lastSearchText; 
    93184    }, 
    94185 
    95186    searchCanceled: function searchCanceled () { 
    96       lastKeyword = null; 
    97       XMigemoFind.clear(false); 
     187      MF.lastSearchText = MF.previousSearchText; 
    98188    }, 
    99189  }; 
     
    114204  }; 
    115205 
    116 })(); 
     206}catch(e){liberator.log(e);}})();