codemirror-rails 2.21.1 → 2.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/README.md +8 -0
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +160 -86
  4. data/vendor/assets/javascripts/codemirror/modes/clike.js +2 -2
  5. data/vendor/assets/javascripts/codemirror/modes/clojure.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/modes/ecl.js +203 -0
  7. data/vendor/assets/javascripts/codemirror/modes/gfm.js +1 -1
  8. data/vendor/assets/javascripts/codemirror/modes/go.js +20 -22
  9. data/vendor/assets/javascripts/codemirror/modes/less.js +5 -2
  10. data/vendor/assets/javascripts/codemirror/modes/markdown.js +58 -24
  11. data/vendor/assets/javascripts/codemirror/modes/pascal.js +2 -46
  12. data/vendor/assets/javascripts/codemirror/modes/perl.js +1 -1
  13. data/vendor/assets/javascripts/codemirror/modes/php.js +53 -24
  14. data/vendor/assets/javascripts/codemirror/modes/properties.js +57 -0
  15. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.css +5 -0
  16. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.js +1 -1
  17. data/vendor/assets/javascripts/codemirror/modes/ruby.js +1 -1
  18. data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +16 -16
  19. data/vendor/assets/javascripts/codemirror/modes/verilog.js +194 -194
  20. data/vendor/assets/javascripts/codemirror/modes/xml.js +15 -8
  21. data/vendor/assets/javascripts/codemirror/utils/dialog.js +63 -0
  22. data/vendor/assets/javascripts/codemirror/utils/foldcode.js +186 -0
  23. data/vendor/assets/javascripts/codemirror/utils/formatting.js +294 -0
  24. data/vendor/assets/javascripts/codemirror/utils/javascript-hint.js +132 -0
  25. data/vendor/assets/javascripts/codemirror/utils/match-highlighter.js +44 -0
  26. data/vendor/assets/javascripts/codemirror/{overlay.js → utils/overlay.js} +0 -0
  27. data/vendor/assets/javascripts/codemirror/utils/runmode.js +49 -0
  28. data/vendor/assets/javascripts/codemirror/utils/search.js +114 -0
  29. data/vendor/assets/javascripts/codemirror/utils/searchcursor.js +117 -0
  30. data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +66 -0
  31. data/vendor/assets/stylesheets/codemirror.css +3 -0
  32. data/vendor/assets/stylesheets/codemirror/modes/properties.css +3 -0
  33. data/vendor/assets/stylesheets/codemirror/themes/rubyblue.css +1 -1
  34. data/vendor/assets/stylesheets/codemirror/utils/dialog.css +23 -0
  35. data/vendor/assets/stylesheets/codemirror/utils/simple-hint.css +16 -0
  36. metadata +20 -6
  37. data/vendor/assets/javascripts/codemirror/runmode.js +0 -27
