codemirror-rails 3.20 → 3.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +240 -135
  4. data/vendor/assets/javascripts/codemirror/addons/comment/comment.js +6 -2
  5. data/vendor/assets/javascripts/codemirror/addons/comment/continuecomment.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +1 -0
  7. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +5 -3
  8. data/vendor/assets/javascripts/codemirror/addons/edit/closetag.js +10 -6
  9. data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +2 -0
  10. data/vendor/assets/javascripts/codemirror/addons/edit/matchbrackets.js +1 -1
  11. data/vendor/assets/javascripts/codemirror/addons/fold/comment-fold.js +3 -1
  12. data/vendor/assets/javascripts/codemirror/addons/fold/foldcode.js +13 -2
  13. data/vendor/assets/javascripts/codemirror/addons/fold/foldgutter.js +1 -1
  14. data/vendor/assets/javascripts/codemirror/addons/fold/indent-fold.js +2 -2
  15. data/vendor/assets/javascripts/codemirror/addons/fold/xml-fold.js +6 -0
  16. data/vendor/assets/javascripts/codemirror/addons/hint/anyword-hint.js +3 -5
  17. data/vendor/assets/javascripts/codemirror/addons/hint/css-hint.js +29 -33
  18. data/vendor/assets/javascripts/codemirror/addons/hint/javascript-hint.js +1 -1
  19. data/vendor/assets/javascripts/codemirror/addons/hint/pig-hint.js +1 -1
  20. data/vendor/assets/javascripts/codemirror/addons/hint/python-hint.js +1 -5
  21. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +58 -9
  22. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +58 -17
  23. data/vendor/assets/javascripts/codemirror/addons/hint/xml-hint.js +5 -5
  24. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +1 -1
  25. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +6 -1
  26. data/vendor/assets/javascripts/codemirror/addons/mode/multiplex.js +5 -3
  27. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode-standalone.js +26 -11
  28. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.js +1 -1
  29. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.node.js +22 -11
  30. data/vendor/assets/javascripts/codemirror/addons/search/search.js +22 -9
  31. data/vendor/assets/javascripts/codemirror/addons/search/searchcursor.js +48 -24
  32. data/vendor/assets/javascripts/codemirror/addons/selection/active-line.js +15 -9
  33. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +3 -3
  34. data/vendor/assets/javascripts/codemirror/addons/wrap/hardwrap.js +21 -9
  35. data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +12 -1
  36. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +110 -28
  37. data/vendor/assets/javascripts/codemirror/modes/clike.js +28 -9
  38. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +3 -4
  39. data/vendor/assets/javascripts/codemirror/modes/css.js +341 -297
  40. data/vendor/assets/javascripts/codemirror/modes/erlang.js +302 -179
  41. data/vendor/assets/javascripts/codemirror/modes/gfm.js +10 -5
  42. data/vendor/assets/javascripts/codemirror/modes/gherkin.js +45 -50
  43. data/vendor/assets/javascripts/codemirror/modes/haml.js +0 -4
  44. data/vendor/assets/javascripts/codemirror/modes/haskell.js +5 -3
  45. data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +0 -2
  46. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +0 -2
  47. data/vendor/assets/javascripts/codemirror/modes/javascript.js +43 -30
  48. data/vendor/assets/javascripts/codemirror/modes/jinja2.js +13 -3
  49. data/vendor/assets/javascripts/codemirror/modes/less.js +7 -6
  50. data/vendor/assets/javascripts/codemirror/modes/markdown.js +231 -45
  51. data/vendor/assets/javascripts/codemirror/modes/{ocaml.js → mllike.js} +88 -13
  52. data/vendor/assets/javascripts/codemirror/modes/pegjs.js +5 -9
  53. data/vendor/assets/javascripts/codemirror/modes/php.js +6 -7
  54. data/vendor/assets/javascripts/codemirror/modes/python.js +6 -0
  55. data/vendor/assets/javascripts/codemirror/modes/r.js +5 -1
  56. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.js +1 -1
  57. data/vendor/assets/javascripts/codemirror/modes/ruby.js +3 -1
  58. data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +4 -2
  59. data/vendor/assets/javascripts/codemirror/modes/smartymixed.js +0 -2
  60. data/vendor/assets/javascripts/codemirror/modes/sql.js +5 -4
  61. data/vendor/assets/javascripts/codemirror/modes/xml.js +87 -100
  62. data/vendor/assets/stylesheets/codemirror/themes/mbo.css +1 -1
  63. data/vendor/assets/stylesheets/codemirror/themes/midnight.css +1 -1
  64. data/vendor/assets/stylesheets/codemirror/themes/pastel-on-dark.css +49 -0
  65. data/vendor/assets/stylesheets/codemirror/themes/the-matrix.css +1 -1
  66. metadata +3 -2
