概要

  • PukiWiki の codehighlight プラグイン用のキーワード設定ファイルを作成する。
  • CSS のグループとキーワードを .yml ファイルから読み取る。
  • 単語一つ一つにどのグループに属するか書くのが面倒なので…。
  • 文字スイッチとコメントも設定ファイルから設定できるように機能追加。(2013/02/02)
  • アウトライン用文字スイッチも設定できるように機能追加。(2013-02-10)
  • Script-Fu用設定ファイルのサンプルを追加。(2013-02-10)

ソース

makeKeyword.pl

#!/usr/bin/perl
# PukiWiki CodeHighlight プラグイン用キーワード設定ファイル生成スクリプト

use strict;
use warnings;
use utf8;
use Encode;
use YAML::Syck;

$YAML::Syck::ImplicitUnicode = 1;
#$YAML::Syck::ImplicitTyping = 1;
$YAML::Syck::Headless = 1;

my $config_file = $ARGV[0] or die( "usage: makeKeyword <Config>\n" );
my $inputname = my $outputname = 'keyword.template.php';

my $config = YAML::Syck::LoadFile( "$config_file" ) or die( "$config_file: $!\n" );
$outputname =~ s/template/lc($config->{'Name'})/e;
my $ignore_case = ( $config->{'IgnoreCase'} =~ /true|1/i );

my $charclass = "";
foreach my $class ( sort( keys( %{$config->{'CharClass'}} ) ) ){
	foreach my $char ( @{$config->{'CharClass'}{$class}} ){
		$charclass .= "\$switchHash['$char']\t= PLUGIN_CODE_$class;\n";
	}
}

my $comment = "";
my @comment_switches = sort( keys( %{$config->{'Comment'}} ) );
foreach my $char ( @comment_switches ){
	$comment .= "\$switchHash['$char']\t= PLUGIN_CODE_COMMENT;\n";
}
$comment .= "\$code_comment = Array(\n";
foreach my $char ( @comment_switches ){
	$comment .= "\t'$char' => Array(\n";
	foreach my $def ( @{$config->{'Comment'}{$char}} ){
		$comment .= "\t\tArray( '/^" . quotemeta( $def->[0] ). "/', \"$def->[1]\", $def->[2] ),\n";
	}
	$comment .= "\t),\n";
}
$comment .= ");\n";

my $outline = "";
foreach my $outline_pair ( @{$config->{'Outline'}} ){
	$outline .= "\t\$switchHash['" . $outline_pair->[0] . "']\t= PLUGIN_CODE_BLOCK_START;\n";
	$outline .= "\t\$switchHash['" . $outline_pair->[1] . "']\t= PLUGIN_CODE_BLOCK_END;\n";
}

my $keywords = "";
my @types = sort( keys( %{$config->{'Keywords'}} ) );
for( my $i=0; $i<@types; ++$i ){
	$keywords .= "// " . $types[$i] . "\n";
	my $index = $i + 1;
	foreach my $word ( sort( @{$config->{'Keywords'}{$types[$i]}} ) ){
		if ( $ignore_case ){ $word = lc( $word ); }
		$keywords .= "\t'$word'\t=> $index,\n";
	}
}

open( my $IN, "<:utf8", $inputname ) 
	or die( "$inputname: $!\n" );
my @body = <$IN>;
close( $IN );
my $body = join( "", @body );

$body =~ s/__Name__/$config->{'Name'}/g;
$body =~ s/__IgnoreCase__/($ignore_case)?'true':'false'/e;
$body =~ s/__CharClass__\n/$charclass/;
$body =~ s/__Comment__\n/$comment/;
$body =~ s/__Outline__\n/$outline/;
$body =~ s/__Types__\n/join("",map{"\t'$_',\n";}@types)/e;
$body =~ s/__Keywords__\n/$keywords/;

# CrLf で保存される
open( my $OUT, ">:utf8", $outputname ) 
	or die( "$outputname: $!\n" );
print $OUT $body;
close( $OUT );

# EOF

keyword.template.php

<?php
/**
 * __Name__ キーワード定義ファイル
 */

$capital = __IgnoreCase__;

__CharClass__

// コメント定義
__Comment__

// アウトライン用
if($mkoutline){
__Outline__
}

$code_css = Array(
__Types__
);

$code_keyword = Array(
__Keywords__
);
?>

Dummy

ymlファイル

# Dummy キーワード

Name: Dummy
IgnoreCase: false