@@ -0,0 +1,132 @@
1
+ (function () {
2
+ function forEach(arr, f) {
3
+ for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
4
+ }
5
+
6
+ function arrayContains(arr, item) {
7
+ if (!Array.prototype.indexOf) {
8
+ var i = arr.length;
9
+ while (i--) {
10
+ if (arr[i] === item) {
11
+ return true;
12
+ }
13
+ }
14
+ return false;
15
+ }
16
+ return arr.indexOf(item) != -1;
17
+ }
18
+
19
+ function scriptHint(editor, keywords, getToken) {
20
+ // Find the token at the cursor
21
+ var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
22
+ // If it's not a 'word-style' token, ignore the token.
23
+ if (!/^[\w$_]*$/.test(token.string)) {
24
+ token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
25
+ className: token.string == "." ? "property" : null};
26
+ }
27
+ // If it is a property, find out what it is a property of.
28
+ while (tprop.className == "property") {
29
+ tprop = getToken(editor, {line: cur.line, ch: tprop.start});
30
+ if (tprop.string != ".") return;
31
+ tprop = getToken(editor, {line: cur.line, ch: tprop.start});
32
+ if (tprop.string == ')') {
33
+ var level = 1;
34
+ do {
35
+ tprop = getToken(editor, {line: cur.line, ch: tprop.start});
36
+ switch (tprop.string) {
37
+ case ')': level++; break;
38
+ case '(': level--; break;
39
+ default: break;
40
+ }
41
+ } while (level > 0)
42
+ tprop = getToken(editor, {line: cur.line, ch: tprop.start});
43
+ if (tprop.className == 'variable')
44
+ tprop.className = 'function';
45
+ else return; // no clue
46
+ }
47
+ if (!context) var context = [];
48
+ context.push(tprop);
49
+ }
50
+ return {list: getCompletions(token, context, keywords),
51
+ from: {line: cur.line, ch: token.start},
52
+ to: {line: cur.line, ch: token.end}};
53
+ }
54
+
55
+ CodeMirror.javascriptHint = function(editor) {
56
+ return scriptHint(editor, javascriptKeywords,
57
+ function (e, cur) {return e.getTokenAt(cur);});
58
+ }
59
+
60
+ function getCoffeeScriptToken(editor, cur) {
61
+ // This getToken, it is for coffeescript, imitates the behavior of
62
+ // getTokenAt method in javascript.js, that is, returning "property"
63
+ // type and treat "." as indepenent token.
64
+ var token = editor.getTokenAt(cur);
65
+ if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
66
+ token.end = token.start;
67
+ token.string = '.';
68
+ token.className = "property";
69
+ }
70
+ else if (/^\.[\w$_]*$/.test(token.string)) {
71
+ token.className = "property";
72
+ token.start++;
73
+ token.string = token.string.replace(/\./, '');
74
+ }
75
+ return token;
76
+ }
77
+
78
+ CodeMirror.coffeescriptHint = function(editor) {
79
+ return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken);
80
+ }
81
+
82
+ var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
83
+ "toUpperCase toLowerCase split concat match replace search").split(" ");
84
+ var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
85
+ "lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
86
+ var funcProps = "prototype apply call bind".split(" ");
87
+ var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function " +
88
+ "if in instanceof new null return switch throw true try typeof var void while with").split(" ");
89
+ var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
90
+ "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
91
+
92
+ function getCompletions(token, context, keywords) {
93
+ var found = [], start = token.string;
94
+ function maybeAdd(str) {
95
+ if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
96
+ }
97
+ function gatherCompletions(obj) {
98
+ if (typeof obj == "string") forEach(stringProps, maybeAdd);
99
+ else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
100
+ else if (obj instanceof Function) forEach(funcProps, maybeAdd);
101
+ for (var name in obj) maybeAdd(name);
102
+ }
103
+
104
+ if (context) {
105
+ // If this is a property, see if it belongs to some object we can
106
+ // find in the current environment.
107
+ var obj = context.pop(), base;
108
+ if (obj.className == "variable")
109
+ base = window[obj.string];
110
+ else if (obj.className == "string")
111
+ base = "";
112
+ else if (obj.className == "atom")
113
+ base = 1;
114
+ else if (obj.className == "function") {
115
+ if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
116
+ (typeof jQuery == 'function')) base = jQuery();
117
+ else if (window._ != null && (obj.string == '_') && (typeof _ == 'function')) base = _();
118
+ }
119
+ while (base != null && context.length)
120
+ base = base[context.pop().string];
121
+ if (base != null) gatherCompletions(base);
122
+ }
123
+ else {
124
+ // If not, just look in the window object and any local scope
125
+ // (reading into JS mode internals to get at the local variables)
126
+ for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
127
+ gatherCompletions(window);
128
+ forEach(keywords, maybeAdd);
129
+ }
130
+ return found;
131
+ }
132
+ })();
@@ -0,0 +1,44 @@
1
+ // Define match-highlighter commands. Depends on searchcursor.js
2
+ // Use by attaching the following function call to the onCursorActivity event:
3
+ //myCodeMirror.matchHighlight(minChars);
4
+ // And including a special span.CodeMirror-matchhighlight css class (also optionally a separate one for .CodeMirror-focused -- see demo matchhighlighter.html)
5
+
6
+ (function() {
7
+ var DEFAULT_MIN_CHARS = 2;
8
+
9
+ function MatchHighlightState() {
10
+ this.marked = [];
11
+ }
12
+ function getMatchHighlightState(cm) {
13
+ return cm._matchHighlightState || (cm._matchHighlightState = new MatchHighlightState());
14
+ }
15
+
16
+ function clearMarks(cm) {
17
+ var state = getMatchHighlightState(cm);
18
+ for (var i = 0; i < state.marked.length; ++i)
19
+ state.marked[i].clear();
20
+ state.marked = [];
21
+ }
22
+
23
+ function markDocument(cm, className, minChars) {
24
+ clearMarks(cm);
25
+ minChars = (typeof minChars !== 'undefined' ? minChars : DEFAULT_MIN_CHARS);
26
+ if (cm.somethingSelected() && cm.getSelection().length >= minChars) {
27
+ var state = getMatchHighlightState(cm);
28
+ var query = cm.getSelection();
29
+ cm.operation(function() {
30
+ if (cm.lineCount() < 2000) { // This is too expensive on big documents.
31
+ for (var cursor = cm.getSearchCursor(query); cursor.findNext();) {
32
+ //Only apply matchhighlight to the matches other than the one actually selected
33
+ if (!(cursor.from().line === cm.getCursor(true).line && cursor.from().ch === cm.getCursor(true).ch))
34
+ state.marked.push(cm.markText(cursor.from(), cursor.to(), className));
35
+ }
36
+ }
37
+ });
38
+ }
39
+ }
40
+
41
+ CodeMirror.defineExtension("matchHighlight", function(className, minChars) {
42
+ markDocument(this, className, minChars);
43
+ });
44
+ })();
@@ -0,0 +1,49 @@
1
+ CodeMirror.runMode = function(string, modespec, callback, options) {
2
+ var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
3
+ var isNode = callback.nodeType == 1;
4
+ var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
5
+ if (isNode) {
6
+ var node = callback, accum = [], col = 0;
7
+ callback = function(text, style) {
8
+ if (text == "\n") {
9
+ accum.push("<br>");
10
+ col = 0;
11
+ return;
12
+ }
13
+ var escaped = "";
14
+ // HTML-escape and replace tabs
15
+ for (var pos = 0;;) {
16
+ var idx = text.indexOf("\t", pos);
17
+ if (idx == -1) {
18
+ escaped += CodeMirror.htmlEscape(text.slice(pos));
19
+ col += text.length - pos;
20
+ break;
21
+ } else {
22
+ col += idx - pos;
23
+ escaped += CodeMirror.htmlEscape(text.slice(pos, idx));
24
+ var size = tabSize - col % tabSize;
25
+ col += size;
26
+ for (var i = 0; i < size; ++i) escaped += " ";
27
+ pos = idx + 1;
28
+ }
29
+ }
30
+
31
+ if (style)
32
+ accum.push("<span class=\"cm-" + CodeMirror.htmlEscape(style) + "\">" + escaped + "</span>");
33
+ else
34
+ accum.push(escaped);
35
+ }
36
+ }
37
+ var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
38
+ for (var i = 0, e = lines.length; i < e; ++i) {
39
+ if (i) callback("\n");
40
+ var stream = new CodeMirror.StringStream(lines[i]);
41
+ while (!stream.eol()) {
42
+ var style = mode.token(stream, state);
43
+ callback(stream.current(), style, i, stream.start);
44
+ stream.start = stream.pos;
45
+ }
46
+ }
47
+ if (isNode)
48
+ node.innerHTML = accum.join("");
49
+ };
@@ -0,0 +1,114 @@
1
+ // Define search commands. Depends on dialog.js or another
2
+ // implementation of the openDialog method.
3
+
4
+ // Replace works a little oddly -- it will do the replace on the next
5
+ // Ctrl-G (or whatever is bound to findNext) press. You prevent a
6
+ // replace by making sure the match is no longer selected when hitting
7
+ // Ctrl-G.
8
+
9
+ (function() {
10
+ function SearchState() {
11
+ this.posFrom = this.posTo = this.query = null;
12
+ this.marked = [];
13
+ }
14
+ function getSearchState(cm) {
15
+ return cm._searchState || (cm._searchState = new SearchState());
16
+ }
17
+ function dialog(cm, text, shortText, f) {
18
+ if (cm.openDialog) cm.openDialog(text, f);
19
+ else f(prompt(shortText, ""));
20
+ }
21
+ function confirmDialog(cm, text, shortText, fs) {
22
+ if (cm.openConfirm) cm.openConfirm(text, fs);
23
+ else if (confirm(shortText)) fs[0]();
24
+ }
25
+ function parseQuery(query) {
26
+ var isRE = query.match(/^\/(.*)\/$/);
27
+ return isRE ? new RegExp(isRE[1]) : query;
28
+ }
29
+ var queryDialog =
30
+ 'Search: <input type="text" style="width: 10em"> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
31
+ function doSearch(cm, rev) {
32
+ var state = getSearchState(cm);
33
+ if (state.query) return findNext(cm, rev);
34
+ dialog(cm, queryDialog, "Search for:", function(query) {
35
+ cm.operation(function() {
36
+ if (!query || state.query) return;
37
+ state.query = parseQuery(query);
38
+ if (cm.lineCount() < 2000) { // This is too expensive on big documents.
39
+ for (var cursor = cm.getSearchCursor(query); cursor.findNext();)
40
+ state.marked.push(cm.markText(cursor.from(), cursor.to(), "CodeMirror-searching"));
41
+ }
42
+ state.posFrom = state.posTo = cm.getCursor();
43
+ findNext(cm, rev);
44
+ });
45
+ });
46
+ }
47
+ function findNext(cm, rev) {cm.operation(function() {
48
+ var state = getSearchState(cm);
49
+ var cursor = cm.getSearchCursor(state.query, rev ? state.posFrom : state.posTo);
50
+ if (!cursor.find(rev)) {
51
+ cursor = cm.getSearchCursor(state.query, rev ? {line: cm.lineCount() - 1} : {line: 0, ch: 0});
52
+ if (!cursor.find(rev)) return;
53
+ }
54
+ cm.setSelection(cursor.from(), cursor.to());
55
+ state.posFrom = cursor.from(); state.posTo = cursor.to();
56
+ })}
57
+ function clearSearch(cm) {cm.operation(function() {
58
+ var state = getSearchState(cm);
59
+ if (!state.query) return;
60
+ state.query = null;
61
+ for (var i = 0; i < state.marked.length; ++i) state.marked[i].clear();
62
+ state.marked.length = 0;
63
+ })}
64
+
65
+ var replaceQueryDialog =
66
+ 'Replace: <input type="text" style="width: 10em"> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
67
+ var replacementQueryDialog = 'With: <input type="text" style="width: 10em">';
68
+ var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
69
+ function replace(cm, all) {
70
+ dialog(cm, replaceQueryDialog, "Replace:", function(query) {
71
+ if (!query) return;
72
+ query = parseQuery(query);
73
+ dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
74
+ if (all) {
75
+ cm.operation(function() {
76
+ for (var cursor = cm.getSearchCursor(query); cursor.findNext();) {
77
+ if (typeof query != "string") {
78
+ var match = cm.getRange(cursor.from(), cursor.to()).match(query);
79
+ cursor.replace(text.replace(/\$(\d)/, function(w, i) {return match[i];}));
80
+ } else cursor.replace(text);
81
+ }
82
+ });
83
+ } else {
84
+ clearSearch(cm);
85
+ var cursor = cm.getSearchCursor(query, cm.getCursor());
86
+ function advance() {
87
+ var start = cursor.from(), match;
88
+ if (!(match = cursor.findNext())) {
89
+ cursor = cm.getSearchCursor(query);
90
+ if (!(match = cursor.findNext()) ||
91
+ (cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
92
+ }
93
+ cm.setSelection(cursor.from(), cursor.to());
94
+ confirmDialog(cm, doReplaceConfirm, "Replace?",
95
+ [function() {doReplace(match);}, advance]);
96
+ }
97
+ function doReplace(match) {
98
+ cursor.replace(typeof query == "string" ? text :
99
+ text.replace(/\$(\d)/, function(w, i) {return match[i];}));
100
+ advance();
101
+ }
102
+ advance();
103
+ }
104
+ });
105
+ });
106
+ }
107
+
108
+ CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
109
+ CodeMirror.commands.findNext = doSearch;
110
+ CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
111
+ CodeMirror.commands.clearSearch = clearSearch;
112
+ CodeMirror.commands.replace = replace;
113
+ CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
114
+ })();
@@ -0,0 +1,117 @@
1
+ (function(){
2
+ function SearchCursor(cm, query, pos, caseFold) {
3
+ this.atOccurrence = false; this.cm = cm;
4
+ if (caseFold == null) caseFold = typeof query == "string" && query == query.toLowerCase();
5
+
6
+ pos = pos ? cm.clipPos(pos) : {line: 0, ch: 0};
7
+ this.pos = {from: pos, to: pos};
8
+
9
+ // The matches method is filled in based on the type of query.
10
+ // It takes a position and a direction, and returns an object
11
+ // describing the next occurrence of the query, or null if no
12
+ // more matches were found.
13
+ if (typeof query != "string") // Regexp match
14
+ this.matches = function(reverse, pos) {
15
+ if (reverse) {
16
+ var line = cm.getLine(pos.line).slice(0, pos.ch), match = line.match(query), start = 0;
17
+ while (match) {
18
+ var ind = line.indexOf(match[0]);
19
+ start += ind;
20
+ line = line.slice(ind + 1);
21
+ var newmatch = line.match(query);
22
+ if (newmatch) match = newmatch;
23
+ else break;
24
+ start++;
25
+ }
26
+ }
27
+ else {
28
+ var line = cm.getLine(pos.line).slice(pos.ch), match = line.match(query),
29
+ start = match && pos.ch + line.indexOf(match[0]);
30
+ }
31
+ if (match)
32
+ return {from: {line: pos.line, ch: start},
33
+ to: {line: pos.line, ch: start + match[0].length},
34
+ match: match};
35
+ };
36
+ else { // String query
37
+ if (caseFold) query = query.toLowerCase();
38
+ var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
39
+ var target = query.split("\n");
40
+ // Different methods for single-line and multi-line queries
41
+ if (target.length == 1)
42
+ this.matches = function(reverse, pos) {
43
+ var line = fold(cm.getLine(pos.line)), len = query.length, match;
44
+ if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
45
+ : (match = line.indexOf(query, pos.ch)) != -1)
46
+ return {from: {line: pos.line, ch: match},
47
+ to: {line: pos.line, ch: match + len}};
48
+ };
49
+ else
50
+ this.matches = function(reverse, pos) {
51
+ var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(cm.getLine(ln));
52
+ var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
53
+ if (reverse ? offsetA >= pos.ch || offsetA != match.length
54
+ : offsetA <= pos.ch || offsetA != line.length - match.length)
55
+ return;
56
+ for (;;) {
57
+ if (reverse ? !ln : ln == cm.lineCount() - 1) return;
58
+ line = fold(cm.getLine(ln += reverse ? -1 : 1));
59
+ match = target[reverse ? --idx : ++idx];
60
+ if (idx > 0 && idx < target.length - 1) {
61
+ if (line != match) return;
62
+ else continue;
63
+ }
64
+ var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);
65
+ if (reverse ? offsetB != line.length - match.length : offsetB != match.length)
66
+ return;
67
+ var start = {line: pos.line, ch: offsetA}, end = {line: ln, ch: offsetB};
68
+ return {from: reverse ? end : start, to: reverse ? start : end};
69
+ }
70
+ };
71
+ }
72
+ }
73
+
74
+ SearchCursor.prototype = {
75
+ findNext: function() {return this.find(false);},
76
+ findPrevious: function() {return this.find(true);},
77
+
78
+ find: function(reverse) {
79
+ var self = this, pos = this.cm.clipPos(reverse ? this.pos.from : this.pos.to);
80
+ function savePosAndFail(line) {
81
+ var pos = {line: line, ch: 0};
82
+ self.pos = {from: pos, to: pos};
83
+ self.atOccurrence = false;
84
+ return false;
85
+ }
86
+
87
+ for (;;) {
88
+ if (this.pos = this.matches(reverse, pos)) {
89
+ this.atOccurrence = true;
90
+ return this.pos.match || true;
91
+ }
92
+ if (reverse) {
93
+ if (!pos.line) return savePosAndFail(0);
94
+ pos = {line: pos.line-1, ch: this.cm.getLine(pos.line-1).length};
95
+ }
96
+ else {
97
+ var maxLine = this.cm.lineCount();
98
+ if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
99
+ pos = {line: pos.line+1, ch: 0};
100
+ }
101
+ }
102
+ },
103
+
104
+ from: function() {if (this.atOccurrence) return this.pos.from;},
105
+ to: function() {if (this.atOccurrence) return this.pos.to;},
106
+
107
+ replace: function(newText) {
108
+ var self = this;
109
+ if (this.atOccurrence)
110
+ self.pos.to = this.cm.replaceRange(newText, self.pos.from, self.pos.to);
111
+ }
112
+ };
113
+
114
+ CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
115
+ return new SearchCursor(this, query, pos, caseFold);
116
+ });
117
+ })();