@@ -28,18 +28,16 @@ enum Commands {
2828
2929#[ derive( Parser , Debug , Default ) ]
3030struct PvmContractArgs {
31- #[ arg( long, value_enum, requires = "non_interactive" ) ]
31+ #[ arg( long, value_enum) ]
3232 init_type : Option < InitType > ,
33- #[ arg( long, requires = "non_interactive" ) ]
33+ #[ arg( long) ]
3434 example : Option < String > ,
35- #[ arg( long, value_enum, requires = "non_interactive" ) ]
35+ #[ arg( long, value_enum) ]
3636 memory_model : Option < MemoryModel > ,
37- #[ arg( long, requires = "non_interactive" ) ]
37+ #[ arg( long) ]
3838 name : Option < String > ,
39- #[ arg( long, requires = "non_interactive" ) ]
40- sol_file : Option < PathBuf > ,
4139 #[ arg( long) ]
42- non_interactive : bool ,
40+ sol_file : Option < PathBuf > ,
4341}
4442
4543#[ derive( Debug , Clone , Copy , PartialEq , ValueEnum ) ]
@@ -143,218 +141,128 @@ fn main() -> Result<()> {
143141}
144142
145143fn init_command ( args : PvmContractArgs ) -> Result < ( ) > {
146- let builder_path = std:: env:: var ( "CARGO_PVM_CONTRACT_BUILDER_PATH" )
147- . ok ( )
148- . filter ( |value| !value. trim ( ) . is_empty ( ) )
149- . map ( PathBuf :: from) ;
150-
151- if let Some ( path) = builder_path. as_deref ( )
152- && !path. exists ( )
153- {
154- anyhow:: bail!( "Builder path does not exist: {}" , path. display( ) ) ;
155- }
156-
157- if args. non_interactive {
158- init_command_non_interactive ( args, builder_path. as_deref ( ) )
159- } else {
160- init_command_interactive ( builder_path. as_deref ( ) )
161- }
162- }
163-
164- fn init_command_interactive ( builder_path : Option < & std:: path:: Path > ) -> Result < ( ) > {
165- // First, prompt for initialization type
166- let init_types = vec ! [ InitType :: SolidityFile , InitType :: Example , InitType :: Blank ] ;
167- let init_type = Select :: new ( "How do you want to initialize the project?" , init_types)
168- . prompt ( )
169- . context ( "Failed to get initialization type" ) ?;
144+ // Get init_type from args or prompt
145+ let init_type = match args. init_type {
146+ Some ( t) => t,
147+ None => {
148+ let init_types = vec ! [ InitType :: SolidityFile , InitType :: Example , InitType :: Blank ] ;
149+ Select :: new ( "How do you want to initialize the project?" , init_types)
150+ . prompt ( )
151+ . context ( "Failed to get initialization type" ) ?
152+ }
153+ } ;
170154
171155 match init_type {
172156 InitType :: Blank => {
173- // Ask for name without prefill
174- let contract_name = Text :: new ( "What is your contract name?" )
175- . with_help_message ( "This will be the name of the project directory" )
176- . prompt ( )
177- . context ( "Failed to get contract name" ) ?;
178-
179- if contract_name. is_empty ( ) {
180- anyhow:: bail!( "Contract name cannot be empty" ) ;
181- }
182-
157+ let contract_name = prompt_name ( args. name , None ) ?;
183158 check_dir_exists ( & contract_name) ?;
184159 debug ! ( "Initializing blank contract: {contract_name}" ) ;
185- scaffold:: init_blank_contract ( & contract_name, builder_path )
160+ scaffold:: init_blank_contract ( & contract_name)
186161 }
187162 InitType :: Example => {
188163 let examples = load_examples ( ) ?;
189- let example = Select :: new ( "Select an example:" , examples)
190- . prompt ( )
191- . context ( "Failed to get example choice" ) ?;
192164
193- // Prompt for memory model
194- let memory_models = vec ! [ MemoryModel :: AllocWithAlloy , MemoryModel :: NoAlloc ] ;
195- let memory_model = Select :: new ( "Which memory model do you want to use?" , memory_models)
196- . prompt ( )
197- . context ( "Failed to get memory model choice" ) ?;
165+ // Get example from args or prompt
166+ let example = match args. example {
167+ Some ( example_name) => find_example ( & examples, & example_name) ?,
168+ None => Select :: new ( "Select an example:" , examples)
169+ . prompt ( )
170+ . context ( "Failed to get example choice" ) ?,
171+ } ;
198172
199- // Ask for name with example name as default
200- let contract_name = Text :: new ( "What is your contract name?" )
201- . with_default ( & example. name )
202- . with_help_message ( "This will be the name of the project directory" )
203- . prompt ( )
204- . context ( "Failed to get contract name" ) ?;
205-
206- if contract_name. is_empty ( ) {
207- anyhow:: bail!( "Contract name cannot be empty" ) ;
208- }
173+ let memory_model = prompt_memory_model ( args. memory_model ) ?;
174+ let contract_name = prompt_name ( args. name , Some ( & example. name ) ) ?;
209175
210176 check_dir_exists ( & contract_name) ?;
211177 debug ! (
212178 "Initializing from example: {} with memory model: {:?}" ,
213179 example. filename, memory_model
214180 ) ;
215181
216- init_from_example ( & example, & contract_name, memory_model, builder_path )
182+ init_from_example ( & example, & contract_name, memory_model)
217183 }
218184 InitType :: SolidityFile => {
219- // Prompt for .sol file path
220- let sol_file = Text :: new ( "Enter path to your .sol file:" )
221- . with_help_message ( "Path to a Solidity interface file" )
222- . prompt ( )
223- . context ( "Failed to get .sol file path" ) ?;
185+ // Get sol_file from args or prompt
186+ let sol_path = match args. sol_file {
187+ Some ( path) => path,
188+ None => {
189+ let sol_file = Text :: new ( "Enter path to your .sol file:" )
190+ . with_help_message ( "Path to a Solidity interface file" )
191+ . prompt ( )
192+ . context ( "Failed to get .sol file path" ) ?;
193+
194+ if sol_file. is_empty ( ) {
195+ anyhow:: bail!( "Solidity file path cannot be empty" ) ;
196+ }
197+ PathBuf :: from ( sol_file)
198+ }
199+ } ;
224200
225- if sol_file. is_empty ( ) {
226- anyhow:: bail!( "Solidity file path cannot be empty" ) ;
227- }
228-
229- // Verify file exists
230- let sol_path = PathBuf :: from ( & sol_file) ;
231201 if !sol_path. exists ( ) {
232- anyhow:: bail!( "Solidity file not found: {sol_file}" ) ;
202+ anyhow:: bail!( "Solidity file not found: {}" , sol_path . display ( ) ) ;
233203 }
234204
235- // Extract default name from .sol filename
236205 let default_name = sol_path
237206 . file_stem ( )
238207 . and_then ( |s| s. to_str ( ) )
239208 . unwrap_or ( "contract" )
240209 . to_string ( ) ;
241210
242- // Prompt for memory model
243- let memory_models = vec ! [ MemoryModel :: AllocWithAlloy , MemoryModel :: NoAlloc ] ;
244- let memory_model = Select :: new ( "Which memory model do you want to use?" , memory_models)
245- . prompt ( )
246- . context ( "Failed to get memory model choice" ) ?;
247-
248- // Ask for name with .sol filename as default
249- let contract_name = Text :: new ( "What is your contract name?" )
250- . with_default ( & default_name)
251- . with_help_message ( "This will be the name of the project directory" )
252- . prompt ( )
253- . context ( "Failed to get contract name" ) ?;
254-
255- if contract_name. is_empty ( ) {
256- anyhow:: bail!( "Contract name cannot be empty" ) ;
257- }
211+ let memory_model = prompt_memory_model ( args. memory_model ) ?;
212+ let contract_name = prompt_name ( args. name , Some ( & default_name) ) ?;
258213
259214 check_dir_exists ( & contract_name) ?;
260215 debug ! (
261- "Initializing from Solidity file: {sol_file} with memory model: {:?}" ,
216+ "Initializing from Solidity file: {} with memory model: {:?}" ,
217+ sol_path. display( ) ,
262218 memory_model
263219 ) ;
264220
221+ let sol_file = sol_path. to_str ( ) . ok_or_else ( || {
222+ anyhow:: anyhow!( "Solidity file path is not valid UTF-8: {:?}" , sol_path)
223+ } ) ?;
265224 let use_alloc = memory_model == MemoryModel :: AllocWithAlloy ;
266- scaffold:: init_from_solidity_file ( & sol_file, & contract_name, use_alloc, builder_path )
225+ scaffold:: init_from_solidity_file ( sol_file, & contract_name, use_alloc)
267226 }
268227 }
269228}
270229
271- fn init_command_non_interactive (
272- args : PvmContractArgs ,
273- builder_path : Option < & std:: path:: Path > ,
274- ) -> Result < ( ) > {
275- let init_type = args
276- . init_type
277- . ok_or_else ( || anyhow:: anyhow!( "--init-type is required with --non-interactive" ) ) ?;
278-
279- match init_type {
280- InitType :: Blank => {
281- let contract_name = args
282- . name
283- . filter ( |name| !name. is_empty ( ) )
284- . ok_or_else ( || anyhow:: anyhow!( "--name is required for blank initialization" ) ) ?;
285-
286- check_dir_exists ( & contract_name) ?;
287- debug ! ( "Initializing blank contract: {contract_name}" ) ;
288- scaffold:: init_blank_contract ( & contract_name, builder_path)
230+ fn prompt_memory_model ( arg : Option < MemoryModel > ) -> Result < MemoryModel > {
231+ match arg {
232+ Some ( m) => Ok ( m) ,
233+ None => {
234+ let memory_models = vec ! [ MemoryModel :: AllocWithAlloy , MemoryModel :: NoAlloc ] ;
235+ Select :: new ( "Which memory model do you want to use?" , memory_models)
236+ . prompt ( )
237+ . context ( "Failed to get memory model choice" )
289238 }
290- InitType :: Example => {
291- let examples = load_examples ( ) ?;
292- let example_name = args. example . ok_or_else ( || {
293- anyhow:: anyhow!( "--example is required for example initialization" )
294- } ) ?;
295- let example = find_example ( & examples, & example_name) ?;
296- let memory_model = args. memory_model . ok_or_else ( || {
297- anyhow:: anyhow!( "--memory-model is required for example initialization" )
298- } ) ?;
299- let contract_name = args. name . unwrap_or_else ( || example. name . clone ( ) ) ;
239+ }
240+ }
300241
301- if contract_name. is_empty ( ) {
302- anyhow:: bail!( "Contract name cannot be empty" ) ;
242+ fn prompt_name ( arg : Option < String > , default : Option < & str > ) -> Result < String > {
243+ let contract_name = match arg {
244+ Some ( name) => name,
245+ None => {
246+ let mut prompt = Text :: new ( "What is your contract name?" )
247+ . with_help_message ( "This will be the name of the project directory" ) ;
248+ if let Some ( d) = default {
249+ prompt = prompt. with_default ( d) ;
303250 }
304-
305- check_dir_exists ( & contract_name) ?;
306- debug ! (
307- "Initializing from example: {} with memory model: {:?}" ,
308- example. filename, memory_model
309- ) ;
310-
311- init_from_example ( & example, & contract_name, memory_model, builder_path)
251+ prompt. prompt ( ) . context ( "Failed to get contract name" ) ?
312252 }
313- InitType :: SolidityFile => {
314- let sol_path = args. sol_file . ok_or_else ( || {
315- anyhow:: anyhow!( "--sol-file is required for Solidity initialization" )
316- } ) ?;
253+ } ;
317254
318- if !sol_path. exists ( ) {
319- anyhow:: bail!( "Solidity file not found: {}" , sol_path. display( ) ) ;
320- }
321-
322- let default_name = sol_path
323- . file_stem ( )
324- . and_then ( |s| s. to_str ( ) )
325- . unwrap_or ( "contract" )
326- . to_string ( ) ;
327- let contract_name = args. name . unwrap_or ( default_name) ;
328-
329- if contract_name. is_empty ( ) {
330- anyhow:: bail!( "Contract name cannot be empty" ) ;
331- }
332-
333- let memory_model = args. memory_model . ok_or_else ( || {
334- anyhow:: anyhow!( "--memory-model is required for Solidity initialization" )
335- } ) ?;
336-
337- check_dir_exists ( & contract_name) ?;
338- debug ! (
339- "Initializing from Solidity file: {} with memory model: {:?}" ,
340- sol_path. display( ) ,
341- memory_model
342- ) ;
343-
344- let sol_file = sol_path. to_str ( ) . ok_or_else ( || {
345- anyhow:: anyhow!( "Solidity file path is not valid UTF-8: {:?}" , sol_path)
346- } ) ?;
347- let use_alloc = memory_model == MemoryModel :: AllocWithAlloy ;
348- scaffold:: init_from_solidity_file ( sol_file, & contract_name, use_alloc, builder_path)
349- }
255+ if contract_name. is_empty ( ) {
256+ anyhow:: bail!( "Contract name cannot be empty" ) ;
350257 }
258+
259+ Ok ( contract_name)
351260}
352261
353262fn init_from_example (
354263 example : & ExampleContract ,
355264 contract_name : & str ,
356265 memory_model : MemoryModel ,
357- builder_path : Option < & std:: path:: Path > ,
358266) -> Result < ( ) > {
359267 // Get the embedded example .sol file
360268 let example_path = format ! ( "examples/{}" , example. filename) ;
@@ -383,7 +291,6 @@ fn init_from_example(
383291 temp_sol_path. to_str ( ) . unwrap ( ) ,
384292 contract_name,
385293 use_alloc,
386- builder_path,
387294 ) ;
388295
389296 // Clean up temp file
0 commit comments