Author: Sébastien Helleu

# WeeChat スクリプト作成ガイド

Sébastien Helleu
flashcode@flashtux.org
version 2.0.1

翻訳者:

- Ryuunosuke Ayanokouzi <i38w7i3@yahoo.co.jp>, 2012-2017

このマニュアルは WeeChat チャットクライアントについて説明しており、WeeChat の一部です。

このマニュアルの最新版は以下のページを参照してください: https://weechat.org/doc

## 1. イントロダクション

WeeChat (Wee Enhanced Environment for Chat) はフリー、高速、軽量な多くのオペレーティングシステムで動くチャットクライアントです。

このマニュアル文書は以下のスクリプト言語を利用して WeeChat 用のスクリプトを製作する方法を解説しています:

- Python

- Perl

- Ruby

- Lua

- Tcl

- Guile (Scheme)

- JavaScript

- PHP

| この文書に含まれるほぼすべての例は Python で書かれていますが API は他の言語でも共通です。

## 2. WeeChat のスクリプト

### 2.1. 言語仕様

#### 2.1.1. Python

- 必ず `import weechat` を使ってください。

- python では `print*` 系の関数は `prnt*` と書きます (print は予約済みキーワードなので)。

- 関数は `weechat.xxx(arg1, arg2, …​)` のように呼び出してください。

#### 2.1.2. Perl

- 関数は `weechat::xxx(arg1, arg2, …​);` のように呼び出してください。

#### 2.1.3. Ruby

- weechat_init を定義して、内部で register を呼び出してください。

- 関数は `Weechat.xxx(arg1, arg2, …​)` のように呼び出してください。

- Ruby では関数に渡せる引数の数が最大 15 個に制限されているため、`Weechat.config_new_option` 関数はコールバック用の引数群を 6 個の文字列からなる 1 個の配列で受け取ります (3 個のコールバック + 3 個のデータ文字列)、したがって `Weechat.config_new_option` 関数を呼び出すには以下のようにしてください:

    Weechat.config_new_option(config, section, "name", "string", "description of option", "", 0, 0,
                              "value", "value", 0, ["check_cb", "", "change_cb", "", "delete_cb", ""])

#### 2.1.4. Lua

- 関数は `weechat.xxx(arg1, arg2, …​)` のように呼び出してください。

#### 2.1.5. Tcl

- 関数は `weechat::xxx arg1 arg2 …​` のように呼び出してください。

#### 2.1.6. Guile (Scheme)

- 関数は `(weechat:xxx arg1 arg2 …​)` のように呼び出してください。

- 以下の関数は引数のリストをひとつだけ取ります (他の関数のように多くの引数を取れません)、この理由は引数の個数が Guile で利用できる引数の数を超えるからです。

  - config_new_section

  - config_new_option

  - bar_new

#### 2.1.7. JavaScript

- 関数は `weechat.xxx(arg1, arg2, …​);` のように呼び出してください。

#### 2.1.8. PHP

- 関数は `weechat_xxx(arg1, arg2, …​);` のように呼び出してください。

### 2.2. 関数の登録

全ての WeeChat スクリプトは WeeChat に自分自身を「登録」し、登録はスクリプトの最初で行われなければいけません。

プロトタイプ:

    weechat.register(name, author, version, license, description, shutdown_function, charset)

引数:

- name: 文字列型、スクリプトの内部名

- author: 文字列型、作者名

- version: 文字列型、スクリプトのバージョン

- license: 文字列型、スクリプトのライセンス

- description: 文字列型、スクリプトの短い説明

- shutdown_function: 文字列型、スクリプトがアンロードされた際に呼び出される関数の名前 (空文字列でも可)

- charset: 文字列型、スクリプトの文字コード (UTF-8 はデフォルトの文字コードなので、スクリプトが UTF-8 で書かれている場合、空文字列を指定してください)

各言語で書かれたスクリプトの例:

- Python:

    import weechat

    weechat.register("test_python", "FlashCode", "1.0", "GPL3", "Test script", "", "")
    weechat.prnt("", "Hello, from python script!")

- Perl:

    weechat::register("test_perl", "FlashCode", "1.0", "GPL3", "Test script", "", "");
    weechat::print("", "Hello, from perl script!");

