multiplex.js
81 lines
| 3.0 KiB
| application/javascript
|
JavascriptLexer
Matthias BUSSONNIER
|
r8053 | 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(state.outer, "")); | ||||
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); | ||||
}, | ||||
compareStates: function(a, b) { | ||||
if (a.innerActive != b.innerActive) return false; | ||||
var mode = a.innerActive || outer; | ||||
if (!mode.compareStates) return CodeMirror.Pass; | ||||
return mode.compareStates(a.innerActive ? a.inner : a.outer, | ||||
b.innerActive ? b.inner : b.outer); | ||||
}, | ||||
electricChars: outer.electricChars | ||||
}; | ||||
}; | ||||