11use clap:: {
22 Parser ,
33 Subcommand ,
4+ ValueEnum ,
45} ;
56use pmrcore:: {
67 exposure:: {
@@ -43,18 +44,70 @@ use std::{
4344 stdin,
4445 BufReader ,
4546 } ,
47+ sync:: OnceLock ,
4648} ;
4749
50+ #[ derive( Clone , Debug , ValueEnum ) ]
51+ pub enum SerdeKind {
52+ Json ,
53+ Toml ,
54+ }
55+
56+ mod display {
57+ use std:: fmt:: { Display , Formatter , Result } ;
58+ use super :: SerdeKind ;
4859
60+ impl Display for SerdeKind {
61+ fn fmt ( & self , f : & mut Formatter ) -> Result {
62+ match self {
63+ Self :: Json => "json" . fmt ( f) ,
64+ Self :: Toml => "toml" . fmt ( f) ,
65+ }
66+ }
67+ }
68+ }
69+
70+ impl SerdeKind {
71+ pub fn to_string < T > ( & self , item : & T ) -> Result < String , anyhow:: Error >
72+ where
73+ T : serde:: Serialize ,
74+ {
75+ Ok ( match self {
76+ Self :: Json => serde_json:: to_string_pretty ( item) ?,
77+ Self :: Toml => toml:: to_string ( item) ?,
78+ } )
79+ }
80+
81+ pub fn from_reader < R , T > ( & self , rdr : R ) -> Result < T , anyhow:: Error >
82+ where
83+ R : std:: io:: Read ,
84+ T : serde:: de:: DeserializeOwned ,
85+ {
86+ Ok ( match self {
87+ Self :: Json => serde_json:: from_reader ( rdr) ?,
88+ Self :: Toml => toml:: from_slice ( & rdr. bytes ( ) . collect :: < Result < Vec < _ > , _ > > ( ) ?) ?,
89+ } )
90+ }
91+ }
92+
93+ #[ derive( Debug , Parser ) ]
94+ struct Config {
95+ #[ clap( short = 'o' , long = "format" , default_value_t = SerdeKind :: Json ) ]
96+ serde_kind : SerdeKind ,
97+ #[ clap( short = 'v' , long = "verbose" , action = clap:: ArgAction :: Count ) ]
98+ verbose : u8 ,
99+ }
100+
101+ static CONF : OnceLock < Config > = OnceLock :: new ( ) ;
49102
50103#[ derive( Debug , Parser ) ]
51104struct Cli {
52105 #[ command( subcommand) ]
53106 command : Commands ,
54107 #[ clap( flatten) ]
55108 platform_builder : PlatformBuilder ,
56- #[ clap( short = 'v' , long = "verbose" , action = clap :: ArgAction :: Count ) ]
57- verbose : u8 ,
109+ #[ clap( flatten ) ]
110+ config : Config ,
58111}
59112
60113
@@ -239,7 +292,7 @@ async fn main() -> anyhow::Result<()> {
239292 . module ( module_path ! ( ) )
240293 . module ( "pmrdb" )
241294 . module ( "pmrtqs" )
242- . verbosity ( ( args. verbose as usize ) + 1 )
295+ . verbosity ( ( args. config . verbose as usize ) + 1 )
243296 . timestamp ( stderrlog:: Timestamp :: Second )
244297 . init ( )
245298 . unwrap ( ) ;
@@ -249,6 +302,8 @@ async fn main() -> anyhow::Result<()> {
249302 . await
250303 . map_err ( anyhow:: Error :: from_boxed) ?;
251304
305+ let _ = CONF . set ( args. config ) ;
306+
252307 match args. command {
253308 Commands :: Alias { cmd } => {
254309 parse_alias ( & platform, cmd) . await ?;
@@ -353,6 +408,7 @@ async fn parse_profile<'p>(
353408 platform : & ' p Platform ,
354409 arg : ProfileCmd ,
355410) -> anyhow:: Result < ( ) > {
411+ let conf = CONF . get ( ) . expect ( "config is set by main" ) ;
356412 match arg {
357413 ProfileCmd :: Create { title, description } => {
358414 let id = ProfileBackend :: insert_profile (
@@ -378,9 +434,9 @@ async fn parse_profile<'p>(
378434 let cache = ChoiceRegistryCache :: from (
379435 & registry as & dyn ChoiceRegistry < _ > ) ;
380436 let uvpr: UserViewProfileRef = ( & result, & cache) . into ( ) ;
381- serde_json :: to_string_pretty ( & uvpr) ?
437+ conf . serde_kind . to_string ( & uvpr) ?
382438 } else {
383- serde_json :: to_string_pretty ( & result) ?
439+ conf . serde_kind . to_string ( & result) ?
384440 } ;
385441 println ! ( "{output}" ) ;
386442 } ,
@@ -431,12 +487,13 @@ async fn parse_vtt<'p>(
431487 platform : & ' p Platform ,
432488 arg : VttCmd ,
433489) -> anyhow:: Result < ( ) > {
490+ let conf = CONF . get ( ) . expect ( "config is set by main" ) ;
434491 match arg {
435492 VttCmd :: Import { input } => {
436493 let id = platform. adds_view_task_template (
437494 match input {
438- Some ( path) => serde_json :: from_reader ( BufReader :: new ( fs:: File :: open ( path) ?) ) ?,
439- None => serde_json :: from_reader ( BufReader :: new ( stdin ( ) ) ) ?,
495+ Some ( path) => conf . serde_kind . from_reader ( BufReader :: new ( fs:: File :: open ( path) ?) ) ?,
496+ None => conf . serde_kind . from_reader ( BufReader :: new ( stdin ( ) ) ) ?,
440497 }
441498 ) . await ?;
442499 println ! ( "imported ViewTaskTemplate {id}" ) ;
@@ -455,7 +512,7 @@ async fn parse_vtt<'p>(
455512 }
456513 VttCmd :: Export { id } => {
457514 let result = platform. get_view_task_template ( id) . await ?;
458- let output = serde_json :: to_string_pretty ( & result) ?;
515+ let output = conf . serde_kind . to_string ( & result) ?;
459516 println ! ( "{output}" ) ;
460517 }
461518 }
@@ -496,6 +553,7 @@ async fn parse_exposure_path<'p>(
496553) -> anyhow:: Result < ( ) > {
497554 let ec = platform. get_exposure ( exposure_id) . await ?;
498555 let efc = ec. ctrl_path ( path) . await ?;
556+ let conf = CONF . get ( ) . expect ( "config is set by main" ) ;
499557 match arg {
500558 ExposurePathCmd :: Assign { profile_id } => {
501559 let exposure_file_id = efc. exposure_file ( ) . id ( ) ;
@@ -506,7 +564,7 @@ async fn parse_exposure_path<'p>(
506564 ExposurePathCmd :: Prompts => {
507565 let efvttsc = efc. build_vttc ( ) . await ?;
508566 let upgr = efvttsc. create_user_prompt_groups ( ) ?;
509- let output = serde_json :: to_string_pretty ( & upgr) ?;
567+ let output = conf . serde_kind . to_string ( & upgr) ?;
510568 println ! ( "{output}" ) ;
511569 } ,
512570 ExposurePathCmd :: Answer { arg_id, answer } => {
@@ -583,7 +641,7 @@ async fn parse_exposure_path<'p>(
583641 efc. process_vttc_tasks ( vttc_tasks) . await ?;
584642 println ! ( "{len} task(s) queued" ) ;
585643 } else {
586- let output = serde_json :: to_string_pretty ( & vttc_tasks) ?;
644+ let output = conf . serde_kind . to_string ( & vttc_tasks) ?;
587645 println ! ( "The generated VTTCTasks:" ) ;
588646 println ! ( "{output}" ) ;
589647 } ;
0 commit comments