@@ -5,7 +5,7 @@ use crate::{
5
5
} ,
6
6
shell:: { ColorChoice , Shell } ,
7
7
} ;
8
- use anyhow:: { anyhow, Context as _} ;
8
+ use anyhow:: { anyhow, bail , Context as _} ;
9
9
use heck:: KebabCase as _;
10
10
use itertools:: Itertools as _;
11
11
use liquid:: object;
@@ -88,12 +88,14 @@ pub fn run(opt: OptCompeteNew, ctx: crate::Context<'_>) -> anyhow::Result<()> {
88
88
shell,
89
89
) ?;
90
90
91
- let package_name = outcome
91
+ let contest = outcome
92
92
. contest
93
93
. as_ref ( )
94
94
. map ( |RetrieveTestCasesOutcomeContest { id, .. } | id)
95
95
. unwrap_or ( & contest) ;
96
96
97
+ let group = Group :: Atcoder ( contest) ;
98
+
97
99
let problems = outcome
98
100
. problems
99
101
. iter ( )
@@ -105,9 +107,8 @@ pub fn run(opt: OptCompeteNew, ctx: crate::Context<'_>) -> anyhow::Result<()> {
105
107
let ( manifest_dir, src_paths) = create_new_package (
106
108
& cargo_compete_config_path,
107
109
& cargo_compete_config,
108
- package_name ,
110
+ group ,
109
111
& problems,
110
- false ,
111
112
shell,
112
113
) ?;
113
114
@@ -145,12 +146,14 @@ pub fn run(opt: OptCompeteNew, ctx: crate::Context<'_>) -> anyhow::Result<()> {
145
146
shell,
146
147
) ?;
147
148
148
- let package_name = outcome
149
+ let contest = outcome
149
150
. contest
150
151
. as_ref ( )
151
152
. map ( |RetrieveTestCasesOutcomeContest { id, .. } | id)
152
153
. unwrap_or ( & contest) ;
153
154
155
+ let group = Group :: Codeforces ( contest) ;
156
+
154
157
let problems = outcome
155
158
. problems
156
159
. iter ( )
@@ -162,9 +165,8 @@ pub fn run(opt: OptCompeteNew, ctx: crate::Context<'_>) -> anyhow::Result<()> {
162
165
let ( manifest_dir, src_paths) = create_new_package (
163
166
& cargo_compete_config_path,
164
167
& cargo_compete_config,
165
- package_name ,
168
+ group ,
166
169
& problems,
167
- false ,
168
170
shell,
169
171
) ?;
170
172
@@ -198,13 +200,16 @@ pub fn run(opt: OptCompeteNew, ctx: crate::Context<'_>) -> anyhow::Result<()> {
198
200
let outcome =
199
201
crate :: web:: retrieve_testcases:: dl_from_yukicoder ( contest, problems, full, shell) ?;
200
202
201
- let package_name = outcome
203
+ let contest = outcome
202
204
. contest
203
205
. as_ref ( )
204
206
. map ( |RetrieveTestCasesOutcomeContest { id, .. } | & * * id)
205
207
. or ( contest) ;
206
- let is_no = package_name. is_none ( ) ;
207
- let package_name = package_name. unwrap_or ( "problems" ) ;
208
+
209
+ let group = match contest {
210
+ None => Group :: YukicoderProblems ,
211
+ Some ( contest) => Group :: YukicoderContest ( contest) ,
212
+ } ;
208
213
209
214
let problems = outcome
210
215
. problems
@@ -217,9 +222,8 @@ pub fn run(opt: OptCompeteNew, ctx: crate::Context<'_>) -> anyhow::Result<()> {
217
222
let ( manifest_dir, src_paths) = create_new_package (
218
223
& cargo_compete_config_path,
219
224
& cargo_compete_config,
220
- package_name ,
225
+ group ,
221
226
& problems,
222
- is_no,
223
227
shell,
224
228
) ?;
225
229
@@ -254,31 +258,47 @@ fn urls(outcome: &RetrieveTestCasesOutcome) -> Vec<Url> {
254
258
outcome. problems . iter ( ) . map ( |p| p. url . clone ( ) ) . collect ( )
255
259
}
256
260
261
+ #[ derive( Copy , Clone , Debug ) ]
262
+ enum Group < ' a > {
263
+ Atcoder ( & ' a str ) ,
264
+ Codeforces ( & ' a str ) ,
265
+ YukicoderProblems ,
266
+ YukicoderContest ( & ' a str ) ,
267
+ }
268
+
269
+ impl < ' a > Group < ' a > {
270
+ fn contest ( self ) -> Option < & ' a str > {
271
+ match self {
272
+ Self :: Atcoder ( contest)
273
+ | Self :: Codeforces ( contest)
274
+ | Self :: YukicoderContest ( contest) => Some ( contest) ,
275
+ Self :: YukicoderProblems => None ,
276
+ }
277
+ }
278
+
279
+ fn package_name ( self ) -> String {
280
+ match self {
281
+ Self :: Atcoder ( contest) => contest. to_owned ( ) ,
282
+ Self :: Codeforces ( contest) | Self :: YukicoderContest ( contest) => {
283
+ format ! ( "contest{}" , contest)
284
+ }
285
+ Self :: YukicoderProblems => "problems" . to_owned ( ) ,
286
+ }
287
+ }
288
+ }
289
+
257
290
fn create_new_package (
258
291
cargo_compete_config_path : & Path ,
259
292
cargo_compete_config : & CargoCompeteConfig ,
260
- package_name : & str ,
293
+ group : Group < ' _ > ,
261
294
problems : & BTreeMap < & str , & Url > ,
262
- problems_are_yukicoder_no : bool ,
263
295
shell : & mut Shell ,
264
296
) -> anyhow:: Result < ( PathBuf , Vec < PathBuf > ) > {
265
- crate :: process:: process ( crate :: process:: cargo_exe ( ) ?)
266
- . args ( & [
267
- "new" ,
268
- "-q" ,
269
- "--vcs" ,
270
- "none" ,
271
- "--name" ,
272
- package_name,
273
- package_name,
274
- ] )
275
- . cwd ( cargo_compete_config_path. with_file_name ( "" ) )
276
- . exec ( ) ?;
277
-
278
297
let cargo_compete_config_dir = cargo_compete_config_path. with_file_name ( "" ) ;
279
298
280
299
let manifest_dir = cargo_compete_config. new . path . render ( & object ! ( {
281
- "package_name" : package_name,
300
+ "contest" : group. contest( ) ,
301
+ "package_name" : group. package_name( ) ,
282
302
} ) ) ?;
283
303
let manifest_dir = Path :: new ( & manifest_dir) ;
284
304
let manifest_dir = cargo_compete_config_path
@@ -287,21 +307,39 @@ fn create_new_package(
287
307
288
308
let manifest_path = manifest_dir. join ( "Cargo.toml" ) ;
289
309
310
+ if manifest_dir. exists ( ) {
311
+ bail ! (
312
+ "could not create a new package. `{}` already exists" ,
313
+ manifest_dir. display( ) ,
314
+ ) ;
315
+ }
316
+
317
+ crate :: process:: process ( crate :: process:: cargo_exe ( ) ?)
318
+ . arg ( "new" )
319
+ . arg ( "-q" )
320
+ . arg ( "--vcs" )
321
+ . arg ( "none" )
322
+ . arg ( "--name" )
323
+ . arg ( group. package_name ( ) )
324
+ . arg ( & manifest_dir)
325
+ . cwd ( cargo_compete_config_path. with_file_name ( "" ) )
326
+ . exec ( ) ?;
327
+
290
328
let mut package_metadata_cargo_compete_bin = problems
291
329
. keys ( )
292
330
. map ( |problem_index| {
293
331
format ! (
294
332
r#"{} = {{ name = "", problem = {{ {} }} }}
295
333
"# ,
296
334
escape_key( & problem_index. to_kebab_case( ) ) ,
297
- match ( cargo_compete_config . new . platform , problems_are_yukicoder_no ) {
298
- ( PlatformKind :: Atcoder , _) | ( PlatformKind :: Codeforces , _) => {
335
+ match group {
336
+ Group :: Atcoder ( _) | Group :: Codeforces ( _) => {
299
337
r#"platform = "", contest = "", index = "", url = """#
300
338
}
301
- ( PlatformKind :: Yukicoder , true ) => {
302
- r#"platform = "", kind = "no ", no = "" , url = """#
339
+ Group :: YukicoderProblems => {
340
+ r#"platform = "", kind = "problem ", no = 0 , url = """#
303
341
}
304
- ( PlatformKind :: Yukicoder , false ) => {
342
+ Group :: YukicoderContest ( _ ) => {
305
343
r#"platform = "", kind = "contest", contest = "", index = "", url = """#
306
344
}
307
345
}
@@ -314,34 +352,35 @@ fn create_new_package(
314
352
package_metadata_cargo_compete_bin[ & problem_index. to_kebab_case ( ) ] [ "name" ] =
315
353
toml_edit:: value ( format ! (
316
354
"{}-{}" ,
317
- package_name,
355
+ group . package_name( ) ,
318
356
problem_index. to_kebab_case( ) ,
319
357
) ) ;
320
358
321
359
let tbl =
322
360
& mut package_metadata_cargo_compete_bin[ & problem_index. to_kebab_case ( ) ] [ "problem" ] ;
323
361
324
- match cargo_compete_config . new . platform {
325
- PlatformKind :: Atcoder => {
362
+ match group {
363
+ Group :: Atcoder ( contest ) => {
326
364
tbl[ "platform" ] = toml_edit:: value ( "atcoder" ) ;
327
- tbl[ "contest" ] = toml_edit:: value ( package_name ) ;
365
+ tbl[ "contest" ] = toml_edit:: value ( contest ) ;
328
366
tbl[ "index" ] = toml_edit:: value ( & * * problem_index) ;
329
367
tbl[ "url" ] = toml_edit:: value ( problem_url. as_str ( ) ) ;
330
368
}
331
- PlatformKind :: Codeforces => {
369
+ Group :: Codeforces ( contest ) => {
332
370
tbl[ "platform" ] = toml_edit:: value ( "codeforces" ) ;
333
- tbl[ "contest" ] = toml_edit:: value ( package_name ) ;
371
+ tbl[ "contest" ] = toml_edit:: value ( contest ) ;
334
372
tbl[ "index" ] = toml_edit:: value ( & * * problem_index) ;
335
373
tbl[ "url" ] = toml_edit:: value ( problem_url. as_str ( ) ) ;
336
374
}
337
- PlatformKind :: Yukicoder => {
375
+ Group :: YukicoderProblems => {
338
376
tbl[ "platform" ] = toml_edit:: value ( "yukicoder" ) ;
339
- if problems_are_yukicoder_no {
340
- tbl[ "no" ] = toml_edit:: value ( & * * problem_index) ;
341
- } else {
342
- tbl[ "contest" ] = toml_edit:: value ( package_name) ;
343
- tbl[ "index" ] = toml_edit:: value ( & * * problem_index) ;
344
- }
377
+ tbl[ "no" ] = toml_edit:: value ( problem_index. parse :: < i64 > ( ) ?) ;
378
+ tbl[ "url" ] = toml_edit:: value ( problem_url. as_str ( ) ) ;
379
+ }
380
+ Group :: YukicoderContest ( contest) => {
381
+ tbl[ "platform" ] = toml_edit:: value ( "yukicoder" ) ;
382
+ tbl[ "contest" ] = toml_edit:: value ( contest) ;
383
+ tbl[ "index" ] = toml_edit:: value ( & * * problem_index) ;
345
384
tbl[ "url" ] = toml_edit:: value ( problem_url. as_str ( ) ) ;
346
385
}
347
386
}
@@ -353,7 +392,7 @@ fn create_new_package(
353
392
let mut tbl = toml_edit:: Table :: new ( ) ;
354
393
tbl[ "name" ] = toml_edit:: value ( format ! (
355
394
"{}-{}" ,
356
- package_name,
395
+ group . package_name( ) ,
357
396
problem_index. to_kebab_case( ) ,
358
397
) ) ;
359
398
tbl[ "path" ] = toml_edit:: value ( format ! ( "src/bin/{}.rs" , problem_index. to_kebab_case( ) ) ) ;
@@ -461,7 +500,11 @@ fn create_new_package(
461
500
462
501
shell. status (
463
502
"Created" ,
464
- format ! ( "`{}` package at {}" , package_name, manifest_dir. display( ) ) ,
503
+ format ! (
504
+ "`{}` package at {}" ,
505
+ group. package_name( ) ,
506
+ manifest_dir. display( ) ,
507
+ ) ,
465
508
) ?;
466
509
467
510
Ok ( ( manifest_dir, src_paths) )
0 commit comments