diff options
author | Jeremy Dorn <jeremy@jeremydorn.com> | 2013-09-02 10:12:06 -0700 |
---|---|---|
committer | Jeremy Dorn <jeremy@jeremydorn.com> | 2013-09-02 10:12:06 -0700 |
commit | f258a98eb42c5566da277acf8e97c1e918e04771 (patch) | |
tree | 65e33289acdb938cf3451d30fe6f0537812315a9 | |
parent | 0b30579a48dc7deaa3905ea7d6a457998e33e5a8 (diff) | |
download | sql-formatter-f258a98eb42c5566da277acf8e97c1e918e04771.zip sql-formatter-f258a98eb42c5566da277acf8e97c1e918e04771.tar.gz sql-formatter-f258a98eb42c5566da277acf8e97c1e918e04771.tar.bz2 |
Add highlighting support for binary/hex numbers and user-defined variables.
Add ":" to the boundary list (fixes ":=" assignment operator).
Standardize whitespace around "if" clauses in the php code. Now there is always a space after "if" and before "(".
Fixes #50
-rw-r--r-- | lib/SqlFormatter.php | 84 | ||||
-rw-r--r-- | tests/clihighlight.html | 2 | ||||
-rw-r--r-- | tests/format-highlight.html | 2 | ||||
-rw-r--r-- | tests/highlight.html | 2 |
4 files changed, 70 insertions, 20 deletions
diff --git a/lib/SqlFormatter.php b/lib/SqlFormatter.php index be326f0..9b07e33 100644 --- a/lib/SqlFormatter.php +++ b/lib/SqlFormatter.php @@ -9,7 +9,7 @@ * @copyright 2013 Jeremy Dorn * @license http://opensource.org/licenses/MIT * @link http://github.com/jdorn/sql-formatter - * @version 1.2.12 + * @version 1.2.13 */ class SqlFormatter { @@ -26,6 +26,7 @@ class SqlFormatter const TOKEN_TYPE_BLOCK_COMMENT = 9; const TOKEN_TYPE_NUMBER = 10; const TOKEN_TYPE_ERROR = 11; + const TOKEN_TYPE_VARIABLE = 12; // Constants for different components of a token const TOKEN_TYPE = 0; @@ -101,7 +102,7 @@ class SqlFormatter ); // Punctuation that can be used as a boundary between other tokens - protected static $boundaries = array(',', ';', ')', '(', '.', '=', '<', '>', '+', '-', '*', '/', '!', '^', '%', '|', '&', '#'); + protected static $boundaries = array(',', ';',':', ')', '(', '.', '=', '<', '>', '+', '-', '*', '/', '!', '^', '%', '|', '&', '#'); // For HTML syntax highlighting // Styles applied to different token types @@ -113,6 +114,7 @@ class SqlFormatter public static $word_attributes = 'style="color: #333;"'; public static $error_attributes = 'style="background-color: red;"'; public static $comment_attributes = 'style="color: #aaa;"'; + public static $variable_attributes = 'style="color: orange;"'; public static $pre_attributes = 'style="color: black; background-color: white;"'; // Boolean - whether or not the current environment is the CLI @@ -130,6 +132,7 @@ class SqlFormatter public static $cli_error = "\x1b[31;1;7m"; public static $cli_comment = "\x1b[30;1m"; public static $cli_functions = "\x1b[37m"; + public static $cli_variable = "\x1b[36;1m"; // The tab character to use when formatting SQL public static $tab = ' '; @@ -173,7 +176,7 @@ class SqlFormatter */ protected static function init() { - if(self::$init) return; + if (self::$init) return; // Sort reserved word list from longest word to shortest usort(self::$reserved, array('SqlFormatter', 'sortLength')); @@ -233,22 +236,40 @@ class SqlFormatter if ($string[0]==='"' || $string[0]==='\'' || $string[0]==='`') { $return = array( self::TOKEN_TYPE => ($string[0]==='`'? self::TOKEN_TYPE_BACKTICK_QUOTE : self::TOKEN_TYPE_QUOTE), - self::TOKEN_VALUE => $string + self::TOKEN_VALUE => self::getQuotedString($string) ); - - // This checks for the following patterns: - // 1. backtick quoted string using `` to escape - // 2. double quoted string using "" or \" to escape - // 3. single quoted string using '' or \' to escape - if ( preg_match('/^(((`[^`]*($|`))+)|(("[^"\\\\]*(?:\\\\.[^"\\\\]*)*("|$))+)|((\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*(\'|$))+))/s', $string, $matches)) { - $return[self::TOKEN_VALUE] = $matches[1]; + + // If a quote was opened, but doesn't have a closing quote, return the remaining string + if ($return[self::TOKEN_VALUE] === null) { + $return[self::TOKEN_VALUE] = $string; } - + return $return; } + + // User-defined Variable + if ($string[0] === '@' && isset($string[1])) { + // If the variable name is quoted + if ($string[1]==='"' || $string[1]==='\'' || $string[1]==='`') { + return array( + self::TOKEN_VALUE => '@'.self::getQuotedString(substr($string,1)), + self::TOKEN_TYPE => self::TOKEN_TYPE_VARIABLE + ); + } + // Non-quoted variable name + else { + preg_match('/^(@[a-zA-Z0-9\._\$]+)/',$string,$matches); + if ($matches) { + return array( + self::TOKEN_VALUE => $matches[1], + self::TOKEN_TYPE => self::TOKEN_TYPE_VARIABLE + ); + } + } + } - // Number - if (preg_match('/^([0-9]+(\.[0-9]+)?)($|\s|"\'`|'.self::$regex_boundaries.')/',$string,$matches)) { + // Number (decimal, binary, or hex) + if (preg_match('/^([0-9]+(\.[0-9]+)?|0x[0-9a-fA-F]+|0b[01]+)($|\s|"\'`|'.self::$regex_boundaries.')/',$string,$matches)) { return array( self::TOKEN_VALUE => $matches[1], self::TOKEN_TYPE=>self::TOKEN_TYPE_NUMBER @@ -310,6 +331,17 @@ class SqlFormatter ); } + protected static function getQuotedString($string) { + // This checks for the following patterns: + // 1. backtick quoted string using `` to escape + // 2. double quoted string using "" or \" to escape + // 3. single quoted string using '' or \' to escape + if ( preg_match('/^(((`[^`]*($|`))+)|(("[^"\\\\]*(?:\\\\.[^"\\\\]*)*("|$))+)|((\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*(\'|$))+))/s', $string, $matches)) { + return $matches[1]; + } + return null; + } + /** * Takes a SQL string and breaks it into tokens. * Each token is an associative array with type and value. @@ -500,7 +532,7 @@ class SqlFormatter $length = 0; for ($j=1;$j<=250;$j++) { // Reached end of string - if(!isset($tokens[$i+$j])) break; + if (!isset($tokens[$i+$j])) break; $next = $tokens[$i+$j]; @@ -823,6 +855,8 @@ class SqlFormatter return self::highlightReservedWord($token); } elseif ($type===self::TOKEN_TYPE_NUMBER) { return self::highlightNumber($token); + } elseif ($type===self::TOKEN_TYPE_VARIABLE) { + return self::highlightVariable($token); } elseif ($type===self::TOKEN_TYPE_COMMENT || $type===self::TOKEN_TYPE_BLOCK_COMMENT) { return self::highlightComment($token); } @@ -887,7 +921,7 @@ class SqlFormatter */ protected static function highlightBoundary($value) { - if($value==='(' || $value===')') return $value; + if ($value==='(' || $value===')') return $value; if (self::is_cli()) { return self::$cli_boundary . $value . "\x1b[0m"; @@ -959,6 +993,22 @@ class SqlFormatter return '<span ' . self::$word_attributes . '>' . $value . '</span>'; } } + + /** + * Highlights a variable token + * + * @param String $value The token's value + * + * @return String HTML code of the highlighted token. + */ + protected static function highlightVariable($value) + { + if (self::is_cli()) { + return self::$cli_variable . $value . "\x1b[0m"; + } else { + return '<span ' . self::$variable_attributes . '>' . $value . '</span>'; + } + } /** * Helper function for sorting the list of reserved words by length @@ -1008,7 +1058,7 @@ class SqlFormatter private static function is_cli() { - if(isset(self::$cli)) return self::$cli; + if (isset(self::$cli)) return self::$cli; else return php_sapi_name() === 'cli'; } diff --git a/tests/clihighlight.html b/tests/clihighlight.html index 936df43..657f324 100644 --- a/tests/clihighlight.html +++ b/tests/clihighlight.html @@ -207,7 +207,7 @@ [35;1m`value`[0m text[0m ) -[37mSET[0m @defaultOOS[0m =[0m ([37mSELECT[0m value[0m [37mFROM[0m [35;1m`PREFIX_configuration`[0m [37mWHERE[0m name[0m =[0m [34;1m'PS_ORDER_OUT_OF_STOCK'[0m) +[37mSET[0m [36;1m@defaultOOS[0m =[0m ([37mSELECT[0m value[0m [37mFROM[0m [35;1m`PREFIX_configuration`[0m [37mWHERE[0m name[0m =[0m [34;1m'PS_ORDER_OUT_OF_STOCK'[0m) [37mUPDATE[0m [35;1m`PREFIX_product`[0m p[0m [37mSET[0m [35;1m`cache_default_attribute`[0m =[0m [32;1m0[0m [37mWHERE[0m [35;1m`id_product`[0m [37mNOT[0m [37mIN[0m ([37mSELECT[0m [35;1m`id_product`[0m [37mFROM[0m [35;1m`PREFIX_product_attribute`[0m) diff --git a/tests/format-highlight.html b/tests/format-highlight.html index 15908b1..ee70147 100644 --- a/tests/format-highlight.html +++ b/tests/format-highlight.html @@ -636,7 +636,7 @@ <pre style="color: black; background-color: white;"><span style="font-weight:bold;">CREATE</span> <span style="font-weight:bold;">TEMPORARY</span> <span style="font-weight:bold;">TABLE</span> <span style="color: purple;">`PREFIX_configuration_tmp`</span> (<span style="color: purple;">`value`</span> <span style="color: #333;">text</span>)</pre> <pre style="color: black; background-color: white;"><span style="font-weight:bold;">SET</span> - <span style="color: #333;">@defaultOOS</span> <span >=</span> ( + <span style="color: orange;">@defaultOOS</span> <span >=</span> ( <span style="font-weight:bold;">SELECT</span> <span style="color: #333;">value</span> <span style="font-weight:bold;">FROM</span> diff --git a/tests/highlight.html b/tests/highlight.html index 5db651d..9579569 100644 --- a/tests/highlight.html +++ b/tests/highlight.html @@ -207,7 +207,7 @@ <span style="color: purple;">`value`</span> <span style="color: #333;">text</span> )</pre> -<pre style="color: black; background-color: white;"><span style="font-weight:bold;">SET</span> <span style="color: #333;">@defaultOOS</span> <span >=</span> (<span style="font-weight:bold;">SELECT</span> <span style="color: #333;">value</span> <span style="font-weight:bold;">FROM</span> <span style="color: purple;">`PREFIX_configuration`</span> <span style="font-weight:bold;">WHERE</span> <span style="color: #333;">name</span> <span >=</span> <span style="color: blue;">'PS_ORDER_OUT_OF_STOCK'</span>)</pre> +<pre style="color: black; background-color: white;"><span style="font-weight:bold;">SET</span> <span style="color: orange;">@defaultOOS</span> <span >=</span> (<span style="font-weight:bold;">SELECT</span> <span style="color: #333;">value</span> <span style="font-weight:bold;">FROM</span> <span style="color: purple;">`PREFIX_configuration`</span> <span style="font-weight:bold;">WHERE</span> <span style="color: #333;">name</span> <span >=</span> <span style="color: blue;">'PS_ORDER_OUT_OF_STOCK'</span>)</pre> <pre style="color: black; background-color: white;"><span style="font-weight:bold;">UPDATE</span> <span style="color: purple;">`PREFIX_product`</span> <span style="color: #333;">p</span> <span style="font-weight:bold;">SET</span> <span style="color: purple;">`cache_default_attribute`</span> <span >=</span> <span style="color: green;">0</span> <span style="font-weight:bold;">WHERE</span> <span style="color: purple;">`id_product`</span> <span style="font-weight:bold;">NOT</span> <span style="font-weight:bold;">IN</span> (<span style="font-weight:bold;">SELECT</span> <span style="color: purple;">`id_product`</span> <span style="font-weight:bold;">FROM</span> <span style="color: purple;">`PREFIX_product_attribute`</span>)</pre> |