beautify($script); } else { $this->script = $script; } } // Attempt to beautify the script a bit public function beautify($input = NULL) { // Beautify the script $script = ($input === NULL ? $this->script : $input); // Break apart commands separated by | $script = preg_replace('/\s+\|\s+/',"\n",$script); // Put newlines before } and after { $script = preg_replace('/\s+\}\s*(?:\s|$)/',"\n}\n",$script); $script = preg_replace('/(?<=\s|^)\{\s+/',"{\n",$script); // Put () around some if conditions $script = preg_replace('/(if|elseif|while)\s+([^\(].*?)\s+\{/','\1 (\2) {',$script); $this->script = $script; } public function __set($var,$value) { $this->data[$var] = $value; if ($var == 'script') { if ($value !== NULL) { $this->split_script(); } } } public function __get($var) { return $this->data[$var]; } // Split the script into an array of characters private function split_script() { $this->script = str_replace("\r",'',$this->script); $this->chars = array_slice(preg_split('//',$this->script),1,strlen($this->script)); array_map(array(&$this,'escape_chars'),&$this->chars); } // Escape HTML characters private function escape_chars(&$char) { $char = str_replace(array('&','<','>'),array('&','<','>'),$char); } // Apply highlighting to the script public function highlight() { $open = '\s,!@^&*\050='; // Characters that start a token $close = '\s,!@^&*\051'; // Characters that end a token $script = $this->script; // Conditional Operators $operators = '!?(?:=|==|===|>|<|>=|<=|\/\/|\\\\|&|isin|isincs|iswm|isnum|isletter'. '|isalnum|isalpha|islower|isupper|ison|isop|ishop|isvoice|isvo|isreg|ischan|' . 'isban|isaop|isavoice|isignore|isprotect|isnotify|iswmcs|\|\||&&|\+|\-|\*|%|\^)'; // Patterns to match for different parts of mIRC scripts $patterns = array( // Comments //Block Style // Here I've put a d in front of the pattern. This is a lazy thing I did to tell the script to delete the matched portion of text. It's not part of the regular expression. 'd/\\013?\s*(\/\*.*?\*\/)\s*\\013?/s' // The first element of the replacement will go before each callback, and the second element after each callback => array('',''), // Single Line 'd/^\s*(;.*)$/m' => array('',''), // Number '/(?<=^|['.$open.'])([+-]?[\d]+?(?:\.[\d]+?)?)(?=$|['.$close.'%])/m' => array('',''), // Identifier '/(?<=^|['.$open.'])(\$[^\s\050\051\[,]+)/m' => array('',''), // Identifier Property '/(?<=\051)(\.[^\s$\051]+)/m' => array('',''), // Variable '/(?<=^|['.$open.'])(\%[^'.$close.']+)(?=$|['.$close.'])/m' => array('',''), // Operators '/(?<=[\s])('.$operators.')(?=[\s])/m' => array('',''), // Special Characters '/([\[\]\{\}\050\051\|]+)/m' => array('',''), // Events '/(?<=^)\s*(on|ctcp|raw)\s+([^\:]+?):([^\:]+?):/m' => array('',''), // Commands '/(?<=^|[\{\|]\s)\s*([^\$\%\s]+?)(?=\s|$)/m' => array('',''), // Command Switches '/(?<=^|[\{\|]\s)\s*(?:[^\$\%\s]+?)\s+(-[^\s]+)(?=\s|$)/m' => array('',''), ); $patterns_keys = array_keys($patterns); foreach ($patterns_keys as $rpattern) { // Iterate through each pattern if ($rpattern{0} == 'd') { // The 'd' switch means delete the text after matching $delete = TRUE; $pattern = substr($rpattern,1); } else { $delete = FALSE; $pattern = $rpattern; } if (preg_match_all($pattern,$script,$matches,PREG_OFFSET_CAPTURE)) { // Get all matches for this pattern array_shift($matches); // Shift off the part we don't want foreach ($matches as $matches2) { // Iterate through each callback foreach ($matches2 as $match) { // Iterate through each match of each callback list($text,$offset) = $match; // Put the first element before the first character of the callback $this->chars[$offset] = $patterns[$rpattern][0] . $this->chars[$offset] ; // Put the second element after the last character of the callback $this->chars[$offset -1 + strlen($text)] = $this->chars[$offset-1 + strlen($text)] . $patterns[$rpattern][1]; if ($delete) { // Delete the entire matched text so we don't match it again $script = substr($script,0,$offset) . str_repeat(' ',strlen($text)) . substr($script,$offset + strlen($text)); } } // End iterate through each match of callback } // End iterate through each callback } // End if } // End iterate through each pattern return $line; } // Returns the script after processing // Specify TRUE for $indent to have the script indented public function get_script($indent = FALSE) { // Implode the array of characters into the finished script $output = implode('',$this->chars); if ($indent) { $lines = explode("\n",$this->script); $output = explode("\n",$output); $level = 0; foreach ($lines as $key => &$line) { if ($in_comment) { // Don't indent parts of the script that are commented out if (preg_match('/^\s*\*\//',$line)) { $in_comment = FALSE; } continue; } // Check for beginning of a comment if (preg_match('/^\s*\/\*/',$line)) { $in_comment = TRUE; continue; } if (preg_match('/^\s*;/',$line)) { continue; } // Remove spaces at the beginning of the line $output[$key] = preg_replace('/^\s*/','',$output[$key]); // Decrease indentation if there's a } $decrease = preg_match_all('/(?<=\s|^)}(?=\s|$)/',$line); // Increase indentation if there's a { $increase = preg_match_all('/(?<=\s|^|:){(?=\s|$)/',$line); // Increase indentation if there's a $& $increase = preg_match_all('/\$\&\s*$/',$line); $difference = $increase - $decrease; if ($difference < 0) { $level += $difference; $difference = 0; } if ($level < 0) $level = 0; $output[$key] = str_repeat(' ',$level * 2) . $output[$key]; $level += $difference; $difference = 0; } $output = implode("\n",$output); } return $output; } } ?>