- Ruby:

    def weechat_init
      Weechat.register("test_ruby", "FlashCode", "1.0", "GPL3", "Test script", "", "")
      Weechat.print("", "Hello, from ruby script!")
      return Weechat::WEECHAT_RC_OK
    end

- Lua:

    weechat.register("test_lua", "FlashCode", "1.0", "GPL3", "Test script", "", "")
    weechat.print("", "Hello, from lua script!")

- Tcl:

    weechat::register "test_tcl" "FlashCode" "1.0" "GPL3" "Test script" "" ""
    weechat::print "" "Hello, from tcl script!"

- Guile (Scheme):

    (weechat:register "test_scheme" "FlashCode" "1.0" "GPL3" "Test script" "" "")
    (weechat:print "" "Hello, from scheme script!")

- JavaScript:

    weechat.register("test_js", "FlashCode", "1.0", "GPL3", "Test script", "", "");
    weechat.print("", "Hello, from javascript script!");

- PHP:

    weechat_register('test_php', 'FlashCode', '1.0', 'GPL3', 'Test script', '', '');
    weechat_print('', 'Hello, from PHP script!');

### 2.3. スクリプトのロード

スクリプトをロードするには "script" プラグインを使うことを推奨します。例:

    /script load script.py
    /script load script.pl
    /script load script.rb
    /script load script.lua
    /script load script.tcl
    /script load script.scm
    /script load script.js
    /script load script.php

プログラミング言語ごとの固有コマンドを利用することもできます:

    /python load script.py
    /perl load script.pl
    /ruby load script.rb
    /lua load script.lua
    /tcl load script.tcl
    /guile load script.scm
    /javascript load script.js
    /php load script.php

WeeChat の開始時にスクリプトを自動ロードするには language/autoload ディレクトリ内にリンクを作ってください。

例えば Python の場合:

    $ cd ~/.weechat/python/autoload
    $ ln -s ../script.py

| `/script install` コマンドでスクリプトをインストールした場合、autoload ディレクトリ内にリンクが自動的に作成されます。

## 3. C API との違い

スクリプト API は C 言語プラグイン API とほぼ同じです。API に含まれる各関数の詳細 (プロトタイプ、引数、戻り値、例) については WeeChat プラグイン API リファレンスを参照してください。

プラグイン と スクリプト の違いを理解することは重要です: プラグイン とはコンパイル済みバイナリファイルで `/plugin` コマンドを使ってロードします、これに対して スクリプト とはテキストファイルで例えば python プラグインであれば `/python` コマンドを使ってロードします。

例えば test.py スクリプトが WeeChat API 関数を呼び出す場合、以下の順に呼び出されます:

                   ┌──────────────────────┐        ╔══════════════════╗
                   │     python plugin    │        ║  WeeChat "core"  ║
                   ├────────────┬─────────┤        ╟─────────┐        ║
    test.py ─────► │ script API │  C API  │ ─────► ║  C API  │        ║
                   └────────────┴─────────┘        ╚═════════╧════════╝

WeeChat が test.py スクリプトで定義されたコールバックを呼び出す場合、順番は逆になります:

    ╔══════════════════╗        ┌──────────────────────┐
    ║  WeeChat "core"  ║        │     python plugin    │
    ║        ┌─────────╢        ├─────────┬────────────┤
    ║        │  C API  ║ ─────► │  C API  │ script API │ ─────► test.py
    ╚════════╧═════════╝        └─────────┴────────────┘

### 3.1. ポインタ

ご存知かもしれませんが、スクリプトには本当の意味での「ポインタ」はありません。このため API 関数がポインタを返す場合、スクリプトでは文字列に変換されます。

例えば、関数がポインタ 0x1234ab56 を返した場合、スクリプトは "0x1234ab56" という文字列を受け取ることになります。

API 関数の引数にポインタを与える場合、スクリプトではポインタを文字列型として渡さなければいけません。C 言語 API 関数を呼び出す前に C 言語プラグインがこれを本来のポインタ型に変換します。

空文字列や "0x0" を使うことも許されています。これらは C 言語で言うところの NULL と解釈されます。例えば、データをコアバッファ (WeeChat メインバッファ) に表示する場合、以下のようになります:

    weechat.prnt("", "hi!")

