From f6f44c64ab391a16957d92c4ba05bd40486fb1e8 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Fri, 21 Apr 2023 17:21:33 +1000 Subject: [PATCH] Force progress bar to output to stderr even when not a terminal --- Cargo.lock | 1 + Cargo.toml | 1 + src/intcox.rs | 9 +++---- src/lib.rs | 2 ++ src/term.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 src/term.rs diff --git a/Cargo.lock b/Cargo.lock index 9ca76c9..8689cf0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -312,6 +312,7 @@ name = "hpstat" version = "0.1.0" dependencies = [ "clap", + "console", "indicatif", "nalgebra", "prettytable-rs", diff --git a/Cargo.toml b/Cargo.toml index d648221..1246e78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] clap = { version = "4.2.1", features = ["derive"] } +console = "0.15.5" indicatif = {version = "0.17.3", features = ["rayon"]} nalgebra = "0.32.2" prettytable-rs = "0.10.0" diff --git a/src/intcox.rs b/src/intcox.rs index d08e66a..05c68dc 100644 --- a/src/intcox.rs +++ b/src/intcox.rs @@ -20,12 +20,14 @@ use std::fs; use std::io; use clap::{Args, ValueEnum}; -use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle}; +use indicatif::{ParallelProgressIterator, ProgressBar, ProgressDrawTarget, ProgressStyle}; use nalgebra::{DMatrix, DVector, Matrix1xX}; use prettytable::{Table, format, row}; use rayon::prelude::*; use serde::{Serialize, Deserialize}; +use crate::term::UnconditionalTermLike; + #[derive(Args)] pub struct IntCoxArgs { /// Path to CSV input file containing the observations @@ -98,10 +100,7 @@ pub fn main(args: IntCoxArgs) { } // Fit regression - let progress_bar = match args.output { - OutputFormat::Text => ProgressBar::new(0), - OutputFormat::Json => ProgressBar::hidden(), - }; + let progress_bar = ProgressBar::with_draw_target(Some(0), ProgressDrawTarget::term_like(Box::new(UnconditionalTermLike::stderr()))); let result = fit_interval_censored_cox(data_times, data_indep, args.max_iterations, args.tolerance, args.reduced, progress_bar); // Display output diff --git a/src/lib.rs b/src/lib.rs index c250616..5954c91 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,3 @@ pub mod intcox; + +mod term; diff --git a/src/term.rs b/src/term.rs new file mode 100644 index 0000000..609da05 --- /dev/null +++ b/src/term.rs @@ -0,0 +1,74 @@ +// hpstat: High-performance statistics implementations +// Copyright © 2023 Lee Yingtong Li (RunasSudo) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +use std::io; + +use console::Term; +use indicatif::TermLike; + +#[derive(Debug)] +pub struct UnconditionalTermLike { + term: Term +} + +impl UnconditionalTermLike { + //pub fn new(term: Term) -> UnconditionalTermLike { + // return UnconditionalTermLike { term: term }; + //} + + pub fn stderr() -> UnconditionalTermLike { + return UnconditionalTermLike { term: Term::stderr() }; + } +} + +impl TermLike for UnconditionalTermLike { + fn width(&self) -> u16 { + return self.term.width(); + } + + fn move_cursor_up(&self, n: usize) -> io::Result<()> { + return self.term.move_cursor_up(n); + } + + fn move_cursor_down(&self, n: usize) -> io::Result<()> { + return self.term.move_cursor_down(n); + } + + fn move_cursor_right(&self, n: usize) -> io::Result<()> { + return self.term.move_cursor_right(n); + } + + fn move_cursor_left(&self, n: usize) -> io::Result<()> { + return self.term.move_cursor_left(n); + } + + fn write_line(&self, s: &str) -> io::Result<()> { + return self.term.write_line(s); + } + + fn write_str(&self, s: &str) -> io::Result<()> { + return self.term.write_str(s); + } + + fn clear_line(&self) -> io::Result<()> { + return self.term.clear_line(); + } + + fn flush(&self) -> io::Result<()> { + return self.term.flush(); + } + +}