go.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. ;(function (mod) {
  4. if (typeof exports == 'object' && typeof module == 'object')
  5. // CommonJS
  6. mod(require('../../lib/codemirror'))
  7. else if (typeof define == 'function' && define.amd)
  8. // AMD
  9. define(['../../lib/codemirror'], mod)
  10. // Plain browser env
  11. else mod(CodeMirror)
  12. })(function (CodeMirror) {
  13. 'use strict'
  14. CodeMirror.defineMode('go', function (config) {
  15. var indentUnit = config.indentUnit
  16. var keywords = {
  17. break: true,
  18. case: true,
  19. chan: true,
  20. const: true,
  21. continue: true,
  22. default: true,
  23. defer: true,
  24. else: true,
  25. fallthrough: true,
  26. for: true,
  27. func: true,
  28. go: true,
  29. goto: true,
  30. if: true,
  31. import: true,
  32. interface: true,
  33. map: true,
  34. package: true,
  35. range: true,
  36. return: true,
  37. select: true,
  38. struct: true,
  39. switch: true,
  40. type: true,
  41. var: true,
  42. bool: true,
  43. byte: true,
  44. complex64: true,
  45. complex128: true,
  46. float32: true,
  47. float64: true,
  48. int8: true,
  49. int16: true,
  50. int32: true,
  51. int64: true,
  52. string: true,
  53. uint8: true,
  54. uint16: true,
  55. uint32: true,
  56. uint64: true,
  57. int: true,
  58. uint: true,
  59. uintptr: true,
  60. error: true,
  61. rune: true,
  62. }
  63. var atoms = {
  64. true: true,
  65. false: true,
  66. iota: true,
  67. nil: true,
  68. append: true,
  69. cap: true,
  70. close: true,
  71. complex: true,
  72. copy: true,
  73. delete: true,
  74. imag: true,
  75. len: true,
  76. make: true,
  77. new: true,
  78. panic: true,
  79. print: true,
  80. println: true,
  81. real: true,
  82. recover: true,
  83. }
  84. var isOperatorChar = /[+\-*&^%:=<>!|\/]/
  85. var curPunc
  86. function tokenBase(stream, state) {
  87. var ch = stream.next()
  88. if (ch == '"' || ch == "'" || ch == '`') {
  89. state.tokenize = tokenString(ch)
  90. return state.tokenize(stream, state)
  91. }
  92. if (/[\d\.]/.test(ch)) {
  93. if (ch == '.') {
  94. stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/)
  95. } else if (ch == '0') {
  96. stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/)
  97. } else {
  98. stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/)
  99. }
  100. return 'number'
  101. }
  102. if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
  103. curPunc = ch
  104. return null
  105. }
  106. if (ch == '/') {
  107. if (stream.eat('*')) {
  108. state.tokenize = tokenComment
  109. return tokenComment(stream, state)
  110. }
  111. if (stream.eat('/')) {
  112. stream.skipToEnd()
  113. return 'comment'
  114. }
  115. }
  116. if (isOperatorChar.test(ch)) {
  117. stream.eatWhile(isOperatorChar)
  118. return 'operator'
  119. }
  120. stream.eatWhile(/[\w\$_\xa1-\uffff]/)
  121. var cur = stream.current()
  122. if (keywords.propertyIsEnumerable(cur)) {
  123. if (cur == 'case' || cur == 'default') curPunc = 'case'
  124. return 'keyword'
  125. }
  126. if (atoms.propertyIsEnumerable(cur)) return 'atom'
  127. return 'variable'
  128. }
  129. function tokenString(quote) {
  130. return function (stream, state) {
  131. var escaped = false,
  132. next,
  133. end = false
  134. while ((next = stream.next()) != null) {
  135. if (next == quote && !escaped) {
  136. end = true
  137. break
  138. }
  139. escaped = !escaped && quote != '`' && next == '\\'
  140. }
  141. if (end || !(escaped || quote == '`')) state.tokenize = tokenBase
  142. return 'string'
  143. }
  144. }
  145. function tokenComment(stream, state) {
  146. var maybeEnd = false,
  147. ch
  148. while ((ch = stream.next())) {
  149. if (ch == '/' && maybeEnd) {
  150. state.tokenize = tokenBase
  151. break
  152. }
  153. maybeEnd = ch == '*'
  154. }
  155. return 'comment'
  156. }
  157. function Context(indented, column, type, align, prev) {
  158. this.indented = indented
  159. this.column = column
  160. this.type = type
  161. this.align = align
  162. this.prev = prev
  163. }
  164. function pushContext(state, col, type) {
  165. return (state.context = new Context(state.indented, col, type, null, state.context))
  166. }
  167. function popContext(state) {
  168. if (!state.context.prev) return
  169. var t = state.context.type
  170. if (t == ')' || t == ']' || t == '}') state.indented = state.context.indented
  171. return (state.context = state.context.prev)
  172. }
  173. // Interface
  174. return {
  175. startState: function (basecolumn) {
  176. return {
  177. tokenize: null,
  178. context: new Context((basecolumn || 0) - indentUnit, 0, 'top', false),
  179. indented: 0,
  180. startOfLine: true,
  181. }
  182. },
  183. token: function (stream, state) {
  184. var ctx = state.context
  185. if (stream.sol()) {
  186. if (ctx.align == null) ctx.align = false
  187. state.indented = stream.indentation()
  188. state.startOfLine = true
  189. if (ctx.type == 'case') ctx.type = '}'
  190. }
  191. if (stream.eatSpace()) return null
  192. curPunc = null
  193. var style = (state.tokenize || tokenBase)(stream, state)
  194. if (style == 'comment') return style
  195. if (ctx.align == null) ctx.align = true
  196. if (curPunc == '{') pushContext(state, stream.column(), '}')
  197. else if (curPunc == '[') pushContext(state, stream.column(), ']')
  198. else if (curPunc == '(') pushContext(state, stream.column(), ')')
  199. else if (curPunc == 'case') ctx.type = 'case'
  200. else if (curPunc == '}' && ctx.type == '}') popContext(state)
  201. else if (curPunc == ctx.type) popContext(state)
  202. state.startOfLine = false
  203. return style
  204. },
  205. indent: function (state, textAfter) {
  206. if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass
  207. var ctx = state.context,
  208. firstChar = textAfter && textAfter.charAt(0)
  209. if (ctx.type == 'case' && /^(?:case|default)\b/.test(textAfter)) {
  210. state.context.type = '}'
  211. return ctx.indented
  212. }
  213. var closing = firstChar == ctx.type
  214. if (ctx.align) return ctx.column + (closing ? 0 : 1)
  215. else return ctx.indented + (closing ? 0 : indentUnit)
  216. },
  217. electricChars: '{}):',
  218. closeBrackets: '()[]{}\'\'""``',
  219. fold: 'brace',
  220. blockCommentStart: '/*',
  221. blockCommentEnd: '*/',
  222. lineComment: '//',
  223. }
  224. })
  225. CodeMirror.defineMIME('text/x-go', 'go')
  226. })