ユーザー定義ステートメント link

ユーザー定義ステートメント (CDS) は独自のステートメントを Ren'Py に追加出来るようにします。これにより現在の Ren'Py の文法ではサポートされない機能が追加出来ます。CDS はダイレクトな python コードより柔軟です。ほとんどの場合、繰り返し構造があるときに使用できます。例えば決まった1つの引数で関数を呼ぶときです。 Ren'Py はこの関数が何をして、どのように実行されるべきか分からないため、 実行まで何もせず、例外が出たらエラーとなります。CDSの使用により parse を使用して文法の妥当性の確認(引数が妥当な文字列かなど)や実行時に不正なデータの無視(致命的でないエラーでは、例外を投げるよりその実行をスキップした方がよいです)、(使用するなら) displayable の予想、Lint 時の追加情報の掲示(実行時に無視させてもこちらで情報を得られます)が出来ます。CDS は実行の成功は保証しませんが、ステートメントのコーティングを改善し、Ren'Py に何がしたいかを「理解」させられます。

ユーザー定義ステートメントは python early ブロックで定義され、さらにそれを定義するファイルはそれを使用するどのファイルよりも先にロードされる必要があります。 Ren'Py はユニコード順にファイルをロードするので一般的にはユーザー定義ステートメントを含めるファイル名は 01 か、それより小さい数字が接頭辞に付きます。

ユーザー定義ステートメントはそれが定義されたファイル内では使用不能です。

ユーザー定義ステートメントは renpy.register_statement() 関数を使用して登録されます。

renpy.register_statement(name, parse=None, lint=None, execute=None, predict=None, next=None, scry=None, block=False, init=False, translatable=False, execute_init=None, init_priority=0, label=None, warp=None, translation_strings=None, force_begin_rollback=False, post_execute=None, post_label=None, predict_all=True, predict_next=None) link

これはユーザー定義ステートメントを登録します。

name

これはステートメントを開始する名前のスペース区切りのリストか、または空の文字列にして新しいデフォルトステートメントを定義します ( デフォルトステートメントは say ステートメントを置き換えるでしょう )。

block

False なら、ステートメントはブロックを予測しません。 True ならブロックを予測し、 そのブロックの解釈は lexer に任せます。文字列 "script" なら、ブロックは一つ以上の Ren'Py スクリプト言語を含むものとして解釈されれます。文字列 "possible" なら、パース関数でブロックを予測するか決定します。

parse

これは Lexer オブジェクトを引数に取る関数です。この関数はステートメントを解析し、任意のオブジェクトを返すべきです。このオブジェクトは他のすべての関数に引数として渡されます。

lint

これはステートメントをチェックするために呼び出され、 parse から返された 1 つのオブジェクトを引数として渡されます。 renpy.error() を呼び出してエラーを報告するとよいでしょう。

execute

これはステートメントが実行されると呼び出される関数で、 parse から返された 1 つのオブジェクトを引数として渡されます。

execute_init

これは優先度 0 で初期化時に呼び出される関数です。

predict

これはステートメントに使用される画像を予測するために呼び出される関数で、 parse から返された 1 つのオブジェクトを引数として渡されます。 ステートメントに使用される displayable のリストを返すべきです。

next

これは次のステートメントを決定するために呼び出される関数です。

block が "script" でないなら、これには一つの引数が渡され、パース関数から返されたオブジェクトです。 block が "script" なら、追加の引数が渡され、そのブロックの最初のステートメントを名付けるオブジェクトです。

ジャンプ先のラベルを指定する文字列またはブロックへ制御を移すなら第二引数、この後のステートメントに制御を移すなら None を返す関数であるべきです。

label

ステートメントのラベルを決定する関数です。返した文字列がステートメントのラベルとしてしようされ、その他のラベル同様に呼び出しやジャンプが出来ます。

warp

ステートメントがワープ中に実行されるかを決定する関数です。関数が存在し、 True を返せばワープ中に実行され、そうでなければ実行されません。

scry

Ren'Py 内部で使用されます。

init

このステートメントの初期化時にのみ実行されるべきなら True です ( ステートメントが init ブロック内になければ自動的に init 0 ブロックに配置されます)。これは execute_init 関数に加えて execute 関数を呼び出します。

init_priority

