@@ -17,8 +17,14 @@ use crate::modules::wired::Wired;
1717use crate :: modules:: wireless:: Wireless ;
1818use crate :: Config ;
1919use crate :: ModuleMsg ;
20+
21+ use anyhow:: { anyhow, Result } ;
2022use std:: convert:: TryFrom ;
2123use std:: sync:: mpsc:: Sender ;
24+ use std:: thread:: JoinHandle ;
25+ use tracing:: { error, info, instrument} ;
26+
27+ const MODULE_FAILED_ICON : & str = "✗" ;
2228
2329pub type RunPtr = fn ( char , Config , Sender < ModuleMsg > ) -> Result < ( ) , Error > ;
2430
@@ -137,19 +143,39 @@ impl<'a> Bar for Module<'a> {
137143 }
138144}
139145
146+ #[ derive( Debug , Clone ) ]
147+ pub enum ModuleState {
148+ NotStarted ,
149+ Running ,
150+ /// Module's `run` function returned without errors
151+ Finished ,
152+ /// Module's `run` function returned an error or panicked
153+ Failed ,
154+ }
155+
140156#[ derive( Debug ) ]
141157pub struct ModuleData < ' a > {
142158 pub key : char ,
143159 pub module : Module < ' a > ,
144160 data : Option < String > ,
161+ state : ModuleState ,
162+ handle : Option < JoinHandle < Result < ( ) , Error > > > ,
163+ failed_placeholder : String ,
145164}
146165
147166impl < ' a > ModuleData < ' a > {
148- pub fn new ( key : char , config : & ' a Config ) -> Result < Self , Error > {
167+ pub fn new ( key : char , config : & ' a Config ) -> Result < Self > {
149168 Ok ( ModuleData {
150169 key,
151170 module : Module :: try_from ( ( key, config) ) ?,
152171 data : None ,
172+ state : ModuleState :: NotStarted ,
173+ handle : None ,
174+ failed_placeholder : config
175+ . failed_icon
176+ . as_ref ( )
177+ . map ( |icon| format ! ( "{}:{}" , & key, icon) )
178+ . unwrap_or_else ( || format ! ( "{}:{}" , & key, MODULE_FAILED_ICON ) ) ,
153179 } )
154180 }
155181
@@ -167,10 +193,53 @@ impl<'a> ModuleData<'a> {
167193 }
168194
169195 pub fn output ( & self ) -> & str {
196+ if matches ! ( self . state, ModuleState :: Failed ) {
197+ return & self . failed_placeholder ;
198+ }
199+
170200 if let Some ( data) = & self . data {
171201 data
172202 } else {
173203 self . module . placeholder ( )
174204 }
175205 }
206+
207+ pub fn start ( & mut self , handle : JoinHandle < Result < ( ) , Error > > ) {
208+ self . handle = Some ( handle) ;
209+ self . state = ModuleState :: Running ;
210+ }
211+
212+ #[ instrument( skip_all) ]
213+ pub fn update_state ( & mut self ) -> Result < ( ) > {
214+ let Some ( handle) = & self . handle else {
215+ return Ok ( ( ) ) ;
216+ } ;
217+ if !handle. is_finished ( ) {
218+ return Ok ( ( ) ) ;
219+ }
220+
221+ // module thread has finished for some reason, join it
222+ // and update the state accordingly
223+ self . state = match self
224+ . handle
225+ . take ( )
226+ . ok_or ( anyhow ! ( "failed to unwrap handle" ) ) ?
227+ . join ( )
228+ {
229+ Ok ( Ok ( _) ) => {
230+ info ! ( "[{}] module finished" , self . module. name( ) ) ;
231+ ModuleState :: Finished
232+ }
233+ Ok ( Err ( e) ) => {
234+ error ! ( "[{}] module failed: {}" , self . module. name( ) , e) ;
235+ ModuleState :: Failed
236+ }
237+ Err ( _) => {
238+ let msg = format ! ( "[{}] module panicked" , self . module. name( ) ) ;
239+ error ! ( "{}" , & msg) ;
240+ ModuleState :: Failed
241+ }
242+ } ;
243+ Ok ( ( ) )
244+ }
176245}
0 commit comments