diff --git a/AUTHORS b/AUTHORS index 9af00e54e4..a7e3335b45 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,14 +3,17 @@ List of CodeMirror contributors. Updated before every release. 4r2r Aaron Brooks Abe Fettig +Adam Ahmed Adam King adanlobato Adán Lobato +Adrian Aichner aeroson Ahmad Amireh Ahmad M. Zawawi ahoward Akeksandr Motsjonov +Alberto González Palomo Alberto Pose Albert Xing Alexander Pavlov @@ -46,6 +49,8 @@ Benjamin DeCoste Ben Keen Bernhard Sirlinger Billy Moon +binny +B Krishna Chaitanya Blaine G boomyjee borawjm @@ -79,6 +84,7 @@ David Mignot David Pathakjee deebugger Deep Thought +dignifiedquire domagoj412 Dominator008 Domizio Demichelis @@ -106,6 +112,7 @@ ForbesLindesay Forbes Lindesay Ford_Lawnmower Frank Wiegand +Gabriel Horner Gabriel Nahmias galambalazs Gautam Mehta @@ -192,6 +199,7 @@ Luciano Longo lynschinzer Maksim Lin Maksym Taran +Malay Majithia Manuel Rego Casasnovas Marat Dreizin Marco Aurélio @@ -238,6 +246,7 @@ ndr nerbert nextrevision nguillaumin +Ng Zhi An Nicholas Bollweg Niels van Groningen Nikita Beloglazov @@ -246,6 +255,7 @@ Nikolay Kostov nlwillia pablo Page +Patil Arpith Patrick Strawderman Paul Garvin Paul Ivanov @@ -283,6 +293,7 @@ Shmuel Englard soliton4 sonson spastorelli +srajanpaliwal Stanislav Oaserele Stas Kobzar Stefan Borsje @@ -307,6 +318,7 @@ Tom MacWright Tony Jian Travis Heppe Triangle717 +twifkak Vestimir Markov vf Volker Mische diff --git a/addon/comment/comment.js b/addon/comment/comment.js index 5975b0bf69..1eb9a05c5d 100644 --- a/addon/comment/comment.js +++ b/addon/comment/comment.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; var noOptions = {}; @@ -11,8 +18,21 @@ } CodeMirror.commands.toggleComment = function(cm) { - var from = cm.getCursor("start"), to = cm.getCursor("end"); - cm.uncomment(from, to) || cm.lineComment(from, to); + var minLine = Infinity, ranges = cm.listSelections(), mode = null; + for (var i = ranges.length - 1; i >= 0; i--) { + var from = ranges[i].from(), to = ranges[i].to(); + if (from.line >= minLine) continue; + if (to.line >= minLine) to = Pos(minLine, 0); + minLine = from.line; + if (mode == null) { + if (cm.uncomment(from, to)) mode = "un"; + else { cm.lineComment(from, to); mode = "line"; } + } else if (mode == "un") { + cm.uncomment(from, to); + } else { + cm.lineComment(from, to); + } + } }; CodeMirror.defineExtension("lineComment", function(from, to, options) { @@ -146,4 +166,4 @@ }); return true; }); -})(); +}); diff --git a/addon/comment/continuecomment.js b/addon/comment/continuecomment.js index c59cee1aa2..42277267f5 100644 --- a/addon/comment/continuecomment.js +++ b/addon/comment/continuecomment.js @@ -1,46 +1,61 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { var modes = ["clike", "css", "javascript"]; for (var i = 0; i < modes.length; ++i) CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "}); function continueComment(cm) { - var pos = cm.getCursor(), token = cm.getTokenAt(pos); - if (token.type != "comment" || cm.getOption("disableInput")) return CodeMirror.Pass; - var mode = CodeMirror.innerMode(cm.getMode(), token.state).mode; + if (cm.getOption("disableInput")) return CodeMirror.Pass; + var ranges = cm.listSelections(), mode, inserts = []; + for (var i = 0; i < ranges.length; i++) { + var pos = ranges[i].head, token = cm.getTokenAt(pos); + if (token.type != "comment") return CodeMirror.Pass; + var modeHere = CodeMirror.innerMode(cm.getMode(), token.state).mode; + if (!mode) mode = modeHere; + else if (mode != modeHere) return CodeMirror.Pass; - var insert; - if (mode.blockCommentStart && mode.blockCommentContinue) { - var end = token.string.indexOf(mode.blockCommentEnd); - var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found; - if (end != -1 && end == token.string.length - mode.blockCommentEnd.length && pos.ch >= end) { - // Comment ended, don't continue it - } else if (token.string.indexOf(mode.blockCommentStart) == 0) { - insert = full.slice(0, token.start); - if (!/^\s*$/.test(insert)) { - insert = ""; - for (var i = 0; i < token.start; ++i) insert += " "; + var insert = null; + if (mode.blockCommentStart && mode.blockCommentContinue) { + var end = token.string.indexOf(mode.blockCommentEnd); + var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found; + if (end != -1 && end == token.string.length - mode.blockCommentEnd.length && pos.ch >= end) { + // Comment ended, don't continue it + } else if (token.string.indexOf(mode.blockCommentStart) == 0) { + insert = full.slice(0, token.start); + if (!/^\s*$/.test(insert)) { + insert = ""; + for (var j = 0; j < token.start; ++j) insert += " "; + } + } else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 && + found + mode.blockCommentContinue.length > token.start && + /^\s*$/.test(full.slice(0, found))) { + insert = full.slice(0, found); } - } else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 && - found + mode.blockCommentContinue.length > token.start && - /^\s*$/.test(full.slice(0, found))) { - insert = full.slice(0, found); + if (insert != null) insert += mode.blockCommentContinue; } - if (insert != null) insert += mode.blockCommentContinue; - } - if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) { - var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment); - if (found > -1) { - insert = line.slice(0, found); - if (/\S/.test(insert)) insert = null; - else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\s*/)[0]; + if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) { + var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment); + if (found > -1) { + insert = line.slice(0, found); + if (/\S/.test(insert)) insert = null; + else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\s*/)[0]; + } } + if (insert == null) return CodeMirror.Pass; + inserts[i] = "\n" + insert; } - if (insert != null) - cm.replaceSelection("\n" + insert, "end"); - else - return CodeMirror.Pass; + cm.operation(function() { + for (var i = ranges.length - 1; i >= 0; i--) + cm.replaceRange(inserts[i], ranges[i].from(), ranges[i].to(), "+insert"); + }); } function continueLineCommentEnabled(cm) { @@ -64,4 +79,4 @@ cm.addKeyMap(map); } }); -})(); +}); diff --git a/addon/dialog/dialog.js b/addon/dialog/dialog.js index d21643490c..586b7370dc 100644 --- a/addon/dialog/dialog.js +++ b/addon/dialog/dialog.js @@ -1,6 +1,13 @@ // Open simple dialogs on top of an editor. Relies on dialog.css. -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { function dialogDiv(cm, template, bottom) { var wrap = cm.getWrapperElement(); var dialog; @@ -120,4 +127,4 @@ if (duration) doneTimer = setTimeout(close, options.duration); }); -})(); +}); diff --git a/addon/display/fullscreen.js b/addon/display/fullscreen.js index a442f6a433..e39c6e162f 100644 --- a/addon/display/fullscreen.js +++ b/addon/display/fullscreen.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; CodeMirror.defineOption("fullScreen", false, function(cm, val, old) { @@ -28,4 +35,4 @@ window.scrollTo(info.scrollLeft, info.scrollTop); cm.refresh(); } -})(); +}); diff --git a/addon/display/placeholder.js b/addon/display/placeholder.js index 748afe7275..0fdc9b0d5b 100644 --- a/addon/display/placeholder.js +++ b/addon/display/placeholder.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { CodeMirror.defineOption("placeholder", "", function(cm, val, old) { var prev = old && old != CodeMirror.Init; if (val && !prev) { @@ -45,4 +52,4 @@ function isEmpty(cm) { return (cm.lineCount() === 1) && (cm.getLine(0) === ""); } -})(); +}); diff --git a/addon/display/rulers.js b/addon/display/rulers.js index 958c8eaf8d..eb0ff06e3a 100644 --- a/addon/display/rulers.js +++ b/addon/display/rulers.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; CodeMirror.defineOption("rulers", false, function(cm, val, old) { @@ -44,4 +51,4 @@ clearRulers(cm); setRulers(cm); } -})(); +}); diff --git a/addon/edit/closebrackets.js b/addon/edit/closebrackets.js index 0575222be6..f48ad881aa 100644 --- a/addon/edit/closebrackets.js +++ b/addon/edit/closebrackets.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { var DEFAULT_BRACKETS = "()[]{}''\"\""; var DEFAULT_EXPLODE_ON_ENTER = "[]{}"; var SPACE_CHAR_REGEX = /\s/; @@ -28,57 +35,89 @@ var map = { name : "autoCloseBrackets", Backspace: function(cm) { - if (cm.somethingSelected() || cm.getOption("disableInput")) return CodeMirror.Pass; - var cur = cm.getCursor(), around = charsAround(cm, cur); - if (around && pairs.indexOf(around) % 2 == 0) + if (cm.getOption("disableInput")) return CodeMirror.Pass; + var ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) return CodeMirror.Pass; + var around = charsAround(cm, ranges[i].head); + if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; + } + for (var i = ranges.length - 1; i >= 0; i--) { + var cur = ranges[i].head; cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.Pos(cur.line, cur.ch + 1)); - else - return CodeMirror.Pass; + } } }; var closingBrackets = ""; for (var i = 0; i < pairs.length; i += 2) (function(left, right) { if (left != right) closingBrackets += right; - function surround(cm) { - var selection = cm.getSelection(); - cm.replaceSelection(left + selection + right); - } - function maybeOverwrite(cm) { - var cur = cm.getCursor(), ahead = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1)); - if (ahead != right || cm.somethingSelected()) return CodeMirror.Pass; - else cm.execCommand("goCharRight"); - } map["'" + left + "'"] = function(cm) { - if (left == "'" && cm.getTokenAt(cm.getCursor()).type == "comment" || - cm.getOption("disableInput")) - return CodeMirror.Pass; - if (cm.somethingSelected()) return surround(cm); - if (left == right && maybeOverwrite(cm) != CodeMirror.Pass) return; - var cur = cm.getCursor(), ahead = CodeMirror.Pos(cur.line, cur.ch + 1); - var line = cm.getLine(cur.line), nextChar = line.charAt(cur.ch), curChar = cur.ch > 0 ? line.charAt(cur.ch - 1) : ""; - if (left == right && CodeMirror.isWordChar(curChar)) - return CodeMirror.Pass; - if (line.length == cur.ch || closingBrackets.indexOf(nextChar) >= 0 || SPACE_CHAR_REGEX.test(nextChar)) - cm.replaceSelection(left + right, {head: ahead, anchor: ahead}); - else - return CodeMirror.Pass; + if (cm.getOption("disableInput")) return CodeMirror.Pass; + var ranges = cm.listSelections(), type, next; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i], cur = range.head, curType; + if (left == "'" && cm.getTokenTypeAt(cur) == "comment") + return CodeMirror.Pass; + var next = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1)); + if (!range.empty()) + curType = "surround"; + else if (left == right && next == right) + curType = "skip"; + else if (left == right && CodeMirror.isWordChar(next)) + return CodeMirror.Pass; + else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) + curType = "both"; + else + return CodeMirror.Pass; + if (!type) type = curType; + else if (type != curType) return CodeMirror.Pass; + } + + if (type == "skip") { + cm.execCommand("goCharRight"); + } else if (type == "surround") { + var sels = cm.getSelections(); + for (var i = 0; i < sels.length; i++) + sels[i] = left + sels[i] + right; + cm.replaceSelections(sels, "around"); + } else if (type == "both") { + cm.replaceSelection(left + right, null); + cm.execCommand("goCharLeft"); + } + }; + if (left != right) map["'" + right + "'"] = function(cm) { + var ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + if (!range.empty() || + cm.getRange(range.head, CodeMirror.Pos(range.head.line, range.head.ch + 1)) != right) + return CodeMirror.Pass; + } + cm.execCommand("goCharRight"); }; - if (left != right) map["'" + right + "'"] = maybeOverwrite; })(pairs.charAt(i), pairs.charAt(i + 1)); return map; } function buildExplodeHandler(pairs) { return function(cm) { - var cur = cm.getCursor(), around = charsAround(cm, cur); - if (!around || pairs.indexOf(around) % 2 != 0 || cm.getOption("disableInput")) - return CodeMirror.Pass; + if (cm.getOption("disableInput")) return CodeMirror.Pass; + var ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) return CodeMirror.Pass; + var around = charsAround(cm, ranges[i].head); + if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; + } cm.operation(function() { - var newPos = CodeMirror.Pos(cur.line + 1, 0); - cm.replaceSelection("\n\n", {anchor: newPos, head: newPos}, "+input"); - cm.indentLine(cur.line + 1, null, true); - cm.indentLine(cur.line + 2, null, true); + cm.replaceSelection("\n\n", null); + cm.execCommand("goCharLeft"); + ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + var line = ranges[i].head.line; + cm.indentLine(line, null, true); + cm.indentLine(line + 1, null, true); + } }); }; } -})(); +}); diff --git a/addon/edit/closetag.js b/addon/edit/closetag.js index 762a94ccbb..c7c0701ba5 100644 --- a/addon/edit/closetag.js +++ b/addon/edit/closetag.js @@ -22,7 +22,14 @@ * See demos/closetag.html for a usage example. */ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../fold/xml-fold")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../fold/xml-fold"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) { if (old != CodeMirror.Init && old) cm.removeKeyMap("autoCloseTags"); @@ -41,48 +48,63 @@ "h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"]; function autoCloseGT(cm) { - var pos = cm.getCursor(), tok = cm.getTokenAt(pos); - var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; - if (inner.mode.name != "xml" || !state.tagName || cm.getOption("disableInput")) return CodeMirror.Pass; + if (cm.getOption("disableInput")) return CodeMirror.Pass; + var ranges = cm.listSelections(), replacements = []; + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) return CodeMirror.Pass; + var pos = ranges[i].head, tok = cm.getTokenAt(pos); + var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; + if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass; + var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html"; + var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose); + var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent); - var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html"; - var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose); - var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent); + var tagName = state.tagName; + if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch); + var lowerTagName = tagName.toLowerCase(); + // Don't process the '>' at the end of an end-tag or self-closing tag + if (!tagName || + tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) || + tok.type == "tag" && state.type == "closeTag" || + tok.string.indexOf("/") == (tok.string.length - 1) || // match something like + dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 || + CodeMirror.scanForClosingTag && CodeMirror.scanForClosingTag(cm, pos, tagName, + Math.min(cm.lastLine() + 1, pos.line + 50))) + return CodeMirror.Pass; - var tagName = state.tagName; - if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch); - var lowerTagName = tagName.toLowerCase(); - // Don't process the '>' at the end of an end-tag or self-closing tag - if (!tagName || - tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) || - tok.type == "tag" && state.type == "closeTag" || - tok.string.indexOf("/") == (tok.string.length - 1) || // match something like - dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 || - CodeMirror.scanForClosingTag && CodeMirror.scanForClosingTag(cm, pos, tagName, - Math.min(cm.lastLine() + 1, pos.line + 50))) - return CodeMirror.Pass; + var indent = indentTags && indexOf(indentTags, lowerTagName) > -1; + replacements[i] = {indent: indent, + text: ">" + (indent ? "\n\n" : "") + "", + newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)}; + } - var doIndent = indentTags && indexOf(indentTags, lowerTagName) > -1; - var curPos = doIndent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1); - cm.replaceSelection(">" + (doIndent ? "\n\n" : "") + "", - {head: curPos, anchor: curPos}); - if (doIndent) { - cm.indentLine(pos.line + 1, null, true); - cm.indentLine(pos.line + 2, null); + for (var i = ranges.length - 1; i >= 0; i--) { + var info = replacements[i]; + cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert"); + var sel = cm.listSelections().slice(0); + sel[i] = {head: info.newPos, anchor: info.newPos}; + cm.setSelections(sel); + if (info.indent) { + cm.indentLine(info.newPos.line, null, true); + cm.indentLine(info.newPos.line + 1, null, true); + } } } function autoCloseSlash(cm) { - var pos = cm.getCursor(), tok = cm.getTokenAt(pos); - var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; - if (tok.type == "string" || tok.string.charAt(0) != "<" || - tok.start != pos.ch - 1 || inner.mode.name != "xml" || - cm.getOption("disableInput")) - return CodeMirror.Pass; - - var tagName = state.context && state.context.tagName; - if (tagName) cm.replaceSelection("/" + tagName + ">", "end"); - else return CodeMirror.Pass; + if (cm.getOption("disableInput")) return CodeMirror.Pass; + var ranges = cm.listSelections(), replacements = []; + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) return CodeMirror.Pass; + var pos = ranges[i].head, tok = cm.getTokenAt(pos); + var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; + if (tok.type == "string" || tok.string.charAt(0) != "<" || + tok.start != pos.ch - 1 || inner.mode.name != "xml" || + !state.context || !state.context.tagName) + return CodeMirror.Pass; + replacements[i] = "/" + state.context.tagName + ">"; + } + cm.replaceSelections(replacements); } function indexOf(collection, elt) { @@ -91,4 +113,4 @@ if (collection[i] == elt) return i; return -1; } -})(); +}); diff --git a/addon/edit/continuelist.js b/addon/edit/continuelist.js index 190b41dcbe..2946aa6a24 100644 --- a/addon/edit/continuelist.js +++ b/addon/edit/continuelist.js @@ -1,27 +1,35 @@ -(function() { - 'use strict'; +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; var listRE = /^(\s*)([*+-]|(\d+)\.)(\s*)/, - unorderedBullets = '*+-'; + unorderedBullets = "*+-"; CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) { if (cm.getOption("disableInput")) return CodeMirror.Pass; + var ranges = cm.listSelections(), replacements = []; + for (var i = 0; i < ranges.length; i++) { + var pos = ranges[i].head, match; + var inList = cm.getStateAfter(pos.line).list !== false; - var pos = cm.getCursor(), - inList = cm.getStateAfter(pos.line).list !== false, - match; + if (!ranges[i].empty() || !inList || !(match = cm.getLine(pos.line).match(listRE))) { + cm.execCommand("newlineAndIndent"); + return; + } + var indent = match[1], after = match[4]; + var bullet = unorderedBullets.indexOf(match[2]) >= 0 + ? match[2] + : (parseInt(match[3], 10) + 1) + "."; - if (!inList || !(match = cm.getLine(pos.line).match(listRE))) { - cm.execCommand('newlineAndIndent'); - return; + replacements[i] = "\n" + indent + bullet + after; } - var indent = match[1], after = match[4]; - var bullet = unorderedBullets.indexOf(match[2]) >= 0 - ? match[2] - : (parseInt(match[3], 10) + 1) + '.'; - - cm.replaceSelection('\n' + indent + bullet + after, 'end'); + cm.replaceSelections(replacements); }; - -}()); +}); diff --git a/addon/edit/matchbrackets.js b/addon/edit/matchbrackets.js index 465b6ccaa9..576ec143aa 100644 --- a/addon/edit/matchbrackets.js +++ b/addon/edit/matchbrackets.js @@ -1,73 +1,91 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { var ie_lt8 = /MSIE \d/.test(navigator.userAgent) && (document.documentMode == null || document.documentMode < 8); var Pos = CodeMirror.Pos; var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; - function findMatchingBracket(cm, where, strict) { - var state = cm.state.matchBrackets; - var maxScanLen = (state && state.maxScanLineLength) || 10000; - var maxScanLines = (state && state.maxScanLines) || 100; - var cur = where || cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1; + function findMatchingBracket(cm, where, strict, config) { + var line = cm.getLineHandle(where.line), pos = where.ch - 1; var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; if (!match) return null; - var forward = match.charAt(1) == ">", d = forward ? 1 : -1; - if (strict && forward != (pos == cur.ch)) return null; - var style = cm.getTokenTypeAt(Pos(cur.line, pos + 1)); + var dir = match.charAt(1) == ">" ? 1 : -1; + if (strict && (dir > 0) != (pos == where.ch)) return null; + var style = cm.getTokenTypeAt(Pos(where.line, pos + 1)); - var stack = [line.text.charAt(pos)], re = /[(){}[\]]/; - function scan(line, lineNo, start) { - if (!line.text) return; - var pos = forward ? 0 : line.text.length - 1, end = forward ? line.text.length : -1; - if (line.text.length > maxScanLen) return null; - if (start != null) pos = start + d; - for (; pos != end; pos += d) { - var ch = line.text.charAt(pos); - if (re.test(ch) && cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style) { + var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config); + return {from: Pos(where.line, pos), to: found && found.pos, + match: found && found.ch == match.charAt(0), forward: dir > 0}; + } + + function scanForBracket(cm, where, dir, style, config) { + var maxScanLen = (config && config.maxScanLineLength) || 10000; + var maxScanLines = (config && config.maxScanLines) || 500; + + var stack = [], re = /[(){}[\]]/; + var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) + : Math.max(cm.firstLine() - 1, where.line - maxScanLines); + for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { + var line = cm.getLine(lineNo); + if (!line) continue; + var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1; + if (line.length > maxScanLen) continue; + if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0); + for (; pos != end; pos += dir) { + var ch = line.charAt(pos); + if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) { var match = matching[ch]; - if (match.charAt(1) == ">" == forward) stack.push(ch); - else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false}; - else if (!stack.length) return {pos: pos, match: true}; + if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch); + else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch}; + else stack.pop(); } } } - for (var i = cur.line, found, e = forward ? Math.min(i + maxScanLines, cm.lineCount()) : Math.max(-1, i - maxScanLines); i != e; i+=d) { - if (i == cur.line) found = scan(line, i, pos); - else found = scan(cm.getLineHandle(i), i); - if (found) break; - } - return {from: Pos(cur.line, pos), to: found && Pos(i, found.pos), - match: found && found.match, forward: forward}; } - function matchBrackets(cm, autoclear) { + function matchBrackets(cm, autoclear, config) { // Disable brace matching in long lines, since it'll cause hugely slow updates var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000; - var found = findMatchingBracket(cm); - if (!found || cm.getLine(found.from.line).length > maxHighlightLen || - found.to && cm.getLine(found.to.line).length > maxHighlightLen) - return; + var marks = [], ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) { + var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config); + if (match && cm.getLine(match.from.line).length <= maxHighlightLen && + match.to && cm.getLine(match.to.line).length <= maxHighlightLen) { + var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; + marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style})); + if (match.to) + marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style})); + } + } + + if (marks.length) { + // Kludge to work around the IE bug from issue #1193, where text + // input stops going to the textare whever this fires. + if (ie_lt8 && cm.state.focused) cm.display.input.focus(); - var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; - var one = cm.markText(found.from, Pos(found.from.line, found.from.ch + 1), {className: style}); - var two = found.to && cm.markText(found.to, Pos(found.to.line, found.to.ch + 1), {className: style}); - // Kludge to work around the IE bug from issue #1193, where text - // input stops going to the textarea whenever this fires. - if (ie_lt8 && cm.state.focused) cm.display.input.focus(); - var clear = function() { - cm.operation(function() { one.clear(); two && two.clear(); }); - }; - if (autoclear) setTimeout(clear, 800); - else return clear; + var clear = function() { + cm.operation(function() { + for (var i = 0; i < marks.length; i++) marks[i].clear(); + }); + }; + if (autoclear) setTimeout(clear, 800); + else return clear; + } } var currentlyHighlighted = null; function doMatchBrackets(cm) { cm.operation(function() { if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} - if (!cm.somethingSelected()) currentlyHighlighted = matchBrackets(cm, false); + currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets); }); } @@ -84,4 +102,7 @@ CodeMirror.defineExtension("findMatchingBracket", function(pos, strict){ return findMatchingBracket(this, pos, strict); }); -})(); + CodeMirror.defineExtension("scanForBracket", function(pos, dir, style){ + return scanForBracket(this, pos, dir, style); + }); +}); diff --git a/addon/edit/matchtags.js b/addon/edit/matchtags.js index f189c1f8ef..76a7b87c9a 100644 --- a/addon/edit/matchtags.js +++ b/addon/edit/matchtags.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../fold/xml-fold")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../fold/xml-fold"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; CodeMirror.defineOption("matchTags", false, function(cm, val, old) { @@ -50,7 +57,7 @@ var found = CodeMirror.findMatchingTag(cm, cm.getCursor()); if (found) { var other = found.at == "close" ? found.open : found.close; - if (other) cm.setSelection(other.to, other.from); + if (other) cm.extendSelection(other.to, other.from); } }; -})(); +}); diff --git a/addon/edit/trailingspace.js b/addon/edit/trailingspace.js index f6bb02645d..ec07221e30 100644 --- a/addon/edit/trailingspace.js +++ b/addon/edit/trailingspace.js @@ -1,15 +1,24 @@ -CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) { - if (prev == CodeMirror.Init) prev = false; - if (prev && !val) - cm.removeOverlay("trailingspace"); - else if (!prev && val) - cm.addOverlay({ - token: function(stream) { - for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {} - if (i > stream.pos) { stream.pos = i; return null; } - stream.pos = l; - return "trailingspace"; - }, - name: "trailingspace" - }); +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) { + if (prev == CodeMirror.Init) prev = false; + if (prev && !val) + cm.removeOverlay("trailingspace"); + else if (!prev && val) + cm.addOverlay({ + token: function(stream) { + for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {} + if (i > stream.pos) { stream.pos = i; return null; } + stream.pos = l; + return "trailingspace"; + }, + name: "trailingspace" + }); + }); }); diff --git a/addon/fold/brace-fold.js b/addon/fold/brace-fold.js index 2560b2b94c..f0ee62029a 100644 --- a/addon/fold/brace-fold.js +++ b/addon/fold/brace-fold.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.registerHelper("fold", "brace", function(cm, start) { var line = start.line, lineText = cm.getLine(line); var startCh, tokenType; @@ -45,7 +55,6 @@ CodeMirror.registerHelper("fold", "brace", function(cm, start) { return {from: CodeMirror.Pos(line, startCh), to: CodeMirror.Pos(end, endCh)}; }); -CodeMirror.braceRangeFinder = CodeMirror.fold.brace; // deprecated CodeMirror.registerHelper("fold", "import", function(cm, start) { function hasImport(line) { @@ -70,7 +79,6 @@ CodeMirror.registerHelper("fold", "import", function(cm, start) { } return {from: cm.clipPos(CodeMirror.Pos(start, has.startCh + 1)), to: end}; }); -CodeMirror.importRangeFinder = CodeMirror.fold["import"]; // deprecated CodeMirror.registerHelper("fold", "include", function(cm, start) { function hasInclude(line) { @@ -90,4 +98,5 @@ CodeMirror.registerHelper("fold", "include", function(cm, start) { return {from: CodeMirror.Pos(start, has + 1), to: cm.clipPos(CodeMirror.Pos(end))}; }); -CodeMirror.includeRangeFinder = CodeMirror.fold.include; // deprecated + +}); diff --git a/addon/fold/comment-fold.js b/addon/fold/comment-fold.js index 26e72f09f5..d72c5479a7 100644 --- a/addon/fold/comment-fold.js +++ b/addon/fold/comment-fold.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.registerGlobalHelper("fold", "comment", function(mode) { return mode.blockCommentStart && mode.blockCommentEnd; }, function(cm, start) { @@ -40,3 +50,5 @@ CodeMirror.registerGlobalHelper("fold", "comment", function(mode) { return {from: CodeMirror.Pos(line, startCh), to: CodeMirror.Pos(end, endCh)}; }); + +}); diff --git a/addon/fold/foldcode.js b/addon/fold/foldcode.js index 3c0817b8fe..d7a0bb5e2d 100644 --- a/addon/fold/foldcode.js +++ b/addon/fold/foldcode.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; function doFold(cm, pos, options, force) { @@ -68,9 +75,27 @@ if (marks[i].__isFold) return true; }); - CodeMirror.commands.fold = function(cm) { + CodeMirror.commands.toggleFold = function(cm) { cm.foldCode(cm.getCursor()); }; + CodeMirror.commands.fold = function(cm) { + cm.foldCode(cm.getCursor(), null, "fold"); + }; + CodeMirror.commands.unfold = function(cm) { + cm.foldCode(cm.getCursor(), null, "unfold"); + }; + CodeMirror.commands.foldAll = function(cm) { + cm.operation(function() { + for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++) + cm.foldCode(CodeMirror.Pos(i, 0), null, "fold"); + }); + }; + CodeMirror.commands.unfoldAll = function(cm) { + cm.operation(function() { + for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++) + cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold"); + }); + }; CodeMirror.registerHelper("fold", "combine", function() { var funcs = Array.prototype.slice.call(arguments, 0); @@ -89,4 +114,4 @@ if (cur) return cur; } }); -})(); +}); diff --git a/addon/fold/foldgutter.js b/addon/fold/foldgutter.js index a4f3bb3186..9caba59aad 100644 --- a/addon/fold/foldgutter.js +++ b/addon/fold/foldgutter.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("./foldcode")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "./foldcode"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; CodeMirror.defineOption("foldGutter", false, function(cm, val, old) { @@ -121,4 +128,4 @@ if (line >= state.from && line < state.to) updateFoldInfo(cm, line, line + 1); } -})(); +}); diff --git a/addon/fold/indent-fold.js b/addon/fold/indent-fold.js index 434c2bc5ca..d0130836a2 100644 --- a/addon/fold/indent-fold.js +++ b/addon/fold/indent-fold.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.registerHelper("fold", "indent", function(cm, start) { var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line); if (!/\S/.test(firstLine)) return; @@ -27,4 +37,5 @@ CodeMirror.registerHelper("fold", "indent", function(cm, start) { to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length) }; }); -CodeMirror.indentRangeFinder = CodeMirror.fold.indent; // deprecated + +}); diff --git a/addon/fold/markdown-fold.js b/addon/fold/markdown-fold.js index aeb3c04565..3bbf5b6077 100644 --- a/addon/fold/markdown-fold.js +++ b/addon/fold/markdown-fold.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.registerHelper("fold", "markdown", function(cm, start) { var maxDepth = 100; @@ -32,3 +42,5 @@ CodeMirror.registerHelper("fold", "markdown", function(cm, start) { to: CodeMirror.Pos(end, cm.getLine(end).length) }; }); + +}); diff --git a/addon/fold/xml-fold.js b/addon/fold/xml-fold.js index db5aed7041..d554e2fc42 100644 --- a/addon/fold/xml-fold.js +++ b/addon/fold/xml-fold.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; var Pos = CodeMirror.Pos; @@ -136,8 +143,6 @@ } } }); - CodeMirror.tagRangeFinder = CodeMirror.fold.xml; // deprecated - CodeMirror.findMatchingTag = function(cm, pos, range) { var iter = new Iter(cm, pos.line, pos.ch, range); if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return; @@ -170,4 +175,4 @@ var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null); return !!findMatchingClose(iter, name); }; -})(); +}); diff --git a/addon/hint/anyword-hint.js b/addon/hint/anyword-hint.js index c3358cd9b5..3ef979b524 100644 --- a/addon/hint/anyword-hint.js +++ b/addon/hint/anyword-hint.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; var WORD = /[\w$]+/, RANGE = 500; @@ -29,4 +36,4 @@ } return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)}; }); -})(); +}); diff --git a/addon/hint/css-hint.js b/addon/hint/css-hint.js index 6789c458ba..9e5b1e132d 100644 --- a/addon/hint/css-hint.js +++ b/addon/hint/css-hint.js @@ -1,4 +1,11 @@ -(function () { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../../mode/css/css")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../../mode/css/css"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1, @@ -43,4 +50,4 @@ to: CodeMirror.Pos(cur.line, end) }; }); -})(); +}); diff --git a/addon/hint/html-hint.js b/addon/hint/html-hint.js index cf256851ef..cbe7c61ad4 100755 --- a/addon/hint/html-hint.js +++ b/addon/hint/html-hint.js @@ -1,4 +1,13 @@ -(function () { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; + var langs = "ab aa af ak sq am ar an hy as av ae ay az bm ba eu be bn bh bi bs br bg my ca ch ce ny zh cv kw co cr hr cs da dv nl dz en eo et ee fo fj fi fr ff gl ka de el gn gu ht ha he hz hi ho hu ia id ie ga ig ik io is it iu ja jv kl kn kr ks kk km ki rw ky kv kg ko ku kj la lb lg li ln lo lt lu lv gv mk mg ms ml mt mi mr mh mn na nv nb nd ne ng nn no ii nr oc oj cu om or os pa pi fa pl ps pt qu rm rn ro ru sa sc sd se sm sg sr gd sn si sk sl so st es su sw ss sv ta te tg th ti bo tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa cy wo fy xh yi yo za zu".split(" "); var targets = ["_blank", "_self", "_top", "_parent"]; var charsets = ["ascii", "utf-8", "utf-16", "latin1", "latin1"]; @@ -332,6 +341,5 @@ if (options) for (var opt in options) local[opt] = options[opt]; return CodeMirror.hint.xml(cm, local); } - CodeMirror.htmlHint = htmlHint; // deprecated CodeMirror.registerHelper("hint", "html", htmlHint); -})(); +}); diff --git a/addon/hint/javascript-hint.js b/addon/hint/javascript-hint.js index c347c206ec..305bb85a29 100644 --- a/addon/hint/javascript-hint.js +++ b/addon/hint/javascript-hint.js @@ -1,4 +1,11 @@ -(function () { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { var Pos = CodeMirror.Pos; function forEach(arr, f) { @@ -47,7 +54,6 @@ function (e, cur) {return e.getTokenAt(cur);}, options); }; - CodeMirror.javascriptHint = javascriptHint; // deprecated CodeMirror.registerHelper("hint", "javascript", javascriptHint); function getCoffeeScriptToken(editor, cur) { @@ -71,7 +77,6 @@ function coffeescriptHint(editor, options) { return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options); } - CodeMirror.coffeescriptHint = coffeescriptHint; // deprecated CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint); var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " + @@ -128,4 +133,4 @@ } return found; } -})(); +}); diff --git a/addon/hint/python-hint.js b/addon/hint/python-hint.js index 248284e8c5..eebfcc76dc 100644 --- a/addon/hint/python-hint.js +++ b/addon/hint/python-hint.js @@ -1,4 +1,13 @@ -(function () { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; + function forEach(arr, f) { for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]); } @@ -40,7 +49,6 @@ function pythonHint(editor) { return scriptHint(editor, pythonKeywordsU, function (e, cur) {return e.getTokenAt(cur);}); } - CodeMirror.pythonHint = pythonHint; // deprecated CodeMirror.registerHelper("hint", "python", pythonHint); var pythonKeywords = "and del from not while as elif global or with assert else if pass yield" @@ -88,4 +96,4 @@ } return found; } -})(); +}); diff --git a/addon/hint/show-hint.js b/addon/hint/show-hint.js index 9b143fdd04..6f04c56584 100644 --- a/addon/hint/show-hint.js +++ b/addon/hint/show-hint.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; var HINT_ELEMENT_CLASS = "CodeMirror-hint"; @@ -6,7 +13,7 @@ CodeMirror.showHint = function(cm, getHints, options) { // We want a single cursor position. - if (cm.somethingSelected()) return; + if (cm.listSelections().length > 1 || cm.somethingSelected()) return; if (getHints == null) { if (options && options.async) return; else getHints = CodeMirror.hint.auto; @@ -339,4 +346,4 @@ }); CodeMirror.commands.autocomplete = CodeMirror.showHint; -})(); +}); diff --git a/addon/hint/sql-hint.js b/addon/hint/sql-hint.js index baa3f83369..a48d2b3cea 100644 --- a/addon/hint/sql-hint.js +++ b/addon/hint/sql-hint.js @@ -1,4 +1,11 @@ -(function () { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("../../mode/sql/sql")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "../../mode/sql/sql"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; var tables; @@ -151,4 +158,4 @@ }; } CodeMirror.registerHelper("hint", "sql", sqlHint); -})(); +}); diff --git a/addon/hint/xml-hint.js b/addon/hint/xml-hint.js index 69f2b771fe..857564909a 100644 --- a/addon/hint/xml-hint.js +++ b/addon/hint/xml-hint.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; var Pos = CodeMirror.Pos; @@ -64,6 +71,5 @@ }; } - CodeMirror.xmlHint = getHints; // deprecated CodeMirror.registerHelper("hint", "xml", getHints); -})(); +}); diff --git a/addon/lint/coffeescript-lint.js b/addon/lint/coffeescript-lint.js index 7f55a294dd..6df17f8f84 100644 --- a/addon/lint/coffeescript-lint.js +++ b/addon/lint/coffeescript-lint.js @@ -2,6 +2,16 @@ // declare global: coffeelint +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.registerHelper("lint", "coffeescript", function(text) { var found = []; var parseError = function(err) { @@ -24,4 +34,5 @@ CodeMirror.registerHelper("lint", "coffeescript", function(text) { } return found; }); -CodeMirror.coffeeValidator = CodeMirror.lint.coffeescript; // deprecated + +}); diff --git a/addon/lint/css-lint.js b/addon/lint/css-lint.js index 1de71fbcbd..2a799ddc4f 100644 --- a/addon/lint/css-lint.js +++ b/addon/lint/css-lint.js @@ -2,6 +2,16 @@ // declare global: CSSLint +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.registerHelper("lint", "css", function(text) { var found = []; var results = CSSLint.verify(text), messages = results.messages, message = null; @@ -17,3 +27,5 @@ CodeMirror.registerHelper("lint", "css", function(text) { } return found; }); + +}); diff --git a/addon/lint/javascript-lint.js b/addon/lint/javascript-lint.js index 7123ab7e64..bbb51083b8 100644 --- a/addon/lint/javascript-lint.js +++ b/addon/lint/javascript-lint.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; // declare global: JSHINT @@ -19,7 +26,6 @@ } CodeMirror.registerHelper("lint", "javascript", validator); - CodeMirror.javascriptValidator = CodeMirror.lint.javascript; // deprecated function cleanup(error) { // All problems are warnings by default @@ -123,4 +129,4 @@ } } } -})(); +}); diff --git a/addon/lint/json-lint.js b/addon/lint/json-lint.js index e10e11bcaf..1f5f82d0ca 100644 --- a/addon/lint/json-lint.js +++ b/addon/lint/json-lint.js @@ -2,6 +2,16 @@ // declare global: jsonlint +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.registerHelper("lint", "json", function(text) { var found = []; jsonlint.parseError = function(str, hash) { @@ -14,4 +24,5 @@ CodeMirror.registerHelper("lint", "json", function(text) { catch(e) {} return found; }); -CodeMirror.jsonValidator = CodeMirror.lint.json; // deprecated + +}); diff --git a/addon/lint/lint.js b/addon/lint/lint.js index 6121735d3f..393a689036 100644 --- a/addon/lint/lint.js +++ b/addon/lint/lint.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; var GUTTER_ID = "CodeMirror-lint-markers"; var SEVERITIES = /^(?:error|warning)$/; @@ -170,7 +177,7 @@ if (!/\bCodeMirror-lint-mark-/.test((e.target || e.srcElement).className)) return; for (var i = 0; i < nearby.length; i += 2) { var spans = cm.findMarksAt(cm.coordsChar({left: e.clientX + nearby[i], - top: e.clientY + nearby[i + 1]})); + top: e.clientY + nearby[i + 1]}, "client")); for (var j = 0; j < spans.length; ++j) { var span = spans[j], ann = span.__annotation; if (ann) return popupSpanTooltip(ann, e); @@ -178,7 +185,7 @@ } } - function optionHandler(cm, val, old) { + CodeMirror.defineOption("lint", false, function(cm, val, old) { if (old && old != CodeMirror.Init) { clearMarks(cm); cm.off("change", onChange); @@ -196,8 +203,5 @@ startLinting(cm); } - } - - CodeMirror.defineOption("lintWith", false, optionHandler); // deprecated - CodeMirror.defineOption("lint", false, optionHandler); // deprecated -})(); + }); +}); diff --git a/addon/lint/yaml-lint.js b/addon/lint/yaml-lint.js index b7d6a3de11..b53673af4b 100644 --- a/addon/lint/yaml-lint.js +++ b/addon/lint/yaml-lint.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + // Depends on js-yaml.js from https://github.com/nodeca/js-yaml // declare global: jsyaml @@ -11,4 +21,5 @@ CodeMirror.registerHelper("lint", "yaml", function(text) { } return found; }); -CodeMirror.yamlValidator = CodeMirror.lint.yaml; // deprecated + +}); diff --git a/addon/merge/merge.js b/addon/merge/merge.js index f2d100754f..fc1cb2f5a1 100644 --- a/addon/merge/merge.js +++ b/addon/merge/merge.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; // declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL @@ -495,4 +502,4 @@ function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; } function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; } function posEq(a, b) { return a.line == b.line && a.ch == b.ch; } -})(); +}); diff --git a/addon/mode/loadmode.js b/addon/mode/loadmode.js index 60fafbb178..e08c281321 100644 --- a/addon/mode/loadmode.js +++ b/addon/mode/loadmode.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js"; var loading = {}; @@ -48,4 +55,4 @@ instance.setOption("mode", instance.getOption("mode")); }); }; -}()); +}); diff --git a/addon/mode/multiplex.js b/addon/mode/multiplex.js index 614ab1add3..07385c35f2 100644 --- a/addon/mode/multiplex.js +++ b/addon/mode/multiplex.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.multiplexingMode = function(outer /*, others */) { // Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects var others = Array.prototype.slice.call(arguments, 1); @@ -101,3 +111,5 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { } }; }; + +}); diff --git a/addon/mode/overlay.js b/addon/mode/overlay.js index b7928a7bbf..6f556a13a7 100644 --- a/addon/mode/overlay.js +++ b/addon/mode/overlay.js @@ -6,8 +6,17 @@ // overlay wins, unless the combine argument was true, in which case // the styles are combined. -// overlayParser is the old, deprecated name -CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, combine) { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + +CodeMirror.overlayMode = function(base, overlay, combine) { return { startState: function() { return { @@ -57,3 +66,5 @@ CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, comb } }; }; + +}); diff --git a/addon/runmode/colorize.js b/addon/runmode/colorize.js index 62286d21e4..0f9530b17b 100644 --- a/addon/runmode/colorize.js +++ b/addon/runmode/colorize.js @@ -1,4 +1,12 @@ -CodeMirror.colorize = (function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("./runmode")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "./runmode"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; var isBlock = /^(p|li|div|h\\d|pre|blockquote|td)$/; @@ -10,7 +18,7 @@ CodeMirror.colorize = (function() { } } - return function(collection, defaultMode) { + CodeMirror.colorize = function(collection, defaultMode) { if (!collection) collection = document.body.getElementsByTagName("pre"); for (var i = 0; i < collection.length; ++i) { @@ -26,4 +34,4 @@ CodeMirror.colorize = (function() { node.className += " cm-s-default"; } }; -})(); +}); diff --git a/addon/runmode/runmode-standalone.js b/addon/runmode/runmode-standalone.js index ec06ba11cb..eaa2b8f2fb 100644 --- a/addon/runmode/runmode-standalone.js +++ b/addon/runmode/runmode-standalone.js @@ -1,5 +1,3 @@ -/* Just enough of CodeMirror to run runMode under node.js */ - window.CodeMirror = {}; (function() { diff --git a/addon/runmode/runmode.js b/addon/runmode/runmode.js index 2cafa811f8..351840e08e 100644 --- a/addon/runmode/runmode.js +++ b/addon/runmode/runmode.js @@ -1,3 +1,13 @@ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + CodeMirror.runMode = function(string, modespec, callback, options) { var mode = CodeMirror.getMode(CodeMirror.defaults, modespec); var ie = /MSIE \d/.test(navigator.userAgent); @@ -54,3 +64,5 @@ CodeMirror.runMode = function(string, modespec, callback, options) { } } }; + +}); diff --git a/addon/runmode/runmode.node.js b/addon/runmode/runmode.node.js index ecb2ea56f1..74c39be7e7 100644 --- a/addon/runmode/runmode.node.js +++ b/addon/runmode/runmode.node.js @@ -1,5 +1,7 @@ /* Just enough of CodeMirror to run runMode under node.js */ +// declare global: StringStream + function splitLines(string){ return string.split(/\r?\n|\r/); }; function StringStream(string) { @@ -112,3 +114,5 @@ exports.runMode = function(string, modespec, callback, options) { } } }; + +require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")]; diff --git a/addon/scroll/scrollpastend.js b/addon/scroll/scrollpastend.js index 58720ad413..467b7aa1cf 100644 --- a/addon/scroll/scrollpastend.js +++ b/addon/scroll/scrollpastend.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; CodeMirror.defineOption("scrollPastEnd", false, function(cm, val, old) { @@ -33,4 +40,4 @@ cm.setSize(); } } -})(); +}); diff --git a/addon/search/match-highlighter.js b/addon/search/match-highlighter.js index e5cbeacab2..d9c818b838 100644 --- a/addon/search/match-highlighter.js +++ b/addon/search/match-highlighter.js @@ -12,7 +12,16 @@ // actual CSS class name. showToken, when enabled, will cause the // current token to be highlighted when nothing is selected. -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; + var DEFAULT_MIN_CHARS = 2; var DEFAULT_TOKEN_STYLE = "matchhighlight"; var DEFAULT_DELAY = 100; @@ -68,7 +77,7 @@ return; } if (cm.getCursor("head").line != cm.getCursor("anchor").line) return; - var selection = cm.getSelection().replace(/^\s+|\s+$/g, ""); + var selection = cm.getSelections()[0].replace(/^\s+|\s+$/g, ""); if (selection.length >= state.minChars) cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style)); }); @@ -88,4 +97,4 @@ stream.skipTo(query.charAt(0)) || stream.skipToEnd(); }}; } -})(); +}); diff --git a/addon/search/search.js b/addon/search/search.js index 690db3f5ef..19f51f1dcd 100644 --- a/addon/search/search.js +++ b/addon/search/search.js @@ -6,7 +6,15 @@ // replace by making sure the match is no longer selected when hitting // Ctrl-G. -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; function searchOverlay(query, caseInsensitive) { var startChar; if (typeof query == "string") { @@ -144,4 +152,4 @@ CodeMirror.commands.clearSearch = clearSearch; CodeMirror.commands.replace = replace; CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);}; -})(); +}); diff --git a/addon/search/searchcursor.js b/addon/search/searchcursor.js index 711cf4ce5a..899f44c4ab 100644 --- a/addon/search/searchcursor.js +++ b/addon/search/searchcursor.js @@ -1,4 +1,12 @@ -(function(){ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; var Pos = CodeMirror.Pos; function SearchCursor(doc, query, pos, caseFold) { @@ -164,4 +172,15 @@ CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) { return new SearchCursor(this, query, pos, caseFold); }); -})(); + + CodeMirror.defineExtension("selectMatches", function(query, caseFold) { + var ranges = [], next; + var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold); + while (next = cur.findNext()) { + if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break; + ranges.push({anchor: cur.from(), head: cur.to()}); + } + if (ranges.length) + this.setSelections(ranges, 0); + }); +}); diff --git a/addon/selection/active-line.js b/addon/selection/active-line.js index 7cf7793c07..a818f109b6 100644 --- a/addon/selection/active-line.js +++ b/addon/selection/active-line.js @@ -4,7 +4,14 @@ // active line's wrapping
the CSS class "CodeMirror-activeline", // and gives its background
the class "CodeMirror-activeline-background". -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; var WRAP_CLASS = "CodeMirror-activeline"; var BACK_CLASS = "CodeMirror-activeline-background"; @@ -12,34 +19,48 @@ CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) { var prev = old && old != CodeMirror.Init; if (val && !prev) { - updateActiveLine(cm, cm.getCursor().line); + cm.state.activeLines = []; + updateActiveLines(cm, cm.listSelections()); cm.on("beforeSelectionChange", selectionChange); } else if (!val && prev) { cm.off("beforeSelectionChange", selectionChange); - clearActiveLine(cm); - delete cm.state.activeLine; + clearActiveLines(cm); + delete cm.state.activeLines; } }); - function clearActiveLine(cm) { - if ("activeLine" in cm.state) { - cm.removeLineClass(cm.state.activeLine, "wrap", WRAP_CLASS); - cm.removeLineClass(cm.state.activeLine, "background", BACK_CLASS); + function clearActiveLines(cm) { + for (var i = 0; i < cm.state.activeLines.length; i++) { + cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS); + cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS); } } - function updateActiveLine(cm, selectedLine) { - var line = cm.getLineHandleVisualStart(selectedLine); - if (cm.state.activeLine == line) return; + function sameArray(a, b) { + if (a.length != b.length) return false; + for (var i = 0; i < a.length; i++) + if (a[i] != b[i]) return false; + return true; + } + + function updateActiveLines(cm, ranges) { + var active = []; + for (var i = 0; i < ranges.length; i++) { + var line = cm.getLineHandleVisualStart(ranges[i].head.line); + if (active[active.length - 1] != line) active.push(line); + } + if (sameArray(cm.state.activeLines, active)) return; cm.operation(function() { - clearActiveLine(cm); - cm.addLineClass(line, "wrap", WRAP_CLASS); - cm.addLineClass(line, "background", BACK_CLASS); - cm.state.activeLine = line; + clearActiveLines(cm); + for (var i = 0; i < active.length; i++) { + cm.addLineClass(active[i], "wrap", WRAP_CLASS); + cm.addLineClass(active[i], "background", BACK_CLASS); + } + cm.state.activeLines = active; }); } function selectionChange(cm, sel) { - updateActiveLine(cm, sel.head.line); + updateActiveLines(cm, sel.ranges); } -})(); +}); diff --git a/addon/selection/mark-selection.js b/addon/selection/mark-selection.js index c97776e492..ae0d393143 100644 --- a/addon/selection/mark-selection.js +++ b/addon/selection/mark-selection.js @@ -4,7 +4,14 @@ // selected text the CSS class given as option value, or // "CodeMirror-selectedtext" when the value is not a string. -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) { @@ -34,10 +41,7 @@ var CHUNK_SIZE = 8; var Pos = CodeMirror.Pos; - - function cmp(pos1, pos2) { - return pos1.line - pos2.line || pos1.ch - pos2.ch; - } + var cmp = CodeMirror.cmpPos; function coverRange(cm, from, to, addAt) { if (cmp(from, to) == 0) return; @@ -63,13 +67,16 @@ function reset(cm) { clear(cm); - var from = cm.getCursor("start"), to = cm.getCursor("end"); - coverRange(cm, from, to); + var ranges = cm.listSelections(); + for (var i = 0; i < ranges.length; i++) + coverRange(cm, ranges[i].from(), ranges[i].to()); } function update(cm) { + if (!cm.somethingSelected()) return clear(cm); + if (cm.listSelections().length > 1) return reset(cm); + var from = cm.getCursor("start"), to = cm.getCursor("end"); - if (cmp(from, to) == 0) return clear(cm); var array = cm.state.markedSelection; if (!array.length) return coverRange(cm, from, to); @@ -105,4 +112,4 @@ } } } -})(); +}); diff --git a/addon/tern/tern.js b/addon/tern/tern.js index 7f83c4e4c0..6fbd10c55d 100644 --- a/addon/tern/tern.js +++ b/addon/tern/tern.js @@ -40,7 +40,14 @@ // load. Or, if you minified those into a single script and included // them in the workerScript, simply leave this undefined. -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; // declare global: tern @@ -106,6 +113,8 @@ rename: function(cm) { rename(this, cm); }, + selectName: function(cm) { selectName(this, cm); }, + request: function (cm, query, c, pos) { var self = this; var doc = findDoc(this, cm.getDoc()); @@ -167,7 +176,7 @@ function sendDoc(ts, doc) { ts.server.request({files: [{type: "full", name: doc.name, text: docValue(ts, doc)}]}, function(error) { - if (error) console.error(error); + if (error) window.console.error(error); else doc.changed = null; }); } @@ -429,6 +438,25 @@ }); } + function selectName(ts, cm) { + var cur = cm.getCursor(), token = cm.getTokenAt(cur); + if (!/\w/.test(token.string)) showError(ts, cm, "Not at a variable"); + var name = findDoc(ts, cm.doc).name; + ts.request(cm, {type: "refs"}, function(error, data) { + if (error) return showError(ts, cm, error); + var ranges = [], cur = 0; + for (var i = 0; i < data.refs.length; i++) { + var ref = data.refs[i]; + if (ref.file == name) { + ranges.push({anchor: ref.start, head: ref.end}); + if (cmpPos(cur, ref.start) >= 0 && cmpPos(cur, ref.end) <= 0) + cur = ranges.length - 1; + } + } + cm.setSelections(ranges, cur); + }); + } + var nextChangeOrig = 0; function applyChanges(ts, changes) { var perFile = Object.create(null); @@ -521,7 +549,7 @@ // Generic utilities - function cmpPos(a, b) { return a.line - b.line || a.ch - b.ch; } + var cmpPos = CodeMirror.cmpPos; function elt(tagname, cls /*, ... elts*/) { var e = document.createElement(tagname); @@ -614,7 +642,7 @@ send({type: "getFile", err: String(err), text: text, id: data.id}); }); } else if (data.type == "debug") { - console.log(data.message); + window.console.log(data.message); } else if (data.id && pending[data.id]) { pending[data.id](data.err, data.body); delete pending[data.id]; @@ -629,4 +657,4 @@ this.delFile = function(name) { send({type: "del", name: name}); }; this.request = function(body, c) { send({type: "req", body: body}, c); }; } -})(); +}); diff --git a/addon/wrap/hardwrap.js b/addon/wrap/hardwrap.js index f6d99212a8..87aab1b8f6 100644 --- a/addon/wrap/hardwrap.js +++ b/addon/wrap/hardwrap.js @@ -1,4 +1,11 @@ -(function() { +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { "use strict"; var Pos = CodeMirror.Pos; @@ -89,6 +96,24 @@ return wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options); }); + CodeMirror.commands.wrapLines = function(cm) { + cm.operation(function() { + var ranges = cm.listSelections(), at = cm.lastLine() + 1; + for (var i = ranges.length - 1; i >= 0; i--) { + var range = ranges[i], span; + if (range.empty()) { + var para = findParagraph(cm, range.head, {}); + span = {from: Pos(para.from, 0), to: Pos(para.to - 1)}; + } else { + span = {from: range.from(), to: range.to()}; + } + if (span.to.line >= at) continue; + at = span.from.line; + wrapRange(cm, span.from, span.to, {}); + } + }); + }; + CodeMirror.defineExtension("wrapRange", function(from, to, options) { return wrapRange(this, from, to, options || {}); }); @@ -108,4 +133,4 @@ }); return madeChange; }); -})(); +}); diff --git a/bin/source-highlight b/bin/source-highlight index 1373f6626f..6d15f1ae3f 100755 --- a/bin/source-highlight +++ b/bin/source-highlight @@ -8,7 +8,7 @@ var fs = require("fs"); -CodeMirror = require("../addon/runmode/runmode.node.js"); +var CodeMirror = require("../addon/runmode/runmode.node.js"); require("../mode/meta.js"); var sPos = process.argv.indexOf("-s"); @@ -26,18 +26,8 @@ CodeMirror.modeInfo.forEach(function(info) { } }); -function ensureMode(name) { - if (CodeMirror.modes[name] || name == "null") return; - try { - require("../mode/" + name + "/" + name + ".js"); - } catch(e) { - console.error("Could not load mode " + name + "."); - process.exit(1); - } - var obj = CodeMirror.modes[name]; - if (obj.dependencies) obj.dependencies.forEach(ensureMode); -} -ensureMode(modeName); +if (!CodeMirror.modes[modeName]) + require("../mode/" + modeName + "/" + modeName + ".js"); function esc(str) { return str.replace(/[<&]/g, function(ch) { return ch == "&" ? "&" : "<"; }); diff --git a/demo/btree.html b/demo/btree.html index 7635ca1bb4..b7bd39088d 100644 --- a/demo/btree.html +++ b/demo/btree.html @@ -58,7 +58,6 @@ var gray = Math.min(line.text.length * 3, 230), col = gray.toString(16); if (col.length == 1) col = "0" + col; lineElt.style.background = "#" + col + col + col; - console.log(line.height, line); lineElt.style.width = Math.max(Math.round(line.height / 3), 1) + "px"; } } else { diff --git a/demo/closebrackets.html b/demo/closebrackets.html index 8c0dc1cc3e..f7d5afbd87 100644 --- a/demo/closebrackets.html +++ b/demo/closebrackets.html @@ -26,36 +26,25 @@