| WeeChat の多くのスクリプト API 関数は計算量を減らすために、ポインタの値が正当なものか否かの確認を行いません。ポインタの正当性を確認することはプログラマが行わなければいけません。不正なポインタを利用した場合、細かなクラッシュレポートを目にすることになるでしょう ;)

### 3.2. コールバック

ほとんど全ての WeeChat コールバックは WEECHAT_RC_OK または WEECHAT_RC_ERROR を返さなければいけません (modifier コールバックは例外で、これは文字列を返します)。

C 言語コールバックはポインタ型の "data" 引数を利用します。スクリプト API では、"data" は文字列型で任意の値を取れます (ポインタ型ではありません)。

各プログラミング言語でコールバックを利用する例:

- Python:

    def timer_cb(data, remaining_calls):
        weechat.prnt("", "timer! data=%s" % data)
        return weechat.WEECHAT_RC_OK

    weechat.hook_timer(1000, 0, 1, "timer_cb", "test")

- Perl:

    sub timer_cb {
        my ($data, $remaining_calls) = @_;
        weechat::print("", "timer! data=$data");
        return weechat::WEECHAT_RC_OK;
    }

    weechat::hook_timer(1000, 0, 1, "timer_cb", "test");

- Ruby:

    def timer_cb(data, remaining_calls)
      Weechat.print("", "timer! data=#{data}");
      return Weechat::WEECHAT_RC_OK
    end

    Weechat.hook_timer(1000, 0, 1, "timer_cb", "test");

- Lua:

    function timer_cb(data, remaining_calls)
        weechat.print("", "timer! data="..data)
        return weechat.WEECHAT_RC_OK
    end

    weechat.hook_timer(1000, 0, 1, "timer_cb", "test")

- Tcl:

    proc timer_cb { data remaining_calls } {
        weechat::print {} "timer! data=$data"
        return $::weechat::WEECHAT_RC_OK
    }

    weechat::hook_timer 1000 0 1 timer_cb test

- Guile (Scheme):

    (define (timer_cb data remaining_calls)
      (weechat:print "" (string-append "timer! data=" data))
      weechat:WEECHAT_RC_OK
    )

    (weechat:hook_timer 1000 0 1 "timer_cb" "test")

- JavaScript:

    function timer_cb(data, remaining_calls) {
        weechat.print("", "timer! data=" + data);
        return weechat.WEECHAT_RC_OK;
    }

    weechat.hook_timer(1000, 0, 1, "timer_cb", "test");

- PHP:

    $timer_cb = function ($data, $remaining_calls) {
        weechat_print('', 'timer! data=' . $data);
        return WEECHAT_RC_OK;
    };

    weechat_hook_timer(1000, 0, 1, $timer_cb, 'test');

## 4. スクリプト API

API に含まれる関数の詳しい情報は WeeChat プラグイン API リファレンスを参照してください。

### 4.1. 関数

スクリプト API に含まれる関数のリスト:

