- git: fetch branch and changed files in one `git status --porcelain --branch` (3 subprocesses -> 2) - transcript: read only the last 1 MB from the file tail instead of parsing the whole jsonl - color: add a shared palette and route heat() and every widget through it - widgets: drop the preview bridge functions; preview now calls the component fns directly - add unit tests for the pure helpers (parse_branch, interval merge, heat, percentages, formatting)
126 lines
3.9 KiB
Rust
126 lines
3.9 KiB
Rust
//! `statusline test <目标>` 子命令:在终端预览各组件效果。
|
||
|
||
use crate::sources::git::GitInfo;
|
||
use crate::sources::transcript::Speed;
|
||
use crate::widgets;
|
||
|
||
/// `test`:依次显示所有组件的预览。
|
||
pub fn run() {
|
||
header("usage");
|
||
usage();
|
||
header("git");
|
||
git();
|
||
header("speed");
|
||
speed();
|
||
header("model");
|
||
model();
|
||
header("rate");
|
||
rate();
|
||
header("dir");
|
||
dir();
|
||
}
|
||
|
||
/// 打印分节标题。
|
||
fn header(name: &str) {
|
||
println!("\n=== {name} ===");
|
||
}
|
||
|
||
/// 预览上下文百分比 1% → 100% 的渐变色,每行 10 个。
|
||
fn usage() {
|
||
for pct in 1..=100 {
|
||
print!("{} ", widgets::context::colored(pct as f64));
|
||
if pct % 10 == 0 {
|
||
println!();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 用合成数据预览 git 段的所有显示情况与配色。
|
||
fn git() {
|
||
// 非仓库时 render 直接返回 "-",这里单列。
|
||
println!("{} -", pad("非仓库", 12));
|
||
|
||
let samples = [
|
||
("干净", GitInfo { branch: "main".into(), changed_files: 0, insertions: 0, deletions: 0 }),
|
||
("仅改文件", GitInfo { branch: "main".into(), changed_files: 3, insertions: 0, deletions: 0 }),
|
||
("改文件+增", GitInfo { branch: "dev".into(), changed_files: 3, insertions: 128, deletions: 0 }),
|
||
("改文件+删", GitInfo { branch: "hotfix".into(), changed_files: 2, insertions: 0, deletions: 42 }),
|
||
("增删都有", GitInfo { branch: "feature/login".into(), changed_files: 5, insertions: 128, deletions: 17 }),
|
||
];
|
||
for (label, info) in &samples {
|
||
println!("{} {}", pad(label, 12), widgets::git::format_info(info));
|
||
}
|
||
}
|
||
|
||
/// 用合成数据预览 token 速度的各种情况。
|
||
fn speed() {
|
||
let samples = [
|
||
("正常", Speed { input_per_sec: Some(2.7), output_per_sec: Some(134.4) }),
|
||
("高速(k)", Speed { input_per_sec: Some(1234.0), output_per_sec: Some(3456.0) }),
|
||
("缺输入", Speed { input_per_sec: None, output_per_sec: Some(88.5) }),
|
||
("无数据", Speed::EMPTY),
|
||
];
|
||
for (label, speed) in &samples {
|
||
println!("{} {}", pad(label, 12), widgets::speed::display(speed));
|
||
}
|
||
}
|
||
|
||
/// 预览模型(思考) 合并格式。
|
||
fn model() {
|
||
println!("思考等级(模型固定 Opus 4.8):");
|
||
for (label, level) in [
|
||
("low", "low"),
|
||
("medium", "medium"),
|
||
("high", "high"),
|
||
("xhigh", "xhigh"),
|
||
("缺失/未知", ""),
|
||
] {
|
||
println!(" {} {}", pad(label, 10), widgets::model::combined("Opus 4.8 (1M context)", level));
|
||
}
|
||
|
||
println!("模型名(思考固定 high):");
|
||
for (label, name) in [
|
||
("Opus", "Opus 4.8 (1M context)"),
|
||
("Sonnet", "Sonnet 4.6"),
|
||
("Haiku", "Haiku 4.5"),
|
||
("Fable", "Fable 5"),
|
||
("缺失", "-"),
|
||
] {
|
||
println!(" {} {}", pad(label, 10), widgets::model::combined(name, "high"));
|
||
}
|
||
}
|
||
|
||
/// 用合成数据预览额度的各种情况。
|
||
fn rate() {
|
||
let samples = [
|
||
("正常", Some(10.0), Some(40.0), Some(6300i64)),
|
||
("接近满", Some(92.0), Some(78.0), Some(900)),
|
||
("无倒计时", Some(10.0), Some(40.0), None),
|
||
("缺数据", None, None, None),
|
||
];
|
||
for (label, five, seven, secs) in samples {
|
||
println!("{} {}", pad(label, 10), widgets::rate::display(five, seven, secs));
|
||
}
|
||
}
|
||
|
||
/// 用合成数据预览目录显示。
|
||
fn dir() {
|
||
let samples = [
|
||
("项目根", "/path/to/project", true),
|
||
("子目录", "/path/to/project/src/widgets", false),
|
||
("非项目", "/some/other/dir", false),
|
||
];
|
||
for (label, path, at_root) in samples {
|
||
println!("{} {}", pad(label, 10), widgets::dir::format_dir(path, at_root));
|
||
}
|
||
}
|
||
|
||
/// 把文本按显示列宽右侧补空格对齐(中文字符算 2 列)。
|
||
fn pad(text: &str, width: usize) -> String {
|
||
let shown: usize = text
|
||
.chars()
|
||
.map(|c| if (c as u32) >= 0x1100 { 2 } else { 1 })
|
||
.sum();
|
||
format!("{text}{}", " ".repeat(width.saturating_sub(shown)))
|
||
}
|