init ブロックで初期化優先度の整数値です。

translation_strings

パースされたブロックを引数に呼び出される関数で、翻訳可能として報告される文字列のリストを返します。

force_begin_rollback

これは menucall screen のようなファストスキップを停止するステートメントでは True にするべきです。

post_execute

次のステートメントの一部としてじ実行される関数です( post_execute 関数の追加により RPYC ファイルの内容が変化するため、強制コンパイルが必要になります )。

post_label

post_execute ステートメントのラベルを決定する関数です。返した文字列がステートメントのラベルとしてしようされ、その他のラベル同様に呼び出しやジャンプが出来ます。これを使用して唯一のリターンポイントを作成できます。

predict_all

True なら、このステートメントと次のステートメントのすべての sub-parse を予測します。

predict_next

これはこのステートメントの次のステートメントのラベルを引数とする関数です。

これは次に実行するステートメントを予測するために呼び出されるべきです。ラベルか SubParse オブジェクトのリストを返します。 predict_all が True だと呼び出されません。

parse メソッドは Lexer オブジェクトを受け取ります。

class Lexer link
error(msg) link

検出されたパースエラーのリストに(現在位置とともに) msg を追加します。これは現在のステートメントのパースを停止しますが、以降のパースは妨げません。

require(thing, name=None) link

thing のパースを試み、出来なければエラーを返します。

thing が文字列なら、 match() を使用してパースを試みます。それ以外なら、 thing は引数なしで呼び出されるこの Lexer オブジェクトの他のメソッドであるべきです。 name が指定されなければ、メソッド名が (文字列であるなら thing が) メッセージに使用され、そうでないければ name が使用されます。

eol() link

lexerが行の末端に達していれば True を返します。

expect_eol() link

行の末端に達していなければエラーを投げます。

expect_noblock(stmt) link

このステートメントブロックを予測しないと示すために呼び出されます。ブロックが発見されると、例外が投げられます。 stmt はエラーとともにメッセージに追加される文字列です。

expect_block(stmt) link

このステートメントが空でないブロックを予測すると示すために呼び出されます。 stmt はエラーとともにメッセージに追加される文字列です。

has_block() link

現在行に空でないブロックがあれば True です。

match(re) link

任意の正規表現文字列にマッチします。

何かをマッチさせる lexer のすべてのステートメントは、この関数と同様な方法で実装されています。最初に空白をスキップし、その行に対してマッチするかを試みます。マッチが成功すればマッチしたテキストが返され、そうでなければ None が返され、 Lexer は変更されません。

keyword(s) link

キーワードとして s にマッチします。

name() link

名前にマッチしますが組み込みのキーワードにはマッチしません。

word() link

キーワードを含むどのような単語にもマッチします。マッチした単語を返します。

image_name_component() link

画像名にマッチします。単語と違い画像名は数字で始められます。

string() link

文字列にマッチします。

integer() link

整数にマッチし、整数の文字列を返します。

float() link

浮動小数点にマッチし、浮動小数点の文字列を返します。

label_name(declare=False) link

ラベル名または、absolute, relative にマッチします。 declare が True なら、グローバルラベルが設定され( ステートメントはラベル関数からラベルを返すためにそうする必要あるだけで、実際にはラベルを宣言しないコトに注意してください)。

simple_expression() link

単純式にマッチし、それを文字列として返します。これはしばしば変数名を期待する時に使用されます。結果の変更は推奨されません。結果を評価してください。

delimited_python(delim) link

':' のような delim で終わる Python 式にマッチします。これはしばしばデリミタまでを条件として期待する場合に使用されます。結果の変更は推奨されません。結果を評価してください。デリミタの前に行端に達すればエラーを投げます。

arguments() link

これは引数リストの丸括弧の前に呼び出されなければなりません。引数リストが確認されなければ None を返し、そうでなければ引数を表すオブジェクトを関数呼び出しに渡します。このオブジェクトには scope 辞書を省略可能な引数にとる evalute メソッドがあり、1番目が一引数のタプル、二番目がキーワード引数の辞書であるタプルを返します。

rest() link

空白をスキップし、行の残りを返します。

checkpoint() link

現在の lexer の状態を表現するオブジェクトを返します。

revert(o) link

