codemirror/CodeMirror — pull request #2905 by heppe (2014-10-31 20:45:04+00:00)
Title: Workaround for an error in getting to insert mode. 

This was very difficult to reproduce (happened exactly once in all my usage), and I don't know what led to it, but the ">" mark was set but returned undefined when find() was called. The end result was that it was that when I did a 's' command to substitute a single character, it would throw a caught exception that would cause it to skip the point where it would otherwise have entered insert mode. This should work around the problem if it happens again.

The following is my analysis from the developer console at the point at which it started happening.

at the following stack trace:
clipPos (1146875727-code…formatted:2168)
createObj.setBookmark (1146875727-code…formatted:7332)
(anonymous function) (1146875727-code…formatted:7456)
operators.change (1146875727-code…ormatted:16551)
commandDispatcher.evalInput (1146875727-code…ormatted:16228)
commandDispatcher.processMotion (1146875727-code…ormatted:15906)
commandDispatcher.processCommand (1146875727-code…ormatted:15881)
vimApi.handleKey (1146875727-code…ormatted:15659)
vimApi.handleKey (1146875727-code…ormatted:15655)
(anonymous function) (1146875727-code…ormatted:18628)
doHandleBinding (1146875727-code…formatted:4097)
(anonymous function) (1146875727-code…formatted:4147)
lookup (1146875727-code…formatted:5728)
CodeMirror.lookupKey (1146875727-code…formatted:5745)
handleCharBinding (1146875727-code…formatted:4146)
onKeyPress (1146875727-code…formatted:4208)
(anonymous function) (1146875727-code…formatted:3157)

clipPos is trying to check
if (pos.line < doc.first)
but pos is undefined. That, in turn throws an error that is caught, but makes it skip the point where it would otherwise enter insert mode.

Tracking back up the stack, in operators.change, I can see that it is undefined because we have
var selectionEnd = vim.marks[">"] ? vim.marks[">"].find() : cm.getCursor("head");

vim.marks[">"] is
CodeMirror.TextMarker {lines: Array[0], type: "bookmark", doc: CodeMirror.Doc, replacedWith: undefined, insertLeft: undefined…}clearWhenEmpty: falsedoc: CodeMirror.DocinsertLeft: undefinedlines: Array[0]replacedWith: undefinedshared: undefinedtype: "bookmark"__proto__: CodeMirror.TextMarker

but vim.marks[">"].find() returns undefined. I can work around this problem with a bit of defensive programming:
var selectionEnd = vim.marks[">"] && vim.marks[">"].find();
if (!slectionEnd) {
selectionEnd = cm.getCursor("head");
}
But without knowing exactly how I got into the state of vim.marks[">"].find() returning undefined, I don't know how to write a test.