Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Update codemirror to 2.15 and make the code internally more version-agnostic #850

Merged
merged 5 commits into from

2 participants

Fernando Perez Brian E. Granger
Fernando Perez
Owner

Just updated to the recently released CM and changed things around a little so that we don't have an explicit version number path inside our templates.

Since 0.12 may live for a while in a long-term Ubuntu release (12.04), it would be nice to release with the most updated CM...

fperez added some commits
Fernando Perez fperez Update CodeMirror code to v2.15 6652b19
Fernando Perez fperez Do not use version # in codemirror directory name.
Simply call it 'codemirror', so we don't have explicit version numbers
inside a bunch of files.

A file called ipython-version-N.NN will be kept to easily let us know
which version we're shipping with IPython.
265d40c
Fernando Perez fperez Update templates to new directory name for codemirror. 5b206ff
Brian E. Granger
Owner
Fernando Perez
Owner

No, I hadn't realized that you had made changes. If they were made in a single commit, then it should be relatively easy to reapply them as a patch, do you have the commit number?

And what I can do is apply them again as a single commit and record that info in a little README, so that it's easy later to apply again when we upgrade CM. Eventually the right way to do this is to keep the patch set separately using something like stgit, but for small changes we can get away with a one-off manual process.

Brian E. Granger
Owner
Fernando Perez
Owner
Brian E. Granger
Owner
Fernando Perez
Owner

Found it, the only difference from CM 2.12 and your code is this:

diff --git a/IPython/frontend/html/notebook/static/codemirror-2.12/mode/python/python.js b/IPython/frontend/html/notebook/static/codemirror-2.12/mode/python/python.js
index baeec03..0cda2aa 100644
--- a/IPython/frontend/html/notebook/static/codemirror-2.12/mode/python/python.js
+++ b/IPython/frontend/html/notebook/static/codemirror-2.12/mode/python/python.js
@@ -5,7 +5,7 @@ CodeMirror.defineMode("python", function(conf) {
         return new RegExp("^((" + words.join(")|(") + "))\\b");
     }
     
-    var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~!]");
+    var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~!\\?]");
     var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
     var doubleOperators = new RegExp("^((==)|(!=)|(=)|()|(>)|(//)|(\\*\\*))");
     var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))")

It's a single line change where you added some operators. I'm now going to see how much of that is actually even needed in 2.15, since they've also updated the python code somewhat.

So this is going to be pretty easy, in fact.

Fernando Perez
Owner

OK, @ellisonbg, I've applied back the changes you had, and it was done as a single-commit in bef6551 so we can find them again easily later on. If this ever gets big we can make a little patch queue for it, but something this small is just as easily copy/pasted by hand, esp. now that it's in its own commit and hence easy to find.

I'll make a little file with this info so we know what to do in future updates too.

Fernando Perez
Owner

OK, ipython-specific readme added, let me know if you see anything else that sticks out prior to merge.

Thanks for the feedback!

Brian E. Granger
Owner
Fernando Perez
Owner

@ellisonbg, does this look OK to merge, or do you want anything else on it? Just being a good citizen here and not merging my own stuff without someone else giving the final OK :)

Brian E. Granger
Owner
Fernando Perez fperez merged commit e5a1dff into from
Fernando Perez fperez referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 9, 2011
  1. Fernando Perez
  2. Fernando Perez

    Do not use version # in codemirror directory name.

    fperez authored
    Simply call it 'codemirror', so we don't have explicit version numbers
    inside a bunch of files.
    
    A file called ipython-version-N.NN will be kept to easily let us know
    which version we're shipping with IPython.
  3. Fernando Perez
Commits on Oct 14, 2011
  1. Fernando Perez
  2. Fernando Perez
This page is out of date. Refresh to see the latest.
Showing with 810 additions and 135 deletions.
  1. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/LICENSE
  2. +33 −0 IPython/frontend/html/notebook/static/codemirror/README-IPython.rst
  3. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/README.md
  4. +1 −0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/lib/codemirror.css
  5. +132 −79 IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/lib/codemirror.js
  6. +1 −1  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/lib/overlay.js
  7. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/lib/runmode.js
  8. +3 −3 IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/css/css.js
  9. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/css/index.html
  10. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/htmlmixed/htmlmixed.js
  11. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/htmlmixed/index.html
  12. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/javascript/index.html
  13. +6 −2 IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/javascript/javascript.js
  14. +340 −0 IPython/frontend/html/notebook/static/codemirror/mode/markdown/index.html
  15. +10 −0 IPython/frontend/html/notebook/static/codemirror/mode/markdown/markdown.css
  16. +230 −0 IPython/frontend/html/notebook/static/codemirror/mode/markdown/markdown.js
  17. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/python/LICENSE.txt
  18. +1 −1  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/python/index.html
  19. +35 −32 IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/python/python.js
  20. +0 −1  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/rst/index.html
  21. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/rst/rst.css
  22. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/rst/rst.js
  23. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/xml/index.html
  24. +4 −4 IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/mode/xml/xml.js
  25. +1 −0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/theme/default.css
  26. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/theme/elegant.css
  27. +0 −1  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/theme/ipython.css
  28. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/theme/neat.css
  29. 0  IPython/frontend/html/notebook/static/{codemirror-2.12 → codemirror}/theme/night.css
  30. +13 −11 IPython/frontend/html/notebook/templates/notebook.html
