openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

puppet.js (7568B)


      1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
      2 // Distributed under an MIT license: http://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 
     14 CodeMirror.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 
    218 CodeMirror.defineMIME("text/x-puppet", "puppet");
    219 
    220 });