grep その3

grep 更新しました

主に標準の検索っぽくしました。

  • 標準の検索のように 選択を緑っぽい色に変更
  • use_highlight_option

true で option に h を 追加
実行時に全ての結果 を マゼンダ っぽい 色で選択

  • typo を修正
  • 「nN」の移動を 現状フォーカス位置から開始するように変更
  • highlight を 消す「cleargrep」コマンドを追加


highlightのマゼンダは、目が痛いです。
これ変更する方法あるのでしょうか?

コード

全文
差分

diff -r 66b576f6fade grep.js
--- a/grep.js	Mon Jan 25 22:38:12 2010 +0900
+++ b/grep.js	Sun Jan 31 23:58:34 2010 +0900
@@ -7,14 +7,17 @@
 	const grep_info_attr = "__vmp_grep_cmd";
 	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|| "imx";
+	var default_option = liberator.globalVariables.vimp_grep_default_option|| "imxh";
 
 	//{{{core
 	const vimp = "liberator-completions";
 	var finder = Cc["@mozilla.org/embedcomp/rangefind;1"]
 		.getService(Ci.nsIFind);
-	const option_list = "imxnr";
+	const option_list = "imxnr" + (use_highlight_option ? "h" : "");
+  const gFm = Cc["@mozilla.org/focus-manager;1"]
+              .getService(Ci.nsIFocusManager);
 	//}}}
 	//}}}
 
@@ -129,7 +132,6 @@
 			for([,w] in Iterator(words)){
 				list = list.concat(normal_find(win, w));
 			}
-			//list.sort(function(a,b) a.compareBoundaryPoints(Range.START_TOSTART, b));
 			list.sort(range_compare);
 			ret = ret.concat(list);
 		}
@@ -147,22 +149,38 @@
 	//}}}
 
 	function range_compare(a,b) 
-		a.compareBoundaryPoints(Range.START_TOSTART, b) 
-		|| a.compareBoundaryPoints(Range.END_TOEND, b) 
+		a.compareBoundaryPoints(Range.START_TO_START, b) 
+      || a.compareBoundaryPoints(Range.END_TO_END, b) 
+
+	function range_compare_d(win){ 
+    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;
+
+      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;
+      }
+    };
+  }
 
 	var mode_func = { };
 	mode_func.n = normal_grep;
 	mode_func.r = regexp_grep;
 	mode_func.x = migemo_grep;
 
-
 	//{{{ range cache
 	function get_cache(){
 		return content.document[grep_info_attr];
 	}
 
 	function get_grep_info(arg){
-		let m,word,flags,mode,num;
+		let m,word,flags,mode,num,opt;
 		let re = new RegExp(
 		<>^((\d*)([{option_list}]*)/)?([^/]+)(/([{option_list}]*))?$</>.toString()
 		,"i");
@@ -178,16 +196,18 @@
 				s = m[3];
 			}
 			flags = "";
+      opt = "";
 			if(/i/.test(s)) flags += "i";
 			if(/m/.test(s)) flags += "m";
+			if(/h/.test(s)) opt   += "h";
 			if(m=/.+([xnr])/.exec("n"+default_option+s)){
 				mode = m[1];
 			}
 		}
-		var query = <>{flags}{mode}/{word}</>.toString();
+    let option = <>{flags}{mode}{opt}</>.toString();
 		var info = get_cache();
 		if(info){
-			if(info.query === query){
+			if(info.word === word && info.option === option){
 				info.index = num;
 				info.enabled = false;
 				return info;
@@ -201,14 +221,24 @@
 		}
 
 		var list = func(word, flags + "g");
-		info = {list:list, index:num, query: query, enabled:false};
+		info = {list:list, index:num, word: word, option: option};
 		content.document[grep_info_attr] = info;
 		return info;
 	}
 
+	function getSelectionController(view){
+		return view
+			.QueryInterface(Ci.nsIInterfaceRequestor)
+			.getInterface(Ci.nsIWebNavigation)
+			.QueryInterface(Ci.nsIDocShell)
+			.QueryInterface(Ci.nsIInterfaceRequestor)
+			.getInterface(Ci.nsISelectionDisplay)
+			.QueryInterface(Ci.nsISelectionController);
+	}
+
 	function grep_jump(info){
 		if(info.list.length == 0){
-			liberator.echoerr(<>no match "{info.query}"</>);
+			liberator.echoerr(<>no match "{info.option}/{info.word}"</>);
 			return;
 		}
 		var n = info.list[info.index];
@@ -217,16 +247,29 @@
 			return;
 		}
 		var win = n.startContainer.ownerDocument.defaultView;
-		var selection = win.getSelection();
+
+    if(gFm.focusedWindow){
+      gFm.focusedWindow.getSelection().removeAllRanges();
+    }
+		var selection = getSelectionController(win)
+			.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);
+
+      let ctrl = getSelectionController(win);
+      ctrl.setDisplaySelection(Ci.nsISelectionController.SELECTION_ATTENTION);
+      ctrl.repaintSelection(Ci.nsISelectionController.SELECTION_NORMAL);
+    }
 
 		info.enabled = true;
 
 		selection
 			.QueryInterface(Ci.nsISelection2)
 			.scrollIntoView(Ci.nsISelectionController.SELECTION_ANCHOR_REGION,true,screen_position[0],screen_position[1]);
