2
2
#![ allow( clippy:: almost_swapped) ]
3
3
4
4
use anyhow:: { anyhow, Context , Result } ;
5
- use clap:: { Parser , Subcommand } ;
5
+ use clap:: { Parser , Subcommand , ValueEnum } ;
6
6
use semver:: Version ;
7
7
use spin_plugins:: {
8
8
error:: Error ,
@@ -616,6 +616,16 @@ pub struct List {
616
616
/// Filter the list to plugins containing this string.
617
617
#[ clap( long = "filter" ) ]
618
618
pub filter : Option < String > ,
619
+
620
+ /// The format in which to list the templates.
621
+ #[ clap( value_enum, long = "format" , default_value = "plain" ) ]
622
+ pub format : ListFormat ,
623
+ }
624
+
625
+ #[ derive( ValueEnum , Clone , Debug ) ]
626
+ pub enum ListFormat {
627
+ Plain ,
628
+ Json ,
619
629
}
620
630
621
631
impl List {
@@ -636,11 +646,13 @@ impl List {
636
646
plugins. retain ( |p| p. name . contains ( filter) ) ;
637
647
}
638
648
639
- Self :: print ( & plugins) ;
640
- Ok ( ( ) )
649
+ match self . format {
650
+ ListFormat :: Plain => Self :: print_plain ( & plugins) ,
651
+ ListFormat :: Json => Self :: print_json ( & plugins) ,
652
+ }
641
653
}
642
654
643
- fn print ( plugins : & [ PluginDescriptor ] ) {
655
+ fn print_plain ( plugins : & [ PluginDescriptor ] ) -> anyhow :: Result < ( ) > {
644
656
if plugins. is_empty ( ) {
645
657
println ! ( "No plugins found" ) ;
646
658
} else {
@@ -662,6 +674,16 @@ impl List {
662
674
println ! ( "{} {}{}{}" , p. name, p. version, installed, compat) ;
663
675
}
664
676
}
677
+
678
+ Ok ( ( ) )
679
+ }
680
+
681
+ fn print_json ( plugins : & [ PluginDescriptor ] ) -> anyhow:: Result < ( ) > {
682
+ let json_vals: Vec < _ > = plugins. iter ( ) . map ( json_list_format) . collect ( ) ;
683
+
684
+ let json_text = serde_json:: to_string_pretty ( & json_vals) ?;
685
+ println ! ( "{}" , json_text) ;
686
+ Ok ( ( ) )
665
687
}
666
688
}
667
689
@@ -670,6 +692,10 @@ impl List {
670
692
pub struct Search {
671
693
/// The text to search for. If omitted, all plugins are returned.
672
694
pub filter : Option < String > ,
695
+
696
+ /// The format in which to list the plugins.
697
+ #[ clap( value_enum, long = "format" , default_value = "plain" ) ]
698
+ pub format : ListFormat ,
673
699
}
674
700
675
701
impl Search {
@@ -679,6 +705,7 @@ impl Search {
679
705
all : true ,
680
706
summary : false ,
681
707
filter : self . filter . clone ( ) ,
708
+ format : self . format . clone ( ) ,
682
709
} ;
683
710
684
711
list_cmd. run ( ) . await
@@ -731,6 +758,36 @@ impl PluginDescriptor {
731
758
}
732
759
}
733
760
761
+ #[ derive( serde:: Serialize ) ]
762
+ #[ serde( rename_all = "camelCase" ) ]
763
+ struct PluginJsonFormat {
764
+ name : String ,
765
+ installed : bool ,
766
+ version : String ,
767
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
768
+ installed_version : Option < String > ,
769
+ }
770
+
771
+ fn json_list_format ( plugin : & PluginDescriptor ) -> PluginJsonFormat {
772
+ let installed_version = if plugin. installed {
773
+ Some (
774
+ plugin
775
+ . installed_version
776
+ . clone ( )
777
+ . unwrap_or_else ( || plugin. version . clone ( ) ) ,
778
+ )
779
+ } else {
780
+ None
781
+ } ;
782
+
783
+ PluginJsonFormat {
784
+ name : plugin. name . clone ( ) ,
785
+ installed : plugin. installed ,
786
+ version : plugin. version . clone ( ) ,
787
+ installed_version,
788
+ }
789
+ }
790
+
734
791
// Auxiliar function for Upgrade::upgrade_multiselect
735
792
fn elements_at < T > ( source : Vec < T > , indexes : Vec < usize > ) -> Vec < T > {
736
793
source
0 commit comments