Spaces:
Running
Running
CodeMirror.multiplexingMode = function(outer /*, others */) { | |
// Others should be {open, close, mode [, delimStyle]} objects | |
var others = Array.prototype.slice.call(arguments, 1); | |
var n_others = others.length; | |
function indexOf(string, pattern, from) { | |
if (typeof pattern == "string") return string.indexOf(pattern, from); | |
var m = pattern.exec(from ? string.slice(from) : string); | |
return m ? m.index + from : -1; | |
} | |
return { | |
startState: function() { | |
return { | |
outer: CodeMirror.startState(outer), | |
innerActive: null, | |
inner: null | |
}; | |
}, | |
copyState: function(state) { | |
return { | |
outer: CodeMirror.copyState(outer, state.outer), | |
innerActive: state.innerActive, | |
inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner) | |
}; | |
}, | |
token: function(stream, state) { | |
if (!state.innerActive) { | |
var cutOff = Infinity, oldContent = stream.string; | |
for (var i = 0; i < n_others; ++i) { | |
var other = others[i]; | |
var found = indexOf(oldContent, other.open, stream.pos); | |
if (found == stream.pos) { | |
stream.match(other.open); | |
state.innerActive = other; | |
state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0); | |
return other.delimStyle; | |
} else if (found != -1 && found < cutOff) { | |
cutOff = found; | |
} | |
} | |
if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff); | |
var outerToken = outer.token(stream, state.outer); | |
if (cutOff != Infinity) stream.string = oldContent; | |
return outerToken; | |
} else { | |
var curInner = state.innerActive, oldContent = stream.string; | |
var found = indexOf(oldContent, curInner.close, stream.pos); | |
if (found == stream.pos) { | |
stream.match(curInner.close); | |
state.innerActive = state.inner = null; | |
return curInner.delimStyle; | |
} | |
if (found > -1) stream.string = oldContent.slice(0, found); | |
var innerToken = curInner.mode.token(stream, state.inner); | |
if (found > -1) stream.string = oldContent; | |
var cur = stream.current(), found = cur.indexOf(curInner.close); | |
if (found > -1) stream.backUp(cur.length - found); | |
return innerToken; | |
} | |
}, | |
indent: function(state, textAfter) { | |
var mode = state.innerActive ? state.innerActive.mode : outer; | |
if (!mode.indent) return CodeMirror.Pass; | |
return mode.indent(state.innerActive ? state.inner : state.outer, textAfter); | |
}, | |
blankLine: function(state) { | |
var mode = state.innerActive ? state.innerActive.mode : outer; | |
if (mode.blankLine) { | |
mode.blankLine(state.innerActive ? state.inner : state.outer); | |
} | |
if (!state.innerActive) { | |
for (var i = 0; i < n_others; ++i) { | |
var other = others[i]; | |
if (other.open === "\n") { | |
state.innerActive = other; | |
state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "") : 0); | |
} | |
} | |
} else if (mode.close === "\n") { | |
state.innerActive = state.inner = null; | |
} | |
}, | |
electricChars: outer.electricChars, | |
innerMode: function(state) { | |
return state.inner ? {state: state.inner, mode: state.innerActive.mode} : {state: state.outer, mode: outer}; | |
} | |
}; | |
}; | |