@@ -3,6 +3,10 @@
3
3
 
4
4
  var tables;
5
5
  var keywords;
6
+ var CONS = {
7
+ QUERY_DIV: ";",
8
+ ALIAS_KEYWORD: "AS"
9
+ };
6
10
 
7
11
  function getKeywords(editor) {
8
12
  var mode = editor.doc.modeOption;
@@ -34,11 +38,10 @@
34
38
  var string = token.string.substr(1);
35
39
  var prevCur = CodeMirror.Pos(cur.line, token.start);
36
40
  var table = editor.getTokenAt(prevCur).string;
37
- var columns = tables[table];
38
- if(!columns) {
41
+ if( !tables.hasOwnProperty( table ) ){
39
42
  table = findTableByAlias(table, editor);
40
43
  }
41
- columns = tables[table];
44
+ var columns = tables[table];
42
45
  if(!columns) {
43
46
  return;
44
47
  }
@@ -46,32 +49,72 @@
46
49
  function(w) {return "." + w;});
47
50
  }
48
51
 
49
- function eachWord(line, f) {
50
- var words = line.text.split(" ");
51
- for(var i = 0; i < words.length; i++) {
52
- f(words[i]);
52
+ function eachWord(lineText, f) {
53
+ if( !lineText ){return;}
54
+ var excepted = /[,;]/g;
55
+ var words = lineText.split( " " );
56
+ for( var i = 0; i < words.length; i++ ){
57
+ f( words[i]?words[i].replace( excepted, '' ) : '' );
53
58
  }
54
59
  }
55
60
 
56
- // Tries to find possible table name from alias.
61
+ function convertCurToNumber( cur ){
62
+ // max characters of a line is 999,999.
63
+ return cur.line + cur.ch / Math.pow( 10, 6 );
64
+ }
65
+
66
+ function convertNumberToCur( num ){
67
+ return CodeMirror.Pos(Math.floor( num ), +num.toString().split( '.' ).pop());
68
+ }
69
+
57
70
  function findTableByAlias(alias, editor) {
71
+ var doc = editor.doc;
72
+ var fullQuery = doc.getValue();
58
73
  var aliasUpperCase = alias.toUpperCase();
59
74
  var previousWord = "";
60
75
  var table = "";
76
+ var separator = [];
77
+ var validRange = {
78
+ start: CodeMirror.Pos( 0, 0 ),
79
+ end: CodeMirror.Pos( editor.lastLine(), editor.getLineHandle( editor.lastLine() ).length )
80
+ };
61
81
 
62
- editor.eachLine(function(line) {
63
- eachWord(line, function(word) {
82
+ //add separator
83
+ var indexOfSeparator = fullQuery.indexOf( CONS.QUERY_DIV );
84
+ while( indexOfSeparator != -1 ){
85
+ separator.push( doc.posFromIndex(indexOfSeparator));
86
+ indexOfSeparator = fullQuery.indexOf( CONS.QUERY_DIV, indexOfSeparator+1);
87
+ }
88
+ separator.unshift( CodeMirror.Pos( 0, 0 ) );
89
+ separator.push( CodeMirror.Pos( editor.lastLine(), editor.getLineHandle( editor.lastLine() ).text.length ) );
90
+
91
+ //find valieRange
92
+ var prevItem = 0;
93
+ var current = convertCurToNumber( editor.getCursor() );
94
+ for( var i=0; i< separator.length; i++){
95
+ var _v = convertCurToNumber( separator[i] );
96
+ if( current > prevItem && current <= _v ){
97
+ validRange = { start: convertNumberToCur( prevItem ), end: convertNumberToCur( _v ) };
98
+ break;
99
+ }
100
+ prevItem = _v;
101
+ }
102
+
103
+ var query = doc.getRange(validRange.start, validRange.end, false);
104
+
105
+ for(var i=0; i < query.length; i++){
106
+ var lineText = query[i];
107
+ eachWord( lineText, function( word ){
64
108
  var wordUpperCase = word.toUpperCase();
65
- if(wordUpperCase === aliasUpperCase) {
66
- if(tables.hasOwnProperty(previousWord)) {
109
+ if( wordUpperCase === aliasUpperCase && tables.hasOwnProperty( previousWord ) ){
67
110
  table = previousWord;
68
- }
69
111
  }
70
- if(wordUpperCase !== "AS") {
112
+ if( wordUpperCase !== CONS.ALIAS_KEYWORD ){
71
113
  previousWord = word;
72
114
  }
73
115
  });
74
- });
116
+ if( table ){ break; }
117
+ }
75
118
  return table;
76
119
  }
77
120
 
@@ -80,9 +123,7 @@
80
123
  keywords = keywords || getKeywords(editor);
81
124
  var cur = editor.getCursor();
82
125
  var token = editor.getTokenAt(cur);
83
-
84
126
  var result = [];
85
-
86
127
  var search = token.string.trim();
87
128
 
88
129
  addMatches(result, search, keywords,
@@ -20,13 +20,13 @@
20
20
  var cx = inner.state.context, curTag = cx && tags[cx.tagName];
21
21
  var childList = cx ? curTag && curTag.children : tags["!top"];
22
22
  if (childList) {
23
- for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].indexOf(prefix) == 0)
23
+ for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].lastIndexOf(prefix, 0) == 0)
24
24
  result.push("<" + childList[i]);
25
25
  } else {
26
- for (var name in tags) if (tags.hasOwnProperty(name) && name != "!top" && (!prefix || name.indexOf(prefix) == 0))
26
+ for (var name in tags) if (tags.hasOwnProperty(name) && name != "!top" && (!prefix || name.lastIndexOf(prefix, 0) == 0))
27
27
  result.push("<" + name);
28
28
  }
29
- if (cx && (!prefix || ("/" + cx.tagName).indexOf(prefix) == 0))
29
+ if (cx && (!prefix || ("/" + cx.tagName).lastIndexOf(prefix, 0) == 0))
30
30
  result.push("</" + cx.tagName + ">");
31
31
  } else {
32
32
  // Attribute completion
@@ -46,14 +46,14 @@
46
46
  }
47
47
  replaceToken = true;
48
48
  }
49
- for (var i = 0; i < atValues.length; ++i) if (!prefix || atValues[i].indexOf(prefix) == 0)
49
+ for (var i = 0; i < atValues.length; ++i) if (!prefix || atValues[i].lastIndexOf(prefix, 0) == 0)
50
50
  result.push(quote + atValues[i] + quote);
51
51
  } else { // An attribute name
52
52
  if (token.type == "attribute") {
53
53
  prefix = token.string;
54
54
  replaceToken = true;
55
55
  }
56
- for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || attr.indexOf(prefix) == 0))
56
+ for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || attr.lastIndexOf(prefix, 0) == 0))
57
57
  result.push(attr);
