# BluntIRCのスクリプト機能

## 概要

BluntIRCはDynamicJavaを内蔵しています。 プラグインを書いてフックやアクションを登録することでIRCクライアントの機能を拡張することができます。

## スクリプトの登録と管理

メニューのTool-スクリプト一覧から スクリプトの追加、削除、開始、停止、更新を行えます。

## hello world

じゃ最初はhello world から。 この例ではテキストをバッファに出力します。

hello.djava

## アクション

アクションはユーザの操作から実行される機能を追加するためのものです。 hook_manager.addScriptAction() にアクションの名前と、 javax.Swing.Action を実装したクラスのオブジェクトを指定することで登録されます。 アクションの名前はスクリプトのファイル名とaddScriptActionに指定した名前を ハイフンでつないだものになります。 例えばスクリプトがsample3.djavaというファイル名で登録時に"test"と指定した場合、 登録されたアクションの名前は sample3-test になります。

ユーザがアクションを呼び出す方法はいくつかあります。

- 入力バッファに /sample3-test というふうにアクションの名前を入力する
- メニュー設定ファイルにアクションを指定する。キーボードアクセラレータの設定も可能。

sample3.djava

## アクションの引数と戻り値

引数を得るには App.action_manager.getStackParameter() を使用します。 引数の型はinstanceofを使って判断することができます。

- /call-test aaa bbb ccc のように入力して実行した場合は 文字列が得られるでしょう。
- メニューやボタンから実行した場合はnullになるでしょう。 この場合は ActionEvent#getActionCommand() でActionCommandを読めるかもしれません。
- 他のスクリプトから呼び出された場合は何も仮定できません。

戻り値はApp.action_manager.setStackParameter() で設定できます。 設定しない場合は引数と同じものが戻り値になります。

アクションの引数と戻り値を扱うサンプル

call.djava

## フック

フックはイベントが発生した際に何か処理を行ったりメッセージを書き換えたりするものです。 pluginがフックの種類ごとに用意されたinterfaceをimplementsすると イベントが発生した時に呼び出されます。 フックの詳細は sources/hook フォルダを参照してください。

timer.djava

autoOp.djava

## アプリケーションへのアクセス

スクリプトとアプリケーションは同じ空間で動いています。 アプリケーション固有のクラス及びJ2SEのクラスを普通に使用できます。

ここではアプリケーション固有のクラスのいくつかについて説明します。

class bluntirc.App extends JFrame
  アプリケーションの主ウィンドウです。 staticメソッド getApp() でインスタンスを取得できます。
class bluntirc.ConnTreeNode
  接続、チャンネル、プリブバッファなどの「バッファを持つ項目」です。
  サブクラスには CTN_App CTN_Conn CTN_Chan CTN_Priv があり、ツリー状の階層を持っています。
  現在選択中のノードは App.getSelected() で取得できます。
  また、ノードは任意のパラメータを拡張するための PropertyManager property を持っています。
class bluntirc.PropertyManager
  接続ツリーのノードごとに保持されます。 プロパティはTreeMap,LinkedList,Stringを組み合わせた階層を持ったデータです。 プログラム及びスクリプトが扱う情報を格納するためのものです。 どのような型のオブジェクトも格納できますが、 プログラムの再起動を行っても保持されるのは上記の3つの型のデータだけです。 ユーザはプロパティインスペクタを使用して情報の閲覧と編集が行えます。
irc.IRCMessage
  IRCサーバから送られてきたメッセージを表すクラスです。

## 細かい注意点

- 日本語を扱う場合はソースをUTF-8で保存するようにしてください。
- パッケージ名は好きに設定して構いませんが、 名称を省略するとDynamicJavaが匿名パッケージを用意してくれます。
- トップレベルに変数や関数を書くと スクリプトの最初の評価(ロード前)に実行されますが、 フックやアクションの内部からはトップレベルの変数や関数にアクセスできません。 従ってあまり有用ではないと思います。

  スクリプトのロードとアンロードはスクリプト全体の評価の後に行われます。

  ロード時
    hook_manager などの変数をインタプリタのトップレベルに定義する
    plugin=new Plugin(hook_manager); をインタプリタから評価する
  アンロード時
    アクションとフックの登録を解除
    plugin.unload(); をインタプリタから評価する
- awt/swing を使う関係上、スレッドの使用はなるべく控えること。 awt/swingと競合しない用途、たとえばソケットからの読み込みのためだけに スレッドを使うのはOKだが、読んだ結果から何かする前にSwingUtility#invokeLater を通すこと。