@@ -13,12 +13,13 @@ use crossbeam_channel::{select, Receiver, Sender};
1313use eframe:: egui:: { vec2, ViewportBuilder } ;
1414use eframe:: { egui, icon_data} ;
1515use egui_plot:: PlotPoint ;
16+ pub use gumdrop:: Options ;
1617use preferences:: AppInfo ;
1718use std:: cmp:: max;
1819use std:: path:: PathBuf ;
1920use std:: sync:: { Arc , RwLock } ;
21+ use std:: thread;
2022use std:: time:: Duration ;
21- use std:: { env, thread} ;
2223
2324mod color_picker;
2425mod custom_highlighter;
@@ -76,6 +77,7 @@ fn main_thread(
7677 load_rx : Receiver < PathBuf > ,
7778 load_names_tx : Sender < Vec < String > > ,
7879 gui_cmd_rx : Receiver < GuiCommand > ,
80+ cli_column_labels : Vec < String > ,
7981) {
8082 // reads data from mutex, samples and saves if needed
8183 let mut data = DataContainer :: default ( ) ;
@@ -110,7 +112,7 @@ fn main_thread(
110112 data. dataset = vec![ vec![ ] ; max( split_data. len( ) , 1 ) ] ;
111113 if let Ok ( mut gui_data) = data_lock. write( ) {
112114 gui_data. plots = ( 0 ..max( split_data. len( ) , 1 ) )
113- . map( |i| ( format!( "Column {i}" ) , vec![ ] ) )
115+ . map( |i| ( cli_column_labels . get ( i ) . cloned ( ) . unwrap_or_else ( || format!( "Column {i}" ) ) , vec![ ] ) )
114116 . collect( ) ;
115117 }
116118 failed_format_counter = 0 ;
@@ -262,13 +264,114 @@ fn main_thread(
262264 }
263265}
264266
267+ fn parse_databits ( s : & str ) -> Result < serialport:: DataBits , String > {
268+ let d: u8 = s
269+ . parse ( )
270+ . map_err ( |_e| format ! ( "databits not a number: {s}" ) ) ?;
271+ Ok ( serialport:: DataBits :: try_from ( d) . map_err ( |_e| format ! ( "invalid databits: {s}" ) ) ?)
272+ }
273+
274+ fn parse_flow ( s : & str ) -> Result < serialport:: FlowControl , String > {
275+ match s {
276+ "none" => Ok ( serialport:: FlowControl :: None ) ,
277+ "soft" => Ok ( serialport:: FlowControl :: Software ) ,
278+ "hard" => Ok ( serialport:: FlowControl :: Hardware ) ,
279+ _ => Err ( format ! ( "invalid flow-control: {s}" ) ) ,
280+ }
281+ }
282+
283+ fn parse_stopbits ( s : & str ) -> Result < serialport:: StopBits , String > {
284+ let d: u8 = s
285+ . parse ( )
286+ . map_err ( |_e| format ! ( "stopbits not a number: {s}" ) ) ?;
287+ Ok ( serialport:: StopBits :: try_from ( d) . map_err ( |_e| format ! ( "invalid stopbits: {s}" ) ) ?)
288+ }
289+
290+ fn parse_parity ( s : & str ) -> Result < serialport:: Parity , String > {
291+ match s {
292+ "none" => Ok ( serialport:: Parity :: None ) ,
293+ "odd" => Ok ( serialport:: Parity :: Odd ) ,
294+ "even" => Ok ( serialport:: Parity :: Even ) ,
295+ _ => Err ( format ! ( "invalid parity setting: {s}" ) ) ,
296+ }
297+ }
298+
299+ fn parse_color ( s : & str ) -> Result < egui:: Color32 , String > {
300+ Ok ( egui:: ecolor:: HexColor :: from_str_without_hash ( s)
301+ . map_err ( |e| format ! ( "invalid color {s:?}: {e:?}" ) ) ?
302+ . color ( ) )
303+ }
304+
305+ #[ derive( Debug , Options ) ]
306+ struct CliOptions {
307+ /// Serial port device to open on startup
308+ #[ options( free) ]
309+ device : Option < String > ,
310+
311+ /// Baudrate (default=9600)
312+ #[ options( short = "b" ) ]
313+ baudrate : Option < u32 > ,
314+
315+ /// Data bits (5, 6, 7, default=8)
316+ #[ options( short = "d" , parse( try_from_str = "parse_databits" ) ) ]
317+ databits : Option < serialport:: DataBits > ,
318+
319+ /// Flow conrol (hard, soft, default=none)
320+ #[ options( short = "f" , parse( try_from_str = "parse_flow" ) ) ]
321+ flow : Option < serialport:: FlowControl > ,
322+
323+ /// Stop bits (default=1, 2)
324+ #[ options( short = "s" , parse( try_from_str = "parse_stopbits" ) ) ]
325+ stopbits : Option < serialport:: StopBits > ,
326+
327+ /// Parity (odd, even, default=none)
328+ #[ options( short = "p" , parse( try_from_str = "parse_parity" ) ) ]
329+ parity : Option < serialport:: Parity > ,
330+
331+ /// Load data from a file instead of a serial port
332+ #[ options( short = "F" ) ]
333+ file : Option < std:: path:: PathBuf > ,
334+
335+ /// Column labels, can be specified multiple times for more columns
336+ #[ options( no_short, long = "column" ) ]
337+ column_labels : Vec < String > ,
338+
339+ /// Column colors (hex color without #), can be specified multiple times for more columns
340+ #[ options( no_short, long = "color" , parse( try_from_str = "parse_color" ) ) ]
341+ column_colors : Vec < egui:: Color32 > ,
342+
343+ help : bool ,
344+ }
345+
265346fn main ( ) {
266347 egui_logger:: builder ( ) . init ( ) . unwrap ( ) ;
267348
349+ let args = CliOptions :: parse_args_default_or_exit ( ) ;
350+
268351 let gui_settings = load_gui_settings ( ) ;
269352 let saved_serial_device_configs = load_serial_settings ( ) ;
270353
271- let device_lock = Arc :: new ( RwLock :: new ( Device :: default ( ) ) ) ;
354+ let mut device = Device :: default ( ) ;
355+ if let Some ( name) = args. device {
356+ device. name = name;
357+ }
358+ if let Some ( baudrate) = args. baudrate {
359+ device. baud_rate = baudrate;
360+ }
361+ if let Some ( databits) = args. databits {
362+ device. data_bits = databits;
363+ }
364+ if let Some ( flow) = args. flow {
365+ device. flow_control = flow;
366+ }
367+ if let Some ( stopbits) = args. stopbits {
368+ device. stop_bits = stopbits;
369+ }
370+ if let Some ( parity) = args. parity {
371+ device. parity = parity;
372+ }
373+
374+ let device_lock = Arc :: new ( RwLock :: new ( device) ) ;
272375 let devices_lock = Arc :: new ( RwLock :: new ( vec ! [ gui_settings. device. clone( ) ] ) ) ;
273376 let data_lock = Arc :: new ( RwLock :: new ( GuiOutputDataContainer :: default ( ) ) ) ;
274377 let connected_lock = Arc :: new ( RwLock :: new ( false ) ) ;
@@ -316,14 +419,12 @@ fn main() {
316419 load_rx,
317420 loaded_names_tx,
318421 gui_cmd_rx,
422+ args. column_labels ,
319423 ) ;
320424 } ) ;
321425
322- let args: Vec < String > = env:: args ( ) . collect ( ) ;
323- if args. len ( ) > 1 {
324- load_tx
325- . send ( PathBuf :: from ( & args[ 1 ] ) )
326- . expect ( "failed to send file" ) ;
426+ if let Some ( file) = args. file {
427+ load_tx. send ( file) . expect ( "failed to send file" ) ;
327428 }
328429
329430 let options = eframe:: NativeOptions {
@@ -372,6 +473,7 @@ fn main() {
372473 loaded_names_rx,
373474 send_tx,
374475 gui_cmd_tx,
476+ args. column_colors ,
375477 ) ) )
376478 } ) ,
377479 ) {
0 commit comments