diff --git a/local/recipes/system/redbear-power/source/src/acpi.rs b/local/recipes/system/redbear-power/source/src/acpi.rs index c2abdbe465..87bcf4db33 100644 --- a/local/recipes/system/redbear-power/source/src/acpi.rs +++ b/local/recipes/system/redbear-power/source/src/acpi.rs @@ -33,20 +33,20 @@ pub fn read_cpu_freq_khz_sysfs(cpu: u32) -> Option { "/sys/devices/system/cpu/cpu{}/cpufreq/scaling_cur_freq", cpu ); - if let Ok(s) = fs::read_to_string(&path) { - if let Ok(khz) = s.trim().parse::() { - return Some(khz); - } + if let Ok(s) = fs::read_to_string(&path) + && let Ok(khz) = s.trim().parse::() + { + return Some(khz); } // Fallback: cpuinfo_cur_freq (some drivers expose this instead). let path2 = format!( "/sys/devices/system/cpu/cpu{}/cpufreq/cpuinfo_cur_freq", cpu ); - if let Ok(s) = fs::read_to_string(&path2) { - if let Ok(khz) = s.trim().parse::() { - return Some(khz); - } + if let Ok(s) = fs::read_to_string(&path2) + && let Ok(khz) = s.trim().parse::() + { + return Some(khz); } None } @@ -69,16 +69,16 @@ pub fn read_rapl_package_energy() -> Option<(u64, Instant)> { } // 2. Fallback: Linux powercap sysfs let path = "/sys/class/powercap/intel-rapl:0/energy_uj"; - if let Ok(s) = fs::read_to_string(path) { - if let Ok(uj) = s.trim().parse::() { - return Some((uj, Instant::now())); - } + if let Ok(s) = fs::read_to_string(path) + && let Ok(uj) = s.trim().parse::() + { + return Some((uj, Instant::now())); } let path2 = "/sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj"; - if let Ok(s) = fs::read_to_string(path2) { - if let Ok(uj) = s.trim().parse::() { - return Some((uj, Instant::now())); - } + if let Ok(s) = fs::read_to_string(path2) + && let Ok(uj) = s.trim().parse::() + { + return Some((uj, Instant::now())); } None } @@ -94,12 +94,7 @@ pub fn rapl_power_watts(curr: (u64, Instant), prev: (u64, Instant)) -> (f64, (u6 if dt < Duration::from_millis(100) || dt > Duration::from_secs(5) { return (0.0, curr); } - let de = if e_curr >= e_prev { - e_curr - e_prev - } else { - // Energy counter wrapped (unlikely at u64 microjoules, but handle it). - 0 - }; + let de = e_curr.saturating_sub(e_prev); let watts = (de as f64 / 1_000_000.0) / dt.as_secs_f64(); (watts, curr) } @@ -119,12 +114,11 @@ pub fn detect_cpus() -> Vec { // not exist on Redox. Linux falls back to /dev/cpu/N entries. if let Ok(data) = fs::read_to_string("/scheme/sys/cpu") { for line in data.lines() { - if let Some(rest) = line.strip_prefix("CPUs: ") { - if let Ok(n) = rest.trim().parse::() { - if n > 0 { - return (0..n).collect(); - } - } + if let Some(rest) = line.strip_prefix("CPUs: ") + && let Ok(n) = rest.trim().parse::() + && n > 0 + { + return (0..n).collect(); } } } @@ -214,10 +208,10 @@ fn delta_load(total: u64, idle: u64, prev: &mut (u64, u64)) -> f64 { pub fn read_acpi_pss(cpu: u32) -> Vec { // Try Redox ACPI _PSS first. let scheme_path = format!("/scheme/acpi/processor/CPU{}/pss", cpu); - if let Ok(s) = fs::read_to_string(&scheme_path) { - if let Some(out) = parse_pss(&s) { - return out; - } + if let Ok(s) = fs::read_to_string(&scheme_path) + && let Some(out) = parse_pss(&s) + { + return out; } // Linux fallback: /sys/devices/system/cpu/cpu{N}/cpufreq/scaling_available_frequencies // (kHz strings separated by spaces, e.g. "2400000 2200000 1900000 ..."). @@ -263,25 +257,23 @@ pub fn read_acpi_pss(cpu: u32) -> Vec { "/sys/devices/system/cpu/cpu{}/cpufreq/cpuinfo_max_freq", cpu ); - if let (Ok(min_s), Ok(max_s)) = (fs::read_to_string(&min_path), fs::read_to_string(&max_path)) { - if let (Ok(min_khz), Ok(max_khz)) = + if let (Ok(min_s), Ok(max_s)) = (fs::read_to_string(&min_path), fs::read_to_string(&max_path)) + && let (Ok(min_khz), Ok(max_khz)) = (min_s.trim().parse::(), max_s.trim().parse::()) - { - if max_khz > min_khz { - let steps: u32 = 5; - let mut out = Vec::with_capacity(steps as usize + 1); - for i in 0..=steps { - let freq = min_khz + (max_khz - min_khz) * i / steps; - let ctl = (i as u64) << 8; - out.push(PState { - freq_khz: freq, - power_mw: 0, - ctl, - }); - } - return out; - } + && max_khz > min_khz + { + let steps: u32 = 5; + let mut out = Vec::with_capacity(steps as usize + 1); + for i in 0..=steps { + let freq = min_khz + (max_khz - min_khz) * i / steps; + let ctl = (i as u64) << 8; + out.push(PState { + freq_khz: freq, + power_mw: 0, + ctl, + }); } + return out; } Vec::new() } @@ -290,18 +282,18 @@ fn parse_pss(s: &str) -> Option> { let mut out = Vec::new(); for line in s.lines() { let w: Vec<&str> = line.split_whitespace().collect(); - if w.len() >= 6 { - if let (Ok(f), Ok(pw), Ok(ct)) = ( + if w.len() >= 6 + && let (Ok(f), Ok(pw), Ok(ct)) = ( w[0].parse::(), w[2].parse::(), u64::from_str_radix(w[5], 16), - ) { - out.push(PState { - freq_khz: f, - power_mw: pw, - ctl: ct, - }); - } + ) + { + out.push(PState { + freq_khz: f, + power_mw: pw, + ctl: ct, + }); } } if out.is_empty() { None } else { Some(out) } @@ -328,15 +320,11 @@ pub fn read_cpu_id() -> Option<(String, String)> { continue; } match key.as_str() { - "vendor_id" | "vendor" | "manufacturer" => { - if vendor.is_empty() { - vendor = val; - } + "vendor_id" | "vendor" | "manufacturer" if vendor.is_empty() => { + vendor = val; } - "model name" | "model" | "product name" | "cpu" | "hardware" => { - if model.is_empty() { - model = val; - } + "model name" | "model" | "product name" | "cpu" | "hardware" if model.is_empty() => { + model = val; } _ => {} } diff --git a/local/recipes/system/redbear-power/source/src/app.rs b/local/recipes/system/redbear-power/source/src/app.rs index e71e72a7c3..866454a627 100644 --- a/local/recipes/system/redbear-power/source/src/app.rs +++ b/local/recipes/system/redbear-power/source/src/app.rs @@ -572,10 +572,10 @@ impl App { // without hammering /proc/meminfo on every tick. self.refresh_counter = self.refresh_counter.wrapping_add(1); // Clear MSR failure cache every ~30s so permission changes are picked up. - if self.refresh_counter % 60 == 0 { + if self.refresh_counter.is_multiple_of(60) { crate::msr::clear_msr_cache(); } - if self.refresh_counter % 4 == 0 { + if self.refresh_counter.is_multiple_of(4) { self.meminfo = crate::meminfo::read_meminfo(); self.os_info = crate::meminfo::read_os_info(); self.load_avg = std::fs::read_to_string("/proc/loadavg").ok().and_then(|s| { @@ -598,7 +598,7 @@ impl App { // Battery tab stays useful without hammering sysfs at 2 Hz. // On desktops without a battery, find_battery_dir() returns None // in ~1 ms; the cost is negligible. - if self.refresh_counter % 5 == 0 { + if self.refresh_counter.is_multiple_of(5) { self.battery = crate::battery::BatteryInfo::read(); } @@ -607,7 +607,7 @@ impl App { // modulus is coprime to meminfo's 4-tick and battery's 5-tick // moduli, so sensor reads don't synchronize with other data // sources (no thundering-herd syscalls). - if self.refresh_counter % 3 == 0 { + if self.refresh_counter.is_multiple_of(3) { self.sensors = crate::sensor::SensorInfo::read(); } @@ -617,7 +617,7 @@ impl App { // so network reads don't synchronize with any other data // source. 3.5 sec cadence is the same order as cpu-x's // network panel update rate. - if self.refresh_counter % 7 == 0 { + if self.refresh_counter.is_multiple_of(7) { let now_secs = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .map(|d| d.as_secs_f64()) @@ -653,7 +653,7 @@ impl App { // read_bytes/write_bytes vs previous 11th-tick refresh, // divided by elapsed wall time. SMART data is also refreshed // at the same cadence since it pairs naturally with disk info. - if self.refresh_counter % 11 == 0 { + if self.refresh_counter.is_multiple_of(11) { let now_secs = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .map(|d| d.as_secs_f64()) @@ -691,7 +691,7 @@ impl App { // 7, 11), so process reads don't synchronize with any other // data source. 6.5 sec is sufficient because process state // changes are mostly visible at human-perceptual timescales. - if self.refresh_counter % 13 == 0 { + if self.refresh_counter.is_multiple_of(13) { let now_secs = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .map(|d| d.as_secs_f64()) diff --git a/local/recipes/system/redbear-power/source/src/battery.rs b/local/recipes/system/redbear-power/source/src/battery.rs index d07b6bd11c..2b4cafaed8 100644 --- a/local/recipes/system/redbear-power/source/src/battery.rs +++ b/local/recipes/system/redbear-power/source/src/battery.rs @@ -71,10 +71,10 @@ impl BatteryInfo { let dir = fs::read_dir(&search_root).ok()?; for entry in dir.flatten() { let type_path = entry.path().join("type"); - if let Some(t) = read_sysfs(&type_path) { - if t == "Battery" { - return Some(entry.path()); - } + if let Some(t) = read_sysfs(&type_path) + && t == "Battery" + { + return Some(entry.path()); } } None diff --git a/local/recipes/system/redbear-power/source/src/bench.rs b/local/recipes/system/redbear-power/source/src/bench.rs index 42a1fed843..f1da50f37a 100644 --- a/local/recipes/system/redbear-power/source/src/bench.rs +++ b/local/recipes/system/redbear-power/source/src/bench.rs @@ -135,7 +135,7 @@ fn prime_worker(cancel: &AtomicBool, duration: Duration) -> u64 { let mut is_prime = n >= 2; let mut i: u64 = 2; while i * i <= n && is_prime { - if n % i == 0 { + if n.is_multiple_of(i) { is_prime = false; } i += 1; diff --git a/local/recipes/system/redbear-power/source/src/config.rs b/local/recipes/system/redbear-power/source/src/config.rs index 4141b5b467..86421faa82 100644 --- a/local/recipes/system/redbear-power/source/src/config.rs +++ b/local/recipes/system/redbear-power/source/src/config.rs @@ -26,6 +26,7 @@ use serde::Deserialize; #[derive(Clone, Debug, Deserialize)] #[serde(default)] +#[derive(Default)] pub struct Config { pub display: DisplayConfig, pub theme: ThemeConfig, @@ -33,17 +34,6 @@ pub struct Config { pub benchmark: BenchmarkConfig, } -impl Default for Config { - fn default() -> Self { - Self { - display: DisplayConfig::default(), - theme: ThemeConfig::default(), - keybindings: KeyBindings::default(), - benchmark: BenchmarkConfig::default(), - } - } -} - #[derive(Clone, Debug, Deserialize)] #[serde(default)] pub struct DisplayConfig { diff --git a/local/recipes/system/redbear-power/source/src/cpufreq.rs b/local/recipes/system/redbear-power/source/src/cpufreq.rs index a7cb9757c7..2fc10a17dd 100644 --- a/local/recipes/system/redbear-power/source/src/cpufreq.rs +++ b/local/recipes/system/redbear-power/source/src/cpufreq.rs @@ -210,11 +210,11 @@ impl Cpufreq { continue; } // Verify. - if let Some(actual) = backend.read_active() { - if actual == *candidate { - self.active = candidate.clone(); - return Some(candidate.clone()); - } + if let Some(actual) = backend.read_active() + && actual == *candidate + { + self.active = candidate.clone(); + return Some(candidate.clone()); } } None @@ -228,11 +228,11 @@ impl Cpufreq { if !backend.write(name) { return false; } - if let Some(actual) = backend.read_active() { - if actual == name { - self.active = name.to_string(); - return true; - } + if let Some(actual) = backend.read_active() + && actual == name + { + self.active = name.to_string(); + return true; } false } @@ -270,10 +270,11 @@ fn discover_by_probing(backend: &Backend) -> Vec { if !backend.write(candidate) { continue; } - if let Some(actual) = backend.read_active() { - if actual == *candidate && !found.contains(&candidate.to_string()) { - found.push(candidate.to_string()); - } + if let Some(actual) = backend.read_active() + && actual == *candidate + && !found.contains(&candidate.to_string()) + { + found.push(candidate.to_string()); } } diff --git a/local/recipes/system/redbear-power/source/src/cpuid.rs b/local/recipes/system/redbear-power/source/src/cpuid.rs index 9b06555861..2f388a01dc 100644 --- a/local/recipes/system/redbear-power/source/src/cpuid.rs +++ b/local/recipes/system/redbear-power/source/src/cpuid.rs @@ -35,7 +35,7 @@ pub struct CpuId { /// Intel hybrid CPU (12th gen+) identifies P-cores and E-cores via /// CPUID leaf 0x1A; AMD Zen 2+ identifies CCDs via 0x8000001E. Both /// schemes map each logical processor to a `CoreType` for grouping. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] pub enum CoreType { /// Intel Performance core (Raptor Lake / Alder Lake). IntelP, @@ -45,15 +45,10 @@ pub enum CoreType { /// The CCD number is stored separately. AmdCcd(u8), /// Unknown / vendor without hybrid support. + #[default] Unknown, } -impl Default for CoreType { - fn default() -> Self { - CoreType::Unknown - } -} - #[derive(Clone, Debug, Default)] pub struct HybridInfo { pub is_hybrid: bool, @@ -251,20 +246,20 @@ fn detect_hybrid(max_leaf: u32, max_ext: u32, num_cpus: u32, vendor: &str) -> Ve // which is our display group. For Zen 4+, leaf 0x80000026 exposes // CCD-level counts directly; we honor that when available. let (_, ebx_1e, _, _) = raw::cpuid(0x8000_001e, 0); - let nc = ((ebx_1e >> 8) & 0xff) as u32; + let nc = (ebx_1e >> 8) & 0xff; let cores_per_ccx = if nc > 0 { nc as usize } else { 1 }; let (zen4_ccds, _zen4_cores_per_ccd) = if max_ext >= 0x8000_0026 { // Zen 4+ topology leaf: EAX bits 7:0 = # of enabled CCDs, // ECX bits 7:0 = # of cores per CCD (0 = not supported). let (eax_26, _ebx_26, ecx_26, _edx_26) = raw::cpuid(0x8000_0026, 0); - ((eax_26 & 0xff) as u32, (ecx_26 & 0xff) as u32) + ((eax_26 & 0xff), (ecx_26 & 0xff)) } else { (0, 0) }; let mut out = Vec::with_capacity(num_cpus as usize); for cpu in 0..num_cpus { if zen4_ccds > 0 { - let ccd_id = cpu / _zen4_cores_per_ccd.max(1) as u32; + let ccd_id = cpu / _zen4_cores_per_ccd.max(1); out.push((cpu, CoreType::AmdCcd(ccd_id as u8))); } else { let ccd_id = cpu / cores_per_ccx.max(1) as u32; diff --git a/local/recipes/system/redbear-power/source/src/graph.rs b/local/recipes/system/redbear-power/source/src/graph.rs index 2cc589da63..4a7300ff38 100644 --- a/local/recipes/system/redbear-power/source/src/graph.rs +++ b/local/recipes/system/redbear-power/source/src/graph.rs @@ -108,17 +108,18 @@ impl Widget for BrailleGraph<'_> { .render(canvas_area, buf); // Render y-axis labels in the reserved left margin. - if let Some((ref top_label, ref bot_label)) = self.y_labels { - if inner.height >= 2 && inner.width >= 4 { - let label_style = Style::new().dark_gray(); - // Top label: right-aligned in 4-char space. - let top = format!("{:>4}", top_label.chars().take(4).collect::()); - buf.set_string(inner.x, inner.y, &top, label_style); - // Bottom label. - let bot_y = inner.y + inner.height.saturating_sub(1); - let bot = format!("{:>4}", bot_label.chars().take(4).collect::()); - buf.set_string(inner.x, bot_y, &bot, label_style); - } + if let Some((ref top_label, ref bot_label)) = self.y_labels + && inner.height >= 2 + && inner.width >= 4 + { + let label_style = Style::new().dark_gray(); + // Top label: right-aligned in 4-char space. + let top = format!("{:>4}", top_label.chars().take(4).collect::()); + buf.set_string(inner.x, inner.y, &top, label_style); + // Bottom label. + let bot_y = inner.y + inner.height.saturating_sub(1); + let bot = format!("{:>4}", bot_label.chars().take(4).collect::()); + buf.set_string(inner.x, bot_y, &bot, label_style); } // Render optional x-axis labels. diff --git a/local/recipes/system/redbear-power/source/src/kill.rs b/local/recipes/system/redbear-power/source/src/kill.rs index 3c81f05a3a..3e05a4ef58 100644 --- a/local/recipes/system/redbear-power/source/src/kill.rs +++ b/local/recipes/system/redbear-power/source/src/kill.rs @@ -77,10 +77,10 @@ impl KillDialog { } pub fn auto_close_if_done(&mut self) { - if let Some(at) = self.result_at { - if at.elapsed().as_millis() > 2000 { - self.close(); - } + if let Some(at) = self.result_at + && at.elapsed().as_millis() > 2000 + { + self.close(); } } } diff --git a/local/recipes/system/redbear-power/source/src/main.rs b/local/recipes/system/redbear-power/source/src/main.rs index d17348b62a..e0d3916e8d 100644 --- a/local/recipes/system/redbear-power/source/src/main.rs +++ b/local/recipes/system/redbear-power/source/src/main.rs @@ -184,19 +184,19 @@ fn handle_mouse(me: MouseEvent, header: &Rect, table: &Rect, keybar: &Rect, app: // Header line is y == table.y; rows start at y == table.y + 1. let row = y.saturating_sub(table.y + 1) as usize; let id = app.cpus.get(row).map(|c| c.id); - if let Some(id) = id { - if let Some(idx) = app.cpus.iter().position(|c| c.id == id) { - app.table_state.select(Some(idx)); - // Re-click on the same row toggles expand - // (mirrors htop). A click on a different - // row just selects that row. - if app.last_clicked_cpu == Some(id) { - app.toggle_expand(); - } else { - app.expanded_cpu = None; - } - app.last_clicked_cpu = Some(id); + if let Some(id) = id + && let Some(idx) = app.cpus.iter().position(|c| c.id == id) + { + app.table_state.select(Some(idx)); + // Re-click on the same row toggles expand + // (mirrors htop). A click on a different + // row just selects that row. + if app.last_clicked_cpu == Some(id) { + app.toggle_expand(); + } else { + app.expanded_cpu = None; } + app.last_clicked_cpu = Some(id); } } else if hit_test(*header, x, y) { // Header click cycles the governor (the most common @@ -271,7 +271,7 @@ fn main() -> io::Result<()> { let theme_mode = args .theme_mode .as_deref() - .unwrap_or_else(|| cfg.theme.mode.as_str()); + .unwrap_or(cfg.theme.mode.as_str()); app.theme_idx = match theme_mode { "light" => 1, "high-contrast" => 2, @@ -395,18 +395,18 @@ fn main() -> io::Result<()> { app.refresh(); last_refresh = Instant::now(); app.bench_line = bench.status_line(app.cpus.len()); - if bench.running { - if let Some((elapsed, _)) = bench.progress() { - let dur = bench.duration.as_secs() as u32; - if dur > 0 && elapsed >= dur { - bench.stop(); - app.flash_toast(format!( - "Benchmark done: {} {} in {}s", - bench.last_score, - bench.unit_name(), - bench.last_duration_s - )); - } + if bench.running + && let Some((elapsed, _)) = bench.progress() + { + let dur = bench.duration.as_secs() as u32; + if dur > 0 && elapsed >= dur { + bench.stop(); + app.flash_toast(format!( + "Benchmark done: {} {} in {}s", + bench.last_score, + bench.unit_name(), + bench.last_duration_s + )); } } if let Some(server) = dbus_server.as_ref() { @@ -605,29 +605,28 @@ fn main() -> io::Result<()> { if app.affinity_editor.open { f.render_widget(&mut app.affinity_editor, full); } - if app.show_open_files { - if let Some(files) = &app.open_files_result { - let pid = app.open_files_for_pid.unwrap_or(0); - let area = - full.centered(Constraint::Percentage(70), Constraint::Percentage(60)); - f.render_widget(Clear, area); - let lines: Vec = - crate::open_files::format_files(files) - .into_iter() - .map(ratatui::text::Line::from) - .collect(); - let block = ratatui::widgets::Block::default() - .borders(ratatui::widgets::Borders::ALL) - .title(format!( - " Open FDs: PID {} ({}) \u{2014} Esc to close ", - pid, - files.len() - )); - let para = ratatui::widgets::Paragraph::new(lines) - .block(block) - .scroll((0, 0)); - f.render_widget(para, area); - } + if app.show_open_files + && let Some(files) = &app.open_files_result + { + let pid = app.open_files_for_pid.unwrap_or(0); + let area = + full.centered(Constraint::Percentage(70), Constraint::Percentage(60)); + f.render_widget(Clear, area); + let lines: Vec = crate::open_files::format_files(files) + .into_iter() + .map(ratatui::text::Line::from) + .collect(); + let block = ratatui::widgets::Block::default() + .borders(ratatui::widgets::Borders::ALL) + .title(format!( + " Open FDs: PID {} ({}) \u{2014} Esc to close ", + pid, + files.len() + )); + let para = ratatui::widgets::Paragraph::new(lines) + .block(block) + .scroll((0, 0)); + f.render_widget(para, area); } // Hint bar: remind user how to exit expand mode. let hint = ratatui::widgets::Paragraph::new(ratatui::text::Line::styled( @@ -863,10 +862,8 @@ fn main() -> io::Result<()> { app.kill_dialog.close(); app.flash_status("kill cancelled"); } - Key::Char('\n') if app.kill_dialog.open => { - if app.kill_dialog.result.is_none() { - app.kill_dialog.send_signal(); - } + Key::Char('\n') if app.kill_dialog.open && app.kill_dialog.result.is_none() => { + app.kill_dialog.send_signal(); } Key::Up if app.kill_dialog.open => { app.kill_dialog.move_selection(-1); @@ -1000,17 +997,17 @@ fn main() -> io::Result<()> { }); } Key::Char('+') => { - let themes: [(&str, fn() -> crate::theme::Theme); 6] = [ - ("dark", crate::theme::Theme::dark), - ("light", crate::theme::Theme::light), - ("high-contrast", crate::theme::Theme::high_contrast), - ("nord", crate::theme::Theme::nord), - ("gruvbox", crate::theme::Theme::gruvbox), - ("solarized-dark", crate::theme::Theme::solarized_dark), + let themes: [(&str, crate::theme::Theme); 6] = [ + ("dark", crate::theme::Theme::dark()), + ("light", crate::theme::Theme::light()), + ("high-contrast", crate::theme::Theme::high_contrast()), + ("nord", crate::theme::Theme::nord()), + ("gruvbox", crate::theme::Theme::gruvbox()), + ("solarized-dark", crate::theme::Theme::solarized_dark()), ]; app.theme_idx = (app.theme_idx + 1) % themes.len(); - let (name, ctor) = themes[app.theme_idx]; - app.theme = ctor(); + let (name, theme) = &themes[app.theme_idx]; + app.theme = theme.clone(); app.flash_toast(format!("theme: {name}")); } Key::Char('k') if app.current_tab == TabId::Process => { @@ -1107,10 +1104,11 @@ fn main() -> io::Result<()> { app.flash_status("refresh interval (ms): type digits + Enter (50..60000)"); } Key::Char(c) if interval_input.is_some() => { - if let Some(buf) = interval_input.as_mut() { - if c.is_ascii_digit() && buf.len() < 5 { - buf.push(c); - } + if let Some(buf) = interval_input.as_mut() + && c.is_ascii_digit() + && buf.len() < 5 + { + buf.push(c); } } Key::Backspace if interval_input.is_some() => { @@ -1256,20 +1254,20 @@ fn main() -> io::Result<()> { "process filter: type chars + Enter to apply, Esc to clear", ); } - Key::Char(c) if process_filter_input.is_some() && !interval_input.is_some() => { + Key::Char(c) if process_filter_input.is_some() && interval_input.is_none() => { if let Some(buf) = process_filter_input.as_mut() { buf.push(c); } } Key::Backspace - if process_filter_input.is_some() && !interval_input.is_some() => + if process_filter_input.is_some() && interval_input.is_none() => { if let Some(buf) = process_filter_input.as_mut() { buf.pop(); } } Key::Char('\n') - if process_filter_input.is_some() && !interval_input.is_some() => + if process_filter_input.is_some() && interval_input.is_none() => { let new_filter = process_filter_input.take().unwrap_or_default(); app.process_filter = new_filter.clone(); diff --git a/local/recipes/system/redbear-power/source/src/meminfo.rs b/local/recipes/system/redbear-power/source/src/meminfo.rs index f6d231d182..f7369c418d 100644 --- a/local/recipes/system/redbear-power/source/src/meminfo.rs +++ b/local/recipes/system/redbear-power/source/src/meminfo.rs @@ -68,18 +68,18 @@ impl MemInfo { pub fn read_meminfo() -> MemInfo { let mut info = MemInfo::default(); // Redox scheme: a single file with key:value lines (analogous to /proc/meminfo). - if let Ok(s) = fs::read_to_string("/scheme/sys/mem") { - if parse_meminfo_kv(&s, &mut info) { - info.available = true; - return info; - } + if let Ok(s) = fs::read_to_string("/scheme/sys/mem") + && parse_meminfo_kv(&s, &mut info) + { + info.available = true; + return info; } // Linux /proc/meminfo. - if let Ok(s) = fs::read_to_string("/proc/meminfo") { - if parse_meminfo_kv(&s, &mut info) { - info.available = true; - return info; - } + if let Ok(s) = fs::read_to_string("/proc/meminfo") + && parse_meminfo_kv(&s, &mut info) + { + info.available = true; + return info; } info } @@ -171,15 +171,15 @@ pub fn read_os_info() -> OsInfo { } } // Redox fallback: use uname release string as the name (no /etc/os-release). - if info.name.is_empty() { - if let Ok(s) = fs::read_to_string("/scheme/sys/uname") { - for line in s.lines() { - if let Some(rest) = line.strip_prefix("release=") { - let v = rest.trim().to_string(); - if !v.is_empty() { - info.name = v; - break; - } + if info.name.is_empty() + && let Ok(s) = fs::read_to_string("/scheme/sys/uname") + { + for line in s.lines() { + if let Some(rest) = line.strip_prefix("release=") { + let v = rest.trim().to_string(); + if !v.is_empty() { + info.name = v; + break; } } } @@ -214,12 +214,11 @@ pub fn read_os_info() -> OsInfo { } // Uptime: /proc/uptime first field is seconds (float). - if let Ok(s) = fs::read_to_string("/proc/uptime") { - if let Some(first) = s.split_whitespace().next() { - if let Ok(v) = first.parse::() { - info.uptime_secs = v as u64; - } - } + if let Ok(s) = fs::read_to_string("/proc/uptime") + && let Some(first) = s.split_whitespace().next() + && let Ok(v) = first.parse::() + { + info.uptime_secs = v as u64; } info.available = !info.kernel.is_empty() || !info.name.is_empty() || info.uptime_secs > 0; diff --git a/local/recipes/system/redbear-power/source/src/msr.rs b/local/recipes/system/redbear-power/source/src/msr.rs index 3560bc9883..1a8627a511 100644 --- a/local/recipes/system/redbear-power/source/src/msr.rs +++ b/local/recipes/system/redbear-power/source/src/msr.rs @@ -171,10 +171,10 @@ pub fn read_msr(cpu: u32, msr: u32) -> Option { let scheme_path = format!("/scheme/sys/msr/{}/0x{:x}", cpu, msr); if Path::new(&scheme_path).exists() { let mut data = [0u8; 8]; - if let Ok(mut f) = fs::File::open(&scheme_path) { - if f.read_exact(&mut data).is_ok() { - return Some(u64::from_le_bytes(data)); - } + if let Ok(mut f) = fs::File::open(&scheme_path) + && f.read_exact(&mut data).is_ok() + { + return Some(u64::from_le_bytes(data)); } // Path exists but open/read failed — permission denied or similar. mark_msr_failed(cpu); @@ -183,12 +183,12 @@ pub fn read_msr(cpu: u32, msr: u32) -> Option { // Linux fallback: /dev/cpu/{cpu}/msr let dev_path = format!("/dev/cpu/{}/msr", cpu); if Path::new(&dev_path).exists() { - if let Ok(mut f) = fs::File::open(&dev_path) { - if f.seek(SeekFrom::Start(msr as u64)).is_ok() { - let mut data = [0u8; 8]; - if f.read_exact(&mut data).is_ok() { - return Some(u64::from_le_bytes(data)); - } + if let Ok(mut f) = fs::File::open(&dev_path) + && f.seek(SeekFrom::Start(msr as u64)).is_ok() + { + let mut data = [0u8; 8]; + if f.read_exact(&mut data).is_ok() { + return Some(u64::from_le_bytes(data)); } } // Dev path exists but open/read failed. @@ -201,14 +201,14 @@ pub fn read_msr(cpu: u32, msr: u32) -> Option { pub fn write_msr(cpu: u32, msr: u32, val: u64) -> bool { let scheme_path = format!("/scheme/sys/msr/{}/0x{:x}", cpu, msr); if Path::new(&scheme_path).exists() { - return fs::write(&scheme_path, &val.to_le_bytes()).is_ok(); + return fs::write(&scheme_path, val.to_le_bytes()).is_ok(); } let dev_path = format!("/dev/cpu/{}/msr", cpu); - if let Ok(mut f) = fs::OpenOptions::new().write(true).open(&dev_path) { - if f.seek(SeekFrom::Start(msr as u64)).is_ok() { - use std::io::Write; - return f.write_all(&val.to_le_bytes()).is_ok(); - } + if let Ok(mut f) = fs::OpenOptions::new().write(true).open(&dev_path) + && f.seek(SeekFrom::Start(msr as u64)).is_ok() + { + use std::io::Write; + return f.write_all(&val.to_le_bytes()).is_ok(); } false } diff --git a/local/recipes/system/redbear-power/source/src/nice_edit.rs b/local/recipes/system/redbear-power/source/src/nice_edit.rs index 43104d2525..dfbbe4c40a 100644 --- a/local/recipes/system/redbear-power/source/src/nice_edit.rs +++ b/local/recipes/system/redbear-power/source/src/nice_edit.rs @@ -10,6 +10,7 @@ use crate::theme; const MIN_NICE: i32 = -20; const MAX_NICE: i32 = 19; +#[derive(Default)] pub struct NiceEdit { pub open: bool, pub pid: u32, @@ -19,24 +20,11 @@ pub struct NiceEdit { pub result_timer: Option, } -impl Default for NiceEdit { - fn default() -> Self { - Self { - open: false, - pid: 0, - comm: String::new(), - value: 0, - result: None, - result_timer: None, - } - } -} - impl NiceEdit { pub fn open_for(&mut self, pid: u32, comm: &str, current_nice: i32) { self.pid = pid; self.comm = comm.to_string(); - self.value = current_nice.clamp(MIN_NICE, MAX_NICE) as i32; + self.value = current_nice.clamp(MIN_NICE, MAX_NICE); self.open = true; self.result = None; self.result_timer = None; @@ -59,10 +47,10 @@ impl NiceEdit { } pub fn auto_close_if_done(&mut self) { - if let Some(t) = self.result_timer { - if t.elapsed().as_secs() >= 2 { - self.close(); - } + if let Some(t) = self.result_timer + && t.elapsed().as_secs() >= 2 + { + self.close(); } } } @@ -131,7 +119,7 @@ impl Widget for &NiceEdit { Span::raw("]"), ]); Widget::render( - &Paragraph::new(slider_line).alignment(Alignment::Center), + Paragraph::new(slider_line).alignment(Alignment::Center), slider_area, buf, ); @@ -150,6 +138,6 @@ impl Widget for &NiceEdit { theme::VALUE_OFF, )) }; - Widget::render(&Paragraph::new(msg), msg_area, buf); + Widget::render(Paragraph::new(msg), msg_area, buf); } } diff --git a/local/recipes/system/redbear-power/source/src/process.rs b/local/recipes/system/redbear-power/source/src/process.rs index 63689081a8..0302a73cc5 100644 --- a/local/recipes/system/redbear-power/source/src/process.rs +++ b/local/recipes/system/redbear-power/source/src/process.rs @@ -107,7 +107,7 @@ impl SortMode { pub fn sort_ascending(self, processes: &mut Vec, ascending: bool) { if ascending { match self { - SortMode::Rss => processes.sort_by(|a, b| a.rss_kb.cmp(&b.rss_kb)), + SortMode::Rss => processes.sort_by_key(|a| a.rss_kb), SortMode::Cpu => processes.sort_by(|a, b| { a.cpu_pct .partial_cmp(&b.cpu_pct) @@ -132,9 +132,9 @@ impl SortMode { SortMode::IoWriteRate => { sort_by_io_rate_field_asc(processes, |p| p.io_write_rate_kbs) } - SortMode::RChar => processes.sort_by(|a, b| a.io_rchar_kb.cmp(&b.io_rchar_kb)), - SortMode::WChar => processes.sort_by(|a, b| a.io_wchar_kb.cmp(&b.io_wchar_kb)), - SortMode::VSize => processes.sort_by(|a, b| a.vsize_kb.cmp(&b.vsize_kb)), + SortMode::RChar => processes.sort_by_key(|a| a.io_rchar_kb), + SortMode::WChar => processes.sort_by_key(|a| a.io_wchar_kb), + SortMode::VSize => processes.sort_by_key(|a| a.vsize_kb), SortMode::Pid => processes.sort_by_key(|p| p.pid), SortMode::Name => processes.sort_by(|a, b| a.comm.cmp(&b.comm)), SortMode::ThreadIo => sort_by_io_field_asc(processes, |p| { @@ -308,7 +308,7 @@ pub fn sort_tree(processes: &mut Vec, sort_mode: SortMode) { let mut out: Vec = Vec::with_capacity(processes.len()); let mut visited: BTreeSet = BTreeSet::new(); for &root in &roots { - dfs_emit(&processes, &children, root, &mut out, &mut visited); + dfs_emit(processes, &children, root, &mut out, &mut visited); } // 5. Append any leftover procs (defensive — should not happen @@ -637,11 +637,11 @@ fn read_thread_io(pid: u32) -> (Option, Option) { total_read = total_read.saturating_add(v); any_counted = true; } - } else if let Some(rest) = line.strip_prefix("write_bytes:") { - if let Ok(v) = rest.trim().parse::() { - total_write = total_write.saturating_add(v); - any_counted = true; - } + } else if let Some(rest) = line.strip_prefix("write_bytes:") + && let Ok(v) = rest.trim().parse::() + { + total_write = total_write.saturating_add(v); + any_counted = true; } } } @@ -721,10 +721,10 @@ pub fn parse_cpu_list(s: &str) -> Vec { out.push(c); } } - } else if let Ok(n) = chunk.parse::() { - if !out.contains(&n) { - out.push(n); - } + } else if let Ok(n) = chunk.parse::() + && !out.contains(&n) + { + out.push(n); } } out.sort_unstable(); @@ -863,20 +863,20 @@ fn read_process(pid: u32) -> Option { } fn derive_sched_policy(pid: u32, priority: i64) -> String { - if let Ok(data) = fs::read(format!("/proc/{}/sched-policy", pid)) { - if let Some(&policy) = data.first() { - return match policy { - 0 => "FIFO", - 1 => "RR", - 2 => "OTHER", - _ => "?", - } - .into(); + if let Ok(data) = fs::read(format!("/proc/{}/sched-policy", pid)) + && let Some(&policy) = data.first() + { + return match policy { + 0 => "FIFO", + 1 => "RR", + 2 => "OTHER", + _ => "?", } + .into(); } if priority > 0 && priority < 40 { "OTHER".into() - } else if priority >= 40 && priority < 100 { + } else if (40..100).contains(&priority) { "RT".into() } else { "OTHER".into() @@ -2005,7 +2005,7 @@ pub fn set_nice(pid: u32, nice: i32) -> Result<(), String> { #[cfg(target_os = "linux")] unsafe { // PRIO_PROCESS = 0, who = pid - if libc::setpriority(0, pid as u32, n) == 0 { + if libc::setpriority(0, pid, n) == 0 { Ok(()) } else { Err(std::io::Error::last_os_error().to_string()) diff --git a/local/recipes/system/redbear-power/source/src/render.rs b/local/recipes/system/redbear-power/source/src/render.rs index 699c929c6c..fd9372f2e7 100644 --- a/local/recipes/system/redbear-power/source/src/render.rs +++ b/local/recipes/system/redbear-power/source/src/render.rs @@ -186,11 +186,9 @@ pub fn render_header<'a>(app: &'a App, focused: bool) -> Paragraph<'a> { " ".into(), "Throttle: ".set_style(theme::LABEL), match app.throttle { - ThrottleMode::Auto => "AUTO".set_style(theme::HEADER_THROTTLE_AUTO).into(), - ThrottleMode::User => "USER".set_style(theme::HEADER_THROTTLE_USER).into(), - ThrottleMode::ForcedMin => { - "FORCED MIN".set_style(theme::HEADER_THROTTLE_FORCED).into() - } + ThrottleMode::Auto => "AUTO".set_style(theme::HEADER_THROTTLE_AUTO), + ThrottleMode::User => "USER".set_style(theme::HEADER_THROTTLE_USER), + ThrottleMode::ForcedMin => "FORCED MIN".set_style(theme::HEADER_THROTTLE_FORCED), }, ]), Line::from(vec![ @@ -986,13 +984,14 @@ pub fn render_network_panel<'a>(app: &'a App, focused: bool) -> Paragraph<'a> { .unwrap_or("?") .set_style(theme::VALUE), ])); - if let Some(mac) = &iface.mac_address { - if !mac.is_empty() && mac != "00:00:00:00:00:00" { - lines.push(Line::from(vec![ - " MAC: ".set_style(theme::LABEL), - mac.clone().set_style(theme::VALUE), - ])); - } + if let Some(mac) = &iface.mac_address + && !mac.is_empty() + && mac != "00:00:00:00:00:00" + { + lines.push(Line::from(vec![ + " MAC: ".set_style(theme::LABEL), + mac.clone().set_style(theme::VALUE), + ])); } if let Some(mtu) = iface.mtu { lines.push(Line::from(vec![ @@ -1000,13 +999,13 @@ pub fn render_network_panel<'a>(app: &'a App, focused: bool) -> Paragraph<'a> { mtu.to_string().set_style(theme::VALUE), ])); } - if let Some(speed) = iface.speed_mbps { - if speed > 0 { - lines.push(Line::from(vec![ - " Speed: ".set_style(theme::LABEL), - format!("{} Mbps", speed).set_style(theme::VALUE), - ])); - } + if let Some(speed) = iface.speed_mbps + && speed > 0 + { + lines.push(Line::from(vec![ + " Speed: ".set_style(theme::LABEL), + format!("{} Mbps", speed).set_style(theme::VALUE), + ])); } lines.push(Line::from(vec![ " RX bytes: ".set_style(theme::LABEL), @@ -1481,7 +1480,7 @@ fn tree_prefix( None => return String::new(), }; let next_ppid = all.get(my_index + 1).map(|n| n.ppid); - let is_last = next_ppid.map_or(true, |np| np != ppid); + let is_last = next_ppid != Some(ppid); // For each ancestor level, decide if the bar continues. The // bar at depth d (counting from 0 for the row's immediate @@ -1494,7 +1493,7 @@ fn tree_prefix( let mut bar = String::new(); for &ancestor in ancestors.iter() { let next_row = all.get(my_index + 1); - let ancestor_active_in_next = next_row.map_or(false, |n| { + let ancestor_active_in_next = next_row.is_some_and(|n| { if n.ppid == ancestor { return true; } @@ -1910,7 +1909,7 @@ pub fn render_cpu_table<'a>( let mut padded: Vec = cpu.load_history.iter().copied().collect(); if padded.len() < SPARK_WIDTH { let pad = SPARK_WIDTH - padded.len(); - padded = std::iter::repeat(0u8).take(pad).chain(padded).collect(); + padded = std::iter::repeat_n(0u8, pad).chain(padded).collect(); } padded_to_sparkline(&padded) }; @@ -1960,76 +1959,76 @@ pub fn render_cpu_table<'a>( }) .collect(); let mut rows = rows; - if let Some(expanded_id) = expanded_cpu { - if let Some(cpu) = cpus.iter().find(|c| c.id == expanded_id) { - let sub_style = theme::LABEL; - let active_style = Style::new().yellow().bold(); - for (idx, pstate) in cpu.pstates.iter().enumerate() { - let is_current = cpu.current_idx == Some(idx); - let s = if is_current { active_style } else { sub_style }; - let marker = if is_current { "▶" } else { "↳" }; - let label = if is_current { - format!("{marker} P{idx} (current)") - } else { - format!("{marker} P{idx}") - }; - let freq_mhz = pstate.freq_khz / 1000; - let power_w = pstate.power_mw as f64 / 1000.0; - rows.push(Row::new(vec![ - label.set_style(s), - format!("{freq_mhz} MHz").set_style(s), - format!("{power_w:.1} W").set_style(s), - format!("0x{:02x}", (pstate.ctl >> 8) & 0x7f).set_style(s), - "".set_style(s), - "".set_style(s), - "".set_style(s), - "".set_style(s), - "".set_style(s), - ])); - } - if let Some(ref hwp) = cpu.hwp { - let s = sub_style; - rows.push(Row::new(vec![ - " HWP caps".set_style(s), - format!( - "eff={} guar={} max={}", - hwp.efficient_perf, hwp.guaranteed_perf, hwp.max_perf - ) - .set_style(s), - "".set_style(s), - "".set_style(s), - "".set_style(s), - format!("{}", if hwp.enabled { "ON" } else { "OFF" }).set_style( - if hwp.enabled { - Style::new().green() - } else { - theme::VALUE_OFF - }, - ), - "".set_style(s), - "".set_style(s), - "".set_style(s), - ])); - rows.push(Row::new(vec![ - " HWP req".set_style(s), - format!( - "min={} max={} des={} EPP={} ({})", - hwp.min_request, - hwp.max_request, - hwp.desired_perf, - hwp.epp, - hwp.epp_label() - ) - .set_style(s), - "".set_style(s), - "".set_style(s), - "".set_style(s), - "".set_style(s), - "".set_style(s), - "".set_style(s), - "".set_style(s), - ])); - } + if let Some(expanded_id) = expanded_cpu + && let Some(cpu) = cpus.iter().find(|c| c.id == expanded_id) + { + let sub_style = theme::LABEL; + let active_style = Style::new().yellow().bold(); + for (idx, pstate) in cpu.pstates.iter().enumerate() { + let is_current = cpu.current_idx == Some(idx); + let s = if is_current { active_style } else { sub_style }; + let marker = if is_current { "▶" } else { "↳" }; + let label = if is_current { + format!("{marker} P{idx} (current)") + } else { + format!("{marker} P{idx}") + }; + let freq_mhz = pstate.freq_khz / 1000; + let power_w = pstate.power_mw as f64 / 1000.0; + rows.push(Row::new(vec![ + label.set_style(s), + format!("{freq_mhz} MHz").set_style(s), + format!("{power_w:.1} W").set_style(s), + format!("0x{:02x}", (pstate.ctl >> 8) & 0x7f).set_style(s), + "".set_style(s), + "".set_style(s), + "".set_style(s), + "".set_style(s), + "".set_style(s), + ])); + } + if let Some(ref hwp) = cpu.hwp { + let s = sub_style; + rows.push(Row::new(vec![ + " HWP caps".set_style(s), + format!( + "eff={} guar={} max={}", + hwp.efficient_perf, hwp.guaranteed_perf, hwp.max_perf + ) + .set_style(s), + "".set_style(s), + "".set_style(s), + "".set_style(s), + (if hwp.enabled { "ON" } else { "OFF" }) + .to_string() + .set_style(if hwp.enabled { + Style::new().green() + } else { + theme::VALUE_OFF + }), + "".set_style(s), + "".set_style(s), + "".set_style(s), + ])); + rows.push(Row::new(vec![ + " HWP req".set_style(s), + format!( + "min={} max={} des={} EPP={} ({})", + hwp.min_request, + hwp.max_request, + hwp.desired_perf, + hwp.epp, + hwp.epp_label() + ) + .set_style(s), + "".set_style(s), + "".set_style(s), + "".set_style(s), + "".set_style(s), + "".set_style(s), + "".set_style(s), + "".set_style(s), + ])); } } Table::new( diff --git a/local/recipes/system/redbear-power/source/src/sched.rs b/local/recipes/system/redbear-power/source/src/sched.rs index 83543906df..0d84ebeb14 100644 --- a/local/recipes/system/redbear-power/source/src/sched.rs +++ b/local/recipes/system/redbear-power/source/src/sched.rs @@ -113,10 +113,10 @@ impl SchedStats { stats.context_switches = rest.trim().parse().ok(); } // "intr ..." — first field is total. - if let Some(rest) = trimmed.strip_prefix("intr ") { - if let Some(total_str) = rest.split_whitespace().next() { - stats.total_irqs = total_str.parse().ok(); - } + if let Some(rest) = trimmed.strip_prefix("intr ") + && let Some(total_str) = rest.split_whitespace().next() + { + stats.total_irqs = total_str.parse().ok(); } } stats diff --git a/local/recipes/system/redbear-power/source/src/smart.rs b/local/recipes/system/redbear-power/source/src/smart.rs index d618146430..90cf9b5474 100644 --- a/local/recipes/system/redbear-power/source/src/smart.rs +++ b/local/recipes/system/redbear-power/source/src/smart.rs @@ -88,7 +88,7 @@ impl SmartInfo { fn read_smart_for_disk(disk: &str) -> SmartHealth { let output = Command::new("smartctl") - .args(["-A", "-H", "/dev/", &format!("{disk}").to_string()]) + .args(["-A", "-H", "/dev/", &disk.to_string().to_string()]) .output(); let output = match output { Ok(o) => o, diff --git a/local/recipes/system/redbear-power/source/src/storage.rs b/local/recipes/system/redbear-power/source/src/storage.rs index 673e240471..e248985387 100644 --- a/local/recipes/system/redbear-power/source/src/storage.rs +++ b/local/recipes/system/redbear-power/source/src/storage.rs @@ -42,7 +42,7 @@ impl DiskStats { Self { read_bytes: fields.get(2).copied().unwrap_or(0), write_bytes: fields.get(6).copied().unwrap_or(0), - reads_completed: fields.get(0).copied().unwrap_or(0), + reads_completed: fields.first().copied().unwrap_or(0), writes_completed: fields.get(4).copied().unwrap_or(0), read_kbps: 0.0, write_kbps: 0.0, @@ -97,10 +97,12 @@ fn read_disk(name: &str, path: &Path) -> Option { if let Ok(entries) = fs::read_dir(path) { for entry in entries.flatten() { let p = entry.path(); - if let Some(n) = p.file_name().and_then(|s| s.to_str()) { - if p.is_dir() && n.starts_with(name) && n != name { - partitions.push(n.to_string()); - } + if let Some(n) = p.file_name().and_then(|s| s.to_str()) + && p.is_dir() + && n.starts_with(name) + && n != name + { + partitions.push(n.to_string()); } } }