14 个版本 (1 个稳定版本)
1.0.0 | 2024年7月24日 |
---|---|
0.8.1 | 2023年6月5日 |
0.8.0 | 2022年9月28日 |
0.6.1 | 2022年6月19日 |
#551 in 解析器实现
1,368 每月下载次数
100KB
321 代码行
🎙 Storyteller
用户输出处理的库
目录
简介
此库旨在由具有多个用户界面选项的工具使用,通过这些选项它们可以通信,同时也有各种单独的命令(或流程),每个命令都需要仔细指定自己的输出格式。
该库由三个主要构建块组成,并在这些构建块之上提供默认实现。它帮助您设置程序架构
三个构建块是
-
EventHandler
:处理用户输出的事件处理器,例如- 将事件格式化为 json 行并打印到 stderr 的处理器
- 更新进度条的处理器
- 收集事件的软件测试处理器
- 为每个事件发送 websocket 消息的处理器
- 更新用户界面的处理器
-
EventReporter
:在程序逻辑期间调用。用于将用户输出通信给用户。在程序逻辑期间,通过事件调用报告器,因此您不需要在程序流程的中间处理格式化和显示细节。 -
EventListener
:接收由报告器发送的事件,并运行EventHandler
。通常在单独的线程中启动,以便不会阻塞。
在这些构建块之上,提供了一个基于通道的实现,该实现将 EventHandler
在单独的线程中运行。要使用此实现,请参阅 ChannelReporter
和 ChannelEventListener
的文档。
除了这些提供的元素外,您还需要
- 定义一个可以被用作事件的类型
- 定义一个或多个事件处理器(例如:
impl EventHandler<Event = YourEventType>
)。
可视化介绍
点击这里查看大图。 (亮色 svg,暗色 svg,亮色 png,暗色 png)
示例
实际应用示例
Storyteller自从v0.16
版本以来就被cargo-msrv所使用。要预览如何指定事件,您可以点击事件模块。在处理器模块中,可以找到多个处理器,例如写入JSON的处理器、打印美观的、易于阅读的输出的处理器、打印用于shell命令的最小最终结果输出的处理器、丢弃输出的处理器以及用于集成测试的处理器。
一窥storyteller的滋味
use std::cell::RefCell;
use std::hash::Hasher;
use std::io::{Stderr, Write};
use std::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::{io, thread};
use storyteller::{EventHandler, FinishProcessing};
use storyteller::{
event_channel, ChannelEventListener, ChannelReporter, EventListener, EventReporter,
};
#[derive(serde::Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
enum Event {
DiceThrow { throw: u8 },
YouWin,
YouLose,
}
#[derive(Default)]
struct JsonHandler;
impl EventHandler for JsonHandler {
type Event = Event;
fn handle(&self, event: Self::Event) {
let serialized_event = serde_json::to_string(&event).unwrap();
eprintln!("{}", serialized_event);
}
}
// See the test function `bar` in src/tests.rs for an example where the handler is a progress bar.
fn main() {
let (sender, receiver) = event_channel::<Event>();
// Handlers are implemented by you. Here you find one which writes jsonlines messages to stderr.
// This can be anything, for example a progress bar (see src/tests.rs for an example of this),
// a fake reporter which collects events for testing or maybe even a "MultiHandler<'h>" which
// consists of a Vec<&'h dyn EventHandler> and executes multiple handlers under the hood.
let handler = JsonHandler::default();
// This one is included with the library. It just needs to be hooked up with a channel.
let reporter = ChannelReporter::new(sender);
// This one is also included with the library. It also needs to be hooked up with a channel.
let listener = ChannelEventListener::new(receiver);
// Here we use the JsonHandler we defined above, in combination with the default `EventListener`
// and `ChannelEventListener` defined above.
//
// If we don't run the handler, we'll end up in an infinite loop, because our `reporter.disconnect()`
// below will block until it receives a Disconnect message.
let fin = listener.run_handler(Arc::new(handler));
// Now onto this program, let's play a game of dice!
for _ in 0..100 {
let dice = roll_dice();
reporter
.report_event(Event::DiceThrow { throw: dice })
.unwrap();
if dice >= 3 {
reporter.report_event(Event::YouWin).unwrap();
} else {
reporter.report_event(Event::YouLose).unwrap();
}
thread::sleep(Duration::from_millis(100))
}
// Within the ChannelReporter, the sender is dropped, thereby disconnecting the channel
// Already sent events can still be processed.
let _ = reporter.disconnect();
// To keep the processing of already sent events alive, we block the handler
let _ = fin.finish_processing();
}
static SEED: AtomicU32 = AtomicU32::new(1);
fn roll_dice() -> u8 {
let mut random = SEED.load(Ordering::SeqCst);
random ^= random << 13;
random ^= random >> 17;
random ^= random << 5;
SEED.store(random, Ordering::SeqCst);
(random % 6 + 1) as u8
}
起源
这个库是基于早期的实验的改进实现。它的目的是被cargo-msrv使用,因为这个项目已经超越了其当前的用户输出实现。
贡献
欢迎贡献、反馈或其他联系!请随意发送消息或创建一个问题 😄。
许可证
根据以下任一许可证授权
- Apache License, Version 2.0, (LICENSE-APACHE或http://www.apache.org/licenses/LICENSE-2.0)
- MIT许可证 (LICENSE-MIT或http://opensource.org/licenses/MIT)
任选其一。
贡献
除非您明确表示,否则任何有意提交以包含在您的工作中的贡献,根据Apache-2.0许可证的定义,应双授权如上所述,不附加任何额外的条款或条件。