PageRenderTime 25ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/inc/syntax.php

https://bitbucket.org/wez/mtrack/
PHP | 195 lines | 188 code | 6 blank | 1 comment | 3 complexity | 1ce524f44834c772152b2b6608fe4a59 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0
  1. <?php # vim:ts=2:sw=2:et:
  2. /* For licensing and copyright terms, see the file named LICENSE */
  3. class MTrackSyntaxHighlight {
  4. static $schemes = array(
  5. '' => 'No syntax highlighting',
  6. 'wezterm' => "Wez's Terminal",
  7. 'zenburn' => "Zenburn",
  8. 'vibrant-ink' => "Vibrant Ink",
  9. );
  10. static $lang_by_ext = array(
  11. 'c' => 'cpp',
  12. 'cc' => 'cpp',
  13. 'cpp' => 'cpp',
  14. 'h' => 'cpp',
  15. 'hpp' => 'cpp',
  16. 'icl' => 'cpp',
  17. 'ipp' => 'cpp',
  18. 'css' => 'css',
  19. 'php' => 'php',
  20. 'php3' => 'php',
  21. 'php4' => 'php',
  22. 'php5' => 'php',
  23. 'phtml' => 'php',
  24. 'pl' => 'perl',
  25. 'pm' => 'perl',
  26. 't' => 'perl',
  27. 'bash' => 'shell',
  28. 'sh' => 'shell',
  29. 'js' => 'javascript',
  30. 'json' => 'javascript',
  31. 'vb' => 'vb',
  32. 'xml' => 'xml',
  33. 'xsl' => 'xml',
  34. 'xslt' => 'xml',
  35. 'xsd' => 'xml',
  36. 'html' => 'xml',
  37. 'diff' => 'diff',
  38. 'patch' => 'diff',
  39. 'wiki' => 'wiki',
  40. );
  41. static $langs = array(
  42. '' => 'No particular file type',
  43. 'cpp' => 'C/C++',
  44. 'css' => 'CSS (Cascading Style Sheet)',
  45. 'php' => 'PHP',
  46. 'perl' => 'Perl',
  47. 'shell' => 'Shell script',
  48. 'javascript' => 'Javascript',
  49. 'vb' => 'Visual Basic',
  50. 'xml' => 'HTML, XML, XSL',
  51. 'wiki' => 'Wiki Markup',
  52. 'diff' => 'Diff/Patch',
  53. );
  54. static function inferFileTypeFromContents($data) {
  55. if (preg_match("/vim:.*ft=(\S+)/", $data, $M)) {
  56. return $M[1];
  57. }
  58. if (preg_match("/^#!.*env\s+(\S+)/", $data, $M)) {
  59. return $M[1];
  60. }
  61. if (preg_match("/^#!\s*(\S+)/", $data, $M)) {
  62. return basename($M[1]);
  63. }
  64. return null;
  65. }
  66. static function register_processors() {
  67. foreach (self::$langs as $lang => $desc) {
  68. if ($lang == '') continue;
  69. MTrackWiki::register_processor($lang,
  70. array('MTrackSyntaxHighlight', 'wiki_processor'));
  71. }
  72. MTrackWiki::register_macro('ListRegisteredSyntaxHighlighters',
  73. array('MTrackSyntaxHighlight', 'macro_list_syntax'));
  74. }
  75. /** Renders a table showing the available syntax highlighters */
  76. static function macro_list_syntax() {
  77. $data = array();
  78. foreach (self::$lang_by_ext as $ext => $lang) {
  79. if (!isset($data[$lang])) {
  80. $name = isset(self::$langs[$lang]) ? self::$langs[$lang] : $lang;
  81. $data[$lang] = array(
  82. 'name' => $name,
  83. 'exts' => array()
  84. );
  85. }
  86. $data[$lang]['exts'][] = $ext;
  87. }
  88. $html = <<<HTML
  89. <table class='wiki report'>
  90. <thead>
  91. <tr>
  92. <th>Langauge</th>
  93. <th>Processor Name</th>
  94. <th>Filename Extensions</th>
  95. </tr>
  96. </thead>
  97. <tbody>
  98. HTML;
  99. foreach ($data as $lang => $info) {
  100. $exts = join(', ', $info['exts']);
  101. $name = htmlentities($info['name'], ENT_QUOTES, 'utf-8');
  102. $html .= <<<HTML
  103. <tr>
  104. <td>$name</td>
  105. <td>$lang</td>
  106. <td>$exts</td>
  107. </tr>
  108. HTML;
  109. }
  110. $html .= <<<HTML
  111. </tbody>
  112. </table>
  113. HTML;
  114. return $html;
  115. }
  116. /** Renders block with syntax highlighting */
  117. static function wiki_processor($type, $content) {
  118. $data = join("\n", $content);
  119. $markup = self::highlightSource($data, $type, null, true);
  120. if ($type == 'diff') {
  121. return $markup;
  122. }
  123. return self::getSchemeSelect() . $markup;
  124. }
  125. static function highlightSource($data, $type = null, $filename = null, $line_numbers = false) {
  126. if ($type === null) {
  127. $type = self::inferFileTypeFromContents($data);
  128. if ($type === null && $filename !== null) {
  129. if (preg_match("/\.([^.]+)$/", $filename, $M)) {
  130. $ext = strtolower($M[1]);
  131. if (isset(self::$lang_by_ext[$ext])) {
  132. $type = self::$lang_by_ext[$ext];
  133. }
  134. }
  135. }
  136. }
  137. if ($type == 'diff') {
  138. return mtrack_diff($data);
  139. }
  140. if (strlen($type) && isset(self::$langs[$type])) {
  141. require_once dirname(__FILE__) . '/hyperlight/hyperlight.php';
  142. $hl = new Hyperlight($type);
  143. $hdata = $hl->render($data);
  144. } else {
  145. $hdata = htmlentities($data);
  146. }
  147. if (!$line_numbers) {
  148. return "<span class='source-code wezterm'>$hdata</span>";
  149. }
  150. $lines = preg_split("/\r?\n/", $data);
  151. $html = <<<HTML
  152. <table class='codeann'>
  153. <tr>
  154. <th class='line'>line</th>
  155. <th class='code'>code</th>
  156. </tr>
  157. HTML;
  158. $nlines = count($lines);
  159. for ($i = 1; $i <= $nlines; $i++) {
  160. $html .= "<tr><td class='line'><a name='l$i'></a><a href='#l$i'>$i</a></td>";
  161. if ($i == 1) {
  162. $html .= "<td rowspan='$nlines' width='100%' class='source-code wezterm'>$hdata</td>";
  163. }
  164. $html .= "</tr>\n";
  165. }
  166. return $html . "</table>\n";
  167. }
  168. static function getSchemeSelect($selected = 'wezterm') {
  169. $html = <<<HTML
  170. <select class='select-hl-scheme'>
  171. HTML;
  172. foreach (self::$schemes as $k => $v) {
  173. $sel = $selected == $k ? " selected" : '';
  174. $html .= "<option value='$k'$sel>" .
  175. htmlentities($v, ENT_QUOTES, 'utf-8') .
  176. "</option>\n";
  177. }
  178. return $html . "</select>";
  179. }
  180. static function getLangSelect($name, $value) {
  181. return mtrack_select_box($name, self::$langs, $value);
  182. }
  183. }
  184. MTrackSyntaxHighlight::register_processors();