docs: function skipAtomic(doc, pos, bias, mayClear) {
      var flipped = false, curPos = pos;
      var dir = bias || 1;
      doc.cantEdit = false;
      search: for (;;) {
        var line = getLine(doc, curPos.line);
        if (line.markedSpans) {
          for (var i = 0; i < line.markedSpans.length; ++i) {
            var sp = line.markedSpans[i], m = sp.marker;
            if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
                (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
              if (mayClear) {
                signal(m, "beforeCursorEnter");
                if (m.explicitlyCleared) {
                  if (!line.markedSpans) break;
                  else {--i; continue;}
                }
              }
              if (!m.atomic) continue;
              var newPos = m.find(dir < 0 ? -1 : 1);
              if (cmp(newPos, curPos) == 0) {
                newPos.ch += dir;
                if (newPos.ch < 0) {
                  if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
                  else newPos = null;
                } else if (newPos.ch > line.text.length) {
                  if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
                  else newPos = null;
                }
                if (!newPos) {
                  if (flipped) {
                    // Driven in a corner -- no valid cursor position found at all
                    // -- try again *with* clearing, if we didn't already
                    if (!mayClear) return skipAtomic(doc, pos, bias, true);
                    // Otherwise, turn off editing until further notice, and return the start of the doc
                    doc.cantEdit = true;
                    return Pos(doc.first, 0);
                  }
                  flipped = true; newPos = pos; dir = -dir;
                }
              }
              curPos = newPos;
              continue search;
            }
          }
        }
        return curPos;
      }
    }