@@ -20,6 +20,7 @@ use heck::{ToKebabCase, ToSnakeCase};
20
20
use regex:: { Regex , RegexBuilder } ;
21
21
use reqwest:: blocking:: multipart:: { Form , Part } ;
22
22
use reqwest:: blocking:: Client ;
23
+ use rust_template:: ProgramTemplate ;
23
24
use semver:: { Version , VersionReq } ;
24
25
use serde:: { Deserialize , Serialize } ;
25
26
use serde_json:: { json, Map , Value as JsonValue } ;
@@ -69,15 +70,23 @@ pub struct Opts {
69
70
pub enum Command {
70
71
/// Initializes a workspace.
71
72
Init {
73
+ /// Workspace name
72
74
name : String ,
75
+ /// Use JavaScript instead of TypeScript
73
76
#[ clap( short, long) ]
74
77
javascript : bool ,
78
+ /// Use Solidity instead of Rust
75
79
#[ clap( short, long) ]
76
80
solidity : bool ,
81
+ /// Don't initialize git
77
82
#[ clap( long) ]
78
83
no_git : bool ,
84
+ /// Use `jest` instead of `mocha` for tests
79
85
#[ clap( long) ]
80
86
jest : bool ,
87
+ /// Rust program template to use
88
+ #[ clap( value_enum, short, long, default_value = "single" ) ]
89
+ template : ProgramTemplate ,
81
90
} ,
82
91
/// Builds the workspace.
83
92
#[ clap( name = "build" , alias = "b" ) ]
@@ -207,9 +216,14 @@ pub enum Command {
207
216
} ,
208
217
/// Creates a new program.
209
218
New {
219
+ /// Program name
220
+ name : String ,
221
+ /// Use Solidity instead of Rust
210
222
#[ clap( short, long) ]
211
223
solidity : bool ,
212
- name : String ,
224
+ /// Rust program template to use
225
+ #[ clap( value_enum, short, long, default_value = "single" ) ]
226
+ template : ProgramTemplate ,
213
227
} ,
214
228
/// Commands for interacting with interface definitions.
215
229
Idl {
@@ -456,8 +470,21 @@ pub fn entry(opts: Opts) -> Result<()> {
456
470
solidity,
457
471
no_git,
458
472
jest,
459
- } => init ( & opts. cfg_override , name, javascript, solidity, no_git, jest) ,
460
- Command :: New { solidity, name } => new ( & opts. cfg_override , solidity, name) ,
473
+ template,
474
+ } => init (
475
+ & opts. cfg_override ,
476
+ name,
477
+ javascript,
478
+ solidity,
479
+ no_git,
480
+ jest,
481
+ template,
482
+ ) ,
483
+ Command :: New {
484
+ solidity,
485
+ name,
486
+ template,
487
+ } => new ( & opts. cfg_override , solidity, name, template) ,
461
488
Command :: Build {
462
489
idl,
463
490
idl_ts,
@@ -604,6 +631,7 @@ fn init(
604
631
solidity : bool ,
605
632
no_git : bool ,
606
633
jest : bool ,
634
+ template : ProgramTemplate ,
607
635
) -> Result < ( ) > {
608
636
if Config :: discover ( cfg_override) ?. is_some ( ) {
609
637
return Err ( anyhow ! ( "Workspace already initialized" ) ) ;
@@ -682,17 +710,11 @@ fn init(
682
710
683
711
// Build the program.
684
712
if solidity {
685
- fs:: create_dir ( "solidity" ) ?;
686
-
687
- new_solidity_program ( & project_name) ?;
713
+ solidity_template:: create_program ( & project_name) ?;
688
714
} else {
689
- // Build virtual manifest for rust programs
690
- fs:: write ( "Cargo.toml" , rust_template:: virtual_manifest ( ) ) ?;
691
-
692
- fs:: create_dir ( "programs" ) ?;
693
-
694
- new_rust_program ( & project_name) ?;
715
+ rust_template:: create_program ( & project_name, template) ?;
695
716
}
717
+
696
718
// Build the test suite.
697
719
fs:: create_dir ( "tests" ) ?;
698
720
// Build the migrations directory.
@@ -783,7 +805,12 @@ fn install_node_modules(cmd: &str) -> Result<std::process::Output> {
783
805
}
784
806
785
807
// Creates a new program crate in the `programs/<name>` directory.
786
- fn new ( cfg_override : & ConfigOverride , solidity : bool , name : String ) -> Result < ( ) > {
808
+ fn new (
809
+ cfg_override : & ConfigOverride ,
810
+ solidity : bool ,
811
+ name : String ,
812
+ template : ProgramTemplate ,
813
+ ) -> Result < ( ) > {
787
814
with_workspace ( cfg_override, |cfg| {
788
815
match cfg. path ( ) . parent ( ) {
789
816
None => {
@@ -802,10 +829,10 @@ fn new(cfg_override: &ConfigOverride, solidity: bool, name: String) -> Result<()
802
829
name. clone ( ) ,
803
830
ProgramDeployment {
804
831
address : if solidity {
805
- new_solidity_program ( & name) ?;
832
+ solidity_template :: create_program ( & name) ?;
806
833
solidity_template:: default_program_id ( )
807
834
} else {
808
- new_rust_program ( & name) ?;
835
+ rust_template :: create_program ( & name, template ) ?;
809
836
rust_template:: get_or_create_program_id ( & name)
810
837
} ,
811
838
path : None ,
@@ -823,26 +850,32 @@ fn new(cfg_override: &ConfigOverride, solidity: bool, name: String) -> Result<()
823
850
} )
824
851
}
825
852
826
- // Creates a new rust program crate in the current directory with `name`.
827
- fn new_rust_program ( name : & str ) -> Result < ( ) > {
828
- if !PathBuf :: from ( "Cargo.toml" ) . exists ( ) {
829
- fs:: write ( "Cargo.toml" , rust_template:: virtual_manifest ( ) ) ?;
853
+ /// Array of (path, content) tuple.
854
+ pub type Files = Vec < ( PathBuf , String ) > ;
855
+
856
+ /// Create files from the given (path, content) tuple array.
857
+ ///
858
+ /// # Example
859
+ ///
860
+ /// ```ignore
861
+ /// crate_files(vec![("programs/my_program/src/lib.rs".into(), "// Content".into())])?;
862
+ /// ```
863
+ pub fn create_files ( files : & Files ) -> Result < ( ) > {
864
+ for ( path, content) in files {
865
+ let path = Path :: new ( path) ;
866
+ if path. exists ( ) {
867
+ continue ;
868
+ }
869
+
870
+ match path. extension ( ) {
871
+ Some ( _) => {
872
+ fs:: create_dir_all ( path. parent ( ) . unwrap ( ) ) ?;
873
+ fs:: write ( path, content) ?;
874
+ }
875
+ None => fs:: create_dir_all ( path) ?,
876
+ }
830
877
}
831
- fs:: create_dir_all ( format ! ( "programs/{name}/src/" ) ) ?;
832
- let mut cargo_toml = File :: create ( format ! ( "programs/{name}/Cargo.toml" ) ) ?;
833
- cargo_toml. write_all ( rust_template:: cargo_toml ( name) . as_bytes ( ) ) ?;
834
- let mut xargo_toml = File :: create ( format ! ( "programs/{name}/Xargo.toml" ) ) ?;
835
- xargo_toml. write_all ( rust_template:: xargo_toml ( ) . as_bytes ( ) ) ?;
836
- let mut lib_rs = File :: create ( format ! ( "programs/{name}/src/lib.rs" ) ) ?;
837
- lib_rs. write_all ( rust_template:: lib_rs ( name) . as_bytes ( ) ) ?;
838
- Ok ( ( ) )
839
- }
840
878
841
- // Creates a new solidity program in the current directory with `name`.
842
- fn new_solidity_program ( name : & str ) -> Result < ( ) > {
843
- fs:: create_dir_all ( "solidity" ) ?;
844
- let mut lib_rs = File :: create ( format ! ( "solidity/{name}.sol" ) ) ?;
845
- lib_rs. write_all ( solidity_template:: solidity ( name) . as_bytes ( ) ) ?;
846
879
Ok ( ( ) )
847
880
}
848
881
@@ -4224,6 +4257,7 @@ mod tests {
4224
4257
false ,
4225
4258
false ,
4226
4259
false ,
4260
+ ProgramTemplate :: default ( ) ,
4227
4261
)
4228
4262
. unwrap ( ) ;
4229
4263
}
@@ -4241,6 +4275,7 @@ mod tests {
4241
4275
false ,
4242
4276
false ,
4243
4277
false ,
4278
+ ProgramTemplate :: default ( ) ,
4244
4279
)
4245
4280
. unwrap ( ) ;
4246
4281
}
@@ -4258,6 +4293,7 @@ mod tests {
4258
4293
false ,
4259
4294
false ,
4260
4295
false ,
4296
+ ProgramTemplate :: default ( ) ,
4261
4297
)
4262
4298
. unwrap ( ) ;
4263
4299
}
0 commit comments