123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- // 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.defineMode('puppet', function () {
- // Stores the words from the define method
- var words = {}
- // Taken, mostly, from the Puppet official variable standards regex
- var variable_regex = /({)?([a-z][a-z0-9_]*)?((::[a-z][a-z0-9_]*)*::)?[a-zA-Z0-9_]+(})?/
- // Takes a string of words separated by spaces and adds them as
- // keys with the value of the first argument 'style'
- function define(style, string) {
- var split = string.split(' ')
- for (var i = 0; i < split.length; i++) {
- words[split[i]] = style
- }
- }
- // Takes commonly known puppet types/words and classifies them to a style
- define('keyword', 'class define site node include import inherits')
- define('keyword', 'case if else in and elsif default or')
- define('atom', 'false true running present absent file directory undef')
- define(
- 'builtin',
- 'action augeas burst chain computer cron destination dport exec ' +
- 'file filebucket group host icmp iniface interface jump k5login limit log_level ' +
- 'log_prefix macauthorization mailalias maillist mcx mount nagios_command ' +
- 'nagios_contact nagios_contactgroup nagios_host nagios_hostdependency ' +
- 'nagios_hostescalation nagios_hostextinfo nagios_hostgroup nagios_service ' +
- 'nagios_servicedependency nagios_serviceescalation nagios_serviceextinfo ' +
- 'nagios_servicegroup nagios_timeperiod name notify outiface package proto reject ' +
- 'resources router schedule scheduled_task selboolean selmodule service source ' +
- 'sport ssh_authorized_key sshkey stage state table tidy todest toports tosource ' +
- 'user vlan yumrepo zfs zone zpool'
- )
- // After finding a start of a string ('|") this function attempts to find the end;
- // If a variable is encountered along the way, we display it differently when it
- // is encapsulated in a double-quoted string.
- function tokenString(stream, state) {
- var current,
- prev,
- found_var = false
- while (!stream.eol() && (current = stream.next()) != state.pending) {
- if (current === '$' && prev != '\\' && state.pending == '"') {
- found_var = true
- break
- }
- prev = current
- }
- if (found_var) {
- stream.backUp(1)
- }
- if (current == state.pending) {
- state.continueString = false
- } else {
- state.continueString = true
- }
- return 'string'
- }
- // Main function
- function tokenize(stream, state) {
- // Matches one whole word
- var word = stream.match(/[\w]+/, false)
- // Matches attributes (i.e. ensure => present ; 'ensure' would be matched)
- var attribute = stream.match(/(\s+)?\w+\s+=>.*/, false)
- // Matches non-builtin resource declarations
- // (i.e. "apache::vhost {" or "mycustomclasss {" would be matched)
- var resource = stream.match(/(\s+)?[\w:_]+(\s+)?{/, false)
- // Matches virtual and exported resources (i.e. @@user { ; and the like)
- var special_resource = stream.match(/(\s+)?[@]{1,2}[\w:_]+(\s+)?{/, false)
- // Finally advance the stream
- var ch = stream.next()
- // Have we found a variable?
- if (ch === '$') {
- if (stream.match(variable_regex)) {
- // If so, and its in a string, assign it a different color
- return state.continueString ? 'variable-2' : 'variable'
- }
- // Otherwise return an invalid variable
- return 'error'
- }
- // Should we still be looking for the end of a string?
- if (state.continueString) {
- // If so, go through the loop again
- stream.backUp(1)
- return tokenString(stream, state)
- }
- // Are we in a definition (class, node, define)?
- if (state.inDefinition) {
- // If so, return def (i.e. for 'class myclass {' ; 'myclass' would be matched)
- if (stream.match(/(\s+)?[\w:_]+(\s+)?/)) {
- return 'def'
- }
- // Match the rest it the next time around
- stream.match(/\s+{/)
- state.inDefinition = false
- }
- // Are we in an 'include' statement?
- if (state.inInclude) {
- // Match and return the included class
- stream.match(/(\s+)?\S+(\s+)?/)
- state.inInclude = false
- return 'def'
- }
- // Do we just have a function on our hands?
- // In 'ensure_resource("myclass")', 'ensure_resource' is matched
- if (stream.match(/(\s+)?\w+\(/)) {
- stream.backUp(1)
- return 'def'
- }
- // Have we matched the prior attribute regex?
- if (attribute) {
- stream.match(/(\s+)?\w+/)
- return 'tag'
- }
- // Do we have Puppet specific words?
- if (word && words.hasOwnProperty(word)) {
- // Negates the initial next()
- stream.backUp(1)
- // rs move the stream
- stream.match(/[\w]+/)
- // We want to process these words differently
- // do to the importance they have in Puppet
- if (stream.match(/\s+\S+\s+{/, false)) {
- state.inDefinition = true
- }
- if (word == 'include') {
- state.inInclude = true
- }
- // Returns their value as state in the prior define methods
- return words[word]
- }
- // Is there a match on a reference?
- if (/(^|\s+)[A-Z][\w:_]+/.test(word)) {
- // Negate the next()
- stream.backUp(1)
- // Match the full reference
- stream.match(/(^|\s+)[A-Z][\w:_]+/)
- return 'def'
- }
- // Have we matched the prior resource regex?
- if (resource) {
- stream.match(/(\s+)?[\w:_]+/)
- return 'def'
- }
- // Have we matched the prior special_resource regex?
- if (special_resource) {
- stream.match(/(\s+)?[@]{1,2}/)
- return 'special'
- }
- // Match all the comments. All of them.
- if (ch == '#') {
- stream.skipToEnd()
- return 'comment'
- }
- // Have we found a string?
- if (ch == "'" || ch == '"') {
- // Store the type (single or double)
- state.pending = ch
- // Perform the looping function to find the end
- return tokenString(stream, state)
- }
- // Match all the brackets
- if (ch == '{' || ch == '}') {
- return 'bracket'
- }
- // Match characters that we are going to assume
- // are trying to be regex
- if (ch == '/') {
- stream.match(/^[^\/]*\//)
- return 'variable-3'
- }
- // Match all the numbers
- if (ch.match(/[0-9]/)) {
- stream.eatWhile(/[0-9]+/)
- return 'number'
- }
- // Match the '=' and '=>' operators
- if (ch == '=') {
- if (stream.peek() == '>') {
- stream.next()
- }
- return 'operator'
- }
- // Keep advancing through all the rest
- stream.eatWhile(/[\w-]/)
- // Return a blank line for everything else
- return null
- }
- // Start it all
- return {
- startState: function () {
- var state = {}
- state.inDefinition = false
- state.inInclude = false
- state.continueString = false
- state.pending = false
- return state
- },
- token: function (stream, state) {
- // Strip the spaces, but regex will account for them eitherway
- if (stream.eatSpace()) return null
- // Go through the main process
- return tokenize(stream, state)
- },
- }
- })
- CodeMirror.defineMIME('text/x-puppet', 'puppet')
- })
|