1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: http://codemirror.net/LICENSE
4 // Utility function that allows modes to be combined. The mode given
5 // as the base argument takes care of most of the normal mode
6 // functionality, but a second (typically simple) mode is used, which
7 // can override the style of text. Both modes get to parse all of the
8 // text, but when both assign a non-null style to a piece of code, the
9 // overlay wins, unless the combine argument was true and not overridden,
10 // or state.overlay.combineTokens was true, in which case the styles are
14 if (typeof exports
== "object" && typeof module
== "object") // CommonJS
15 mod(require("../../lib/codemirror"));
16 else if (typeof define
== "function" && define
.amd
) // AMD
17 define(["../../lib/codemirror"], mod
);
18 else // Plain browser env
20 })(function(CodeMirror
) {
23 CodeMirror
.overlayMode = function(base
, overlay
, combine
) {
25 startState: function() {
27 base
: CodeMirror
.startState(base
),
28 overlay
: CodeMirror
.startState(overlay
),
29 basePos
: 0, baseCur
: null,
30 overlayPos
: 0, overlayCur
: null,
34 copyState: function(state
) {
36 base
: CodeMirror
.copyState(base
, state
.base
),
37 overlay
: CodeMirror
.copyState(overlay
, state
.overlay
),
38 basePos
: state
.basePos
, baseCur
: null,
39 overlayPos
: state
.overlayPos
, overlayCur
: null
43 token: function(stream
, state
) {
44 if (stream
.sol() || stream
.string
!= state
.lineSeen
||
45 Math
.min(state
.basePos
, state
.overlayPos
) < stream
.start
) {
46 state
.lineSeen
= stream
.string
;
47 state
.basePos
= state
.overlayPos
= stream
.start
;
50 if (stream
.start
== state
.basePos
) {
51 state
.baseCur
= base
.token(stream
, state
.base
);
52 state
.basePos
= stream
.pos
;
54 if (stream
.start
== state
.overlayPos
) {
55 stream
.pos
= stream
.start
;
56 state
.overlayCur
= overlay
.token(stream
, state
.overlay
);
57 state
.overlayPos
= stream
.pos
;
59 stream
.pos
= Math
.min(state
.basePos
, state
.overlayPos
);
61 // state.overlay.combineTokens always takes precedence over combine,
63 if (state
.overlayCur
== null) return state
.baseCur
;
64 else if (state
.baseCur
!= null &&
65 state
.overlay
.combineTokens
||
66 combine
&& state
.overlay
.combineTokens
== null)
67 return state
.baseCur
+ " " + state
.overlayCur
;
68 else return state
.overlayCur
;
71 indent
: base
.indent
&& function(state
, textAfter
) {
72 return base
.indent(state
.base
, textAfter
);
74 electricChars
: base
.electricChars
,
76 innerMode: function(state
) { return {state
: state
.base
, mode
: base
}; },
78 blankLine: function(state
) {
79 if (base
.blankLine
) base
.blankLine(state
.base
);
80 if (overlay
.blankLine
) overlay
.blankLine(state
.overlay
);