58
58
  }
59
59
  }
@@ -112,7 +112,7 @@
112
112
  if (options.async)
113
113
  options.getAnnotations(cm, updateLinting, options);
114
114
  else
115
- updateLinting(cm, options.getAnnotations(cm.getValue(), options));
115
+ updateLinting(cm, options.getAnnotations(cm.getValue(), options.options));
116
116
  }
117
117
 
118
118
  function updateLinting(cm, annotationsNotSorted) {
@@ -29,7 +29,7 @@
29
29
  this.edit = this.mv.edit;
30
30
  this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: true}, copyObj(options)));
31
31
 
32
- this.diff = getDiff(orig, options.value);
32
+ this.diff = getDiff(asString(orig), asString(options.value));
33
33
  this.diffOutOfDate = false;
34
34
 
35
35
  this.showDifferences = options.showDifferences !== false;
@@ -352,6 +352,11 @@
352
352
  }
353
353
  };
354
354
 
355
+ function asString(obj) {
356
+ if (typeof obj == "string") return obj;
357
+ else return obj.getValue();
358
+ }
359
+
355
360
  // Operations on diffs
356
361
 
357
362
  var dmp = new diff_match_patch();
@@ -47,7 +47,11 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
47
47
  return outerToken;
48
48
  } else {
49
49
  var curInner = state.innerActive, oldContent = stream.string;
50
- var found = indexOf(oldContent, curInner.close, stream.pos);
50
+ if (!curInner.close && stream.sol()) {
51
+ state.innerActive = state.inner = null;
52
+ return this.token(stream, state);
53
+ }
54
+ var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos) : -1;
51
55
  if (found == stream.pos) {
52
56
  stream.match(curInner.close);
53
57
  state.innerActive = state.inner = null;
@@ -56,8 +60,6 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
56
60
  if (found > -1) stream.string = oldContent.slice(0, found);
57
61
  var innerToken = curInner.mode.token(stream, state.inner);
58
62
  if (found > -1) stream.string = oldContent;
59
- var cur = stream.current(), found = cur.indexOf(curInner.close);
60
- if (found > -1) stream.backUp(cur.length - found);
61
63
 
62
64
  if (curInner.innerStyle) {
63
65
  if (innerToken) innerToken = innerToken + ' ' + curInner.innerStyle;
@@ -10,6 +10,7 @@ function splitLines(string){ return string.split(/\r?\n|\r/); };
10
10
  function StringStream(string) {
11
11
  this.pos = this.start = 0;
12
12
  this.string = string;
13
+ this.lineStart = 0;
13
14
  }
14
15
  StringStream.prototype = {
15
16
  eol: function() {return this.pos >= this.string.length;},
@@ -41,7 +42,7 @@ StringStream.prototype = {
41
42
  if (found > -1) {this.pos = found; return true;}
42
43
  },
43
44
  backUp: function(n) {this.pos -= n;},
44
- column: function() {return this.start;},
45
+ column: function() {return this.start - this.lineStart;},
45
46
  indentation: function() {return 0;},
46
47
  match: function(pattern, consume, caseInsensitive) {
47
48
  if (typeof pattern == "string") {
@@ -58,7 +59,12 @@ StringStream.prototype = {
58
59
  return match;
59
60
  }
60
61
  },
61
- current: function(){return this.string.slice(this.start, this.pos);}
62
+ current: function(){return this.string.slice(this.start, this.pos);},
63
+ hideFirstChars: function(n, inner) {
64
+ this.lineStart += n;
65
+ try { return inner(); }
66
+ finally { this.lineStart -= n; }
67
+ }
62
68
  };
63
69
  CodeMirror.StringStream = StringStream;
64
70
 
@@ -69,17 +75,26 @@ CodeMirror.startState = function (mode, a1, a2) {
69
75
  var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
70
76
  CodeMirror.defineMode = function (name, mode) { modes[name] = mode; };
71
77
  CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; };
72
- CodeMirror.getMode = function (options, spec) {
73
- if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
78
+ CodeMirror.resolveMode = function(spec) {
79
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
74
80
  spec = mimeModes[spec];
75
- if (typeof spec == "string")
76
- var mname = spec, config = {};
77
- else if (spec != null)
78
- var mname = spec.name, config = spec;
79
- var mfactory = modes[mname];
81
+ } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
82
+ spec = mimeModes[spec.name];
83
+ }
84
+ if (typeof spec == "string") return {name: spec};
85
+ else return spec || {name: "null"};
86
+ };
87
+ CodeMirror.getMode = function (options, spec) {
88
+ spec = CodeMirror.resolveMode(spec);
89
+ var mfactory = modes[spec.name];
80
90
  if (!mfactory) throw new Error("Unknown mode: " + spec);
81
- return mfactory(options, config || {});
91
+ return mfactory(options, spec);
82
92
  };
93
+ CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min;
94
+ CodeMirror.defineMode("null", function() {
95
+ return {token: function(stream) {stream.skipToEnd();}};
96
+ });
97
+ CodeMirror.defineMIME("text/plain", "null");
83
98
 
84
99
  CodeMirror.runMode = function (string, modespec, callback, options) {
85
100
  var mode = CodeMirror.getMode({ indentUnit: 2 }, modespec);
@@ -122,7 +137,7 @@ CodeMirror.runMode = function (string, modespec, callback, options) {
122
137
  };
123
138
  }
124
139
 
125
- var lines = splitLines(string), state = CodeMirror.startState(mode);
140
+ var lines = splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
126
141
  for (var i = 0, e = lines.length; i < e; ++i) {
127
142
  if (i) callback("\n");
128
143
  var stream = new CodeMirror.StringStream(lines[i]);
@@ -43,7 +43,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) {
43
43
  };
44
44
  }
45
45
 
46
- var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
46
+ var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
47
47
  for (var i = 0, e = lines.length; i < e; ++i) {
48
48
  if (i) callback("\n");
49
49
  var stream = new CodeMirror.StringStream(lines[i]);
@@ -5,6 +5,7 @@ function splitLines(string){ return string.split(/\r?\n|\r/); };
5
5
  function StringStream(string) {
6
6
  this.pos = this.start = 0;
7
7
  this.string = string;
8
+ this.lineStart = 0;
8
9
  }
9
10
  StringStream.prototype = {
10
11
  eol: function() {return this.pos >= this.string.length;},
@@ -36,7 +37,7 @@ StringStream.prototype = {
36
37
  if (found > -1) {this.pos = found; return true;}
37
38
  },
38
39
  backUp: function(n) {this.pos -= n;},
39
- column: function() {return this.start;},
40
+ column: function() {return this.start - this.lineStart;},
40
41
  indentation: function() {return 0;},
41
42
  match: function(pattern, consume, caseInsensitive) {
42
43
  if (typeof pattern == "string") {
@@ -53,7 +54,12 @@ StringStream.prototype = {
53
54
  return match;
54
55
  }
55
56
  },
56
- current: function(){return this.string.slice(this.start, this.pos);}
57
+ current: function(){return this.string.slice(this.start, this.pos);},
58
+ hideFirstChars: function(n, inner) {
59
+ this.lineStart += n;
60
+ try { return inner(); }
61
+ finally { this.lineStart -= n; }
62
+ }
57
63
  };
58
64
  exports.StringStream = StringStream;
59
65
 
@@ -76,21 +82,26 @@ exports.defineMode("null", function() {
76
82
  });
77
83
  exports.defineMIME("text/plain", "null");
78
84
 
79
- exports.getMode = function(options, spec) {
80
- if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
85
+ exports.resolveMode = function(spec) {
86
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
81
87
  spec = mimeModes[spec];
82
- if (typeof spec == "string")
83
- var mname = spec, config = {};
84
- else if (spec != null)
85
- var mname = spec.name, config = spec;
86
- var mfactory = modes[mname];
88
+ } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
89
+ spec = mimeModes[spec.name];
90
+ }
91
+ if (typeof spec == "string") return {name: spec};
92
+ else return spec || {name: "null"};
93
+ };
94
+ exports.getMode = function(options, spec) {
95
+ spec = exports.resolveMode(mimeModes[spec]);
96
+ var mfactory = modes[spec.name];
87
97
  if (!mfactory) throw new Error("Unknown mode: " + spec);
88
- return mfactory(options, config || {});
98
+ return mfactory(options, spec);
89
99
  };
100
+ exports.registerHelper = exports.registerGlobalHelper = Math.min;
90
101
 
91
102
  exports.runMode = function(string, modespec, callback) {
92
103
  var mode = exports.getMode({indentUnit: 2}, modespec);
93
- var lines = splitLines(string), state = exports.startState(mode);
104
+ var lines = splitLines(string), state = (options && options.state) || exports.startState(mode);
94
105
  for (var i = 0, e = lines.length; i < e; ++i) {
95
106
  if (i) callback("\n");
96
107
  var stream = new exports.StringStream(lines[i]);
@@ -7,7 +7,15 @@
7
7
  // Ctrl-G.
8
8
 
9
9
  (function() {
10
- function searchOverlay(query) {
10
+ function searchOverlay(query, caseInsensitive) {
11
+ var startChar;
12
+ if (typeof query == "string") {
13
+ startChar = query.charAt(0);
14
+ query = new RegExp("^" + query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"),
15
+ caseInsensitive ? "i" : "");
16
+ } else {
17
+ query = new RegExp("^(?:" + query.source + ")", query.ignoreCase ? "i" : "");
18
+ }
11
19
  if (typeof query == "string") return {token: function(stream) {
12
20
  if (stream.match(query)) return "searching";
13
21
  stream.next();
@@ -17,6 +25,8 @@
17
25
  if (stream.match(query)) return "searching";
18
26
  while (!stream.eol()) {
19
27
  stream.next();
28
+ if (startChar)
29
+ stream.skipTo(startChar) || stream.skipToEnd();
20
30
  if (stream.match(query, false)) break;
21
31
  }
22
32
  }};
@@ -29,13 +39,16 @@
29
39
  function getSearchState(cm) {
30
40
  return cm.state.search || (cm.state.search = new SearchState());
31
41
  }
42
+ function queryCaseInsensitive(query) {
43
+ return typeof query == "string" && query == query.toLowerCase();
44
+ }
32
45
  function getSearchCursor(cm, query, pos) {
33
46
  // Heuristic: if the query string is all lowercase, do a case insensitive search.
34
- return cm.getSearchCursor(query, pos, typeof query == "string" && query == query.toLowerCase());
47
+ return cm.getSearchCursor(query, pos, queryCaseInsensitive(query));
35
48
  }
36
- function dialog(cm, text, shortText, f) {
37
- if (cm.openDialog) cm.openDialog(text, f);
38
- else f(prompt(shortText, ""));
49
+ function dialog(cm, text, shortText, deflt, f) {
50
+ if (cm.openDialog) cm.openDialog(text, f, {value: deflt});
51
+ else f(prompt(shortText, deflt));
39
52
  }
40
53
  function confirmDialog(cm, text, shortText, fs) {
41
54
  if (cm.openConfirm) cm.openConfirm(text, fs);
@@ -50,11 +63,11 @@
50
63
  function doSearch(cm, rev) {
51
64
  var state = getSearchState(cm);
52
65
  if (state.query) return findNext(cm, rev);
53
- dialog(cm, queryDialog, "Search for:", function(query) {
66
+ dialog(cm, queryDialog, "Search for:", cm.getSelection(), function(query) {
54
67
  cm.operation(function() {
55
68
  if (!query || state.query) return;
56
69
  state.query = parseQuery(query);
57
- cm.removeOverlay(state.overlay);
70
+ cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
58
71
  state.overlay = searchOverlay(state.query);
59
72
  cm.addOverlay(state.overlay);
60
73
  state.posFrom = state.posTo = cm.getCursor();
@@ -85,10 +98,10 @@
85
98
  var replacementQueryDialog = 'With: <input type="text" style="width: 10em"/>';
86
99
  var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
87
100
  function replace(cm, all) {
88
- dialog(cm, replaceQueryDialog, "Replace:", function(query) {
101
+ dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) {
89
102
  if (!query) return;
90
103
  query = parseQuery(query);
91
- dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
104
+ dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
92
105
  if (all) {
93
106
  cm.operation(function() {
94
107
  for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
@@ -47,6 +47,7 @@
47
47
  match: match};
48
48
  };
49
49
  } else { // String query
50
+ var origQuery = query;
50
51
  if (caseFold) query = query.toLowerCase();
51
52
  var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
52
53
  var target = query.split("\n");
@@ -58,33 +59,45 @@
58
59
  this.matches = function() {};
59
60
  } else {
60
61
  this.matches = function(reverse, pos) {
61
- var line = fold(doc.getLine(pos.line)), len = query.length, match;
62
- if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
63
- : (match = line.indexOf(query, pos.ch)) != -1)
64
- return {from: Pos(pos.line, match),
65
- to: Pos(pos.line, match + len)};
62
+ if (reverse) {
63
+ var orig = doc.getLine(pos.line).slice(0, pos.ch), line = fold(orig);
64
+ var match = line.lastIndexOf(query);
65
+ if (match > -1) {
66
+ match = adjustPos(orig, line, match);
67
+ return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)};
68
+ }
69
+ } else {
70
+ var orig = doc.getLine(pos.line).slice(pos.ch), line = fold(orig);
71
+ var match = line.indexOf(query);
72
+ if (match > -1) {
73
+ match = adjustPos(orig, line, match) + pos.ch;
74
+ return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)};
75
+ }
76
+ }
66
77
  };
67
78
  }
68
79
  } else {
80
+ var origTarget = origQuery.split("\n");
69
81
  this.matches = function(reverse, pos) {
70
- var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(doc.getLine(ln));
71
- var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
72
- if (reverse ? offsetA > pos.ch || offsetA != match.length
73
- : offsetA < pos.ch || offsetA != line.length - match.length)
74
- return;
75
- for (;;) {
76
- if (reverse ? !ln : ln == doc.lineCount() - 1) return;
77
- line = fold(doc.getLine(ln += reverse ? -1 : 1));
78
- match = target[reverse ? --idx : ++idx];
79
- if (idx > 0 && idx < target.length - 1) {
80
- if (line != match) return;
81
- else continue;
82
- }
83
- var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);
84
- if (reverse ? offsetB != line.length - match.length : offsetB != match.length)
85
- return;
86
- var start = Pos(pos.line, offsetA), end = Pos(ln, offsetB);
87
- return {from: reverse ? end : start, to: reverse ? start : end};
82
+ var last = target.length - 1;
83
+ if (reverse) {
84
+ if (pos.line - (target.length - 1) < doc.firstLine()) return;
85
+ if (fold(doc.getLine(pos.line).slice(0, origTarget[last].length)) != target[target.length - 1]) return;
86
+ var to = Pos(pos.line, origTarget[last].length);
87
+ for (var ln = pos.line - 1, i = last - 1; i >= 1; --i, --ln)
88
+ if (target[i] != fold(doc.getLine(ln))) return;
89
+ var line = doc.getLine(ln), cut = line.length - origTarget[0].length;
90
+ if (fold(line.slice(cut)) != target[0]) return;
91
+ return {from: Pos(ln, cut), to: to};
92
+ } else {
93
+ if (pos.line + (target.length - 1) > doc.lastLine()) return;
94
+ var line = doc.getLine(pos.line), cut = line.length - origTarget[0].length;
95
+ if (fold(line.slice(cut)) != target[0]) return;
96
+ var from = Pos(pos.line, cut);
97
+ for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln)
98
+ if (target[i] != fold(doc.getLine(ln))) return;
99
+ if (doc.getLine(ln).slice(0, origTarget[last].length) != target[last]) return;
100
+ return {from: from, to: Pos(ln, origTarget[last].length)};
88
101
  }
89
102
  };
90
103
  }
@@ -106,7 +119,6 @@
106
119
 
107
120
  for (;;) {
108
121
  if (this.pos = this.matches(reverse, pos)) {
109
- if (!this.pos.from || !this.pos.to) { console.log(this.matches, this.pos); }
110
122
  this.atOccurrence = true;
111
123
  return this.pos.match || true;
112
124
  }
@@ -134,6 +146,18 @@
134
146
  }
135
147
  };
136
148
 
149
+ // Maps a position in a case-folded line back to a position in the original line
150
+ // (compensating for codepoints increasing in number during folding)
151
+ function adjustPos(orig, folded, pos) {
152
+ if (orig.length == folded.length) return pos;
153
+ for (var pos1 = Math.min(pos, orig.length);;) {
154
+ var len1 = orig.slice(0, pos1).toLowerCase().length;
155
+ if (len1 < pos) ++pos1;
156
+ else if (len1 > pos) --pos1;
157
+ else return pos1;
158
+ }
159
+ }
160
+
137
161
  CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
138
162
  return new SearchCursor(this.doc, query, pos, caseFold);
139
163
  });