Browse Source

new search box for CodeMirror

Gerald 12 years ago
parent
commit
2c7ce6d5e2
3 changed files with 94 additions and 71 deletions
  1. 1 0
      editor.js
  2. 7 0
      mylib/CodeMirror/search.css
  3. 86 71
      mylib/CodeMirror/search.js

+ 1 - 0
editor.js

@@ -34,6 +34,7 @@ function initCodeMirror(callback,data){
 	addCSS([
 		{href:'lib/CodeMirror/lib/codemirror.css'},
 		{href:'mylib/CodeMirror/fold.css'},
+		{href:'mylib/CodeMirror/search.css'},
 	]);
 	addScript({src:'lib/CodeMirror/lib/codemirror.js'},function(){
 		addScript([

+ 7 - 0
mylib/CodeMirror/search.css

@@ -0,0 +1,7 @@
+.CodeMirror-dialog {
+	position:absolute;
+	top:0;
+	right:0;
+	z-index:15;
+	background:lightgray;
+}

+ 86 - 71
mylib/CodeMirror/search.js

@@ -1,10 +1,5 @@
-// Define search commands. Depends on dialog.js or another
-// implementation of the openDialog method.
-
-// Replace works a little oddly -- it will do the replace on the next
-// Ctrl-G (or whatever is bound to findNext) press. You prevent a
-// replace by making sure the match is no longer selected when hitting
-// Ctrl-G.
+// based on CodeMirror/addon/search/search.js
+// Modified by Gerald <[email protected]>
 
 (function() {
   function searchOverlay(query) {
@@ -33,34 +28,80 @@
     // Heuristic: if the query string is all lowercase, do a case insensitive search.
     return cm.getSearchCursor(query, pos, typeof query == "string" && query == query.toLowerCase());
   }
-  function dialog(cm, text, shortText, f) {
-    if (cm.openDialog) cm.openDialog(text, f);
-    else f(prompt(shortText, ""));
-  }
-  function confirmDialog(cm, text, shortText, fs) {
-    if (cm.openConfirm) cm.openConfirm(text, fs);
-    else if (confirm(shortText)) fs[0]();
+	var dialog=null;
+  function openDialog(cm, state, rep) {
+		function close(){
+			if(closed) return; closed=true;
+			cm.removeOverlay(state.overlay);
+			dialog.parentNode.removeChild(dialog);
+			dialog=null;clearSearch(cm);
+			cm.focus();
+		}
+		if(!dialog) {
+			var wrap = cm.getWrapperElement();
+			dialog = wrap.appendChild(document.createElement("div"));
+			dialog.className='CodeMirror-dialog';
+		}
+		var text='<input class=CodeMirror-search placeholder="Search for"><button class=CodeMirror-findNext>&gt;</button><button class=CodeMirror-findPrev>&lt;</button><button class=CodeMirror-cancel>&times;</button>',closed=false,iS,iR;
+		if(rep) text+='<br><input class=CodeMirror-replace placeholder="Replace with"><button class=CodeMirror-replaceNext>Replace</button><button class=CodeMirror-replaceAll>All</button>';
+		dialog.innerHTML=text;
+		iS=dialog.querySelector('.CodeMirror-search');
+		CodeMirror.on(dialog.querySelector('.CodeMirror-findNext'), "click", function(e) {findNext(cm);});
+		CodeMirror.on(dialog.querySelector('.CodeMirror-findPrev'), "click", function(e) {findNext(cm, true);});
+		CodeMirror.on(dialog.querySelector('.CodeMirror-cancel'), "click", close);
+		CodeMirror.on(dialog, "keydown", function(e) {
+			switch(e.keyCode) {
+				case 27:
+					close();break;
+				default:
+					return;
+			}
+			CodeMirror.e_stop(e);
+		});
+		CodeMirror.on(iS, "keydown", function(e) {
+			switch(e.keyCode) {
+				case 13:
+					findNext(cm, e.shiftKey);break;
+				default:
+					return;
+			}
+			CodeMirror.e_stop(e);
+		});
+		CodeMirror.on(iS, "keyup", function(e) {
+			if(state.query!=iS.value) {
+				state.query=iS.value;
+				cm.operation(function() {
+					cm.removeOverlay(state.overlay);
+					if(!state.query) return;
+					state.overlay = searchOverlay(state.query);
+					cm.addOverlay(state.overlay);
+					state.posTo=state.posFrom;
+					findNext(cm);
+				});
+			}
+		});
+		if(rep) {
+			iR=dialog.querySelector('.CodeMirror-replace');
+			function _replace(all) {
+				state.replace=iR.value;
+				replace(cm, all);
+			}
+			CodeMirror.on(dialog.querySelector('.CodeMirror-replaceNext'), "click", function(e) {_replace();});
+			CodeMirror.on(dialog.querySelector('.CodeMirror-replaceAll'), "click", function(e) {_replace(true);});
+			CodeMirror.on(iR, "keydown", function(e) {
+				switch(e.keyCode) {
+					default:
+						return;
+				}
+				CodeMirror.e_stop(e);
+			});
+		}
+		iS.focus();
   }
-  function parseQuery(query) {
-    var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
-    return isRE ? new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i") : query;
-  }
-  var queryDialog =
-    'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
   function doSearch(cm, rev) {
     var state = getSearchState(cm);
     if (state.query) return findNext(cm, rev);
-    dialog(cm, queryDialog, "Search for:", function(query) {
-      cm.operation(function() {
-        if (!query || state.query) return;
-        state.query = parseQuery(query);
-        cm.removeOverlay(state.overlay);
-        state.overlay = searchOverlay(state.query);
-        cm.addOverlay(state.overlay);
-        state.posFrom = state.posTo = cm.getCursor();
-        findNext(cm, rev);
-      });
-    });
+    openDialog(cm, state);
   }
   function findNext(cm, rev) {cm.operation(function() {
     var state = getSearchState(cm);
@@ -79,47 +120,21 @@
     cm.removeOverlay(state.overlay);
   });}
 
-  var replaceQueryDialog =
-    'Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
-  var replacementQueryDialog = 'With: <input type="text" style="width: 10em"/>';
-  var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
   function replace(cm, all) {
-    dialog(cm, replaceQueryDialog, "Replace:", function(query) {
-      if (!query) return;
-      query = parseQuery(query);
-      dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
-        if (all) {
-          cm.operation(function() {
-            for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
-              if (typeof query != "string") {
-                var match = cm.getRange(cursor.from(), cursor.to()).match(query);
-                cursor.replace(text.replace(/\$(\d)/, function(_, i) {return match[i];}));
-              } else cursor.replace(text);
-            }
-          });
-        } else {
-          clearSearch(cm);
-          var cursor = getSearchCursor(cm, query, cm.getCursor());
-          var advance = function() {
-            var start = cursor.from(), match;
-            if (!(match = cursor.findNext())) {
-              cursor = getSearchCursor(cm, query);
-              if (!(match = cursor.findNext()) ||
-                  (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
-            }
-            cm.setSelection(cursor.from(), cursor.to());
-            confirmDialog(cm, doReplaceConfirm, "Replace?",
-                          [function() {doReplace(match);}, advance]);
-          };
-          var doReplace = function(match) {
-            cursor.replace(typeof query == "string" ? text :
-                           text.replace(/\$(\d)/, function(_, i) {return match[i];}));
-            advance();
-          };
-          advance();
-        }
-      });
-    });
+    var state = getSearchState(cm);
+    if (!state.query) return openDialog(cm, state, true);
+		if(all) cm.operation(function() {
+			for (var cursor = getSearchCursor(cm, state.query); cursor.findNext();) {
+				cursor.replace(state.replace);
+			}
+		}); else {
+			var s=cm.getCursor('start'),e=cm.getCursor('end');
+			state.posTo=state.posFrom;findNext(cm);
+			var s1=cm.getCursor('start'),e1=cm.getCursor('end');
+			if(s.line==s1.line&&s.ch==s1.ch&&e.line==e1.line&&e.ch==e1.ch) {
+				cm.replaceRange(state.replace,s1,e1);findNext(cm);
+			}
+		}
   }
 
   CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};