o が checkpoint() から返されたオブジェクトなら、 lexer の状態を checkpoint() が呼び出されたときにまで戻します ( これはロールバックのために使用されます )。

subblock_lexer() link

現在のブロックと関連付けられたブロックに対する Lexer を返します。

advance() link

サブブロック lexer で、次の行に解析を進めます。一行目を解析できるようにするために、一行目よりも前で呼び出される必要があります。そのブロック内の行に進めれば、 True を返し、末端に達していれば False を返します。

renpy_statement() link

Ren'Py スクリプトステートメントとして現在行をパースし、不可能ならエラーを生成します。このメソッドは get_next() から返されたり renpy.jump()renpy.call() に渡される不透明なオブジェクトを返します。このオブジェクトはステートメントのパース結果としてを除いて保存されるべきではありません。

ステートメントがこの処理を完了すると、制御はユーザー定義ステートメントの次のステートメント( post_execute を使用して作成されたステートメントもありえます)に渡されます。

renpy_block(empty=False) link

これは現在ブロックの残りの行を Ren'Py スクリプトとしてパースし、ブロックの最初のステートメントに対応する SubParse を返します。そのブロック内で実行されるすべてのステートメントとともにブロックが処理されると、制御はこのユーザー定義ステートメントの次のステートメントに渡されます。

これは現在のブロックをパースすることに注意してください。。現在のステートメントのサブブロックをパースしたい場合は、以下のようにしてください。

def mystatement_parse(l):

    l.require(':')
    l.expect_eol()
    l.expect_block("mystatement")

    child = l.subblock_lexer().renpy_block()

    return { "child" : child }
empty

True なら、空のブロックもパースされます( 空のブロックは pass ステートメントのみのブロックと等価です )。

False なら、空のブロックでエラーとなります。

catch_error() link

これは with ステートメントと共に使用され、そのコンテキストブロックないで Lexer エラーをキャッチしてレポートし、次のブロックに続ける context decorator です。

こちらは1つのサブブロック内での複数のエラーをどのようにレポートするかの例です。

def mystatement_parse(l):

    l.require(':')
    l.expect_eol()
    l.expect_block("mystatement")

    strings = [ ]
    ll = l.subblock_lexer()

    while ll.advance():
        with ll.catch_errors():
            strings.append(ll.require(ll.string))
            ll.expect_noblock("string inside mystatement")
            ll.expect_eol()

    return { "strings" : strings }

Lint 用ユーティリティー関数 link

これらの関数は lint 関数を記述するのに便利です。

renpy.check_text_tags(s) link

s 内部のテキストタグが正しいかチェックします。エラーがあればエラー文字列を、なければ None を返します。

renpy.error(msg) link

ユーザーに対してエラーとして表示文字列 msg です。

renpy.try_compile(where, expr, additional=None) link

式をコンパイルし、エラーがあればそれを lint.txt に書き出します。

where

式が見つかる場所を指定する文字列です。 "whereexpr を評価できません。 " のような形式でエラーメッセージを生成するために使用されます。

expr

コンパイルを試みる式です。

additional

指定すると、エラーメッセージへの追加情報となる行になります。

renpy.try_eval(where, expr, additional=None) link

式の評価を試み、 失敗すると lint.txt にエラーを書き込みます。

where

式が見つかる場所を指定する文字列です。 "whereexpr を評価できません。 " のような形式でエラーメッセージを生成するために使用されます。

expr

評価を試みる式です。

additional

指定すると、エラーメッセージへの追加情報となる行になります。

link

ここでは新しいステートメント line を作成し、クォーテーションを付けずにテキストを指定できるようにしています。:

python early:

    def parse_smartline(lex):
        who = lex.simple_expression()
        what = lex.rest()
        return (who, what)

    def execute_smartline(o):
        who, what = o
        renpy.say(eval(who), what)

    def lint_smartline(o):
        who, what = o
        try:
            eval(who)
        except:
            renpy.error("Character not defined: %s" % who)

        tte = renpy.check_text_tags(what)
        if tte:
            renpy.error(tte)

    renpy.register_statement("line", parse=parse_smartline, execute=execute_smartline, lint=lint_smartline)

これは以下のように記述して使用出来ます。

line e "These quotes will show up," Eileen said, "and don't need to be backslashed."