GeSHiで遊ぶ

DokuWiki時代にお世話になったソースコードをハイライトしてくれるPHPライブラリのGeSHiで遊んでみる。
GeSHi - Generic Syntax Highlighter

"php -s"をGeSHiを使ったスクリプトに置き換えてみたり、Smarty修飾子プラグイン書いてみたり、MTプラグイン作りを狙ってみたりと、うだうだやりつつたどり着いたのがCLI。

~% geshi -l php -f input.php -o output.php
~% echo 'echo "hoge\n";' | geshi -l php

イメージは↑な感じね。

で、ちょこちょこ書いて(一応)動くものは書けた。書けたけど、まあ暇つぶし以外の何者でもない。ので、いい加減。意味無し。

書いた後で、同梱されてんじゃね?とちょっと見てみれば、"contrib/aliased.php"とかいうブラウザ経由のViewerらしきものを発見。そもそも、GeSHiのサイトにあるDemoで事足りるような気もする。

コマンドとして運用するにはライブラリの置き場所に困ったり。言語ファイルもgeshi/にあるものとして書いちゃったし。まあ、いいんです。自分用だし。

そんなわけで、(一応)続きにコード晒し。普通に*nixなコマンドがあればそっち使いたい。。。

#!/usr/bin/env php
<?php
 
/**
 * This command is GeSHi CLI
 *
 * @require PHP5
 * @require GeSHi <http://qbnz.com/highlighter/>
 *
 */
 
define("VERSION", "0.0.2");
 
// this module must be under the include_path
// <include_path>/geshi.php
// <include_path>/geshi/<language>.php
if (!is_installed_geshi_lib()) {
    echo "Not found GeSHi library.\n";
    echo "
GeSHi library must be under <include_path>.
 
  include_path/
    geshi.php
    geshi/
      some language files...
 
Download from <http://qbnz.com/highlighter/>
";
    exit(1);
}
require_once("geshi.php");
 
// usage
define("USAGE",
"Usage: geshi -v
       geshi -h
       geshi -e
       geshi -l <language> -f <input file> [-o <output file>]
       STDIN | geshi -l <language> [-o <output file>]
 
  -v            Echo version
  -h            Echo usage and some informations
  -e            Echo elisp
  -l <language> Set code language
  -f <file>     Set input file
  -o <file>     Set output file
 
Supportted languages:
" . implode(", ",  get_languages()) . "\n");
 
// parse options
$options = getopt('vhel:f:o:');
 
// only version echo
if (isset($options["v"])) {
    echo "Version: " . VERSION . "\n";
    exit(0);
}
 
// only echo help(usage)
if (isset($options["h"])) {
    echo USAGE;
    exit(0);
}
 
// only elisp echo
if (isset($options["e"])) {
    $languageAlist = '("' . implode('") ("', get_languages()) . '")';
    echo <<<DOC
;;; ;;; リージョン内のスクリプトをHTML形式でハイライト表示
(defun geshi-region nil "Source code highlight"
  (interactive)
  (let (
    (geshi-language-alist '( $languageAlist )
    ) (completion-ignore-case t))
  (setq geshi-language (completing-read "言語: " geshi-language-alist nil t))
  (shell-command-on-region (region-beginning) (region-end) (concat "geshi -l " geshi-language))
  (switch-to-buffer "*Shell Command Output*"))
)
(global-set-key (kbd "C-c g") 'geshi-region)
DOC;
    echo "\n";
    exit(0);
}
 
// initialization
$source   = "";
$language = "";
$outputFilePath = "";
 
// check language
if (isset($options["l"])) {
    if (validLanguage($options["l"])) {
        $language = $options["l"];
    } else {
        echo "Failed: Not supported such language.\n\n";
        echo USAGE;
        exit(1);
    }
} else {
    echo "Failed: Input code language.\n\n";
    echo USAGE;
    exit(1);
}
 
// check input file
if (isset($options["f"])) {
    $inputFilePath = $options["f"];
    // check file
    if (file_exists($inputFilePath) and is_readable($inputFilePath)) {
        $source = file_get_contents($inputFilePath);
    } else {
        echo "Failed: No such file or permission denied.\n\n";
        echo USAGE;
        exit(1);
    }
} else {
    // check STDIN
    if (($source = get_stdin()) == "") {
        echo "Failed: Cannot get input data from STDIN.\n\n";
        echo USAGE;
        exit(1);
    }
}
 
// source highlight
$geshi     = new GeSHi($source, $language);
$hilighted = $geshi->parse_code();
 
// check output file path
if (isset($options["o"])) {
    $path = $options["o"];
    if (is_make_file($path)) {
        file_put_contents($path, $hilighted);
    } else {
        echo "Failed: Is output file path valid?\n\n";
        echo USAGE;
        exit(1);
    }
} else {
    echo $hilighted;
}
 
 
/**
 * Get STDIN data
 *
 * @return String
 */
function get_stdin($timeout = 1) {
    $stat  = fstat(STDIN);
    $input = "";
    if ($stat["size"] > 0) {
        $input = fread(STDIN, $stat["size"]);
    }
    return $input;
}
 
/**
 * Validation language type
 *
 * @return Boolean
 */
function validLanguage($language) {
    $searchPathList = explode(PATH_SEPARATOR, ini_get("include_path"));
    foreach ($searchPathList as $dir) {
        $path = rtrim($dir, DIRECTORY_SEPARATOR) . "/geshi/" . $language . ".php";
        if (file_exists($path)) {
            return true;
        }
    }
    return false;
}
 
/**
 * test make file
 *
 * @return Boolean
 */
function is_make_file($path) {
    if ((file_exists($path) and is_writable($path)) or
        (!file_exists($path) and is_writable(dirname($path)))) {
        return true;
    } else {
        return false;
    }
}
 
/**
 * get supported languages
 *
 * @return Array
 */
function get_languages() {
    $searchPathList = explode(PATH_SEPARATOR, ini_get("include_path"));
    $languages      = array();
    foreach ($searchPathList as $dir) {
        $path = rtrim($dir, DIRECTORY_SEPARATOR) . "/geshi/";
        if (file_exists($path) and is_dir($path)) {
            $files = scandir($path);
            foreach ($files as $file) {
                if (preg_match("/(.+)\.php$/", $file, $matchs)) {
                    $languages[] = $matchs[1];
                }
            }
        }
    }
    return $languages;
}
 
/**
 * check GeSHi installed
 *
 * @return Boolean
 */
function is_installed_geshi_lib() {
    $searchPathList = explode(PATH_SEPARATOR, ini_get("include_path"));
    foreach ($searchPathList as $dir) {
        if (file_exists($dir . "/geshi.php") and is_readable($dir . "/geshi.php") and
            file_exists($dir . "/geshi/") and is_dir($dir . "/geshi/")) {
            return true;
        }
    }
    return false;
}
 
?>
プロフィール

このブログ記事について

このページは、koshigoeが2006年9月13日 22:41に書いたブログ記事です。

ひとつ前のブログ記事は「Firefoxのタブ移動」です。

次のブログ記事は「自分が今学ぶべきはelispかも」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。