0  ...tend/html/notebook/static/codemirror-2.12/LICENSE → .../frontend/html/notebook/static/codemirror/LICENSE
View
File renamed without changes
33 IPython/frontend/html/notebook/static/codemirror/README-IPython.rst
View
@@ -0,0 +1,33 @@
+=======================
+ CodeMirror in IPython
+=======================
+
+We carry a mostly unmodified copy of CodeMirror. The current version we use
+is (*please update this information when updating versions*)::
+
+ CodeMirror 2.15
+
+The only changes we've applied so far are these::
+
+ diff --git a/IPython/frontend/html/notebook/static/codemirror/mode/python/python.js b/IPython/frontend/html/notebook/static/codemirror/mode/python/python.js
+ index ca94e7a..fc9a503 100644
+ --- a/IPython/frontend/html/notebook/static/codemirror/mode/python/python.js
+ +++ b/IPython/frontend/html/notebook/static/codemirror/mode/python/python.js
+ @@ -5,7 +5,11 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
+ return new RegExp("^((" + words.join(")|(") + "))\\b");
+ }
+
+ - var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
+ + // IPython-specific changes: add '?' as recognized character.
+ + //var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
+ + var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\\?]");
+ + // End IPython changes.
+ +
+ var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
+ var doubleOperators = new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
+ var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
+
+
+In practice it's just a one-line change, adding `\\?` to singleOperators,
+surrounded by a comment. We'll turn this into a proper patchset if it ever
+gets more complicated than this, but for now this note should be enough.
0  ...nd/html/notebook/static/codemirror-2.12/README.md → ...rontend/html/notebook/static/codemirror/README.md
View
File renamed without changes
1  ...otebook/static/codemirror-2.12/lib/codemirror.css → ...tml/notebook/static/codemirror/lib/codemirror.css
View
@@ -13,6 +13,7 @@
.CodeMirror-gutter {
position: absolute; left: 0; top: 0;
+ z-index: 10;
background-color: #f7f7f7;
border-right: 1px solid #eee;
min-width: 2em;
211 ...notebook/static/codemirror-2.12/lib/codemirror.js → ...html/notebook/static/codemirror/lib/codemirror.js
View
@@ -20,14 +20,15 @@ var CodeMirror = (function() {
// This mess creates the base DOM structure for the editor.
wrapper.innerHTML =
'<div style="overflow: hidden; position: relative; width: 1px; height: 0px;">' + // Wraps and hides input textarea
- '<textarea style="position: absolute; width: 2px;" wrap="off"></textarea></div>' +
+ '<textarea style="position: absolute; width: 2px;" wrap="off" ' +
+ 'autocorrect="off" autocapitalize="off"></textarea></div>' +
'<div class="CodeMirror-scroll cm-s-' + options.theme + '">' +
'<div style="position: relative">' + // Set to the height of the text, causes scrolling
'<div style="position: absolute; height: 0; width: 0; overflow: hidden;"></div>' +
'<div style="position: relative">' + // Moved around its parent to cover visible view
'<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
// Provides positioning relative to (visible) text origin
- '<div class="CodeMirror-lines"><div style="position: relative">' +
+ '<div class="CodeMirror-lines"><div style="position: relative" draggable="true">' +
'<pre class="CodeMirror-cursor">&#160;</pre>' + // Absolutely positioned blinky cursor
'<div></div>' + // This DIV contains the actual code
'</div></div></div></div></div>';
@@ -59,10 +60,10 @@ var CodeMirror = (function() {
// whether the user is holding shift. reducedSelection is a hack
// to get around the fact that we can't create inverted
// selections. See below.
- var shiftSelecting, reducedSelection, lastDoubleClick;
+ var shiftSelecting, reducedSelection, lastClick, lastDoubleClick;
// Variables used by startOperation/endOperation to track what
// happened during the operation.
- var updateInput, changes, textChanged, selectionChanged, leaveInputAlone;
+ var updateInput, changes, textChanged, selectionChanged, leaveInputAlone, gutterDirty;
// Current visible range (may be bigger than the view window).
var showingFrom = 0, showingTo = 0, lastHeight = 0, curKeyId = null;
// editing will hold an object describing the things we put in the
@@ -79,12 +80,16 @@ var CodeMirror = (function() {
// Register our event handlers.
connect(scroller, "mousedown", operation(onMouseDown));
+ connect(lineSpace, "dragstart", onDragStart);
// Gecko browsers fire contextmenu *after* opening the menu, at
// which point we can't mess with it anymore. Context menu is
// handled in onMouseDown for Gecko.
if (!gecko) connect(scroller, "contextmenu", onContextMenu);
- connect(code, "dblclick", operation(onDblClick));
- connect(scroller, "scroll", function() {updateDisplay([]); if (options.onScroll) options.onScroll(instance);});
+ connect(scroller, "scroll", function() {
+ updateDisplay([]);
+ if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px";
+ if (options.onScroll) options.onScroll(instance);
+ });
connect(window, "resize", function() {updateDisplay(true);});
connect(input, "keyup", operation(onKeyUp));
connect(input, "keydown", operation(onKeyDown));
@@ -98,8 +103,8 @@ var CodeMirror = (function() {
connect(scroller, "paste", function(){focusInput(); fastPoll();});
connect(input, "paste", function(){fastPoll();});
connect(input, "cut", function(){fastPoll();});
-
- // IE throws unspecified error in certain cases, when
+
+ // IE throws unspecified error in certain cases, when
// trying to access activeElement before onload
var hasFocus; try { hasFocus = (targetDocument.activeElement == input); } catch(e) { }
if (hasFocus) setTimeout(onFocus, 20);
@@ -111,7 +116,7 @@ var CodeMirror = (function() {
// range checking and/or clipping. operation is used to wrap the
// call so that changes it makes are tracked, and the display is
// updated afterwards.
- var instance = {
+ var instance = wrapper.CodeMirror = {
getValue: getValue,
setValue: operation(setValue),
getSelection: getSelection,
@@ -119,7 +124,8 @@ var CodeMirror = (function() {
focus: function(){focusInput(); onFocus(); fastPoll();},
setOption: function(option, value) {
options[option] = value;
- if (option == "lineNumbers" || option == "gutter") gutterChanged();
+ if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber")
+ operation(gutterChanged)();
else if (option == "mode" || option == "indentUnit") loadMode();
else if (option == "readOnly" && value == "nocursor") input.blur();
else if (option == "theme") scroller.className = scroller.className.replace(/cm-s-\w+/, "cm-s-" + value);
@@ -127,7 +133,9 @@ var CodeMirror = (function() {
getOption: function(option) {return options[option];},
undo: operation(undo),
redo: operation(redo),
- indentLine: operation(function(n) {if (isLine(n)) indentLine(n, "smart");}),
+ indentLine: operation(function(n, dir) {
+ if (isLine(n)) indentLine(n, dir == null ? "smart" : dir ? "add" : "subtract");
+ }),
historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
matchBrackets: operation(function(){matchBrackets(true);}),
getTokenAt: function(pos) {
@@ -150,18 +158,17 @@ var CodeMirror = (function() {
},
getSearchCursor: function(query, pos, caseFold) {return new SearchCursor(query, pos, caseFold);},
markText: operation(function(a, b, c){return operation(markText(a, b, c));}),
- setMarker: addGutterMarker,
- clearMarker: removeGutterMarker,
+ setMarker: operation(addGutterMarker),
+ clearMarker: operation(removeGutterMarker),
setLineClass: operation(setLineClass),
lineInfo: lineInfo,
- addWidget: function(pos, node, scroll, where) {
+ addWidget: function(pos, node, scroll, vert, horiz) {
pos = localCoords(clipPos(pos));
var top = pos.yBot, left = pos.x;
node.style.position = "absolute";
code.appendChild(node);
- node.style.left = left + "px";
- if (where == "over") top = pos.y;
- else if (where == "near") {
+ if (vert == "over") top = pos.y;
+ else if (vert == "near") {
var vspace = Math.max(scroller.offsetHeight, lines.length * lineHeight()),
hspace = Math.max(code.clientWidth, lineSpace.clientWidth) - paddingLeft();
if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight)
@@ -170,7 +177,15 @@ var CodeMirror = (function() {
left = hspace - node.offsetWidth;
}
node.style.top = (top + paddingTop()) + "px";
- node.style.left = (left + paddingLeft()) + "px";
+ node.style.left = node.style.right = "";
+ if (horiz == "right") {
+ left = code.clientWidth - node.offsetWidth;
+ node.style.right = "0px";
+ } else {
+ if (horiz == "left") left = 0;
+ else if (horiz == "middle") left = (code.clientWidth - node.offsetWidth) / 2;
+ node.style.left = (left + paddingLeft()) + "px";
+ }
if (scroll)
scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight);
},
@@ -200,7 +215,8 @@ var CodeMirror = (function() {
refresh: function(){updateDisplay(true);},
getInputField: function(){return input;},
getWrapperElement: function(){return wrapper;},
- getScrollerElement: function(){return scroller;}
+ getScrollerElement: function(){return scroller;},
+ getGutterElement: function(){return gutter;}
};
function setValue(code) {
@@ -209,6 +225,7 @@ var CodeMirror = (function() {
updateLines(top, {line: lines.length - 1, ch: lines[lines.length-1].text.length},
splitLines(code), top, top);
history = new History();
+ updateInput = true;
}
function getValue(code) {
var text = [];
@@ -221,17 +238,17 @@ var CodeMirror = (function() {
// Check whether this is a click in a widget
for (var n = e_target(e); n != wrapper; n = n.parentNode)
if (n.parentNode == code && n != mover) return;
- var ld = lastDoubleClick; lastDoubleClick = null;
+
// First, see if this is a click in the gutter
for (var n = e_target(e); n != wrapper; n = n.parentNode)
if (n.parentNode == gutterText) {
if (options.onGutterClick)
- options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom);
+ options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom, e);
return e_preventDefault(e);
}
var start = posFromMouse(e);
-
+
switch (e_button(e)) {
case 3:
if (gecko && !mac) onContextMenu(e);
@@ -246,18 +263,26 @@ var CodeMirror = (function() {
if (!start) {if (e_target(e) == scroller) e_preventDefault(e); return;}
if (!focused) onFocus();
- e_preventDefault(e);
- if (ld && +new Date - ld < 400) return selectLine(start.line);
- setCursor(start.line, start.ch, true);
+ var now = +new Date;
+ if (lastDoubleClick > now - 400) {
+ e_preventDefault(e);
+ return selectLine(start.line);
+ } else if (lastClick > now - 400) {
+ lastDoubleClick = now;
+ e_preventDefault(e);
+ return selectWordAt(start);
+ } else { lastClick = now; }
+
var last = start, going;
- // And then we have to see if it's a drag event, in which case
- // the dragged-over text must be selected.
- function end() {
- focusInput();
- updateInput = true;
- move(); up();
+ if (dragAndDrop && !posEq(sel.from, sel.to) &&
+ !posLess(start, sel.from) && !posLess(sel.to, start)) {
+ // Let the drag handler handle this.
+ return;
}
+ e_preventDefault(e);
+ setCursor(start.line, start.ch, true);
+
function extend(e) {
var cur = posFromMouse(e, true);
if (cur && !posEq(cur, last)) {
@@ -281,16 +306,11 @@ var CodeMirror = (function() {
var cur = posFromMouse(e);
if (cur) setSelectionUser(start, cur);
e_preventDefault(e);
- end();
+ focusInput();
+ updateInput = true;
+ move(); up();
}), true);
}
- function onDblClick(e) {
- var pos = posFromMouse(e);
- if (!pos) return;
- selectWordAt(pos);
- e_preventDefault(e);
- lastDoubleClick = +new Date;
- }
function onDrop(e) {
e.preventDefault();
var pos = posFromMouse(e, true), files = e.dataTransfer.files;
@@ -315,6 +335,13 @@ var CodeMirror = (function() {
catch(e){}
}
}
+ function onDragStart(e) {
+ var txt = getSelection();
+ // This will reset escapeElement
+ htmlEscape(txt);
+ e.dataTransfer.setDragImage(escapeElement, 0, 0);
+ e.dataTransfer.setData("Text", txt);
+ }
function onKeyDown(e) {
if (!focused) onFocus();
@@ -340,6 +367,7 @@ var CodeMirror = (function() {
if (mod && code == 90) {undo(); return e_preventDefault(e);} // ctrl-z
if (mod && ((e.shiftKey && code == 90) || code == 89)) {redo(); return e_preventDefault(e);} // ctrl-shift-z, ctrl-y
}
+ if (code == 36) { if (options.smartHome) { smartHome(); return e_preventDefault(e); } }
// Key id to use in the movementKeys map. We also pass it to
// fastPoll in order to 'self learn'. We need this because
@@ -347,14 +375,16 @@ var CodeMirror = (function() {
// its start when it is inverted and a movement key is pressed
// (and later restore it again), shouldn't be used for
// non-movement keys.
- curKeyId = (mod ? "c" : "") + code;
- if (sel.inverted && movementKeys.hasOwnProperty(curKeyId)) {
+ curKeyId = (mod ? "c" : "") + (e.altKey ? "a" : "") + code;
+ if (sel.inverted && movementKeys[curKeyId] === true) {
var range = selRange(input);
if (range) {
reducedSelection = {anchor: range.start};
setSelRange(input, range.start, range.start);
}
}
+ // Don't save the key as a movementkey unless it had a modifier
+ if (!mod && !e.altKey) curKeyId = null;
fastPoll(curKeyId);
}
function onKeyUp(e) {
@@ -566,7 +596,10 @@ var CodeMirror = (function() {
function p() {
startOperation();
var changed = readInput();
- if (changed == "moved" && keyId) movementKeys[keyId] = true;
+ if (changed && keyId) {
+ if (changed == "moved" && movementKeys[keyId] == null) movementKeys[keyId] = true;
+ if (changed == "changed") movementKeys[keyId] = false;
+ }
if (!changed && !missed) {missed = true; poll.set(80, p);}
else {pollingFast = false; slowPoll();}
endOperation();
@@ -663,6 +696,12 @@ var CodeMirror = (function() {
if (options.readOnly != "nocursor") input.focus();
}
+ function scrollEditorIntoView() {
+ if (!cursor.getBoundingClientRect) return;
+ var rect = cursor.getBoundingClientRect();
+ var winH = window.innerHeight || document.body.offsetHeight || document.documentElement.offsetHeight;
+ if (rect.top < 0 || rect.bottom > winH) cursor.scrollIntoView();
+ }
function scrollCursorIntoView() {
var cursor = localCoords(sel.inverted ? sel.from : sel.to);
return scrollIntoView(cursor.x, cursor.y, cursor.x, cursor.yBot);
@@ -675,9 +714,10 @@ var CodeMirror = (function() {
else if (y2 > screentop + screen) {scroller.scrollTop = y2 + lh - screen; scrolled = true;}
var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;
- if (x1 < screenleft) {
+ var gutterw = options.fixedGutter ? gutter.clientWidth : 0;
+ if (x1 < screenleft + gutterw) {
if (x1 < 50) x1 = 0;
- scroller.scrollLeft = Math.max(0, x1 - 10);
+ scroller.scrollLeft = Math.max(0, x1 - 10 - gutterw);
scrolled = true;
}
else if (x2 > screenw + screenleft) {
@@ -745,6 +785,7 @@ var CodeMirror = (function() {
if (domPos != domEnd || pos != to) {
changedLines += Math.abs(to - pos);
updates.push({from: pos, to: to, domSize: domEnd - domPos, domStart: domPos});
+ if (to - pos != domEnd - domPos) gutterDirty = true;
}
if (!updates.length) return;
@@ -766,8 +807,8 @@ var CodeMirror = (function() {
if (different) {
lastHeight = scroller.clientHeight;
code.style.height = (lines.length * lineHeight() + 2 * paddingTop()) + "px";
- updateGutter();
}
+ if (different || gutterDirty) updateGutter();
if (maxWidth == null) maxWidth = stringWidth(maxLine);
if (maxWidth > scroller.clientWidth) {
@@ -868,13 +909,17 @@ var CodeMirror = (function() {
if (pad) firstNode.insertBefore(targetDocument.createTextNode(pad), firstNode.firstChild);
gutter.style.display = "";
lineSpace.style.marginLeft = gutter.offsetWidth + "px";
+ gutterDirty = false;
}
function updateCursor() {
var head = sel.inverted ? sel.from : sel.to, lh = lineHeight();
- var x = charX(head.line, head.ch) + "px", y = (head.line - showingFrom) * lh + "px";
- inputDiv.style.top = (head.line * lh - scroller.scrollTop) + "px";
+ var x = charX(head.line, head.ch);
+ var top = head.line * lh - scroller.scrollTop;
+ inputDiv.style.top = Math.max(Math.min(top, scroller.offsetHeight), 0) + "px";
+ inputDiv.style.left = (x - scroller.scrollLeft) + "px";
if (posEq(sel.from, sel.to)) {
- cursor.style.top = y; cursor.style.left = x;
+ cursor.style.top = (head.line - showingFrom) * lh + "px";
+ cursor.style.left = x + "px";
cursor.style.display = "";
}
else cursor.style.display = "none";
@@ -994,6 +1039,10 @@ var CodeMirror = (function() {
}
return true;
}
+ function smartHome() {
+ var firstNonWS = Math.max(0, lines[sel.from.line].text.search(/\S/));
+ setCursor(sel.from.line, sel.from.ch <= firstNonWS && sel.from.ch ? 0 : firstNonWS, true);
+ }
function indentLine(n, how) {
if (how == "smart") {
@@ -1036,7 +1085,7 @@ var CodeMirror = (function() {
function gutterChanged() {
var visible = options.gutter || options.lineNumbers;
gutter.style.display = visible ? "" : "none";
- if (visible) updateGutter();
+ if (visible) gutterDirty = true;
else lineDiv.parentNode.style.marginLeft = 0;
}
@@ -1073,13 +1122,13 @@ var CodeMirror = (function() {
function addGutterMarker(line, text, className) {
if (typeof line == "number") line = lines[clipLine(line)];
line.gutterMarker = {text: text, style: className};
- updateGutter();
+ gutterDirty = true;
return line;
}
function removeGutterMarker(line) {
if (typeof line == "number") line = lines[clipLine(line)];
line.gutterMarker = null;
- updateGutter();
+ gutterDirty = true;
}
function setLineClass(line, className) {
if (typeof line == "number") {
@@ -1190,8 +1239,8 @@ var CodeMirror = (function() {
var oldCSS = input.style.cssText;
inputDiv.style.position = "absolute";
- input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e_pageY(e) - 1) +
- "px; left: " + (e_pageX(e) - 1) + "px; z-index: 1000; background: white; " +
+ input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
+ "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; " +
"border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
leaveInputAlone = true;
var val = input.value = getSelection();
@@ -1206,7 +1255,7 @@ var CodeMirror = (function() {
prepareInput();
slowPoll();
}
-
+
if (gecko) {
e_stop(e);
var mouseup = connect(window, "mouseup", function() {
@@ -1284,7 +1333,7 @@ var CodeMirror = (function() {
if (line.stateAfter) return search;
var indented = line.indentation();
if (minline == null || minindent > indented) {
- minline = search;
+ minline = search - 1;
minindent = indented;
}
}
@@ -1321,25 +1370,26 @@ var CodeMirror = (function() {
if (state) state = copyState(mode, state);
else state = startState(mode);
- var unchanged = 0, compare = mode.compareStates;
+ var unchanged = 0, compare = mode.compareStates, realChange = false;
for (var i = start, l = lines.length; i < l; ++i) {
var line = lines[i], hadState = line.stateAfter;
if (+new Date > end) {
work.push(i);
startWorker(options.workDelay);
- changes.push({from: task, to: i + 1});
+ if (realChange) changes.push({from: task, to: i + 1});
return;
}
var changed = line.highlight(mode, state);
+ if (changed) realChange = true;
line.stateAfter = copyState(mode, state);
if (compare) {
if (hadState && compare(hadState, state)) break;
} else {
- if (changed || !hadState) unchanged = 0;
+ if (changed !== false || !hadState) unchanged = 0;
else if (++unchanged > 3) break;
}
}
- changes.push({from: task, to: i + 1});
+ if (realChange) changes.push({from: task, to: i + 1});
}
if (foundWork && options.onHighlightComplete)
options.onHighlightComplete(instance);
@@ -1360,9 +1410,12 @@ var CodeMirror = (function() {
var reScroll = false;
if (selectionChanged) reScroll = !scrollCursorIntoView();
if (changes.length) updateDisplay(changes);
- else if (selectionChanged) updateCursor();
+ else {
+ if (selectionChanged) updateCursor();
+ if (gutterDirty) updateGutter();
+ }
if (reScroll) scrollCursorIntoView();
- if (selectionChanged) restartBlink();
+ if (selectionChanged) {scrollEditorIntoView(); restartBlink();}
// updateInput can be set to a boolean value to force/prevent an
// update.
@@ -1525,8 +1578,10 @@ var CodeMirror = (function() {
onKeyEvent: null,
lineNumbers: false,
gutter: false,
+ fixedGutter: false,
firstLineNumber: 1,
readOnly: false,
+ smartHome: true,
onChange: null,
onCursorActivity: null,
onGutterClick: null,
@@ -1572,7 +1627,7 @@ var CodeMirror = (function() {
CodeMirror.listMIMEs = function() {
var list = [];
for (var m in mimeModes)
- if (mimeModes.propertyIsEnumerable(m)) list.push(m);
+ if (mimeModes.propertyIsEnumerable(m)) list.push({mime: m, mode: mimeModes[m]});
return list;
};
@@ -1660,7 +1715,7 @@ var CodeMirror = (function() {
if (ok) {++this.pos; return ch;}
},
eatWhile: function(match) {
- var start = this.start;
+ var start = this.pos;
while (this.eat(match)){}
return this.pos > start;
},
@@ -1769,10 +1824,10 @@ var CodeMirror = (function() {
}
if (st.length != pos) {st.length = pos; changed = true;}
if (pos && st[pos-2] != prevWord) changed = true;
- // Short lines with simple highlights always count as changed,
- // because they are likely to highlight the same way in various
- // contexts.
- return changed || (st.length < 5 && this.text.length < 10);
+ // Short lines with simple highlights return null, and are
+ // counted as changed by the driver because they are likely to
+ // highlight the same way in various contexts.
+ return changed || (st.length < 5 && this.text.length < 10 ? null : false);
},
// Fetch the parser token for a given character. Useful for hacks
// that want to inspect the mode state (say, for completion).
@@ -1930,16 +1985,6 @@ var CodeMirror = (function() {
else if (e.button & 2) return 3;
else if (e.button & 4) return 2;
}
- function e_pageX(e) {
- if (e.pageX != null) return e.pageX;
- var doc = e_target(e).ownerDocument;
- return e.clientX + doc.body.scrollLeft + doc.documentElement.scrollLeft;
- }
- function e_pageY(e) {
- if (e.pageY != null) return e.pageY;
- var doc = e_target(e).ownerDocument;
- return e.clientY + doc.body.scrollTop + doc.documentElement.scrollTop;
- }
// Event handler registration. If disconnect is true, it'll return a
// function that unregisters the handler.
@@ -1965,6 +2010,15 @@ var CodeMirror = (function() {
pre.innerHTML = " "; return !pre.innerHTML;
})();
+ // Detect drag-and-drop
+ var dragAndDrop = (function() {
+ // IE8 has ondragstart and ondrop properties, but doesn't seem to
+ // actually support ondragstart the way it's supposed to work.
+ if (/MSIE [1-8]\b/.test(navigator.userAgent)) return false;
+ var div = document.createElement('div');
+ return "ondragstart" in div && "ondrop" in div;
+ })();
+
var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
var ie = /MSIE \d/.test(navigator.userAgent);
var safari = /Apple Computer/.test(navigator.vendor);
@@ -2140,5 +2194,4 @@ var CodeMirror = (function() {
CodeMirror.defineMIME("text/plain", "null");
return CodeMirror;
-})()
-;
+})();
2  ...ml/notebook/static/codemirror-2.12/lib/overlay.js → ...nd/html/notebook/static/codemirror/lib/overlay.js
View
@@ -42,7 +42,7 @@ CodeMirror.overlayParser = function(base, overlay, combine) {
if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur;
else return state.overlayCur;
},
-
+
indent: function(state, textAfter) {
return base.indent(state.base, textAfter);
},
0  ...ml/notebook/static/codemirror-2.12/lib/runmode.js → ...nd/html/notebook/static/codemirror/lib/runmode.js
View
File renamed without changes
6 ...l/notebook/static/codemirror-2.12/mode/css/css.js → ...d/html/notebook/static/codemirror/mode/css/css.js
View
@@ -4,7 +4,7 @@ CodeMirror.defineMode("css", function(config) {
function tokenBase(stream, state) {
var ch = stream.next();
- if (ch == "@") {stream.eatWhile(/\w/); return ret("meta", stream.current());}
+ if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());}
else if (ch == "/" && stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
@@ -20,7 +20,7 @@ CodeMirror.defineMode("css", function(config) {
return state.tokenize(stream, state);
}
else if (ch == "#") {
- stream.eatWhile(/\w/);
+ stream.eatWhile(/[\w\\\-]/);
return ret("atom", "hash");
}
else if (ch == "!") {
@@ -38,7 +38,7 @@ CodeMirror.defineMode("css", function(config) {
return ret(null, ch);
}
else {
- stream.eatWhile(/[\w\\\-_]/);
+ stream.eatWhile(/[\w\\\-]/);
return ret("variable", "variable");
}
}
0  ...tebook/static/codemirror-2.12/mode/css/index.html → ...ml/notebook/static/codemirror/mode/css/index.html
View
File renamed without changes
0  ...tatic/codemirror-2.12/mode/htmlmixed/htmlmixed.js → ...ook/static/codemirror/mode/htmlmixed/htmlmixed.js
View
File renamed without changes
0  .../static/codemirror-2.12/mode/htmlmixed/index.html → ...ebook/static/codemirror/mode/htmlmixed/index.html
View
File renamed without changes
0  ...static/codemirror-2.12/mode/javascript/index.html → ...book/static/codemirror/mode/javascript/index.html
View
File renamed without changes
8 ...tic/codemirror-2.12/mode/javascript/javascript.js → ...k/static/codemirror/mode/javascript/javascript.js
View
@@ -52,7 +52,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
else if (ch == "0" && stream.eat(/x/i)) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
- }
+ }
else if (/\d/.test(ch)) {
stream.match(/^\d*(?:\.\d*)?(?:e[+\-]?\d+)?/);
return ret("number", "number");
@@ -75,6 +75,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return ret("operator", null, stream.current());
}
}
+ else if (ch == "#") {
+ stream.skipToEnd();
+ return ret("error", "error");
+ }
else if (isOperatorChar.test(ch)) {
stream.eatWhile(isOperatorChar);
return ret("operator", null, stream.current());
@@ -130,7 +134,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
// Communicate our context to the combinators.
// (Less wasteful than consing up a hundred closures on every call.)
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
-
+
if (!state.lexical.hasOwnProperty("align"))
state.lexical.align = true;
340 IPython/frontend/html/notebook/static/codemirror/mode/markdown/index.html
View
@@ -0,0 +1,340 @@
+<!doctype html>
+<html>
+ <head>
+ <title>CodeMirror 2: Markdown mode</title>
+ <link rel="stylesheet" href="../../lib/codemirror.css">
+ <script src="../../lib/codemirror.js"></script>
+ <script src="../xml/xml.js"></script>
+ <script src="markdown.js"></script>
+ <link rel="stylesheet" href="../../theme/default.css">
+ <link rel="stylesheet" href="markdown.css">
+ <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
+ <link rel="stylesheet" href="../../css/docs.css">
+ </head>
+ <body>
+ <h1>CodeMirror 2: Markdown mode</h1>
+
+<!-- source: http://daringfireball.net/projects/markdown/basics.text -->
+<form><textarea id="code" name="code">
+Markdown: Basics
+================
+
+&lt;ul id="ProjectSubmenu"&gt;
+ &lt;li&gt;&lt;a href="/projects/markdown/" title="Markdown Project Page"&gt;Main&lt;/a&gt;&lt;/li&gt;
+ &lt;li&gt;&lt;a class="selected" title="Markdown Basics"&gt;Basics&lt;/a&gt;&lt;/li&gt;
+ &lt;li&gt;&lt;a href="/projects/markdown/syntax" title="Markdown Syntax Documentation"&gt;Syntax&lt;/a&gt;&lt;/li&gt;
+ &lt;li&gt;&lt;a href="/projects/markdown/license" title="Pricing and License Information"&gt;License&lt;/a&gt;&lt;/li&gt;
+ &lt;li&gt;&lt;a href="/projects/markdown/dingus" title="Online Markdown Web Form"&gt;Dingus&lt;/a&gt;&lt;/li&gt;
+&lt;/ul&gt;
+
+
+Getting the Gist of Markdown's Formatting Syntax
+------------------------------------------------
+
+This page offers a brief overview of what it's like to use Markdown.
+The [syntax page] [s] provides complete, detailed documentation for
+every feature, but Markdown should be very easy to pick up simply by
+looking at a few examples of it in action. The examples on this page
+are written in a before/after style, showing example syntax and the
+HTML output produced by Markdown.
+
+It's also helpful to simply try Markdown out; the [Dingus] [d] is a
+web application that allows you type your own Markdown-formatted text
+and translate it to XHTML.
+
+**Note:** This document is itself written using Markdown; you
+can [see the source for it by adding '.text' to the URL] [src].
+
+ [s]: /projects/markdown/syntax "Markdown Syntax"
+ [d]: /projects/markdown/dingus "Markdown Dingus"
+ [src]: /projects/markdown/basics.text
+
+
+## Paragraphs, Headers, Blockquotes ##
+
+A paragraph is simply one or more consecutive lines of text, separated
+by one or more blank lines. (A blank line is any line that looks like
+a blank line -- a line containing nothing but spaces or tabs is
+considered blank.) Normal paragraphs should not be indented with
+spaces or tabs.
+
+Markdown offers two styles of headers: *Setext* and *atx*.
+Setext-style headers for `&lt;h1&gt;` and `&lt;h2&gt;` are created by
+"underlining" with equal signs (`=`) and hyphens (`-`), respectively.
+To create an atx-style header, you put 1-6 hash marks (`#`) at the
+beginning of the line -- the number of hashes equals the resulting
+HTML header level.
+
+Blockquotes are indicated using email-style '`&gt;`' angle brackets.
+
+Markdown:
+
+ A First Level Header
+ ====================
+
+ A Second Level Header
+ ---------------------
+
+ Now is the time for all good men to come to
+ the aid of their country. This is just a
+ regular paragraph.
+
+ The quick brown fox jumped over the lazy
+ dog's back.
+
+ ### Header 3
+
+ &gt; This is a blockquote.
+ &gt;
+ &gt; This is the second paragraph in the blockquote.
+ &gt;
+ &gt; ## This is an H2 in a blockquote
+
+
+Output:
+
+ &lt;h1&gt;A First Level Header&lt;/h1&gt;
+
+ &lt;h2&gt;A Second Level Header&lt;/h2&gt;
+
+ &lt;p&gt;Now is the time for all good men to come to
+ the aid of their country. This is just a
+ regular paragraph.&lt;/p&gt;
+
+ &lt;p&gt;The quick brown fox jumped over the lazy
+ dog's back.&lt;/p&gt;
+
+ &lt;h3&gt;Header 3&lt;/h3&gt;
+
+ &lt;blockquote&gt;
+ &lt;p&gt;This is a blockquote.&lt;/p&gt;
+
+ &lt;p&gt;This is the second paragraph in the blockquote.&lt;/p&gt;
+
+ &lt;h2&gt;This is an H2 in a blockquote&lt;/h2&gt;
+ &lt;/blockquote&gt;
+
+
+
+### Phrase Emphasis ###
+
+Markdown uses asterisks and underscores to indicate spans of emphasis.
+
+Markdown:
+
+ Some of these words *are emphasized*.
+ Some of these words _are emphasized also_.
+
+ Use two asterisks for **strong emphasis**.
+ Or, if you prefer, __use two underscores instead__.
+
+Output:
+
+ &lt;p&gt;Some of these words &lt;em&gt;are emphasized&lt;/em&gt;.
+ Some of these words &lt;em&gt;are emphasized also&lt;/em&gt;.&lt;/p&gt;
+
+ &lt;p&gt;Use two asterisks for &lt;strong&gt;strong emphasis&lt;/strong&gt;.
+ Or, if you prefer, &lt;strong&gt;use two underscores instead&lt;/strong&gt;.&lt;/p&gt;
+
+
+
+## Lists ##
+
+Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,
+`+`, and `-`) as list markers. These three markers are
+interchangable; this:
+
+ * Candy.
+ * Gum.
+ * Booze.
+
+this:
+
+ + Candy.
+ + Gum.
+ + Booze.
+
+and this:
+
+ - Candy.
+ - Gum.
+ - Booze.
+
+all produce the same output:
+
+ &lt;ul&gt;
+ &lt;li&gt;Candy.&lt;/li&gt;
+ &lt;li&gt;Gum.&lt;/li&gt;
+ &lt;li&gt;Booze.&lt;/li&gt;
+ &lt;/ul&gt;
+
+Ordered (numbered) lists use regular numbers, followed by periods, as
+list markers:
+
+ 1. Red
+ 2. Green
+ 3. Blue
+
+Output:
+
+ &lt;ol&gt;
+ &lt;li&gt;Red&lt;/li&gt;
+ &lt;li&gt;Green&lt;/li&gt;
+ &lt;li&gt;Blue&lt;/li&gt;
+ &lt;/ol&gt;
+
+If you put blank lines between items, you'll get `&lt;p&gt;` tags for the
+list item text. You can create multi-paragraph list items by indenting
+the paragraphs by 4 spaces or 1 tab:
+
+ * A list item.
+
+ With multiple paragraphs.
+
+ * Another item in the list.
+
+Output:
+
+ &lt;ul&gt;
+ &lt;li&gt;&lt;p&gt;A list item.&lt;/p&gt;
+ &lt;p&gt;With multiple paragraphs.&lt;/p&gt;&lt;/li&gt;
+ &lt;li&gt;&lt;p&gt;Another item in the list.&lt;/p&gt;&lt;/li&gt;
+ &lt;/ul&gt;
+
+
+
+### Links ###
+
+Markdown supports two styles for creating links: *inline* and
+*reference*. With both styles, you use square brackets to delimit the
+text you want to turn into a link.
+
+Inline-style links use parentheses immediately after the link text.
+For example:
+
+ This is an [example link](http://example.com/).
+
+Output:
+
+ &lt;p&gt;This is an &lt;a href="http://example.com/"&gt;
+ example link&lt;/a&gt;.&lt;/p&gt;
+
+Optionally, you may include a title attribute in the parentheses:
+
+ This is an [example link](http://example.com/ "With a Title").
+
+Output:
+
+ &lt;p&gt;This is an &lt;a href="http://example.com/" title="With a Title"&gt;
+ example link&lt;/a&gt;.&lt;/p&gt;
+
+Reference-style links allow you to refer to your links by names, which
+you define elsewhere in your document:
+
+ I get 10 times more traffic from [Google][1] than from
+ [Yahoo][2] or [MSN][3].
+
+ [1]: http://google.com/ "Google"
+ [2]: http://search.yahoo.com/ "Yahoo Search"
+ [3]: http://search.msn.com/ "MSN Search"
+
+Output:
+
+ &lt;p&gt;I get 10 times more traffic from &lt;a href="http://google.com/"
+ title="Google"&gt;Google&lt;/a&gt; than from &lt;a href="http://search.yahoo.com/"
+ title="Yahoo Search"&gt;Yahoo&lt;/a&gt; or &lt;a href="http://search.msn.com/"
+ title="MSN Search"&gt;MSN&lt;/a&gt;.&lt;/p&gt;
+
+The title attribute is optional. Link names may contain letters,
+numbers and spaces, but are *not* case sensitive:
+
+ I start my morning with a cup of coffee and
+ [The New York Times][NY Times].
+
+ [ny times]: http://www.nytimes.com/
+
+Output:
+
+ &lt;p&gt;I start my morning with a cup of coffee and
+ &lt;a href="http://www.nytimes.com/"&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;
+
+
+### Images ###
+
+Image syntax is very much like link syntax.
+
+Inline (titles are optional):
+
+ ![alt text](/path/to/img.jpg "Title")
+
+Reference-style:
+
+ ![alt text][id]
+
+ [id]: /path/to/img.jpg "Title"
+
+Both of the above examples produce the same output:
+
+ &lt;img src="/path/to/img.jpg" alt="alt text" title="Title" /&gt;
+
+
+
+### Code ###
+
+In a regular paragraph, you can create code span by wrapping text in
+backtick quotes. Any ampersands (`&amp;`) and angle brackets (`&lt;` or
+`&gt;`) will automatically be translated into HTML entities. This makes
+it easy to use Markdown to write about HTML example code:
+
+ I strongly recommend against using any `&lt;blink&gt;` tags.
+
+ I wish SmartyPants used named entities like `&amp;mdash;`
+ instead of decimal-encoded entites like `&amp;#8212;`.
+
+Output:
+
+ &lt;p&gt;I strongly recommend against using any
+ &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;
+
+ &lt;p&gt;I wish SmartyPants used named entities like
+ &lt;code&gt;&amp;amp;mdash;&lt;/code&gt; instead of decimal-encoded
+ entites like &lt;code&gt;&amp;amp;#8212;&lt;/code&gt;.&lt;/p&gt;
+
+
+To specify an entire block of pre-formatted code, indent every line of
+the block by 4 spaces or 1 tab. Just like with code spans, `&amp;`, `&lt;`,
+and `&gt;` characters will be escaped automatically.
+
+Markdown:
+
+ If you want your page to validate under XHTML 1.0 Strict,
+ you've got to put paragraph tags in your blockquotes:
+
+ &lt;blockquote&gt;
+ &lt;p&gt;For example.&lt;/p&gt;
+ &lt;/blockquote&gt;
+
+Output:
+
+ &lt;p&gt;If you want your page to validate under XHTML 1.0 Strict,
+ you've got to put paragraph tags in your blockquotes:&lt;/p&gt;
+
+ &lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;
+ &amp;lt;p&amp;gt;For example.&amp;lt;/p&amp;gt;
+ &amp;lt;/blockquote&amp;gt;
+ &lt;/code&gt;&lt;/pre&gt;
+</textarea></form>
+
+ <script>
+ var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
+ mode: 'markdown',
+ lineNumbers: true,
+ matchBrackets: true,
+ theme: "default"
+ });
+ </script>
+
+ <p><strong>MIME types defined:</strong> <code>text/x-markdown</code>.</p>
+
+ </body>
+</html>
10 IPython/frontend/html/notebook/static/codemirror/mode/markdown/markdown.css
View
@@ -0,0 +1,10 @@
+.cm-s-default span.cm-header {color: #2f2f4f; font-weight:bold;}
+.cm-s-default span.cm-code {color: #666;}
+.cm-s-default span.cm-quote {color: #090;}
+.cm-s-default span.cm-list {color: #a50;}
+.cm-s-default span.cm-hr {color: #999;}
+.cm-s-default span.cm-linktext {color: #00c; text-decoration: underline;}
+.cm-s-default span.cm-linkhref {color: #00c;}
+.cm-s-default span.cm-em {font-style: italic;}
+.cm-s-default span.cm-strong {font-weight: bold;}
+.cm-s-default span.cm-emstrong {font-style: italic; font-weight: bold;}
230 IPython/frontend/html/notebook/static/codemirror/mode/markdown/markdown.js
View
@@ -0,0 +1,230 @@
+CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
+
+ var htmlMode = CodeMirror.getMode(cmCfg, { name: 'xml', htmlMode: true });
+
+ var header = 'header'
+ , code = 'code'
+ , quote = 'quote'
+ , list = 'list'
+ , hr = 'hr'
+ , linktext = 'linktext'
+ , linkhref = 'linkhref'
+ , em = 'em'
+ , strong = 'strong'
+ , emstrong = 'emstrong';
+
+ var hrRE = /^[*-=_]/
+ , ulRE = /^[*-+]\s+/
+ , olRE = /^[0-9]\.\s+/
+ , headerRE = /^(?:\={3,}|-{3,})$/
+ , codeRE = /^(k:\t|\s{4,})/
+ , textRE = /^[^\[*_\\<>`]+/;
+
+ function switchInline(stream, state, f) {
+ state.f = state.inline = f;
+ return f(stream, state);
+ }
+
+ function switchBlock(stream, state, f) {
+ state.f = state.block = f;
+ return f(stream, state);
+ }
+
+
+ // Blocks
+
+ function blockNormal(stream, state) {
+ if (stream.match(codeRE)) {
+ stream.skipToEnd();
+ return code;
+ }
+
+ if (stream.eatSpace()) {
+ return null;
+ }
+
+ if (stream.peek() === '#' || stream.match(headerRE)) {
+ stream.skipToEnd();
+ return header;
+ }
+ if (stream.eat('>')) {
+ state.indentation++;
+ return quote;
+ }
+ if (stream.peek() === '<') {
+ return switchBlock(stream, state, htmlBlock);
+ }
+ if (stream.peek() === '[') {
+ return switchInline(stream, state, footnoteLink);
+ }
+ if (hrRE.test(stream.peek())) {
+ var re = new RegExp('(?:\s*['+stream.peek()+']){3,}$');
+ if (stream.match(re, true)) {
+ return hr;
+ }
+ }
+
+ var match;
+ if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {
+ state.indentation += match[0].length;
+ return list;
+ }
+
+ return switchInline(stream, state, state.inline);
+ }
+
+ function htmlBlock(stream, state) {
+ var type = htmlMode.token(stream, state.htmlState);
+ if (stream.eol() && !state.htmlState.context) {
+ state.block = blockNormal;
+ }
+ return type;
+ }
+
+
+ // Inline
+
+ function inlineNormal(stream, state) {
+ function getType() {
+ return state.strong ? (state.em ? emstrong : strong)
+ : (state.em ? em : null);
+ }
+
+ if (stream.match(textRE, true)) {
+ return getType();
+ }
+
+ var ch = stream.next();
+
+ if (ch === '\\') {
+ stream.next();
+ return getType();
+ }
+ if (ch === '`') {
+ return switchInline(stream, state, inlineElement(code, '`'));
+ }
+ if (ch === '<') {
+ return switchInline(stream, state, inlineElement(linktext, '>'));
+ }
+ if (ch === '[') {
+ return switchInline(stream, state, linkText);
+ }
+
+ var t = getType();
+ if (ch === '*' || ch === '_') {
+ if (stream.eat(ch)) {
+ return (state.strong = !state.strong) ? getType() : t;
+ }
+ return (state.em = !state.em) ? getType() : t;
+ }
+
+ return getType();
+ }
+
+ function linkText(stream, state) {
+ while (!stream.eol()) {
+ var ch = stream.next();
+ if (ch === '\\') stream.next();
+ if (ch === ']') {
+ state.inline = state.f = linkHref;
+ return linktext;
+ }
+ }
+ return linktext;
+ }
+
+ function linkHref(stream, state) {
+ stream.eatSpace();
+ var ch = stream.next();
+ if (ch === '(' || ch === '[') {
+ return switchInline(stream, state, inlineElement(linkhref, ch === '(' ? ')' : ']'));
+ }
+ return 'error';
+ }
+
+ function footnoteLink(stream, state) {
+ if (stream.match(/^[^\]]*\]:/, true)) {
+ state.f = footnoteUrl;
+ return linktext;
+ }
+ return switchInline(stream, state, inlineNormal);
+ }
+
+ function footnoteUrl(stream, state) {
+ stream.eatSpace();
+ stream.match(/^[^\s]+/, true);
+ state.f = state.inline = inlineNormal;
+ return linkhref;
+ }
+
+ function inlineElement(type, endChar, next) {
+ next = next || inlineNormal;
+ return function(stream, state) {
+ while (!stream.eol()) {
+ var ch = stream.next();
+ if (ch === '\\') stream.next();
+ if (ch === endChar) {
+ state.inline = state.f = next;
+ return type;
+ }
+ }
+ return type;
+ };
+ }
+
+ return {
+ startState: function() {
+ return {
+ f: blockNormal,
+
+ block: blockNormal,
+ htmlState: htmlMode.startState(),
+ indentation: 0,
+
+ inline: inlineNormal,
+ em: false,
+ strong: false
+ };
+ },
+
+ copyState: function(s) {
+ return {
+ f: s.f,
+
+ block: s.block,
+ htmlState: CodeMirror.copyState(htmlMode, s.htmlState),
+ indentation: s.indentation,
+
+ inline: s.inline,
+ em: s.em,
+ strong: s.strong
+ };
+ },
+
+ token: function(stream, state) {
+ if (stream.sol()) {
+ state.f = state.block;
+ var previousIndentation = state.indentation
+ , currentIndentation = 0;
+ while (previousIndentation > 0) {
+ if (stream.eat(' ')) {
+ previousIndentation--;
+ currentIndentation++;
+ } else if (previousIndentation >= 4 && stream.eat('\t')) {
+ previousIndentation -= 4;
+ currentIndentation += 4;
+ } else {
+ break;
+ }
+ }
+ state.indentation = currentIndentation;
+
+ if (currentIndentation > 0) return null;
+ }
+ return state.f(stream, state);
+ }
+ };
+
+});
+
+CodeMirror.defineMIME("text/x-markdown", "markdown");
0  ...ok/static/codemirror-2.12/mode/python/LICENSE.txt → ...otebook/static/codemirror/mode/python/LICENSE.txt
View
File renamed without changes
2  ...ook/static/codemirror-2.12/mode/python/index.html → ...notebook/static/codemirror/mode/python/index.html
View
@@ -11,7 +11,7 @@
</head>
<body>
<h1>CodeMirror 2: Python mode</h1>
-
+
<div><textarea id="code" name="code">
# Literals
1234
67 ...book/static/codemirror-2.12/mode/python/python.js → .../notebook/static/codemirror/mode/python/python.js
View
@@ -1,11 +1,15 @@
-CodeMirror.defineMode("python", function(conf) {
+CodeMirror.defineMode("python", function(conf, parserConf) {
var ERRORCLASS = 'error';
-
+
function wordRegexp(words) {
return new RegExp("^((" + words.join(")|(") + "))\\b");
}
-
+
+ // IPython-specific changes: add '?' as recognized character.
+ //var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\\?]");
+ // End IPython changes.
+
var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
var doubleOperators = new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
@@ -29,7 +33,7 @@ CodeMirror.defineMode("python", function(conf) {
'open', 'range', 'zip'],
'keywords': ['nonlocal']};
- if (!!conf.mode.version && parseInt(conf.mode.version, 10) === 3) {
+ if (!!parserConf.version && parseInt(parserConf.version, 10) === 3) {
commonkeywords = commonkeywords.concat(py3.keywords);
commontypes = commontypes.concat(py3.types);
var stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i");
@@ -65,15 +69,15 @@ CodeMirror.defineMode("python", function(conf) {
if (stream.eatSpace()) {
return null;
}
-
+
var ch = stream.peek();
-
+
// Handle Comments
if (ch === '#') {
stream.skipToEnd();
return 'comment';
}
-
+
// Handle Number Literals
if (stream.match(/^[0-9\.]/, false)) {
var floatLiteral = false;
@@ -109,13 +113,13 @@ CodeMirror.defineMode("python", function(conf) {
return 'number';
}
}
-
+
// Handle Strings
if (stream.match(stringPrefixes)) {
state.tokenize = tokenStringFactory(stream.current());
return state.tokenize(stream, state);
}
-
+
// Handle operators and Delimiters
if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
return null;
@@ -128,32 +132,31 @@ CodeMirror.defineMode("python", function(conf) {
if (stream.match(singleDelimiters)) {
return null;
}
-
+
if (stream.match(types)) {
return 'builtin';
}
-
+
if (stream.match(keywords)) {
return 'keyword';
}
-
+
if (stream.match(identifiers)) {
return 'variable';
}
-
+
// Handle non-detected items
stream.next();
return ERRORCLASS;
}
-
+
function tokenStringFactory(delimiter) {
- while ('rub'.indexOf(delimiter[0].toLowerCase()) >= 0) {
+ while ('rub'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) {
delimiter = delimiter.substr(1);
}
- var delim_re = new RegExp(delimiter);
var singleline = delimiter.length == 1;
var OUTCLASS = 'string';
-
+
return function tokenString(stream, state) {
while (!stream.eol()) {
stream.eatWhile(/[^'"\\]/);
@@ -162,7 +165,7 @@ CodeMirror.defineMode("python", function(conf) {
if (singleline && stream.eol()) {
return OUTCLASS;
}
- } else if (stream.match(delim_re)) {
+ } else if (stream.match(delimiter)) {
state.tokenize = tokenBase;
return OUTCLASS;
} else {
@@ -170,8 +173,8 @@ CodeMirror.defineMode("python", function(conf) {
}
}
if (singleline) {
- if (conf.mode.singleLineStringErrors) {
- OUTCLASS = ERRORCLASS
+ if (parserConf.singleLineStringErrors) {
+ return ERRORCLASS;
} else {
state.tokenize = tokenBase;
}
@@ -179,7 +182,7 @@ CodeMirror.defineMode("python", function(conf) {
return OUTCLASS;
};
}
-
+
function indent(stream, state, type) {
type = type || 'py';
var indentUnit = 0;
@@ -198,7 +201,7 @@ CodeMirror.defineMode("python", function(conf) {
type: type
});
}
-
+
function dedent(stream, state) {
if (state.scopes.length == 1) return;
if (state.scopes[0].type === 'py') {
@@ -238,7 +241,7 @@ CodeMirror.defineMode("python", function(conf) {
return ERRORCLASS;
}
}
-
+
// Handle decorators
if (current === '@') {
style = state.tokenize(stream, state);
@@ -251,7 +254,7 @@ CodeMirror.defineMode("python", function(conf) {
return ERRORCLASS;
}
}
-
+
// Handle scope changes.
if (current === 'pass' || current === 'return') {
state.dedent += 1;
@@ -279,7 +282,7 @@ CodeMirror.defineMode("python", function(conf) {
if (state.scopes.length > 1) state.scopes.shift();
state.dedent -= 1;
}
-
+
return style;
}
@@ -293,27 +296,27 @@ CodeMirror.defineMode("python", function(conf) {
dedent: 0
};
},
-
+
token: function(stream, state) {
var style = tokenLexer(stream, state);
-
+
state.lastToken = {style:style, content: stream.current()};
-
+
if (stream.eol() && stream.lambda) {
state.lambda = false;
}
-
+
return style;
},
-
+
indent: function(state, textAfter) {
if (state.tokenize != tokenBase) {
return 0;
}
-
+
return state.scopes[0].offset;
}
-
+
};
return external;
});
1  ...tebook/static/codemirror-2.12/mode/rst/index.html → ...ml/notebook/static/codemirror/mode/rst/index.html
View
@@ -523,4 +523,3 @@
<p><strong>MIME types defined:</strong> <code>text/x-rst</code>.</p>
</body>
</html>
-
0  .../notebook/static/codemirror-2.12/mode/rst/rst.css → .../html/notebook/static/codemirror/mode/rst/rst.css
View
File renamed without changes
0  ...l/notebook/static/codemirror-2.12/mode/rst/rst.js → ...d/html/notebook/static/codemirror/mode/rst/rst.js
View
File renamed without changes
0  ...tebook/static/codemirror-2.12/mode/xml/index.html → ...ml/notebook/static/codemirror/mode/xml/index.html
View
File renamed without changes
8 ...l/notebook/static/codemirror-2.12/mode/xml/xml.js → ...d/html/notebook/static/codemirror/mode/xml/xml.js
View
@@ -132,7 +132,6 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
var err = false;
if (curState.context) {
err = curState.context.tagName != tagName;
- popContext();
} else {
err = true;
}
@@ -158,8 +157,9 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
function endclosetag(err) {
return function(type) {
if (err) setStyle = "error";
- if (type == "endTag") return cont();
- return pass();
+ if (type == "endTag") { popContext(); return cont(); }
+ setStyle = "error";
+ return cont(arguments.callee);
}
}
@@ -216,7 +216,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
},
compareStates: function(a, b) {
- if (a.indented != b.indented || a.tagName != b.tagName) return false;
+ if (a.indented != b.indented) return false;
for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {
if (!ca || !cb) return ca == cb;
if (ca.tagName != cb.tagName) return false;
1  ...notebook/static/codemirror-2.12/theme/default.css → ...html/notebook/static/codemirror/theme/default.css
View
@@ -9,6 +9,7 @@
.cm-s-default span.cm-operator {color: black;}
.cm-s-default span.cm-comment {color: #a50;}
.cm-s-default span.cm-string {color: #a11;}
+.cm-s-default span.cm-string-2 {color: #f50;}
.cm-s-default span.cm-meta {color: #555;}
.cm-s-default span.cm-error {color: #f00;}
.cm-s-default span.cm-qualifier {color: #555;}
0  ...notebook/static/codemirror-2.12/theme/elegant.css → ...html/notebook/static/codemirror/theme/elegant.css
View
File renamed without changes
1  ...notebook/static/codemirror-2.12/theme/ipython.css → ...html/notebook/static/codemirror/theme/ipython.css
View
@@ -38,4 +38,3 @@
/*span.py-bytes {color: #BA2121;}*/
/*span.py-raw {color: #BA2121;}*/
/*span.py-unicode {color: #BA2121;}*/
-
0  ...ml/notebook/static/codemirror-2.12/theme/neat.css → ...nd/html/notebook/static/codemirror/theme/neat.css
View
File renamed without changes
0  ...l/notebook/static/codemirror-2.12/theme/night.css → ...d/html/notebook/static/codemirror/theme/night.css
View
File renamed without changes
24 IPython/frontend/html/notebook/templates/notebook.html
View
@@ -21,10 +21,11 @@
}
</script>
- <link rel="stylesheet" href="static/codemirror-2.12/lib/codemirror.css">
- <link rel="stylesheet" href="static/codemirror-2.12/mode/rst/rst.css">
- <link rel="stylesheet" href="static/codemirror-2.12/theme/ipython.css">
- <link rel="stylesheet" href="static/codemirror-2.12/theme/default.css">
+ <link rel="stylesheet" href="static/codemirror/lib/codemirror.css">
+ <link rel="stylesheet" href="static/codemirror/mode/markdown/markdown.css">
+ <link rel="stylesheet" href="static/codemirror/mode/rst/rst.css">
+ <link rel="stylesheet" href="static/codemirror/theme/ipython.css">
+ <link rel="stylesheet" href="static/codemirror/theme/default.css">
<link rel="stylesheet" href="static/prettify/prettify.css"/>
@@ -208,13 +209,14 @@ <h3 class="section_header">Help</h3>
<script src="static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script>
<script src="static/jquery/js/jquery.autogrow.js" type="text/javascript" charset="utf-8"></script>
-<script src="static/codemirror-2.12/lib/codemirror.js" charset="utf-8"></script>
-<script src="static/codemirror-2.12/mode/python/python.js" charset="utf-8"></script>
-<script src="static/codemirror-2.12/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script>
-<script src="static/codemirror-2.12/mode/xml/xml.js" charset="utf-8"></script>
-<script src="static/codemirror-2.12/mode/javascript/javascript.js" charset="utf-8"></script>
-<script src="static/codemirror-2.12/mode/css/css.js" charset="utf-8"></script>
-<script src="static/codemirror-2.12/mode/rst/rst.js" charset="utf-8"></script>
+<script src="static/codemirror/lib/codemirror.js" charset="utf-8"></script>
+<script src="static/codemirror/mode/python/python.js" charset="utf-8"></script>
+<script src="static/codemirror/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script>
+<script src="static/codemirror/mode/xml/xml.js" charset="utf-8"></script>
+<script src="static/codemirror/mode/javascript/javascript.js" charset="utf-8"></script>
+<script src="static/codemirror/mode/css/css.js" charset="utf-8"></script>
+<script src="static/codemirror/mode/rst/rst.js" charset="utf-8"></script>
+<script src="static/codemirror/mode/markdown/markdown.js" charset="utf-8"></script>
<script src="static/pagedown/Markdown.Converter.js" charset="utf-8"></script>
Something went wrong with that request. Please try again.