深柳堂

  • Tag:
    标签集合
  • Suggest:

WordPress 更新到2.6.5 停掉了UTW这一伟大的插件...

为project babel加上geshi语法高亮显示

June 8th, 2008

注:本文使用的正则表达式为php风格。

从v2ex到M6,我一直喜欢project babel(PB)。自己也尝试在本地或服务器上架设PB系统。遇到的一个问题是:PB只支持有限的ubb代码,当我想在PB上贴源码时,没有语法高亮很不美观。

管理员对此的答复是,简约是最好的,不必非得使用72号红色字体加上一堆感叹号才能让文字有力度。当然了,这样不给脑残以任何自证的机会,当然是不错。可是因为怕脑残搞乱而消减功能,就有些类似于怕一个男人淫乱而将全天下男人葵花宝典掉一样了。

代码语法高亮,最著名的模块莫过于geshi。我使用过php写过几行代码,语法什么的都需要现查手册;对css、form之类也不是很熟悉。因此让我自己改造PB的话,一时摸不到头绪。于是在M6上发了求教贴。有热心人sara回复如下:

有个缺点,就是一个帖子里同一种代码只能用一次,希望有高手能改进一下。
比如php代码:[php]your code[/php]

  1. 在v2excore.php加geshi的路径。
  2. 在utilities.php加
    preg_match('/\[php\]/i', $text, $_m_php_open);
    preg_match('/\[\/php\]/i', $text, $_m_php_close);
    if ((count($_m_php_open) == 1) && (count($_m_php_open) == count($_m_php_close))) {
    list($a, $b) = explode('[php]', $text);
    list($c, $d) = explode('[/php]', $b);
    $c = str_replace('&lt;', '<', $c);
    $c = str_replace('&gt;', '>', $c);
    $text = $a . '<div class="codes php">' . geshi_highlight($c, 'php', '', 'true') . '</div>' . $d;
    }

    加在

    $text = preg_replace($p, $r, $text);

    的后面。

我读了这段代码之后,发现它并没有大段的CSS内容,这我就放心多了。于是细读之,遇到问题就查手册。

这段代码翻译成自然语言,就是:

  1. 查找文本中[php]的次数$_m_php_open,以及[/php]的次数$_m_php_close;查找时不分大小写。
  2. 次数$_m_php_open与$_m_php_close是否相等且等于1。如果不满足条件,就不处理了。
    只有两者相等且为1时,记录下[php]与[/php]之间的内容$c,把里面所有的”<”、”>”都换成”<"、">“形式。
  3. 把需要处理的代码部分$c使用geshi_highlight的相关语法(这里是PHP)进行格式化。

既如此,那我就可以自已实现了。

刚才使用

preg_match('/\[php\]/i', $text, $_m_php_open);
preg_match('/\[\/php\]/i', $text, $_m_php_close);

寻找配对的标签,不是一种好的方法。因为它的通用性不强,不便于前后配对。较好的解决方法是:

$text=preg_replace_callback("#\[(asp|bash|c|cpp|csharp|css|delphi|div|dos|dot|ini|java|java5|javascript|latex|lisp|luamatlab|mysql|pascal|perl|php|python|qbasic|rails|reg|ruby|scheme|sql|tcl|text|vb|vbnet|xml)\](.*?)\[/\\1\]#ix","geshi_replace",$text);

使用正则表达式,第一组括号捕获了语言种类标签,第二组捕获了程序内容。选项i表示不分大小写,s表示点号可以匹配任意字符(包括换行符)。

之所以使用callback方式的正则匹配,是因为替换的内容多而复杂。该callback函数是这样定义的:

function geshi_replace($matches)  
{
    //matches[1]=lang
    //matches[2]=code
    $code=$matches[2];
    $lang=$matches[1];
    $code = str_replace('&lt;', '<', $code);
    $code = str_replace('&gt;', '>', $code);
    $str = '<div class="code">'. geshi_highlight($code, $lang,'','true') .'</div>';
    $str = str_replace("<br />","",$str);
    return $str;
}

程序与原来给出的大同小异。只是还有一行

$str = str_replace("<br />","",$str);

是新加上去的。这是因为geshi_highlight输出的文本,总是包含”<br /><br />”,因此显示出来的高亮代码行距太大,这里给它修剪一下,就可以了。

总结一下如何在PB6.0中加入geshi:

1. 上传geshi到babel目录;
2. 在v2excore.php加geshi的路径,让pb能找到geshi.php。
3. 在Utilities.php文件下,function format_ubb之前加上如下function:

      function geshi_replace($matches)
      {
      //matches[1]=lang
      //matches[2]=code
      $code=$matches[2];
      $lang=$matches[1];
      $code = str_replace('<', '<', $code);
      $code = str_replace('>', '>', $code);
      $str = '<div class="code">'. geshi_highlight($code, $lang,'','true') .'</div>';
      $str = str_replace("<br />","",$str);
      return $str;
      }

4. 在function format_ubb中的

      $text = preg_replace($p, $r, $text);

之后插入一行代码:

      $text=preg_replace_callback("#\[(asp|bash|c|cpp-qt|cpp|csharp|css|delphi|diff|div|dos|dot|eiffel|fortran|freebasic|genero|gml|groovy|haskell|html4strict|idl|ini|inno|io|java|java5|javascript|latex|lisp|lua|m68k|matlab|mirc|mpasm|mysql|nsis|objc|ocaml-brief|ocaml|oobas|oracle8|pascal|per|perl|php-brief|php|plsql|python|qbasic|rails|reg|robots|ruby|sas|scheme|sdlbasic|smalltalk|smarty|sql|tcl|text|thinbasic|tsql|vb|vbnet|vhdl|visualfoxpro|winbatch|xml)\](.*?)\[/\\1\]#is","geshi_replace",$text);

大功告成。
使用方法:

  1. 在PB贴子的编辑框中使用[lang]…[/lang]标签。
  2. lang标签不可嵌套。
  3. lang的可选方案以geshi支持为限,大致包括:asm, asp , bash, c, cpp-qt, cpp, csharp, css, delphi, diff, div, dos, dot, eiffel, fortran, freebasic, genero, gml, groovy, haskell, html4strict, idl, ini, inno, io, java, java5, javascript, latex, lisp, lua, m68k, matlab, mirc, mpasm, mysql, nsis, objc, ocaml-brief, ocaml, oobas, oracle8, pascal, per, perl, php-brief, php, plsql, python, qbasic, rails, reg, robots, ruby, sas, scheme, sdlbasic, smalltalk, smarty, sql, tcl, text, thinbasic, tsql, vb, vbnet, vhdl, visualfoxpro, winbatch, xml。呵呵。

结论:

  1. 十分感谢sara
  2. 正则表达式一如既往地有用、好用。
  3. 有些问题看上去很难。可是只要打开缺口,剩下的就不成问题;就如慕容复语:“这几步棋我也想得出来。万事起头难,便是第一着怪棋,无论如何想不出。”