カテゴリ | 関数
--- | ---
一般 | register
プラグイン | plugin_get_name
設定 | charset_set iconv_to_internal iconv_from_internal gettext ngettext strlen_screen string_match string_has_highlight string_has_highlight_regex string_mask_to_regex string_remove_color string_is_command_char string_input_for_buffer string_eval_expression string_eval_path_home
ディレクトリ操作 | mkdir_home mkdir mkdir_parents
ソート済みリスト | list_new list_add list_search list_search_pos list_casesearch list_casesearch_pos list_get list_set list_next list_prev list_string list_size list_remove list_remove_all list_free
設定ファイル | config_new config_new_section config_search_section config_new_option config_search_option config_string_to_boolean config_option_reset config_option_set config_option_set_null config_option_unset config_option_rename config_option_is_null config_option_default_is_null config_boolean config_boolean_default config_integer config_integer_default config_string config_string_default config_color config_color_default config_write_option config_write_line config_write config_read config_reload config_option_free config_section_free_options config_section_free config_free config_get config_get_plugin config_is_set_plugin config_set_plugin config_set_desc_plugin config_unset_plugin
キー割り当て | key_bind key_unbind
表示 | prefix color print (python では prnt) print_date_tags (python では prnt_date_tags) print_y (python では prnt_y) log_print
フック | hook_command hook_command_run hook_timer hook_fd hook_process hook_process_hashtable hook_connect hook_print hook_signal hook_signal_send hook_hsignal hook_hsignal_send hook_config hook_completion hook_completion_get_string hook_completion_list_add hook_modifier hook_modifier_exec hook_info hook_info_hashtable hook_infolist hook_focus hook_set unhook unhook_all
バッファ | buffer_new current_buffer buffer_search buffer_search_main buffer_clear buffer_close buffer_merge buffer_unmerge buffer_get_integer buffer_get_string buffer_get_pointer buffer_set buffer_string_replace_local_var buffer_match_list
ウィンドウ | current_window window_search_with_buffer window_get_integer window_get_string window_get_pointer window_set_title
ニックネームリスト | nicklist_add_group nicklist_search_group nicklist_add_nick nicklist_search_nick nicklist_remove_group nicklist_remove_nick nicklist_remove_all nicklist_group_get_integer nicklist_group_get_string nicklist_group_get_pointer nicklist_group_set nicklist_nick_get_integer nicklist_nick_get_string nicklist_nick_get_pointer nicklist_nick_set
バー | bar_item_search bar_item_new bar_item_update bar_item_remove bar_search bar_new bar_set bar_update bar_remove
コマンド | command
インフォ | info_get info_get_hashtable
インフォリスト | infolist_new infolist_new_item infolist_new_var_integer infolist_new_var_string infolist_new_var_pointer infolist_new_var_time infolist_get infolist_next infolist_prev infolist_reset_item_cursor infolist_search_var infolist_fields infolist_integer infolist_string infolist_pointer infolist_time infolist_free
hdata | hdata_get hdata_get_var_offset hdata_get_var_type_string hdata_get_var_array_size hdata_get_var_array_size_string hdata_get_var_hdata hdata_get_list hdata_check_pointer hdata_move hdata_search hdata_char hdata_integer hdata_long hdata_string hdata_pointer hdata_time hdata_hashtable hdata_compare hdata_update hdata_get_string
アップグレード | upgrade_new upgrade_write_object upgrade_read upgrade_close

### 4.2. 定数

スクリプト API に含まれる定数のリスト:

カテゴリ | 定数
--- | ---
リターンコード | WEECHAT_RC_OK WEECHAT_RC_OK_EAT WEECHAT_RC_ERROR
設定ファイル | WEECHAT_CONFIG_READ_OK WEECHAT_CONFIG_READ_MEMORY_ERROR WEECHAT_CONFIG_READ_FILE_NOT_FOUND WEECHAT_CONFIG_WRITE_OK WEECHAT_CONFIG_WRITE_ERROR WEECHAT_CONFIG_WRITE_MEMORY_ERROR WEECHAT_CONFIG_OPTION_SET_OK_CHANGED WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE WEECHAT_CONFIG_OPTION_SET_ERROR WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET WEECHAT_CONFIG_OPTION_UNSET_OK_RESET WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED WEECHAT_CONFIG_OPTION_UNSET_ERROR
ソート済みリスト | WEECHAT_LIST_POS_SORT WEECHAT_LIST_POS_BEGINNING WEECHAT_LIST_POS_END
ホットリスト | WEECHAT_HOTLIST_LOW WEECHAT_HOTLIST_MESSAGE WEECHAT_HOTLIST_PRIVATE WEECHAT_HOTLIST_HIGHLIGHT
プロセスのフック | WEECHAT_HOOK_PROCESS_RUNNING WEECHAT_HOOK_PROCESS_ERROR
接続のフック | WEECHAT_HOOK_CONNECT_OK WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED WEECHAT_HOOK_CONNECT_PROXY_ERROR WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR WEECHAT_HOOK_CONNECT_MEMORY_ERROR WEECHAT_HOOK_CONNECT_TIMEOUT WEECHAT_HOOK_CONNECT_SOCKET_ERROR
シグナルのフック | WEECHAT_HOOK_SIGNAL_STRING WEECHAT_HOOK_SIGNAL_INT WEECHAT_HOOK_SIGNAL_POINTER