Closebrackets Demo

-
+
+ + + + + + + + + + + + + + +
+

Sublime Text bindings demo

+ +

The sublime keymap defines many Sublime Text-specific +bindings for CodeMirror. See the code below for an overview.

+ +

Enable the keymap by +loading keymap/sublime.js +and setting +the keyMap +option to "sublime".

+ +

(A lot of the search functionality is still missing.) + + + +

diff --git a/demo/tern.html b/demo/tern.html index 6843c7f5ec..57027f7267 100644 --- a/demo/tern.html +++ b/demo/tern.html @@ -86,6 +86,7 @@
Ctrl-I
Find type at cursor
Alt-.
Jump to definition (Alt-, to jump back)
Ctrl-Q
Rename variable
+
Ctrl-.
Select all occurrences of a variable

Documentation is sparse for now. See the top of @@ -116,6 +117,7 @@ "Alt-.": function(cm) { server.jumpToDef(cm); }, "Alt-,": function(cm) { server.jumpBack(cm); }, "Ctrl-Q": function(cm) { server.rename(cm); }, + "Ctrl-.": function(cm) { server.selectName(cm); } }) editor.on("cursorActivity", function(cm) { server.updateArgHints(cm); }); }); diff --git a/demo/theme.html b/demo/theme.html index 29b55df2e3..20e273cf59 100644 --- a/demo/theme.html +++ b/demo/theme.html @@ -35,7 +35,6 @@ -