all repos — NoPaste @ 3e3c433f026c49e04d0efa0f0f39fc688ed32bb1

Resurrected - The PussTheCat.org fork of NoPaste

scripts/CodeMirror/mode/puppet/puppet.js (view raw)

  1// CodeMirror, copyright (c) by Marijn Haverbeke and others
  2// Distributed under an MIT license: https://codemirror.net/LICENSE
  3
  4(function(mod) {
  5  if (typeof exports == "object" && typeof module == "object") // CommonJS
  6    mod(require("../../lib/codemirror"));
  7  else if (typeof define == "function" && define.amd) // AMD
  8    define(["../../lib/codemirror"], mod);
  9  else // Plain browser env
 10    mod(CodeMirror);
 11})(function(CodeMirror) {
 12"use strict";
 13
 14CodeMirror.defineMode("puppet", function () {
 15  // Stores the words from the define method
 16  var words = {};
 17  // Taken, mostly, from the Puppet official variable standards regex
 18  var variable_regex = /({)?([a-z][a-z0-9_]*)?((::[a-z][a-z0-9_]*)*::)?[a-zA-Z0-9_]+(})?/;
 19
 20  // Takes a string of words separated by spaces and adds them as
 21  // keys with the value of the first argument 'style'
 22  function define(style, string) {
 23    var split = string.split(' ');
 24    for (var i = 0; i < split.length; i++) {
 25      words[split[i]] = style;
 26    }
 27  }
 28
 29  // Takes commonly known puppet types/words and classifies them to a style
 30  define('keyword', 'class define site node include import inherits');
 31  define('keyword', 'case if else in and elsif default or');
 32  define('atom', 'false true running present absent file directory undef');
 33  define('builtin', 'action augeas burst chain computer cron destination dport exec ' +
 34    'file filebucket group host icmp iniface interface jump k5login limit log_level ' +
 35    'log_prefix macauthorization mailalias maillist mcx mount nagios_command ' +
 36    'nagios_contact nagios_contactgroup nagios_host nagios_hostdependency ' +
 37    'nagios_hostescalation nagios_hostextinfo nagios_hostgroup nagios_service ' +
 38    'nagios_servicedependency nagios_serviceescalation nagios_serviceextinfo ' +
 39    'nagios_servicegroup nagios_timeperiod name notify outiface package proto reject ' +
 40    'resources router schedule scheduled_task selboolean selmodule service source ' +
 41    'sport ssh_authorized_key sshkey stage state table tidy todest toports tosource ' +
 42    'user vlan yumrepo zfs zone zpool');
 43
 44  // After finding a start of a string ('|") this function attempts to find the end;
 45  // If a variable is encountered along the way, we display it differently when it
 46  // is encapsulated in a double-quoted string.
 47  function tokenString(stream, state) {
 48    var current, prev, found_var = false;
 49    while (!stream.eol() && (current = stream.next()) != state.pending) {
 50      if (current === '$' && prev != '\\' && state.pending == '"') {
 51        found_var = true;
 52        break;
 53      }
 54      prev = current;
 55    }
 56    if (found_var) {
 57      stream.backUp(1);
 58    }
 59    if (current == state.pending) {
 60      state.continueString = false;
 61    } else {
 62      state.continueString = true;
 63    }
 64    return "string";
 65  }
 66
 67  // Main function
 68  function tokenize(stream, state) {
 69    // Matches one whole word
 70    var word = stream.match(/[\w]+/, false);
 71    // Matches attributes (i.e. ensure => present ; 'ensure' would be matched)
 72    var attribute = stream.match(/(\s+)?\w+\s+=>.*/, false);
 73    // Matches non-builtin resource declarations
 74    // (i.e. "apache::vhost {" or "mycustomclasss {" would be matched)
 75    var resource = stream.match(/(\s+)?[\w:_]+(\s+)?{/, false);
 76    // Matches virtual and exported resources (i.e. @@user { ; and the like)
 77    var special_resource = stream.match(/(\s+)?[@]{1,2}[\w:_]+(\s+)?{/, false);
 78
 79    // Finally advance the stream
 80    var ch = stream.next();
 81
 82    // Have we found a variable?
 83    if (ch === '$') {
 84      if (stream.match(variable_regex)) {
 85        // If so, and its in a string, assign it a different color
 86        return state.continueString ? 'variable-2' : 'variable';
 87      }
 88      // Otherwise return an invalid variable
 89      return "error";
 90    }
 91    // Should we still be looking for the end of a string?
 92    if (state.continueString) {
 93      // If so, go through the loop again
 94      stream.backUp(1);
 95      return tokenString(stream, state);
 96    }
 97    // Are we in a definition (class, node, define)?
 98    if (state.inDefinition) {
 99      // If so, return def (i.e. for 'class myclass {' ; 'myclass' would be matched)
100      if (stream.match(/(\s+)?[\w:_]+(\s+)?/)) {
101        return 'def';
102      }
103      // Match the rest it the next time around
104      stream.match(/\s+{/);
105      state.inDefinition = false;
106    }
107    // Are we in an 'include' statement?
108    if (state.inInclude) {
109      // Match and return the included class
110      stream.match(/(\s+)?\S+(\s+)?/);
111      state.inInclude = false;
112      return 'def';
113    }
114    // Do we just have a function on our hands?
115    // In 'ensure_resource("myclass")', 'ensure_resource' is matched
116    if (stream.match(/(\s+)?\w+\(/)) {
117      stream.backUp(1);
118      return 'def';
119    }
120    // Have we matched the prior attribute regex?
121    if (attribute) {
122      stream.match(/(\s+)?\w+/);
123      return 'tag';
124    }
125    // Do we have Puppet specific words?
126    if (word && words.hasOwnProperty(word)) {
127      // Negates the initial next()
128      stream.backUp(1);
129      // rs move the stream
130      stream.match(/[\w]+/);
131      // We want to process these words differently
132      // do to the importance they have in Puppet
133      if (stream.match(/\s+\S+\s+{/, false)) {
134        state.inDefinition = true;
135      }
136      if (word == 'include') {
137        state.inInclude = true;
138      }
139      // Returns their value as state in the prior define methods
140      return words[word];
141    }
142    // Is there a match on a reference?
143    if (/(^|\s+)[A-Z][\w:_]+/.test(word)) {
144      // Negate the next()
145      stream.backUp(1);
146      // Match the full reference
147      stream.match(/(^|\s+)[A-Z][\w:_]+/);
148      return 'def';
149    }
150    // Have we matched the prior resource regex?
151    if (resource) {
152      stream.match(/(\s+)?[\w:_]+/);
153      return 'def';
154    }
155    // Have we matched the prior special_resource regex?
156    if (special_resource) {
157      stream.match(/(\s+)?[@]{1,2}/);
158      return 'special';
159    }
160    // Match all the comments. All of them.
161    if (ch == "#") {
162      stream.skipToEnd();
163      return "comment";
164    }
165    // Have we found a string?
166    if (ch == "'" || ch == '"') {
167      // Store the type (single or double)
168      state.pending = ch;
169      // Perform the looping function to find the end
170      return tokenString(stream, state);
171    }
172    // Match all the brackets
173    if (ch == '{' || ch == '}') {
174      return 'bracket';
175    }
176    // Match characters that we are going to assume
177    // are trying to be regex
178    if (ch == '/') {
179      stream.match(/.*?\//);
180      return 'variable-3';
181    }
182    // Match all the numbers
183    if (ch.match(/[0-9]/)) {
184      stream.eatWhile(/[0-9]+/);
185      return 'number';
186    }
187    // Match the '=' and '=>' operators
188    if (ch == '=') {
189      if (stream.peek() == '>') {
190          stream.next();
191      }
192      return "operator";
193    }
194    // Keep advancing through all the rest
195    stream.eatWhile(/[\w-]/);
196    // Return a blank line for everything else
197    return null;
198  }
199  // Start it all
200  return {
201    startState: function () {
202      var state = {};
203      state.inDefinition = false;
204      state.inInclude = false;
205      state.continueString = false;
206      state.pending = false;
207      return state;
208    },
209    token: function (stream, state) {
210      // Strip the spaces, but regex will account for them eitherway
211      if (stream.eatSpace()) return null;
212      // Go through the main process
213      return tokenize(stream, state);
214    }
215  };
216});
217
218CodeMirror.defineMIME("text/x-puppet", "puppet");
219
220});