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;