## 5. 良くあるタスク

この章ではいくつかの良くあるタスクを例を交えて紹介します。ここでは API の一部の機能を使っています。完全なリファレンスは WeeChat プラグイン API リファレンスを参照してください。

### 5.1. バッファ

#### 5.1.1. メッセージの表示

WeeChat コアバッファに対して操作する場合、空文字列を使うことが多いです。他のバッファに対して操作する場合には、ポインタ (文字列型、ポインタ を参照) を与える必要があります。

例:

    # "hello" をコアバッファに表示
    weechat.prnt("", "hello")

    # "hello" をコアバッファに表示するが、ログファイルには書き込まない
    # (WeeChat バージョン 0.3.3 以上で利用可)
    weechat.prnt_date_tags("", 0, "no_log", "hello")

    # プレフィックス "==>" とメッセージ "hello" を現在のバッファに表示
    # (プレフックストメッセージはタブで区切ってください)
    weechat.prnt(weechat.current_buffer(), "==>\thello")

    # コアバッファにエラーメッセージを表示 (エラープレフィックスを利用)
    weechat.prnt("", "%swrong arguments" % weechat.prefix("error"))

    # コアバッファに色付きメッセージを表示
    weechat.prnt("", "text %syellow on blue" % weechat.color("yellow,blue"))

    # バッファを検索してメッセージを表示
    # (バッファの完全な名前は plugin.name のような形です、例えば: "irc.freenode.#weechat")
    buffer = weechat.buffer_search("irc", "freenode.#weechat")
    weechat.prnt(buffer, "message on #weechat channel")

    # ある IRC バッファを見つける他の方法 (推奨)
    # (サーバとチャンネルはコンマで区切ってください。)
    buffer = weechat.info_get("irc_buffer", "freenode,#weechat")
    weechat.prnt(buffer, "message on #weechat channel")

| Print 関数は Python では `prnt`、その他の言語では `print` と呼ばれます。

#### 5.1.2. バッファにテキストを送信

テキストやコマンドをバッファに送信できます。これはテキストやコマンドをタイプして [Enter] を押すことに対応します。

例:

    # 現在のバッファでコマンド "/help" を実行 (結果は core バッファに出力されます)
    weechat.command("", "/help")

    # テキスト "hello" を #weechat IRC チャンネルに送信 (このチャンネルにいるユーザにはメッセージが見えます。)
    buffer = weechat.info_get("irc_buffer", "freenode,#weechat")
    weechat.command(buffer, "hello")

#### 5.1.3. 新規バッファの作成

スクリプトを使って新しいバッファを作成し、このバッファにメッセージを表示させることができます。

2 つのコールバックを定義できます (任意): データの入力時に呼び出されるもの (バッファでテキストを入力して [Enter] を押した時) と、バッファが閉じられたときに呼び出されるもの (例えば `/buffer close` した時等) です。

例:

    # データの入力時に呼び出されるコールバック
    def buffer_input_cb(data, buffer, input_data):
        # ...
        return weechat.WEECHAT_RC_OK

    # バッファが閉じられた時に呼び出されるコールバック
    def buffer_close_cb(data, buffer):
        # ...
        return weechat.WEECHAT_RC_OK

    # バッファの作成
    buffer = weechat.buffer_new("mybuffer", "buffer_input_cb", "", "buffer_close_cb", "")

    # タイトルの設定
    weechat.buffer_set(buffer, "title", "This is title for my buffer.")

    # ローカル変数 "no_log" に "1" を設定することでログ保存を無効化
    weechat.buffer_set(buffer, "localvar_set_no_log", "1")

#### 5.1.4. バッファプロパティ

文字列、整数、ポインタ型のバッファプロパティを読むことができます。

例:

    buffer = weechat.current_buffer()

    number = weechat.buffer_get_integer(buffer, "number")
    name = weechat.buffer_get_string(buffer, "name")
    short_name = weechat.buffer_get_string(buffer, "short_name")

バッファに対するローカル変数を追加、ロード、削除することができます:

    # ローカル変数の追加
    weechat.buffer_set(buffer, "localvar_set_myvar", "my_value")

    # ローカル変数のロード
    myvar = weechat.buffer_get_string(buffer, "localvar_myvar")

    # ローカル変数の削除
    weechat.buffer_set(buffer, "localvar_del_myvar", "")

