#ansi-codes #immediate-mode #buffer #output #diff #change #command-line

ansi-diff

带有ansi代码的连续缓冲区diff,输出最小更改

3个稳定版本

1.1.0 2022年3月4日
1.0.1 2022年3月4日
1.0.0 2022年3月3日

#13 in #ansi-codes

每月40次下载
depot-js中使用

BSD-2-Clause

14KB
272 代码行

ansi-diff

在Rust中使用带有ansi代码的连续缓冲区diff,输出最小更改

您可以使用此crate以“即时模式”的方式构建命令行界面,在输出页面进行diff,从而避免在更新之间清除整个屏幕时出现的闪烁,同时保留该方法的便利性。

您可以在输出中包含用于格式化的ansi代码,但尚不支持调整光标位置的代码。您可以使用此crate的输出管理光标位置,以放置内容窗格,但您需要自己编写粘合代码。

此包是node.js ansi-diff包的Rust版本,还包括从ansi-splitansi-regex中改编的代码。

示例:time

这是一个简单的示例,打印4行文本并更新经过的秒数计数器

use std::io::Write;

fn main() {
  let mut diff = ansi_diff::Diff::new(get_size());
  let start = std::time::Instant::now();
  loop {
    print!["{}", diff.update(&format![
      "-------------\nseconds elapsed: {:.0} ...\n-------------\n",
      start.elapsed().as_secs_f32()
    ])];
    std::io::stdout().flush().unwrap();
    std::thread::sleep(std::time::Duration::from_secs(1));
  }
}

fn get_size() -> (u32,u32) {
  term_size::dimensions().map(|(w,h)| (w as u32, h as u32)).unwrap()
}

示例:resize

这是前面时间示例的版本,为SIGWINCH事件设置了终端调整大小钩子

// to use this example, enable iterator and extended-siginfo features in Cargo.toml dependencies:
// signal-hook = { version = "0.3.13", features = [ "iterator", "extended-siginfo" ] }

use std::io::Write;
use signal_hook::{iterator::{SignalsInfo,exfiltrator::WithOrigin},consts::signal::SIGWINCH};
use std::sync::{Arc,Mutex};
use ansi_diff::Diff;

fn main() {
  let diff = Arc::new(Mutex::new(Diff::new(get_size())));
  let diff_c = diff.clone();
  std::thread::spawn(move || { resizer(diff_c) });

  let start = std::time::Instant::now();
  loop {
    print!["{}", diff.lock().unwrap().update(&format![
      "-------------\nseconds elapsed: {:.0} ...\n-------------\n",
      start.elapsed().as_secs_f32()
    ])];
    std::io::stdout().flush().unwrap();
    std::thread::sleep(std::time::Duration::from_secs(1));
  }
}

fn get_size() -> (u32,u32) {
  term_size::dimensions().map(|(w,h)| (w as u32, h as u32)).unwrap()
}

fn resizer(diff: Arc<Mutex<Diff>>) {
  let mut signals = SignalsInfo::<WithOrigin>::new(&vec![SIGWINCH]).unwrap();
  for info in &mut signals {
    if info.signal == SIGWINCH { diff.lock().unwrap().resize(get_size()) }
  }
}

示例:colors

这是一个更复杂的第一个示例版本,在输出流中包含ansi格式化

use std::io::Write;

fn main() {
  let mut diff = ansi_diff::Diff::new(get_size());
  // todo: on sigwinch, diff.resize()
  let start = std::time::Instant::now();
  loop {
    print!["{}", diff.update(&format![
      "{}\n{}\n{}\n",
      "ABCDEFGHIJKLMNOPQRSTUVWXYZ`0123456789-=",
      format![
        "\x1b[31m{:.0}\x1b[39m seconds have elapsed \x1b[32m!!!\x1b[39m",
        start.elapsed().as_secs_f32(),
      ],
      "abcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+",
    ])];
    std::io::stdout().flush().unwrap();
    std::thread::sleep(std::time::Duration::from_secs(1));
  }
}

fn get_size() -> (u32,u32) {
  term_size::dimensions().map(|(w,h)| (w as u32, h as u32)).unwrap()
}

许可证

bsd-2-clause

依赖项

~2.2–3MB
~53K SLoC