Skip to content

Commit 8172486

Browse files
committed
fear: change refresh interval with hotkeys #16
1 parent bdfb15a commit 8172486

File tree

6 files changed

+73
-17
lines changed

6 files changed

+73
-17
lines changed

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ libc = "0.2.168"
1919
num-traits = "0.2.19"
2020
ratatui = { version = "0.29.0", features = ["serde"] }
2121
serde = { version = "1.0.216", features = ["derive"] }
22+
serde-inline-default = "0.2.3"
2223
serde_json = "1.0.133"

src/app.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::sync::{Arc, RwLock};
12
use std::{io::stdout, time::Instant};
23
use std::{sync::mpsc, time::Duration};
34

@@ -121,6 +122,8 @@ enum Event {
121122
Update(Metrics),
122123
ChangeColor,
123124
ChangeView,
125+
IncInterval,
126+
DecInterval,
124127
Tick,
125128
Quit,
126129
}
@@ -131,6 +134,9 @@ fn handle_key_event(key: &event::KeyEvent, tx: &mpsc::Sender<Event>) -> WithErro
131134
KeyCode::Char('c') if key.modifiers == KeyModifiers::CONTROL => Ok(tx.send(Event::Quit)?),
132135
KeyCode::Char('c') => Ok(tx.send(Event::ChangeColor)?),
133136
KeyCode::Char('v') => Ok(tx.send(Event::ChangeView)?),
137+
KeyCode::Char('+') => Ok(tx.send(Event::IncInterval)?),
138+
KeyCode::Char('=') => Ok(tx.send(Event::IncInterval)?), // fallback to press without shift
139+
KeyCode::Char('-') => Ok(tx.send(Event::DecInterval)?),
134140
_ => Ok(()),
135141
}
136142
}
@@ -157,17 +163,16 @@ fn run_inputs_thread(tx: mpsc::Sender<Event>, tick: u64) {
157163
});
158164
}
159165