-				//.scrollIntoView(Ci.nsISelectionController.SELECTION_FOCUS_REGION,true,50,50)
+    win.focus();// nsIFocusManager の focusedWindow を 更新
 				
 		if(use_show_echo){
 			range2string.max = get_word_max();
@@ -234,9 +277,46 @@
 		}
 	}
 
+	function bi_search(list, n, isReverse){
+		var lhs = 0,rhs = list.length,mid=0,ret;
+    var 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 return mid;
+			}
+			ret = comp(n, list[mid]);
+			if(ret < 0) rhs = mid;
+			else if(ret > 0) lhs = mid;
+			else{ 
+        return isReverse ? mid - 1 : mid;
+      }
+		}
+	}
+
+  function get_grep_list_index(info, isReverse){
+    info = info || get_cache();
+
+    let win = gFm.focusedWindow;
+    let selection = win.getSelection();
+    let r;
+    if(selection.rangeCount === 0){
+      r = win.document.createRange();
+      r.setStart(win.document.body, 0);
+    }else{
+      r = selection.getRangeAt(0);
+    }
+    let index = bi_search(info.list, r, isReverse);
+
+    return index;
+  }
+
 	function grep_next(){
 		var info = get_cache();
 		if(!info) return;
+    info.index = get_grep_list_index(info);
+
 		if(++info.index >= info.list.length){
 			info.index = 0;
 			liberator.echoerr("bottom!");
@@ -245,25 +325,56 @@
 
 		return true;
 	}
+
 	function grep_prev(){
 		var info = get_cache();
 		if(!info) return;
-		if(--info.index < 0){
+    info.index = get_grep_list_index(info, true);
+		if(info.index < 0){
 			info.index = info.list.length-1;
 			liberator.echoerr("top!");
 		}
-		grep_jump(info);
+    grep_jump(info);
 
 		return true;
 	}
 	//}}}
 		
+  //{{{ 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);
+    }
+  }
+
+  function clear_selection_find(win){
+    win = win||content.window;
+    var selection = getSelectionController(win)
+      .getSelection(Ci.nsISelectionController.SELECTION_FIND);
+    if(selection) selection.removeAllRanges();
+  }
+
+  function clear_highlight(){
+    for(let w in iteratorFrame(content.window)){
+      clear_selection_find(w);
+    }
+  }
+  //}}}
+
 	var T={
 		name : cmd_name ,
 		desc :"grep page",
 		action:function(args){
 			var info = get_grep_info(args[0]);
-			if(info) grep_jump(info);
+			if(info){
+        if(/h/.test(info.option)){
+          clear_highlight();
+          show_highlight(info.list);
+        }
+        grep_jump(info);
+      }
 		},
 		option:{ }
 	};
@@ -283,7 +394,7 @@
 			var query = info.query;
 			context.completions = info.list.map(function(n,i){
 				return {
-					text: <>{i}{query}</>.toString(), 
+					text: <>{i}{info.option}/{info.word}</>.toString(), 
 					range: n 
 				}
 			});
@@ -332,4 +443,12 @@
 			}
 		});
 	} //}}}
+	if(use_highlight_option)//{{{
+	{
+    function clear_action(){
+      clear_highlight();
+    }
+
+		commands.addUserCommand(["cleargrep","cgrep"],"clear grep highlight", function() clear_action(), null, true);
+	}//}}}
 })();