@@ -101,6 +101,35 @@ def main():
101101 '.cxx' : 'cpp' ,
102102}
103103
104+ # Supported languages for slug parsing
105+ SUPPORTED_LANGUAGES = {'c' , 'python' , 'java' , 'cpp' , 'go' , 'rust' , 'javascript' , 'typescript' }
106+
107+
108+ def parse_slug (slug : str ):
109+ """
110+ Parse a slug into course, language, and stage components.
111+
112+ Supports two formats:
113+ - 2 parts: "cs50/hello" -> (course="cs50", language=None, stage="hello")
114+ - 3 parts: "cs50/c/hello" -> (course="cs50", language="c", stage="hello")
115+
116+ Returns:
117+ tuple: (course_slug, language_from_slug, stage_slug)
118+ - language_from_slug is None if slug has 2 parts
119+ """
120+ parts = slug .split ("/" )
121+ if len (parts ) == 3 :
122+ course_slug , lang , stage_slug = parts
123+ # Validate that middle part looks like a language
124+ if lang in SUPPORTED_LANGUAGES :
125+ return course_slug , lang , stage_slug
126+ # If middle part doesn't look like a language, treat as 2-part with nested stage
127+ return parts [0 ], None , "/" .join (parts [1 :])
128+ elif len (parts ) == 2 :
129+ return parts [0 ], None , parts [1 ]
130+ else :
131+ return None , None , slug
132+
104133
105134def detect_language (directory : Path = None , explicit : str = None ) -> str :
106135 """
@@ -151,9 +180,15 @@ def run_check(args):
151180 slug = args .slug
152181 force_update = getattr (args , 'update' , False )
153182
154- # Auto-detect language from files in current directory
183+ # Parse slug to extract language if present (e.g., "cs50/c/hello")
184+ course_slug , lang_from_slug , stage_slug = parse_slug (slug )
185+
186+ # Determine language: slug > explicit flag > auto-detect
155187 explicit_lang = getattr (args , 'language' , None )
156- language = detect_language (directory = Path .cwd (), explicit = explicit_lang )
188+ if lang_from_slug :
189+ language = lang_from_slug
190+ else :
191+ language = detect_language (directory = Path .cwd (), explicit = explicit_lang )
157192
158193 # Determine check directory
159194 if args .local :
@@ -307,22 +342,30 @@ def find_check_dir(slug, language: str = "c", force_update: bool = False):
307342 """
308343 Find the check directory for a given slug.
309344
345+ Supports two slug formats:
346+ - 2 parts: "cs50/hello" (language auto-detected or passed as parameter)
347+ - 3 parts: "cs50/c/hello" (language extracted from slug)
348+
310349 Priority:
311350 1. BOOTCS_CHECKS_PATH environment variable (for evaluator)
312351 2. Remote API download (with local cache)
313352 3. Local directories (for development)
314353 """
315- # Extract parts from slug (e.g., "cs50/credit" -> course="cs50", stage="credit")
316- parts = slug .split ("/" )
317- if len (parts ) == 2 :
318- course_slug , stage_name = parts
319- else :
320- stage_name = slug
321- course_slug = None
354+ # Use parse_slug to extract components
355+ course_slug , lang_from_slug , stage_name = parse_slug (slug )
356+
357+ # If slug contains language, use it; otherwise use provided parameter
358+ if lang_from_slug :
359+ language = lang_from_slug
322360
323361 # 1. Check environment variable first (used by evaluator)
324362 if "BOOTCS_CHECKS_PATH" in os .environ :
325363 checks_path = Path (os .environ ["BOOTCS_CHECKS_PATH" ])
364+ # Try with course/language/stage structure (e.g., checks/cs50/c/hello)
365+ if course_slug :
366+ path = checks_path / course_slug / language / stage_name
367+ if path .exists ():
368+ return path
326369 # Try with language/stage structure (e.g., checks/c/hello)
327370 path = checks_path / language / stage_name
328371 if path .exists ():
@@ -378,9 +421,15 @@ def run_submit(args):
378421
379422 slug = args .slug
380423
381- # Auto-detect language from files in current directory
424+ # Parse slug to extract language if present (e.g., "cs50/c/hello")
425+ course_slug , lang_from_slug , stage_slug = parse_slug (slug )
426+
427+ # Determine language: slug > explicit flag > auto-detect
382428 explicit_lang = getattr (args , 'language' , None )
383- language = detect_language (directory = Path .cwd (), explicit = explicit_lang )
429+ if lang_from_slug :
430+ language = lang_from_slug
431+ else :
432+ language = detect_language (directory = Path .cwd (), explicit = explicit_lang )
384433
385434 # Check if logged in
386435 if not is_logged_in ():
0 commit comments