grep
grep 更新しました。
主な更新は、input や textarea(nsIDOMNSEditableElement) の選択に対応です。
nsIDOMNSEditableElement を 効率良く検出する方法がわからなかったので、
都度全ノードをチェックしている部位があります。
なので、「use_clear_editor_range」を false で 全チェックを抑制できます。
代償として、nNで 次へ遷移しても選択範囲が クリアされません。
あと、var を 全て let に変更しました。
あとは、designMode="on"の状態への対応ですが、
検討がついてません…
diff -r b59cbc3c756d grep.js --- a/grep.js Wed Feb 03 21:20:49 2010 +0900 +++ b/grep.js Wed Feb 03 21:29:31 2010 +0900 @@ -8,12 +8,13 @@ const use_hook_search_map = true; const use_show_echo = false; const use_highlight_option = true; - var screen_position = [50, -1];//[垂直,水平] - var default_option = liberator.globalVariables.vimp_grep_default_option|| "imxh"; + const use_clear_editor_range = true; + let screen_position = [-1, -1];//[垂直,水平] + let default_option = liberator.globalVariables.vimp_grep_default_option|| "imx"; //{{{core const vimp = "liberator-completions"; - var finder = Cc["@mozilla.org/embedcomp/rangefind;1"] + let finder = Cc["@mozilla.org/embedcomp/rangefind;1"] .getService(Ci.nsIFind); const option_list = "imxnr" + (use_highlight_option ? "h" : ""); const gFm = Cc["@mozilla.org/focus-manager;1"] @@ -22,12 +23,12 @@ //}}} function range2string(r, max){ - var txt = r.toString(); - var so = r.startOffset; - var eo = r.endOffset; - var et = r.endContainer.textContent; - var st = r.startContainer.textContent; - var max = (arguments.callee.max/2-2) || 0; + let txt = r.toString(); + let so = r.startOffset; + let eo = r.endOffset; + let et = r.endContainer.textContent; + let st = r.startContainer.textContent; + let max = (arguments.callee.max/2-2) || 0; return { abbr : so > max, @@ -38,13 +39,13 @@ } function get_word_max(){ - var win = document.getElementById(vimp).contentWindow; - var fontSize = win.getComputedStyle(win.document.body,'').fontSize.replace("px",""); + let win = document.getElementById(vimp).contentWindow; + let fontSize = win.getComputedStyle(win.document.body,'').fontSize.replace("px",""); return Math.floor(document.width / fontSize); } - var process = [function(i,text){ - var r = range2string(i.item.range); + let process = [function(i,text){ + let r = range2string(i.item.range); return <><div style="position:absolute;"> {r.abbr ? <span style={abbr_style}>~~</span> : ""} @@ -64,9 +65,9 @@ } function create_ranges(win){ - var doc = win.document; - var body = doc.body; - var count = body.childNodes.length; + let doc = win.document; + let body = doc.body; + let count = body.childNodes.length; let searchRange = doc.createRange(); let startPt = doc.createRange(); @@ -143,7 +144,7 @@ } function migemo_grep(word, option){ - var re = new RegExp(window.migemo.query(word), option); + let re = new RegExp(window.migemo.query(word), option); return regexp_grep_core(re); } //}}} @@ -156,12 +157,12 @@ win = win || content.window; let list = [w.document for(w in iteratorFrame(win))]; return function(a,b){ - var n1 = a.startContainer.ownerDocument; - var n2 = b.startContainer.ownerDocument; + let n1 = a.startContainer.ownerDocument; + let n2 = b.startContainer.ownerDocument; + let ret=0; if(n1 === n2) return a.compareBoundaryPoints(Range.START_TO_START, b) || a.compareBoundaryPoints(Range.END_TO_END, b); - var ret=0; for(let [,n] in Iterator(list)){ if(n===n1) return -1; else if(n===n2) return 1; @@ -169,7 +170,7 @@ }; } - var mode_func = { }; + let mode_func = { }; mode_func.n = normal_grep; mode_func.r = regexp_grep; mode_func.x = migemo_grep; @@ -185,7 +186,7 @@ <>^((\d*)([{option_list}]*)/)?([^/]+)(/([{option_list}]*))?$</>.toString() ,"i"); if(m=re.exec(arg)){ - var s = ""; + let s = ""; word = m[4]; num = m[2]||0; if(!m[1] && !m[5]){ @@ -205,7 +206,7 @@ } } let option = <>{flags}{mode}{opt}</>.toString(); - var info = get_cache(); + let info = get_cache(); if(info){ if(info.word === word && info.option === option){ info.index = num; @@ -214,26 +215,76 @@ } } - var func = mode_func[mode]; + let func = mode_func[mode]; if(!func){ liberator.echoerr(<>{mode} is not support</>.toString()); return; } - var list = func(word, flags + "g"); + let list = func(word, flags + "g"); info = {list:list, index:num, word: word, option: option}; content.document[grep_info_attr] = info; return info; } - function getSelectionController(view){ - return view + function getSelectionControllerFromWindow(view){ + let selectionController = null; + try{ + selectionController = view .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShell) .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsISelectionDisplay) .QueryInterface(Ci.nsISelectionController); + }catch(ex){} + + return selectionController; + } + + function checkEditableElement(node){ + let ret = false; + try{ + node.QueryInterface(Ci.nsIDOMNSEditableElement) + ret = true; + }catch(ex){} + return ret; + } + + function getEditor(node){ + while(node){ + if(checkEditableElement(node)){ + return node.editor; + } + node = node.parentNode; + } + return null; + } + + function getSelectionControllerFromRange(aRange){ + let node = aRange.startContainer; + let editor = getEditor(node); + return editor ? editor.selectionController + : getSelectionControllerFromWindow(node.ownerDocument.defaultView); + } + + function clearEditorAllSelections(win, aType){ + win = win || content.window; + aType = aType || Ci.nsISelectionController.SELECTION_NORMAL; + for(let w in iteratorFrame(win)){ + let list = w.document.getElementsByTagName("*"); + for(let [,n] in Iterator(list)){ + if(checkEditableElement(n)){ + let editor = n.editor; + if(editor){ + let selection = editor.selectionController.getSelection(aType); + if(selection.rangeCount>0){ + selection.removeAllRanges(); + } + } + } + } + } } function grep_jump(info){ @@ -241,28 +292,40 @@ liberator.echoerr(<>no match "{info.option}/{info.word}"</>); return; } - var n = info.list[info.index]; + let n = info.list[info.index]; if(!n){ liberator.echoerr(<>index error "{info.index}"</>); return; } - var win = n.startContainer.ownerDocument.defaultView; + let win = n.startContainer.ownerDocument.defaultView; if(gFm.focusedWindow){ + if(use_clear_editor_range) clearEditorAllSelections(); gFm.focusedWindow.getSelection().removeAllRanges(); } - var selection = getSelectionController(win) - .getSelection(Ci.nsISelectionController.SELECTION_NORMAL); + let selectionController = getSelectionControllerFromWindow(win); + if(!selectionController) return; + + //{{{ editable element + let editor = getEditor(n.startContainer); + if(editor){ + let selectionController = editor.selectionController; + let selection = selectionController.getSelection(Ci.nsISelectionController.SELECTION_NORMAL); + selection.removeAllRanges(); + selection.addRange(n); + selectionController.setDisplaySelection(Ci.nsISelectionController.SELECTION_ATTENTION); + } + //}}} + + let selection = selectionController.getSelection(Ci.nsISelectionController.SELECTION_NORMAL); selection.removeAllRanges(); + selection.addRange(n); - { - gFm.moveFocus(win, null, Ci.nsIFocusManager.MOVEFOCUS_CARET, - Ci.nsIFocusManager.FLAG_NOSCROLL | Ci.nsIFocusManager.FLAG_NOSWITCHFRAME); + gFm.moveFocus(win, null, Ci.nsIFocusManager.MOVEFOCUS_CARET, + Ci.nsIFocusManager.FLAG_NOSCROLL | Ci.nsIFocusManager.FLAG_NOSWITCHFRAME); - let ctrl = getSelectionController(win); - ctrl.setDisplaySelection(Ci.nsISelectionController.SELECTION_ATTENTION); - ctrl.repaintSelection(Ci.nsISelectionController.SELECTION_NORMAL); - } + selectionController.setDisplaySelection(Ci.nsISelectionController.SELECTION_ATTENTION); + selectionController.repaintSelection(Ci.nsISelectionController.SELECTION_NORMAL); info.enabled = true; @@ -277,20 +340,20 @@ } } - function bi_search(list, n, isReverse){ - var lhs = 0,rhs = list.length,mid=0,ret; - var comp = range_compare_d(content.window); + function bi_search(list, n, backword){ + let lhs = 0,rhs = list.length,mid=0,ret; + let comp = range_compare_d(content.window); while(1){ if(mid===(mid=Math.floor((lhs+rhs)/2))){ if(mid === 0 && ret < 0) return -1; - else if(mid === list.length-1 && ret > 0 && !isReverse) return mid+1; + else if(mid === list.length-1 && ret > 0 && !backword) return mid+1; else return mid; } ret = comp(n, list[mid]); if(ret < 0) rhs = mid; else if(ret > 0) lhs = mid; else{ - return isReverse ? mid - 1 : mid; + return backword ? mid - 1 : mid; } } } @@ -313,7 +376,7 @@ } function grep_next(){ - var info = get_cache(); + let info = get_cache(); if(!info) return; info.index = get_grep_list_index(info); @@ -327,7 +390,7 @@ } function grep_prev(){ - var info = get_cache(); + let info = get_cache(); if(!info) return; info.index = get_grep_list_index(info, true); if(info.index < 0){ @@ -343,31 +406,42 @@ //{{{ highlight function show_highlight(list){ for(let [,r] in Iterator(list)){ - let selection = getSelectionController(r.startContainer.ownerDocument.defaultView) - .getSelection(Ci.nsISelectionController.SELECTION_FIND); - selection.addRange(r); + let selectionController,n; + n = r.startContainer; + let editor = getEditor(n); + selectionController = editor + ? editor.selectionController + : getSelectionControllerFromWindow(n.ownerDocument.defaultView); + + if(selectionController){ + let selection = selectionController.getSelection(Ci.nsISelectionController.SELECTION_FIND); + selection.addRange(r); + } } } function clear_selection_find(win){ win = win||content.window; - var selection = getSelectionController(win) - .getSelection(Ci.nsISelectionController.SELECTION_FIND); - if(selection) selection.removeAllRanges(); + let selectionController = getSelectionControllerFromWindow(win); + if(selectionController){ + let selection = selectionController.getSelection(Ci.nsISelectionController.SELECTION_FIND); + selection.removeAllRanges(); + } } function clear_highlight(){ for(let w in iteratorFrame(content.window)){ clear_selection_find(w); } + clearEditorAllSelections(null, Ci.nsISelectionController.SELECTION_FIND); } //}}} - var T={ + let T={ name : cmd_name , desc :"grep page", action:function(args){ - var info = get_grep_info(args[0]); + let info = get_grep_info(args[0]); if(info){ if(/h/.test(info.option)){ clear_highlight(); @@ -382,7 +456,7 @@ T.option.args = 1; T.option.completer = function(context, args){ try{ - var info = get_grep_info(args[0]); + let info = get_grep_info(args[0]); if(!info || info.list.length == 0) return; context.process = process; @@ -391,7 +465,7 @@ range2string.max = get_word_max(); - var query = info.query; + let query = info.query; context.completions = info.list.map(function(n,i){ return { text: <>{i}{info.option}/{info.word}</>.toString(), @@ -406,9 +480,9 @@ { function hook_function(obj, attr, func){ const org = "__original"; - var original = obj[attr]; + let original = obj[attr]; if(org in original) original = original[org]; - var ret=function(){ + let ret=function(){ if(!(func.apply(this,arguments)===true)){ original.apply(this,arguments); } @@ -419,13 +493,13 @@ map = mappings.get(modes.NORMAL,"/"); hook_function(map, "action", function(){ - var info = get_cache(); + let info = get_cache(); if(info) info.enabled = false; }); map = mappings.get(modes.NORMAL,"n"); hook_function(map, "action", function(){ if(grep_info_attr in content.document){ - var info = get_cache(); + let info = get_cache(); if(info.enabled){ grep_next(); return true; @@ -435,7 +509,7 @@ map = mappings.get(modes.NORMAL,"N"); hook_function(map, "action", function(){ if(grep_info_attr in content.document){ - var info = get_cache(); + let info = get_cache(); if(info.enabled){ grep_prev(); return true;