11use std:: {
2+ collections:: HashMap ,
23 fs,
34 path:: { Path , PathBuf } ,
5+ sync:: Arc ,
46 time:: SystemTime ,
57} ;
68
79use anyhow:: bail;
10+ use cursive:: Cursive ;
811
912use crate :: data:: { menu:: MenuRoot , types:: ElementType } ;
1013
14+ pub type FeaturesCallback = Arc < dyn Fn ( ) -> Vec < String > + Send + Sync > ;
15+
16+ pub type HockCallback = Arc < dyn Fn ( & mut Cursive , & str ) + Send + Sync > ;
17+
18+ #[ derive( Clone ) ]
19+ pub struct ElemHock {
20+ pub path : String ,
21+ pub callback : HockCallback ,
22+ }
23+
1124#[ derive( Clone ) ]
1225pub struct AppData {
1326 pub root : MenuRoot ,
1427 pub current_key : Vec < String > ,
1528 pub needs_save : bool ,
1629 pub config : PathBuf ,
30+ pub user_data : HashMap < String , String > ,
31+ pub temp_data : Option < ( String , serde_json:: Value ) > ,
32+ pub elem_hocks : Vec < ElemHock > ,
1733}
1834
1935const DEFAULT_CONFIG_PATH : & str = ".config.toml" ;
@@ -39,10 +55,7 @@ impl AppData {
3955 config : Option < impl AsRef < Path > > ,
4056 schema : Option < impl AsRef < Path > > ,
4157 ) -> anyhow:: Result < Self > {
42- let mut init_value_path = PathBuf :: from ( DEFAULT_CONFIG_PATH ) ;
43- if let Some ( cfg) = config {
44- init_value_path = cfg. as_ref ( ) . to_path_buf ( ) ;
45- }
58+ let init_value_path = Self :: init_value_path ( config) ;
4659
4760 let schema_path = if let Some ( sch) = schema {
4861 sch. as_ref ( ) . to_path_buf ( )
@@ -56,8 +69,60 @@ impl AppData {
5669
5770 let schema_content = fs:: read_to_string ( & schema_path) ?;
5871 let schema_json: serde_json:: Value = serde_json:: from_str ( & schema_content) ?;
72+ Self :: new_with_schema ( Some ( init_value_path) , & schema_json)
73+ }
74+
75+ fn init_value_path ( config : Option < impl AsRef < Path > > ) -> PathBuf {
76+ let mut init_value_path = PathBuf :: from ( DEFAULT_CONFIG_PATH ) ;
77+ if let Some ( cfg) = config {
78+ init_value_path = cfg. as_ref ( ) . to_path_buf ( ) ;
79+ }
80+ init_value_path
81+ }
82+
83+ pub fn new_with_init_and_schema (
84+ init : & str ,
85+ init_value_path : & Path ,
86+ schema : & serde_json:: Value ,
87+ ) -> anyhow:: Result < Self > {
88+ let mut root = MenuRoot :: try_from ( schema) ?;
89+
90+ if !init. trim ( ) . is_empty ( ) {
91+ let init_json: serde_json:: Value = match init_value_path
92+ . extension ( )
93+ . and_then ( |s| s. to_str ( ) )
94+ . unwrap_or ( "" )
95+ {
96+ "json" => serde_json:: from_str ( init) ?,
97+ "toml" => {
98+ let v: toml:: Value = toml:: from_str ( init) ?;
99+ serde_json:: to_value ( v) ?
100+ }
101+ ext => {
102+ bail ! ( "Unsupported config file extension: {ext:?}" ) ;
103+ }
104+ } ;
105+ root. update_by_value ( & init_json) ?;
106+ }
107+
108+ Ok ( AppData {
109+ root,
110+ current_key : Vec :: new ( ) ,
111+ needs_save : false ,
112+ config : init_value_path. into ( ) ,
113+ temp_data : None ,
114+ elem_hocks : Vec :: new ( ) ,
115+ user_data : HashMap :: new ( ) ,
116+ } )
117+ }
118+
119+ pub fn new_with_schema (
120+ config : Option < impl AsRef < Path > > ,
121+ schema : & serde_json:: Value ,
122+ ) -> anyhow:: Result < Self > {
123+ let init_value_path = Self :: init_value_path ( config) ;
59124
60- let mut root = MenuRoot :: try_from ( & schema_json ) ?;
125+ let mut root = MenuRoot :: try_from ( schema ) ?;
61126
62127 if init_value_path. exists ( ) {
63128 let init_content = fs:: read_to_string ( & init_value_path) ?;
@@ -85,6 +150,9 @@ impl AppData {
85150 current_key : Vec :: new ( ) ,
86151 needs_save : false ,
87152 config : init_value_path,
153+ temp_data : None ,
154+ elem_hocks : Vec :: new ( ) ,
155+ user_data : HashMap :: new ( ) ,
88156 } )
89157 }
90158
0 commit comments