4 个版本

0.3.2 2024 年 1 月 22 日
0.3.1 2024 年 1 月 20 日
0.2.5 2024 年 1 月 18 日

#455网络编程

每月 26 次下载

MIT 许可证

180KB
3K SLoC

Rust Hexchat API

这个库为 Hexchat 插件接口提供了 Rust API,并具有如下的 Rust 友好特性:

  • 线程安全的 API。
  • 简单的 user_data 对象。
  • Context 之类的抽象,使得与 UI 中的特定标签页/窗口交互变得简单。
  • 在活动 Hexchat 窗口中捕获并显示恐慌。
  • 调试构建包括恐慌的完整堆栈跟踪。
  • 可以像普通函数或闭包一样实现钩子命令。
  • 类型化首选项值和简单的插件首选项访问。

文档

文档可以在 这里 找到

示例

一个完成的插件提供了最多的示例。 这里有一个插件 可以进行自动翻译,使得可以与不同语言的人聊天(聊天时有字幕)。

使用 API 设置和注册命令很简单,语法清晰。

线程和 Hexchat 之间的交互通过 main_thread() 得以实现,它使用 Hexchat 的计时器事件循环来委派任务,例如将输出打印到活动 Hexchat 窗口。

hexchat.hook_command(
    "runthread",
    Priority::Norm,

    |hc, word, word_eol, ud| {
        // Grab a threadsafe version of the API.
        let hcx = hc.threadsafe();

        // Spawn a new thread.
        thread::spawn(|| -> Result<(), HexchatError> {
            // Send a task to the main thread to have executed and
            // get its `AsyncResult` object.
            let ares = main_thread(|hc| {
                hc.print("Hello from main thread!");

                "This is the return value from main!"
            });
            // Get the return data from the main thread callback.
            // The call to `ares.get()` blocks.
            let result = ares.get();

            hc_print_th!("Spawned thread received from main \
                          thread: {}", result);

            // Grab a threadsafe context to the currently focused
            // channel.
            let ctx = hcx.get_context();

            // Get a threadsafe list iterator.
            let user_list = hcx.list_get("users")?;

            for user in user_list {
                // Print user nicknames via the context object.
                ctx.print(&user.get_field("nick")?.str())?;
            }
            Ok(())
        });
        Eat::All
    },

    "Runs a new thread that sets up a closure to run on the main \
     thread.",
    NoData);

链接到 hexchat_api

只需在 Rust 项目的 Cargo.toml 文件中包含一个条目

[dependencies]
hexchat-api = "0.3"

模板

以下代码可以复制以启动一个新的插件项目。TOML 文件内容也包含在下面。

// FILE: lib.rs

//! A starter project template that can be copied and modified.

use hexchat_api::*;
use UserData::*;

// Register the entry points of the plugin.
//
dll_entry_points!(plugin_info, plugin_init, plugin_deinit);

/// Called when the plugin is loaded to register it with Hexchat.
///
fn plugin_info() -> PluginInfo {
    PluginInfo::new(
        "Plugin Template",
        "0.1",
        "A Hexchat plugin to customize.")
}

/// Called when the plugin is loaded.
///
fn plugin_init(hc: &Hexchat) -> i32 {
    hc.print("Plugin template loaded");

    // Example user data to pass to a callback.
    let udata = UserData::boxed("Some data to pass to a callback.");

    // Register a simple command using a function.
    hc.hook_command("HELLOWORLD",
                    Priority::Norm,
                    hello_world,
                    "Prints \"Hello, world!\"",
                    NoData);

    // Register a simple command using a closure.
    hc.hook_command("HELLOHEX",
                    Priority::Norm,
                    |hc, word, word_eol, user_data| {

                        hc.print("Hello, Hexchat!");

                        // Apply an operation to the string
                        // in the `UserData`.
                        user_data.apply(|msg: &&str| {
                            hc.print(msg);
                        });

                        Eat::All
                    },
                    "Prints \"Hello, Hexchat!\", \
                    and the user data.",
                    udata);
    1
}

/// Called when the plugin is unloaded.
///
fn plugin_deinit(hc: &Hexchat) -> i32 {
    hc.print("Plugin template unloaded");
    1
}

/// A command callback implemented as a function.
/// # Arguments
/// * `hc`        - The Hexchat API object reference.
/// * `word`      - A list of parameters passed to the command.
/// * `word_eol`  - Like `word`, but catenates the word args
///                 decrementally.
/// * `user_data` - The user data to be passed back to the command
///                 when invoked by Hexchat.
/// # Returns
/// * One of `Eat::All`, `Eat::Hexchat`, `Eat::Plugin`, `Eat::None`.
///
fn hello_world(hc        : &Hexchat,
               word      : &[String],
               word_eol  : &[String],
               user_data : &UserData
              ) -> Eat
{
    hc.print("Hello, world!");
    Eat::All
}

以及 Cargo.toml 文件。

[package]
name = "hexchat_plugin_template"
version = "0.1.0"
authors = ["you <[email protected]>"]
edition = "2021"

[lib]
name = "hexchat_plugin_template"
crate-type = ["cdylib"]

[dependencies]
hexchat-api = "0.3"

依赖项

~2.4–3.5MB
~72K SLoC