LPrompter は、「ログでトリガーするプロンプター」です。
ログファイルをリアルタイムにモニターし、その内容に応じて文字や音声を出力することで、ユーザーへ行動のタイミングを報せます。「いつ、何をする」を決めるロジック部分は Lua スクリプトで記述するため、簡単かつ柔軟に「台本」を記述できます。
アプリケーションのデバッグログ、システムのアラートログ、ゲームのチャットログなどの、ファイルへ行単位のテキストで追記されていくタイプの情報をリアルタイムにモニターしてユーザーへ通知することができれば、情報を有効に活用することができます。
しかし、ログの量が多かったり、何らかの条件判断が必要な場合、情報を選択して加工する必要がでてきます。
LPrompter を使うと、情報の選択加工や、画面上への文字表示やサウンドの再生が、簡単な Lua スクリプトで実現できます。
Lua は簡素で高速な汎用スクリプト言語で、とくに組み込み用途で人気が高く、広く利用されています。複雑な処理が不要なケースでは、スクリプトの作成は簡単です。たとえば、最小機能のスクリプトは、これだけです。
function PrintError(path, log)
LP:Prompt(1, "エラーが発生しました")
end
function Initialize()
LP:AddEvent("(?i:error)", "PrintError")
end
function Terminate()
end
この例では、ログに "error" という文字列を含むテキストが現れると、エラー発生のお知らせを画面上に表示します。
更新点: 高速かつ大量のログを処理する場合にスレッド不足になるケースを改善
更新点: ファイルの縮小や削除、ファイル名の変更などの対応を改善
配布の zip ファイルには、2 つのサンプルスクリプトが同梱されています。これらのサンプルは、以下の手順で動作デモできます。
echo > C:\tmp\test.log
echo error >> C:\tmp\test.log
echo test1 >> C:\tmp\test.log
echo test2 >> C:\tmp\test.log
LPrompter を起動すると、小型のウィンドウが一つ表示されます。初期状態ではスクリプトが何もインストールされていないため、空白の下にいくつかのボタンが表示されるだけですが、スクリプトをインストールしていくと、そのリストが表示されていきます。
ウィンドウの一番下には、いくつかのボタンが並んでいます。オプションウィンドウを開くと、一部のボタンは入れ替わります。
LPrompter を終了するには、ウィンドウ右上の × をクリックしてください。
オプションウィンドウを開くと、全てのスクリプトは一時停止状態になります。また、プロンプトウィンドウに背景色がつき、移動やサイズの変更ができるようになります。
オプションウィンドウを閉じるには、ウィンドウ右上の × をクリックしてください。
プロンプトウィンドウは 4 つあり、それぞれ個別に位置や大きさ、フォントなどを設定できます。通常時はマウスクリックに対して透過するため、その下のアプリケーションへの操作を阻害しません。位置や大きさを変更したい場合は、オプションウィンドウを開いてください。
別々のスクリプトが同じプロンプトウィンドウへ同時にテキストを表示しようとすると、どちらかが表示の途中で、もう片方が上書き表示してしまいますので、ユーザーは注意する必要があります。一般的には、号の小さいプロンプトウィンドウをより重要なテキストの表示に使うのが良いでしょう。
ログファイルに関する設定項目です。これらの設定を反映するには、一度 LPromter を終了する必要があります。
プロンプトウィンドウに関する設定項目です。
音声合成に関する設定項目です。これらの設定を反映するには、一度 LPromter を終了する必要があります。
全般的な設定項目です。これらの設定を反映するには、一度 LPromter を終了する必要があります。
それぞれの Lua スクリプトは、起動時に LuaInterface の DoFile() 関数によって読み込まれ、さらにスクリプト中の Initialize() 関数が実行されます。また、終了時にはスクリプト中の Terminaite() 関数が実行されます。
組み込まれた Lua インタプリタのバージョンは 5.1.2 です。文字コードは utf-8 で記述してください。LP:Sound() 関数などで文字列を引数とする場合、[[C:\Windows\Media\ding.wav]] のように角括弧で囲む形式を使う必要があるかもしれません。
CoRoutine であれなんであれ、Lua としての機能に制限はありませんが、プロンプターとしての性格上、処理に長時間を必要とするイベントには注意が必要です。LPrompter からスクリプト内の関数の呼び出しは個別にスレッド化されていますが、Suspend ボタンによる一時停止や Disable ボタンによるスクリプトの無効化ではスレッドを強制終了することはないため、実行中のスクリプト内関数が終了するまでスレッドは動作を継続してしまいます。自スクリプトが一時停止や無効の状態になっていないか、定期的に LP:State() 関数を呼び出して確認すべきです。
また、スレッドはスクリプト単位ではなく、スクリプト内関数の呼び出し(イベント)単位で生成されるため、複数のイベントが同時に発生したり、短時間の間にイベントが重なったりすると、それぞれが別スレッドで同時に実行されることになりますので、注意してください。
添付の Sample2.lua を解説します。
-- constant
MES = {"Test 2 Success!!!", "テスト 2 成功!!!"}
-- global
state = 0
lang = 1
-- junction
function Initialize()
LP:Remark("ver. 1.1 by Q+")
LP:Status([[waiting "test1" ...]])
if LP:Variable("LANGUAGE") == "ja-JP" then
lang = 2
end
LP:AddEvent([[(?i:test1)]], "Test1")
end
function Terminate()
end
-- event
function Test1(p, s)
if state == 0 then
state = 1
LP:AddEvent([[(?i:test2)]], "Test2")
LP:Status([[waiting "test2" ...]])
end
end
function Test2(p, s)
LP:Status([[counting down ...]])
for i = 5, 0, -1 do
if LP:State() ~= 0 then
return
end
LP:Prompt(4, i, 1000, "#aaffff00")
LP:Sleep(1000)
end
LP:Prompt(1, MES[lang])
LP:Sound([[C:\Windows\Media\ding.wav]])
LP:RemoveEvent([[(?i:test2)]])
LP:Status('waiting "test1" ...')
state = 0
end
constant 部分では、プロンプトウィンドウで表示する文字列を定義しています。多言語化に対応しようとしたためです。
global 部分では、二つの変数を宣言しています。
junction 部分では、LPrompter 本体から必ず呼び出される二つの function を宣言しています。Initialize() ではコメント行とステータス行の設定、言語環境の設定、さらに一つのイベントを登録しています。
Terminate() では、何もしません。AddEvent() で登録したイベントは、Terminate() の実行直後に、自動的に RemoveEvent() されています。
Test1() は、ログファイルに test1 という文字列を含む行が登場したときに実行される function です。さらに一つのイベントを追加し、ステータス行を変更しています。
Test2() は、test2 という文字列を含む行が登場したときに実行される function です。まずステータス行を変更し、続いて 1000 ミリ秒の間隔を入れながら、カウントダウンを表示しています。このとき、自スクリプトのステートが Enable かどうかを確認し、そうでないときは実行を中止しています。カウントダウンが終了すると、テスト終了を表示し、音を鳴らします。最後に test2 のイベントを削除し、test1 文字列を待つ最初の状態へ戻します。
LP:AddEvent(string regexp, string func)
-- LP:AddEvent("^[a-z]+: err", "PrintError")
ログファイルに正規表現 regexp にマッチする行が現れたときにスクリプト中の関数 func を呼び出すよう、LPrompter にイベントを登録します。
同一の引数で複数回 LP:AddEvent() を実行した場合、それぞれ別のイベントとして登録されます。
正規表現の構文は、基本的には perl 互換ですが、詳細は 正規表現言語要素 を参照してください。
LP:RemoveEvent(string regexp, string func)
-- LP:RemoveEvent("^[a-z]+: err", "PrintError")
LP:AddEvent() で登録したイベントを削除します。
LP:Prompt(number window, string text, [optional] number msec, [optional] string color)
-- LP:Prompter(3, "WARN!", 5000, "#ff990000")
-- LP:Prompter(1, "エラー発生")
window 番目のプロンプトウィンドウへ、text で指定した文字列を表示します。有効なウィンドウ番号は 1 から 4 です。msec で、表示時間をミリ秒単位で指定できます。省略すると 2000 (2 秒) になります。color で、表示色を指定できます。フォーマットは #AARRGGBB です。省略するとユーザーがオプションウィンドウで設定した色を使用します。
LP:Status(string text)
-- LP:Status("waiting for next trigger...")
メインウィンドウのステータス表示領域に、text で指定した文字列を表示します。
LP:Remark(string text)
-- LP:Remask("ver.130605")
メインウィンドウのコメント表示領域に、text で指定した文字列を表示します。
LP:Sound(text path)
-- LP:Sound("C:\\test\\warn.mp3")
-- LP:Sound("ding.wav")
path で指定した音声ファイルを再生します。
LP:Speak(text speech)
-- LP:Speak("上を見ろ")
speech で指定した文字列を読み上げます。
読み上げには、Windows のSAPI(Speech Application Programming Interface)に対応した音声合成エンジンがインストールされている必要があります。SAPI5 対応の日本語音声合成エンジンのインストール などを参考にしてください。
LP:Sleep(number msec)
-- LP:Sleep(1000)
msec で指定したミリ秒だけ、スクリプトの動作を停止します。
number LP:State()
-- s = LP:State()
自スクリプトの状態を数値で取得します。0 でスクリプトは有効な状態、1 で一時停止状態、2 で無効化された状態になります。
この状態は、LPrompter 側が保持するスクリプトの状態であり、実際に自スクリプトがどのような状態であるかを示すものではありません。
string LP:Variable(string key)
-- value = LP:Variable("key")
オプションウィンドウで設定されたユーザー変数の内容を取得します。
See COPYRIGHT file for details.
Copyright (C) 2013 Q+.
Copyright (C) 1994-2007 Lua.org, PUC-Rio.
Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
Copyright (C) 2011 Ury Jamshy.