@@ -8,38 +8,34 @@ use stats::{
88 get_cpu_stats, get_disk_stats, get_memory_stats, get_network_stats, get_system_stats,
99 get_uptime_stats,
1010} ;
11- use sysinfo:: { Disks , Networks , System } ;
12-
13- struct ProcessedFlags {
14- cpu_flags : Option < Vec < String > > ,
15- disk_flags : Option < Vec < String > > ,
16- memory_flags : Option < Vec < String > > ,
17- network_flags : Option < Vec < String > > ,
18- uptime_flags : Option < Vec < String > > ,
11+ use sysinfo:: { Components , Disks , Networks , System } ;
12+
13+ struct ProcessedFlags < ' a > {
14+ cpu_flags : Option < & ' a [ String ] > ,
15+ disk_flags : Option < & ' a [ String ] > ,
16+ memory_flags : Option < & ' a [ String ] > ,
17+ network_flags : Option < & ' a [ String ] > ,
18+ uptime_flags : Option < & ' a [ String ] > ,
1919}
2020
21- impl ProcessedFlags {
21+ impl < ' a > ProcessedFlags < ' a > {
2222 fn cpu_flag_refs ( & self ) -> Option < Vec < & str > > {
2323 self . cpu_flags
24- . as_ref ( )
2524 . map ( |flags| flags. iter ( ) . map ( String :: as_str) . collect ( ) )
2625 }
2726
2827 fn disk_flag_refs ( & self ) -> Option < Vec < & str > > {
2928 self . disk_flags
30- . as_ref ( )
3129 . map ( |flags| flags. iter ( ) . map ( String :: as_str) . collect ( ) )
3230 }
3331
3432 fn memory_flag_refs ( & self ) -> Option < Vec < & str > > {
3533 self . memory_flags
36- . as_ref ( )
3734 . map ( |flags| flags. iter ( ) . map ( String :: as_str) . collect ( ) )
3835 }
3936
4037 fn uptime_flag_refs ( & self ) -> Option < Vec < & str > > {
4138 self . uptime_flags
42- . as_ref ( )
4339 . map ( |flags| flags. iter ( ) . map ( String :: as_str) . collect ( ) )
4440 }
4541}
@@ -48,20 +44,21 @@ struct StatsContext<'a> {
4844 system : & ' a mut System ,
4945 disks : & ' a mut Disks ,
5046 networks : & ' a mut Networks ,
47+ components : & ' a Components ,
5148}
5249
53- struct StatsConfig {
54- flags : ProcessedFlags ,
50+ struct StatsConfig < ' a > {
51+ flags : ProcessedFlags < ' a > ,
5552 refresh_kind : sysinfo:: RefreshKind ,
5653}
5754
58- fn process_cli_flags ( cli : & cli:: Cli ) -> ProcessedFlags {
55+ fn process_cli_flags ( cli : & cli:: Cli ) -> ProcessedFlags < ' _ > {
5956 ProcessedFlags {
60- cpu_flags : cli. cpu . clone ( ) ,
61- disk_flags : cli. disk . clone ( ) ,
62- memory_flags : cli. memory . clone ( ) ,
63- network_flags : cli. network . clone ( ) ,
64- uptime_flags : cli. uptime . clone ( ) ,
57+ cpu_flags : cli. cpu . as_deref ( ) ,
58+ disk_flags : cli. disk . as_deref ( ) ,
59+ memory_flags : cli. memory . as_deref ( ) ,
60+ network_flags : cli. network . as_deref ( ) ,
61+ uptime_flags : cli. uptime . as_deref ( ) ,
6562 }
6663}
6764
@@ -82,7 +79,6 @@ fn validate_network_interfaces(
8279 }
8380 }
8481
85- // Only fail if no interfaces are available at all
8682 if available_interfaces. is_empty ( ) {
8783 anyhow:: bail!( "No network interfaces available on this system" ) ;
8884 }
@@ -95,20 +91,18 @@ async fn send_initial_system_stats(
9591 sketchybar : & Sketchybar ,
9692 system : & mut System ,
9793 refresh_kind : & sysinfo:: RefreshKind ,
94+ buf : & mut String ,
9895) -> Result < ( ) > {
9996 if cli. all || cli. system . is_some ( ) {
10097 system. refresh_specifics ( * refresh_kind) ;
10198 let system_flags = match & cli. system {
10299 Some ( flags) => flags. iter ( ) . map ( |s| s. as_str ( ) ) . collect :: < Vec < & str > > ( ) ,
103100 None => cli:: all_system_flags ( ) ,
104101 } ;
102+ buf. clear ( ) ;
103+ get_system_stats ( & system_flags, buf) ;
105104 sketchybar
106- . send_message (
107- "trigger" ,
108- "system_stats" ,
109- Some ( & get_system_stats ( & system_flags) . join ( "" ) ) ,
110- cli. verbose ,
111- )
105+ . send_message ( "trigger" , "system_stats" , Some ( buf) , cli. verbose )
112106 . await ?;
113107 }
114108
@@ -120,14 +114,23 @@ async fn get_stats(cli: &cli::Cli, sketchybar: &Sketchybar) -> Result<()> {
120114 let mut system = System :: new_with_specifics ( refresh_kind) ;
121115 let mut disks = Disks :: new_with_refreshed_list ( ) ;
122116 let mut networks = Networks :: new_with_refreshed_list ( ) ;
117+ let components = Components :: new_with_refreshed_list ( ) ;
123118
124- // Validate network interfaces exist if specified
125119 if let Some ( network_flags) = & cli. network {
126120 validate_network_interfaces ( & networks, network_flags, cli. verbose ) ?;
127121 }
128122
129123 let flags = process_cli_flags ( cli) ;
130- send_initial_system_stats ( cli, sketchybar, & mut system, & refresh_kind) . await ?;
124+ let mut message_buffer = String :: with_capacity ( 512 ) ;
125+
126+ send_initial_system_stats (
127+ cli,
128+ sketchybar,
129+ & mut system,
130+ & refresh_kind,
131+ & mut message_buffer,
132+ )
133+ . await ?;
131134
132135 let config = StatsConfig {
133136 flags,
@@ -138,54 +141,57 @@ async fn get_stats(cli: &cli::Cli, sketchybar: &Sketchybar) -> Result<()> {
138141 system : & mut system,
139142 disks : & mut disks,
140143 networks : & mut networks,
144+ components : & components,
141145 } ;
142146
143- run_stats_loop ( cli, sketchybar, & config, & mut context) . await
147+ run_stats_loop ( cli, sketchybar, & config, & mut context, & mut message_buffer ) . await
144148}
145149
146150async fn run_stats_loop (
147151 cli : & cli:: Cli ,
148152 sketchybar : & Sketchybar ,
149- config : & StatsConfig ,
153+ config : & StatsConfig < ' _ > ,
150154 context : & mut StatsContext < ' _ > ,
155+ message_buffer : & mut String ,
151156) -> Result < ( ) > {
152157 let mut network_refresh_tick = 0 ;
153158
154159 loop {
155- let ( commands, updated_tick) =
156- collect_stats_commands ( cli, config, context, network_refresh_tick) . await ?;
157- network_refresh_tick = updated_tick;
158-
159- if cli. verbose {
160- println ! ( "Current message: {}" , commands. join( "" ) ) ;
160+ tokio:: select! {
161+ result = collect_stats_commands( cli, config, context, network_refresh_tick, message_buffer) => {
162+ network_refresh_tick = result?;
163+
164+ if cli. verbose {
165+ println!( "Current message: {}" , message_buffer) ;
166+ }
167+ sketchybar
168+ . send_message( "trigger" , "system_stats" , Some ( message_buffer) , cli. verbose)
169+ . await ?;
170+ }
171+ _ = tokio:: signal:: ctrl_c( ) => {
172+ if cli. verbose {
173+ println!( "Received shutdown signal, cleaning up..." ) ;
174+ }
175+ println!( "SketchyBar Stats Provider is shutting down." ) ;
176+ return Ok ( ( ) ) ;
177+ }
161178 }
162- sketchybar
163- . send_message (
164- "trigger" ,
165- "system_stats" ,
166- Some ( & commands. join ( "" ) ) ,
167- cli. verbose ,
168- )
169- . await ?;
170179 }
171180}
172181
173182async fn collect_stats_commands (
174183 cli : & cli:: Cli ,
175- config : & StatsConfig ,
184+ config : & StatsConfig < ' _ > ,
176185 context : & mut StatsContext < ' _ > ,
177186 network_refresh_tick : u32 ,
178- ) -> Result < ( Vec < String > , u32 ) > {
179- let mut commands: Vec < String > = Vec :: new ( ) ;
187+ buf : & mut String ,
188+ ) -> Result < u32 > {
189+ buf. clear ( ) ;
180190
181191 tokio:: time:: sleep ( tokio:: time:: Duration :: from_secs ( cli. interval . into ( ) ) ) . await ;
182192 context. system . refresh_specifics ( config. refresh_kind ) ;
183193 context. disks . refresh ( true ) ;
184194
185- // Refresh network interfaces less frequently than other stats to reduce overhead.
186- // Network interfaces don't change rapidly, so we only refresh the full interface
187- // list every N stat collection cycles (configurable via --network-refresh-rate).
188- // In between full refreshes, we just update existing interface data.
189195 let mut updated_tick = network_refresh_tick + 1 ;
190196 if updated_tick >= cli. network_refresh_rate {
191197 * context. networks = Networks :: new_with_refreshed_list ( ) ;
@@ -195,54 +201,59 @@ async fn collect_stats_commands(
195201 }
196202
197203 if cli. all {
198- commands. push ( get_cpu_stats ( context. system , & cli:: all_cpu_flags ( ) , cli. no_units ) . join ( "" ) ) ;
199- commands. push ( get_disk_stats ( context. disks , & cli:: all_disk_flags ( ) , cli. no_units ) . join ( "" ) ) ;
200- commands. push (
201- get_memory_stats ( context. system , & cli:: all_memory_flags ( ) , cli. no_units ) . join ( "" ) ,
204+ get_cpu_stats (
205+ context. system ,
206+ context. components ,
207+ & cli:: all_cpu_flags ( ) ,
208+ cli. no_units ,
209+ buf,
202210 ) ;
203- commands
204- . push ( get_network_stats ( context. networks , None , cli. interval , cli. no_units ) . join ( "" ) ) ;
205- commands. push ( get_uptime_stats ( & cli:: all_uptime_flags ( ) ) ) ;
211+ get_disk_stats ( context. disks , & cli:: all_disk_flags ( ) , cli. no_units , buf) ;
212+ get_memory_stats ( context. system , & cli:: all_memory_flags ( ) , cli. no_units , buf) ;
213+ get_network_stats ( context. networks , None , cli. interval , cli. no_units , buf) ;
214+ get_uptime_stats ( & cli:: all_uptime_flags ( ) , buf) ;
206215 } else {
207216 if let Some ( cpu_flag_refs) = config. flags . cpu_flag_refs ( ) {
208- commands. push ( get_cpu_stats ( context. system , & cpu_flag_refs, cli. no_units ) . join ( "" ) ) ;
217+ get_cpu_stats (
218+ context. system ,
219+ context. components ,
220+ & cpu_flag_refs,
221+ cli. no_units ,
222+ buf,
223+ ) ;
209224 }
210225
211226 if let Some ( disk_flag_refs) = config. flags . disk_flag_refs ( ) {
212- commands . push ( get_disk_stats ( context. disks , & disk_flag_refs, cli. no_units ) . join ( "" ) ) ;
227+ get_disk_stats ( context. disks , & disk_flag_refs, cli. no_units , buf ) ;
213228 }
214229
215230 if let Some ( memory_flag_refs) = config. flags . memory_flag_refs ( ) {
216- commands
217- . push ( get_memory_stats ( context. system , & memory_flag_refs, cli. no_units ) . join ( "" ) ) ;
231+ get_memory_stats ( context. system , & memory_flag_refs, cli. no_units , buf) ;
218232 }
219233
220- if let Some ( network_flags) = & config. flags . network_flags {
221- commands. push (
222- get_network_stats (
223- context. networks ,
224- Some ( network_flags) ,
225- cli. interval ,
226- cli. no_units ,
227- )
228- . join ( "" ) ,
234+ if let Some ( network_flags) = config. flags . network_flags {
235+ get_network_stats (
236+ context. networks ,
237+ Some ( network_flags) ,
238+ cli. interval ,
239+ cli. no_units ,
240+ buf,
229241 ) ;
230242 }
231243
232244 if let Some ( uptime_flag_refs) = config. flags . uptime_flag_refs ( ) {
233- commands . push ( get_uptime_stats ( & uptime_flag_refs) ) ;
245+ get_uptime_stats ( & uptime_flag_refs, buf ) ;
234246 }
235247 }
236248
237- Ok ( ( commands , updated_tick) )
249+ Ok ( updated_tick)
238250}
239251
240252#[ cfg( target_os = "macos" ) ]
241253#[ tokio:: main]
242254async fn main ( ) -> Result < ( ) > {
243255 let cli = cli:: parse_args ( ) ;
244256
245- // Validate CLI arguments
246257 cli:: validate_cli ( & cli) . context ( "Invalid CLI arguments" ) ?;
247258
248259 println ! ( "SketchyBar Stats Provider is running." ) ;
0 commit comments