バッファに対するローカル変数を見るには、WeeChat で以下のコマンドを実行してください:

    /buffer localvar

### 5.2. フック

#### 5.2.1. 新しいコマンドの追加

カスタムコマンドを追加するには `hook_command` を使ってください。追加したコマンドに対してカスタム補完テンプレートを定義できます。

例:

    def my_command_cb(data, buffer, args):
        # ...
        return weechat.WEECHAT_RC_OK

    hook = weechat.hook_command("myfilter", "description of myfilter",
        "[list] | [enable|disable|toggle [name]] | [add name plugin.buffer tags regex] | [del name|-all]",
        "description of arguments...",
        "list"
        " || enable %(filters_names)"
        " || disable %(filters_names)"
        " || toggle %(filters_names)"
        " || add %(filters_names) %(buffers_plugins_names)|*"
        " || del %(filters_names)|-all",
        "my_command_cb", "")

上で定義したコマンドを WeeChat で以下のように使うことができます:

    /help myfilter

    /myfilter arguments...

#### 5.2.2. タイマーの追加

タイマーを追加するには `hook_timer` を使ってください。

例:

    def timer_cb(data, remaining_calls):
        # ...
        return weechat.WEECHAT_RC_OK

    # 1 分毎に (秒が 00 になった時に) 呼び出されるタイマー
    weechat.hook_timer(60 * 1000, 60, 0, "timer_cb", "")

#### 5.2.3. バックグラウンドプロセスの実行

バックグラウンドプロセスを実行するには `hook_process` を使います。コールバックはデータの準備が整った時点で呼び出されます。複数回呼び出されることもあります。

コールバックの最後の呼び出しでは rc が 0 か正の値に設定されています。これはコマンドのリターンコードになります。

例:

    process_output = ""

    def my_process_cb(data, command, rc, out, err):
        global process_output
        if out != "":
            process_output += out
        if int(rc) >= 0:
            weechat.prnt("", process_output)
        return weechat.WEECHAT_RC_OK

    weechat.hook_process("/bin/ls -l /etc", 10 * 1000, "my_process_cb", "")

#### 5.2.4. URL 転送

WeeChat バージョン 0.3.7 以上で利用可。

URL をダウンロードする (または URL にポストする) には、関数 `hook_process` または URL 転送にオプションが必要な場合は `hook_process_hashtable` を使わなければいけません。

オプション無しの URL 転送の例: HTML ページの内容はコールバックの "out" 引数 (プロセスの標準出力) を通して渡されます。

    # 現在の WeeChat 安定版のバージョンを表示。
    weechat_version = ""

    def weechat_process_cb(data, command, rc, out, err):
        global weechat_version
        if out != "":
            weechat_version += out
        if int(rc) >= 0:
            weechat.prnt("", "Current WeeChat stable is: %s" % weechat_version)
        return weechat.WEECHAT_RC_OK

    weechat.hook_process("url:https://weechat.org/dev/info/stable/",
                         30 * 1000, "weechat_process_cb", "")

| WeeChat に関して利用できる情報は全て https://weechat.org/dev/info にあります

オプション有りの URL 転送の例: 最新の WeeChat 開発パッケージをファイル /tmp/weechat-devel.tar.gz にダウンロード:

    def my_process_cb(data, command, rc, out, err):
        if int(rc) >= 0:
            weechat.prnt("", "End of transfer (rc=%s)" % rc)
        return weechat.WEECHAT_RC_OK

    weechat.hook_process_hashtable("url:https://weechat.org/files/src/weechat-devel.tar.gz",
                                   {"file_out": "/tmp/weechat-devel.tar.gz"},
                                   30 * 1000, "my_process_cb", "")

URL 転送に関するより詳しい情報と利用可能なオプションは WeeChat プラグイン API リファレンスの `hook_process` と `hook_process_hashtable` を参照してください。

### 5.3. 設定 / オプション

#### 5.3.1. スクリプトのオプションを設定

オプションが設定されているかどうかを確認するには `config_is_set_plugin` 関数、オプションを設定するには `config_set_plugin` 関数を使います。

