Skip to content

Commit bea02e4

Browse files
author
William Yang
committed
feat: Auto-detect programming language from files
- Add detect_language() function that scans current directory - Support C, Python, JavaScript, TypeScript, Go, Rust, Java, C++ - Priority: explicit -L flag > file detection > default 'c' - Show detected language in output when not C - Update both check and submit commands
1 parent 1e02008 commit bea02e4

File tree

1 file changed

+76
-9
lines changed

1 file changed

+76
-9
lines changed

bootcs/__main__.py

Lines changed: 76 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ def main():
3838
check_parser.add_argument("--log", action="store_true", help="Show detailed log")
3939
check_parser.add_argument("--target", action="append", metavar="check",
4040
help="Run only the specified check(s)")
41-
check_parser.add_argument("-L", "--language", default="c",
42-
help="Language for checks (default: c)")
41+
check_parser.add_argument("-L", "--language",
42+
help="Language for checks (auto-detected from files if not specified)")
4343
check_parser.add_argument("-u", "--update", action="store_true",
4444
help="Force update checks from remote")
4545
check_parser.add_argument("--local", metavar="PATH", help="Path to local checks directory")
@@ -85,12 +85,76 @@ def main():
8585
return 1
8686

8787

88+
# Language extension mapping
89+
LANGUAGE_EXTENSIONS = {
90+
'.c': 'c',
91+
'.h': 'c',
92+
'.py': 'python',
93+
'.js': 'javascript',
94+
'.mjs': 'javascript',
95+
'.ts': 'typescript',
96+
'.go': 'go',
97+
'.rs': 'rust',
98+
'.java': 'java',
99+
'.cpp': 'cpp',
100+
'.cc': 'cpp',
101+
'.cxx': 'cpp',
102+
}
103+
104+
105+
def detect_language(directory: Path = None, explicit: str = None) -> str:
106+
"""
107+
Detect programming language from files in directory.
108+
109+
Priority:
110+
1. Explicit parameter (user specified -L)
111+
2. Files in current directory
112+
3. Default to 'c'
113+
114+
Args:
115+
directory: Directory to scan for files (defaults to cwd)
116+
explicit: Explicitly specified language (highest priority)
117+
118+
Returns:
119+
Detected language string (e.g., 'c', 'python')
120+
"""
121+
# 1. User explicitly specified
122+
if explicit:
123+
return explicit
124+
125+
# 2. Detect from files in directory
126+
if directory is None:
127+
directory = Path.cwd()
128+
129+
# Count files by language
130+
lang_counts = {}
131+
try:
132+
for item in directory.iterdir():
133+
if item.is_file() and not item.name.startswith('.'):
134+
ext = item.suffix.lower()
135+
if ext in LANGUAGE_EXTENSIONS:
136+
lang = LANGUAGE_EXTENSIONS[ext]
137+
lang_counts[lang] = lang_counts.get(lang, 0) + 1
138+
except OSError:
139+
pass
140+
141+
# Return the most common language
142+
if lang_counts:
143+
return max(lang_counts, key=lang_counts.get)
144+
145+
# 3. Default
146+
return 'c'
147+
148+
88149
def run_check(args):
89150
"""Run the check command."""
90151
slug = args.slug
91-
language = getattr(args, 'language', 'c') or 'c'
92152
force_update = getattr(args, 'update', False)
93153

154+
# Auto-detect language from files in current directory
155+
explicit_lang = getattr(args, 'language', None)
156+
language = detect_language(directory=Path.cwd(), explicit=explicit_lang)
157+
94158
# Determine check directory
95159
if args.local:
96160
check_dir = Path(args.local).resolve()
@@ -133,7 +197,8 @@ def run_check(args):
133197
# Print header (skip in JSON mode for clean output)
134198
if args.output != "json":
135199
print()
136-
termcolor.cprint(f"🔍 Running checks for {slug}...", "cyan", attrs=["bold"])
200+
lang_indicator = f" ({language})" if language != 'c' else ""
201+
termcolor.cprint(f"🔍 Running checks for {slug}{lang_indicator}...", "cyan", attrs=["bold"])
137202
print()
138203

139204
# Run checks
@@ -304,7 +369,10 @@ def run_submit(args):
304369
from .api.submit import collect_files, submit_files, SubmitFile
305370

306371
slug = args.slug
307-
language = getattr(args, 'language', None) # Optional, will be auto-detected if not provided
372+
373+
# Auto-detect language from files in current directory
374+
explicit_lang = getattr(args, 'language', None)
375+
language = detect_language(directory=Path.cwd(), explicit=explicit_lang)
308376

309377
# Check if logged in
310378
if not is_logged_in():
@@ -315,12 +383,10 @@ def run_submit(args):
315383
token = get_token()
316384

317385
# Determine check directory for file list
318-
# Use provided language or default to 'c' for finding checks
319-
check_language = language or 'c'
320386
if args.local:
321387
check_dir = Path(args.local).resolve()
322388
else:
323-
check_dir = find_check_dir(slug, language=check_language)
389+
check_dir = find_check_dir(slug, language=language)
324390

325391
if not check_dir or not check_dir.exists():
326392
termcolor.cprint(f"Error: Could not find config for '{slug}'", "red", file=sys.stderr)
@@ -350,7 +416,8 @@ def run_submit(args):
350416

351417
# Show files to submit
352418
print()
353-
termcolor.cprint(f"📦 Submitting {slug}", "cyan", attrs=["bold"])
419+
lang_indicator = f" ({language})" if language != 'c' else ""
420+
termcolor.cprint(f"📦 Submitting {slug}{lang_indicator}", "cyan", attrs=["bold"])
354421
print()
355422
termcolor.cprint("Files to submit:", "white")
356423
for f in file_list:

0 commit comments

Comments
 (0)