123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- // CodeMirror, copyright (c) by Marijn Haverbeke and others
- // Distributed under an MIT license: https://codemirror.net/LICENSE
- ;(function (mod) {
- if (typeof exports == 'object' && typeof module == 'object')
- // CommonJS
- mod(require('../../lib/codemirror'))
- else if (typeof define == 'function' && define.amd)
- // AMD
- define(['../../lib/codemirror'], mod)
- // Plain browser env
- else mod(CodeMirror)
- })(function (CodeMirror) {
- 'use strict'
- CodeMirror.defineSimpleMode = function (name, states) {
- CodeMirror.defineMode(name, function (config) {
- return CodeMirror.simpleMode(config, states)
- })
- }
- CodeMirror.simpleMode = function (config, states) {
- ensureState(states, 'start')
- var states_ = {},
- meta = states.meta || {},
- hasIndentation = false
- for (var state in states)
- if (state != meta && states.hasOwnProperty(state)) {
- var list = (states_[state] = []),
- orig = states[state]
- for (var i = 0; i < orig.length; i++) {
- var data = orig[i]
- list.push(new Rule(data, states))
- if (data.indent || data.dedent) hasIndentation = true
- }
- }
- var mode = {
- startState: function () {
- return { state: 'start', pending: null, local: null, localState: null, indent: hasIndentation ? [] : null }
- },
- copyState: function (state) {
- var s = { state: state.state, pending: state.pending, local: state.local, localState: null, indent: state.indent && state.indent.slice(0) }
- if (state.localState) s.localState = CodeMirror.copyState(state.local.mode, state.localState)
- if (state.stack) s.stack = state.stack.slice(0)
- for (var pers = state.persistentStates; pers; pers = pers.next)
- s.persistentStates = {
- mode: pers.mode,
- spec: pers.spec,
- state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state),
- next: s.persistentStates,
- }
- return s
- },
- token: tokenFunction(states_, config),
- innerMode: function (state) {
- return state.local && { mode: state.local.mode, state: state.localState }
- },
- indent: indentFunction(states_, meta),
- }
- if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop)) mode[prop] = meta[prop]
- return mode
- }
- function ensureState(states, name) {
- if (!states.hasOwnProperty(name)) throw new Error('Undefined state ' + name + ' in simple mode')
- }
- function toRegex(val, caret) {
- if (!val) return /(?:)/
- var flags = ''
- if (val instanceof RegExp) {
- if (val.ignoreCase) flags = 'i'
- if (val.unicode) flags += 'u'
- val = val.source
- } else {
- val = String(val)
- }
- return new RegExp((caret === false ? '' : '^') + '(?:' + val + ')', flags)
- }
- function asToken(val) {
- if (!val) return null
- if (val.apply) return val
- if (typeof val == 'string') return val.replace(/\./g, ' ')
- var result = []
- for (var i = 0; i < val.length; i++) result.push(val[i] && val[i].replace(/\./g, ' '))
- return result
- }
- function Rule(data, states) {
- if (data.next || data.push) ensureState(states, data.next || data.push)
- this.regex = toRegex(data.regex)
- this.token = asToken(data.token)
- this.data = data
- }
- function tokenFunction(states, config) {
- return function (stream, state) {
- if (state.pending) {
- var pend = state.pending.shift()
- if (state.pending.length == 0) state.pending = null
- stream.pos += pend.text.length
- return pend.token
- }
- if (state.local) {
- if (state.local.end && stream.match(state.local.end)) {
- var tok = state.local.endToken || null
- state.local = state.localState = null
- return tok
- } else {
- var tok = state.local.mode.token(stream, state.localState),
- m
- if (state.local.endScan && (m = state.local.endScan.exec(stream.current()))) stream.pos = stream.start + m.index
- return tok
- }
- }
- var curState = states[state.state]
- for (var i = 0; i < curState.length; i++) {
- var rule = curState[i]
- var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex)
- if (matches) {
- if (rule.data.next) {
- state.state = rule.data.next
- } else if (rule.data.push) {
- ;(state.stack || (state.stack = [])).push(state.state)
- state.state = rule.data.push
- } else if (rule.data.pop && state.stack && state.stack.length) {
- state.state = state.stack.pop()
- }
- if (rule.data.mode) enterLocalMode(config, state, rule.data.mode, rule.token)
- if (rule.data.indent) state.indent.push(stream.indentation() + config.indentUnit)
- if (rule.data.dedent) state.indent.pop()
- var token = rule.token
- if (token && token.apply) token = token(matches)
- if (matches.length > 2 && rule.token && typeof rule.token != 'string') {
- for (var j = 2; j < matches.length; j++) if (matches[j]) (state.pending || (state.pending = [])).push({ text: matches[j], token: rule.token[j - 1] })
- stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0))
- return token[0]
- } else if (token && token.join) {
- return token[0]
- } else {
- return token
- }
- }
- }
- stream.next()
- return null
- }
- }
- function cmp(a, b) {
- if (a === b) return true
- if (!a || typeof a != 'object' || !b || typeof b != 'object') return false
- var props = 0
- for (var prop in a)
- if (a.hasOwnProperty(prop)) {
- if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false
- props++
- }
- for (var prop in b) if (b.hasOwnProperty(prop)) props--
- return props == 0
- }
- function enterLocalMode(config, state, spec, token) {
- var pers
- if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next) if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p
- var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec)
- var lState = pers ? pers.state : CodeMirror.startState(mode)
- if (spec.persistent && !pers) state.persistentStates = { mode: mode, spec: spec.spec, state: lState, next: state.persistentStates }
- state.localState = lState
- state.local = {
- mode: mode,
- end: spec.end && toRegex(spec.end),
- endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false),
- endToken: token && token.join ? token[token.length - 1] : token,
- }
- }
- function indexOf(val, arr) {
- for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true
- }
- function indentFunction(states, meta) {
- return function (state, textAfter, line) {
- if (state.local && state.local.mode.indent) return state.local.mode.indent(state.localState, textAfter, line)
- if (state.indent == null || state.local || (meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1)) return CodeMirror.Pass
- var pos = state.indent.length - 1,
- rules = states[state.state]
- scan: for (;;) {
- for (var i = 0; i < rules.length; i++) {
- var rule = rules[i]
- if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {
- var m = rule.regex.exec(textAfter)
- if (m && m[0]) {
- pos--
- if (rule.next || rule.push) rules = states[rule.next || rule.push]
- textAfter = textAfter.slice(m[0].length)
- continue scan
- }
- }
- }
- break
- }
- return pos < 0 ? 0 : state.indent[pos]
- }
- }
- })
|