例:

    script_options = {
        "option1" : "value1",
        "option2" : "value2",
        "option3" : "value3",
    }
    for option, default_value in script_options.items():
        if not weechat.config_is_set_plugin(option):
            weechat.config_set_plugin(option, default_value)

#### 5.3.2. 変更の検出

ユーザがスクリプトオプションを変更したことを検出するには `hook_config` を使わなければいけません。

例:

    SCRIPT_NAME = "myscript"

    # ...

    def config_cb(data, option, value):
        """スクリプトオプションが変更されたときに呼び出されるコールバック"""
        # 例えば、スクリプト変数に対する全てのスクリプトオプションを読み込む等...
        # ...
        return weechat.WEECHAT_RC_OK

    # ...

    weechat.hook_config("plugins.var.python." + SCRIPT_NAME + ".*", "config_cb", "")
    # 他のスクリプト言語の場合は "python" を適当なもの (perl/ruby/lua/tcl/guile/javascript) に変更してください

#### 5.3.3. WeeChat オプションのロード

`config_get` 関数はオプションへのポインタを返します。オプションの型に従って `config_string`、`config_boolean`、`config_integer`、`config_color` を呼び出さなければいけません。

    # 文字列型の場合
    weechat.prnt("", "value of option weechat.look.item_time_format is: %s"
                     % (weechat.config_string(weechat.config_get("weechat.look.item_time_format"))))

    # ブール型の場合
    weechat.prnt("", "value of option weechat.look.day_change is: %d"
                     % (weechat.config_boolean(weechat.config_get("weechat.look.day_change"))))

    # 整数型の場合
    weechat.prnt("", "value of option weechat.look.scroll_page_percent is: %d"
                     % (weechat.config_integer(weechat.config_get("weechat.look.scroll_page_percent"))))

    # 色型の場合
    weechat.prnt("", "value of option weechat.color.chat_delimiters is: %s"
                     % (weechat.config_color(weechat.config_get("weechat.color.chat_delimiters"))))

### 5.4. IRC

#### 5.4.1. メッセージのキャッチ

メッセージを受信すると IRC プラグインは 2 つのシグナルを送信します (`xxx` は IRC 内部サーバ名で、`yyy` は JOIN、QUIT、PRIVMSG、301 等の IRC コマンド名です):

xxxx,irc_in_yyy

  メッセージの処理が行われる前に送信されるシグナル

xxx,irc_in2_yyy

  メッセージの処理が行われた後に送信されるシグナル

    def join_cb(data, signal, signal_data):
        # シグナル、例えば: "freenode,irc_in2_join"
        # signal_data は IRC メッセージ、例えば: ":nick!user@host JOIN :#channel"
        server = signal.split(",")[0]
        msg = weechat.info_get_hashtable("irc_message_parse", {"message": signal_data})
        buffer = weechat.info_get("irc_buffer", "%s,%s" % (server, msg["channel"]))
        if buffer:
            weechat.prnt(buffer, "%s (%s) has joined this channel!" % (msg["nick"], msg["host"]))
        return weechat.WEECHAT_RC_OK

    # 全ての IRC サーバに対する JOIN メッセージをキャッチするにはサーバの指定に
    # "*" を使うと便利です。
    weechat.hook_signal("*,irc_in2_join", "join_cb", "")

#### 5.4.2. メッセージの修正

メッセージを受信すると IRC プラグインは "irc_in_xxx" ("xxx" は IRC コマンド) と呼ばれる "modifier" を送信します。メッセージを修正するにはこのシグナルを使います。

    def modifier_cb(data, modifier, modifier_data, string):
        # 全てのメッセージにサーバ名を追加する
        # (これは役に立ちませんが、例として!)
        return "%s %s" % (string, modifier_data)

    weechat.hook_modifier("irc_in_privmsg", "modifier_cb", "")

| 不正なメッセージは WeeChat をクラッシュさせ、深刻な問題を引き起こします!

#### 5.4.3. メッセージの構文解析

WeeChat バージョン 0.3.4 以上で利用可。

"irc_message_parse" と呼ばれる info_hashtable を使って IRC メッセージを構文解析できます。