160-
fn run_sampler_thread(tx: mpsc::Sender<Event>, interval: u64) {
161-
let interval = interval.max(100).min(10000);
162-
166+
fn run_sampler_thread(tx: mpsc::Sender<Event>, msec: Arc<RwLock<u32>>) {
163167
std::thread::spawn(move || {
164168
let mut sampler = Sampler::new().unwrap();
165169

166170
// Send initial metrics
167171
tx.send(Event::Update(sampler.get_metrics(100).unwrap())).unwrap();
168172

169173
loop {
170-
tx.send(Event::Update(sampler.get_metrics(interval).unwrap())).unwrap();
174+
let msec = *msec.read().unwrap();
175+
tx.send(Event::Update(sampler.get_metrics(msec).unwrap())).unwrap();
171176
}
172177
});
173178
}
@@ -372,7 +377,7 @@ impl App {
372377
};
373378

374379
let block = self.title_block(&label_l, &label_r);
375-
let usage = " Press 'q' to quit, 'c' – color, 'v' – view ";
380+
let usage = format!(" 'q' quit, 'c' – color, 'v' – view | -/+ {}ms ", self.cfg.interval);
376381
let block = block.title_bottom(Line::from(usage).right_aligned());
377382
let iarea = block.inner(rows[1]);
378383
f.render_widget(block, rows[1]);
@@ -387,10 +392,14 @@ impl App {
387392
f.render_widget(self.get_power_block("ANE", &self.ane_power, 0.0), ha[2]);
388393
}
389394

390-
pub fn run_loop(&mut self, interval: u64) -> WithError<()> {
395+
pub fn run_loop(&mut self, interval: Option<u32>) -> WithError<()> {
396+
// use from arg if provided, otherwise use config restored value
397+
self.cfg.interval = interval.unwrap_or(self.cfg.interval).max(100).min(10_000);
398+
let msec = Arc::new(RwLock::new(self.cfg.interval));
399+
391400
let (tx, rx) = mpsc::channel::<Event>();
392401
run_inputs_thread(tx.clone(), 250);
393-
run_sampler_thread(tx.clone(), interval);
402+
run_sampler_thread(tx.clone(), msec.clone());
394403

395404
let mut term = enter_term();
396405

@@ -402,6 +411,14 @@ impl App {
402411
Event::Update(data) => self.update_metrics(data),
403412
Event::ChangeColor => self.cfg.next_color(),
404413
Event::ChangeView => self.cfg.next_view_type(),
414+
Event::IncInterval => {
415+
self.cfg.inc_interval();
416+
*msec.write().unwrap() = self.cfg.interval;
417+
}
418+
Event::DecInterval => {
419+
self.cfg.dec_interval();
420+
*msec.write().unwrap() = self.cfg.interval;
421+
}
405422
_ => {}
406423
}
407424
}

src/config.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use ratatui::style::Color;
22
use serde::{Deserialize, Serialize};
3+
use serde_inline_default::serde_inline_default;
34

45
const COLORS_OPTIONS: [Color; 7] =
56
[Color::Green, Color::Yellow, Color::Red, Color::Blue, Color::Magenta, Color::Cyan, Color::Reset];
@@ -10,10 +11,23 @@ pub enum ViewType {
1011
Gauge,
1112
}
1213

14+
#[serde_inline_default]
1315
#[derive(Debug, Serialize, Deserialize)]
1416
pub struct Config {
17+
#[serde_inline_default(ViewType::Sparkline)]
1518
pub view_type: ViewType,
19+
20+
#[serde_inline_default(COLORS_OPTIONS[0])]
1621
pub color: Color,
22+
23+
#[serde_inline_default(1000)]
24+
pub interval: u32,
25+
}
26+
27+
impl Default for Config {
28+
fn default() -> Self {
29+
serde_json::from_str("{}").unwrap()
30+
}
1731
}
1832

1933
impl Config {
@@ -72,10 +86,16 @@ impl Config {
7286
};
7387
self.save();
7488
}
75-
}
7689

77-
impl Default for Config {
78-
fn default() -> Self {
79-
Self { color: COLORS_OPTIONS[0], view_type: ViewType::Sparkline }
90+
pub fn dec_interval(&mut self) {
91+
let step = 250;
92+
self.interval = ((self.interval.saturating_sub(step) + step - 1) / step * step).max(step);
93+
self.save();
94+
}
95+
96+
pub fn inc_interval(&mut self) {
97+
let step = 250;
98+
self.interval = (self.interval.saturating_add(step) / step * step).min(10_000);
99+
self.save();
80100
}
81101
}

src/main.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod metrics;
55
mod sources;
66

77
use app::App;
8-
use clap::{Parser, Subcommand};
8+
use clap::{parser::ValueSource, CommandFactory, Parser, Subcommand};
99
use metrics::Sampler;
1010
use std::error::Error;
1111

@@ -33,20 +33,19 @@ struct Cli {
3333

3434
/// Update interval in milliseconds
3535
#[arg(short, long, default_value_t = 1000)]
36-
interval: u64,
36+
interval: u32,
3737
}
3838

3939
fn main() -> Result<(), Box<dyn Error>> {
4040
let args = Cli::parse();
41-
let msec = args.interval.max(100);
4241

4342
match &args.command {
4443
Some(Commands::Pipe { samples }) => {
4544
let mut sampler = Sampler::new()?;
4645
let mut counter = 0u32;
4746

4847
loop {
49-
let doc = sampler.get_metrics(msec)?;
48+
let doc = sampler.get_metrics(args.interval.max(100))?;
5049
let doc = serde_json::to_string(&doc)?;
5150
println!("{}", doc);
5251

@@ -59,6 +58,13 @@ fn main() -> Result<(), Box<dyn Error>> {
5958
Some(Commands::Debug) => debug::print_debug()?,
6059
_ => {
6160
let mut app = App::new()?;
61+
62+
let matches = Cli::command().get_matches();
63+
let msec = match matches.value_source("interval") {
64+
Some(ValueSource::CommandLine) => Some(args.interval),
65+
_ => None,
66+
};
67+
6268
app.run_loop(msec)?;
6369
}
6470
}

src/metrics.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,13 @@ impl Sampler {
216216
Ok(val)
217217
}
218218

219-
pub fn get_metrics(&mut self, duration: u64) -> WithError<Metrics> {
219+
pub fn get_metrics(&mut self, duration: u32) -> WithError<Metrics> {
220220
let measures: usize = 4;
221221
let mut results: Vec<Metrics> = Vec::with_capacity(measures);
222222

223223
// do several samples to smooth metrics
224224
// see: https://github.com/vladkens/macmon/issues/10
225-
for (sample, dt) in self.ior.get_samples(duration, measures) {
225+
for (sample, dt) in self.ior.get_samples(duration as u64, measures) {
226226
let mut ecpu_usages = Vec::new();
227227
let mut pcpu_usages = Vec::new();
228228
let mut rs = Metrics::default();

0 commit comments

Comments
 (0)