CharClass:
  SPECIAL_IDENTIFIRE: [ "#", @ ]
  NONESCAPE_LITERAL:  [ \' ]

Comment:
  "/": [
    [ /*, */, 2 ], 
    [ //, \n, 1 ]
  ]
  "-": [
    [ --, \n, 1 ]
  ]

Outline:
  - [ "{", "}" ]

Keywords:
  # オペレータ
  operator: [
    Mod, Div, Not, Or, And
  ]

  # 識別子
  identifier: [
    New, In, This, Var, Const, With, Function
  ]

  # 制御構文
  control: [
    If, Else, While, For, Break, Continue, Switch, Case, Default, 
    Return, Try, Catch
  ]

  # 標準関数
  function: [
    Abs, Floor, Ceil, Rand, Round
  ]

  # 定数
  constant: [
    "True", "False", "Null"
  ]

  # module, import, 将来対応する pragma
  pragma: [
    module, import, using, 
    '#define', '#undef', '#if', '#elif', '#else', '#endif', 
    '#error', '#warning', '#region', '#endregion', '#line'
  ]

  # __stdcall などの処理系専用の奴とか
  system: [
    Console, Dictionary, Encoding, Exception, IDictionary, Match, 
    MatchCollection, Object, Program, Regex, String
  ]

  # 環境変数
  environment: [
    Env
  ]

  # SQL
  sql: [
    SELECT, INTO, FROM, WHERE, IN, GROUP, HAVING, ORDER, BY, ASC, DESC, 
    AS, DISTINCT, TOP, JOIN, "ON", LIMIT, UNION, ALL, 
    INSERT, VALUES, DUPLICATE, KEY, UPDATE, SET, DELETE, 
    USE, GO
  ]

# EOF

適用結果

/**
	Dummy サンプル
*/
#if !defined(BUFFER)
#define	BUFFER	(1024)
#endif

Var sql1 = qq{
-- ユーザ選択
	SELECT `ID`, `Gender`, `Age`
	FROM `Users`
	WHERE `Name` == :Name
};

Function isExistUser( username ){
	Var find = False;
	Var id = "";
	Var gender = 0;
	Var age = 0;
	Var sth = dbh.prepare( sql1 );
	sth.bind( "Name", username );
	sth.execute();
	While( Var record = sth.fetchrow_array() ){
		find = True;
		id = record[0];
		gender = record[1];
		age = record[2];
		If ( gender == 2 And age > 30 ){
			age = Ceil( age / 10 ) * 10;
		}
		Console.WriteLine("{0}: {1}, {2}", username, id, age);
	}
	Return ( find, id, age );
}

// EOF

Script-Fu

ymlファイル

# Script-Fu キーワード

Name: Script-Fu
IgnoreCase: false

CharClass:
  SPECIAL_IDENTIFIRE: [ "*", "!", "-" ]

Comment:
  ";": [
    [ ;, \n, 1 ]
  ]

Outline:
  - [ "{", "}" ]
  - [ "(", ")" ]
  - [ "[", "]" ]

Keywords:
  # オペレータ
  operator: [
  ]

  # 識別子
  identifier: [
    define, let, let*, cons, list, vector, vector-, set, set!, for-each, lambda, 
    if, char, 
    car, cdr, caar, cadr, cdar, cddr, 
    string-append, string-ref, 
    gimp-context-pop, 
    gimp-context-push, 
    gimp-context-set-background, 
    gimp-context-set-foreground, 
    gimp-display-new, 
    gimp-displays-flush, 
    gimp-drawable-fill, 
    gimp-drawable-get-name, 
    gimp-drawable-height, 
    gimp-drawable-width, 
    gimp-edit-fill, 
    gimp-file-save, 
    gimp-image-add-layer, 
    gimp-image-clean-all, 
    gimp-image-flatten, 
    gimp-image-get-layers, 
    gimp-image-lower-layer, 
    gimp-image-lower-layer-to-bottom, 
    gimp-image-merge-down, 
    gimp-image-new, 
    gimp-image-resize, 
    gimp-image-undo-group-end, 
    gimp-image-undo-group-start, 
    gimp-layer-copy, 
    gimp-layer-new, 
    gimp-layer-set-lock-alpha, 
    gimp-layer-set-name, 
    gimp-layer-set-offsets, 
    gimp-layer-resize, 
    gimp-selection-grow, 
    gimp-selection-layer-alpha, 
    gimp-selection-none, 
    gimp-text-fontname, 
    script-fu-menu-register, 
    script-fu-register, 
    script-fu-text-box, 
    script-fu-util-image-add-layers
  ]

  # 制御構文
  control: [
  ]

  # 標準関数
  function: [
  ]

  # 定数
  constant: [
    "TRUE", "FALSE",
    PIXELS, RGB-IMAGE, NORMAL, 
    BACKGROUND-FILL, FOREGROUND-FILL, 
    SF-IMAGE, SF-DRAWABLE, SF-VALUE, SF-STRING, SF-COLOR, SF-TOGGLE, 
    SF-ADJUSTMENT, SF-FONT, SF-BRUSH, SF-PATTERN, SF-GRADIENT, 
    SF-PALETTE, SF-FILENAME, SF-DIRNAME, SF-OPTION, SF-ENUM, 
    RUN-INTERACTIVE, RUN-NONINTERACTIVE, RUN-WITH-LAST-VALS
  ]

  # module, import, 将来対応する pragma
  pragma: [
  ]

  # __stdcall などの処理系専用の奴とか
  system: [
  ]

  # 環境変数
  environment: [
  ]

# EOF