結果は以下のキーを持つハッシュテーブルです (例の値は以下のメッセージから作られました: `@time=2015-06-27T16:40:35.000Z :nick!user@host PRIVMSG #weechat :hello!`):

キー | WeeChat バージョン | 説明 | 例
--- | --- | --- | ---
tags | 0.4.0 以上 | メッセージに付けられたタグ (空にすることも可) | `time=2015-06-27T16:40:35.000Z`
message_without_tags | 0.4.0 以上 | タグを除いたメッセージ (タグが付けられていなければメッセージと同じ) | `:nick!user@host PRIVMSG #weechat :hello!`
nick | 0.3.4 以上 | 発信者のニックネーム | `nick`
host | 0.3.4 以上 | 発信者のホスト (ニックネームを含む) | `nick!user@host`
command | 0.3.4 以上 | コマンド (PRIVMSG、NOTICE、…​) | `PRIVMSG`
channel | 0.3.4 以上 | 送信先チャンネル | `#weechat`
arguments | 0.3.4 以上 | コマンド引数 (チャンネルを含む) | `#weechat :hello!`
text | 1.3 以上 | テキスト (ユーザメッセージなど) | `hello!`
pos_command | 1.3 以上 | メッセージ内における command のインデックス (command が見つからない場合 "-1") | `47`
pos_arguments | 1.3 以上 | メッセージ内における arguments のインデックス (arguments が見つからない場合 "-1") | `55`
pos_channel | 1.3 以上 | メッセージ内における channel のインデックス (channel が見つからない場合 "-1") | `55`
pos_text | 1.3 以上 | メッセージ内における text のインデックス (text が見つからない場合 "-1") | `65`

    dict = weechat.info_get_hashtable(
        "irc_message_parse",
        {"message": "@time=2015-06-27T16:40:35.000Z :nick!user@host PRIVMSG #weechat :hello!"})

    # dict == {
    #     "tags": "time=2015-06-27T16:40:35.000Z",
    #     "message_without_tags": ":nick!user@host PRIVMSG #weechat :hello!",
    #     "nick": "nick",
    #     "host": "nick!user@host",
    #     "command": "PRIVMSG",
    #     "channel": "#weechat",
    #     "arguments": "#weechat :hello!",
    #     "text": "hello!",
    #     "pos_command": "47",
    #     "pos_arguments": "55",
    #     "pos_channel": "55",
    #     "pos_text": "65",
    # }

### 5.5. 情報

#### 5.5.1. WeeChat のバージョン

バージョンを確認する最良の方法は "version_number" を参照し、16 進数のバージョン番号と整数値比較することです。

例:

    version = weechat.info_get("version_number", "") or 0
    if int(version) >= 0x00030200:
        weechat.prnt("", "This is WeeChat 0.3.2 or newer")
    else:
        weechat.prnt("", "This is WeeChat 0.3.1 or older")

| バージョン 0.3.1.1 以下の場合 info_get("version_number") は空文字列を返すため、値が空でないことを確認しなければいけません。

文字列でバージョンを使うには:

    # 例えば "Version 0.3.2" のような出力が得られます。
    weechat.prnt("", "Version %s" % weechat.info_get("version", ""))

#### 5.5.2. その他の情報

    # WeeChat ホームディレクトリ、例えば: "/home/xxxx/.weechat"
    weechat.prnt("", "WeeChat home dir: %s" % weechat.info_get("weechat_dir", ""))

    # キーボードの不使用時間
    weechat.prnt("", "Inactivity since %s seconds" % weechat.info_get("inactivity", ""))

### 5.6. インフォリスト

#### 5.6.1. インフォリストのロード

WeeChat や他のプラグインによって作られたインフォリストを読み込むことができます。

例:

    # バッファのリストを得るために "buffer" インフォリストを読み込む
    infolist = weechat.infolist_get("buffer", "", "")
    if infolist:
        while weechat.infolist_next(infolist):
            name = weechat.infolist_string(infolist, "name")
            weechat.prnt("", "buffer: %s" % name)
        weechat.infolist_free(infolist)

| WeeChat は自動的にメモリを解放しません、インフォリストによって使われたメモリを解放するには、`infolist_free` を呼び出すことを忘れないでください。