icoa-cli 2.19.95 → 2.19.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -117,10 +117,35 @@ program
117
117
  // wondering why "哪个命令..." appears as "????..." on their machine.
118
118
  const envLang = process.env.LANG || process.env.LC_ALL || process.env.LC_CTYPE || '';
119
119
  if (!/UTF-?8/i.test(envLang)) {
120
- console.log(chalk.yellow('⚠ Your terminal locale is not UTF-8 (LANG=' + (envLang || '(unset)') + ').'));
121
- console.log(chalk.gray(' Non-English text and box characters may display as "?" or garbled glyphs.'));
122
- console.log(chalk.gray(' Fix: ') + chalk.cyan('export LANG=en_US.UTF-8') + chalk.gray(' (or your locale, e.g. ') + chalk.cyan('zh_CN.UTF-8') + chalk.gray(', ') + chalk.cyan('uk_UA.UTF-8') + chalk.gray(')'));
123
- console.log();
120
+ if (process.platform === 'win32') {
121
+ // Windows cmd.exe default code page (437 US, 936 CN, etc.) mangles
122
+ // non-Latin script. Fix is `chcp 65001`, not Unix-style `export LANG`.
123
+ // Skip the warning if the code page is already 65001 (PowerShell +
124
+ // Windows Terminal often set it automatically).
125
+ let codepage = '';
126
+ try {
127
+ const { execFileSync } = await import('node:child_process');
128
+ codepage = execFileSync('chcp.com', [], {
129
+ encoding: 'utf-8',
130
+ timeout: 1500,
131
+ stdio: ['ignore', 'pipe', 'ignore'],
132
+ }).trim();
133
+ }
134
+ catch { /* chcp.com unavailable or timed out */ }
135
+ if (!codepage.includes('65001')) {
136
+ console.log(chalk.yellow('⚠ Windows terminal is not using UTF-8 (current: ' + (codepage || 'unknown') + ').'));
137
+ console.log(chalk.gray(' Non-English text (Ukrainian, Chinese, Japanese, etc.) may show as "?" or garbled glyphs.'));
138
+ console.log(chalk.gray(' Fix (run before ') + chalk.cyan('icoa') + chalk.gray('): ') + chalk.cyan('chcp 65001'));
139
+ console.log(chalk.gray(' Or stay in English inside the CLI: ') + chalk.cyan('lang en'));
140
+ console.log();
141
+ }
142
+ }
143
+ else {
144
+ console.log(chalk.yellow('⚠ Your terminal locale is not UTF-8 (LANG=' + (envLang || '(unset)') + ').'));
145
+ console.log(chalk.gray(' Non-English text and box characters may display as "?" or garbled glyphs.'));
146
+ console.log(chalk.gray(' Fix: ') + chalk.cyan('export LANG=en_US.UTF-8') + chalk.gray(' (or your locale, e.g. ') + chalk.cyan('zh_CN.UTF-8') + chalk.gray(', ') + chalk.cyan('uk_UA.UTF-8') + chalk.gray(')'));
147
+ console.log();
148
+ }
124
149
  }
125
150
  console.log(BANNER);
126
151
  // If running interactively (no extra args or --resume), start REPL
package/dist/repl.js CHANGED
@@ -106,17 +106,29 @@ function checkPython() {
106
106
  // Probe python3.12 first — macOS Homebrew installs python@3.12 alongside a
107
107
  // newer default python3, and we don't want to flag a 3.12-ready machine just
108
108
  // because the default alias moved to 3.13.
109
+ // On Windows (cmd/PowerShell), the binary is `python` not `python3`, and the
110
+ // Python launcher `py -3` is also common. Include these so Windows K-12
111
+ // students don't get a spurious "Python missing" warning when Python IS
112
+ // installed. We also stdio: ignore stderr so cmd.exe's "not recognized as
113
+ // internal or external command" error doesn't leak to the user.
109
114
  const probes = [
110
115
  'python3.12 --version',
111
116
  '/opt/homebrew/opt/python@3.12/bin/python3.12 --version',
112
117
  '/usr/local/opt/python@3.12/bin/python3.12 --version',
113
118
  'python3 --version',
119
+ 'python --version', // Windows default name
120
+ 'py -3.12 --version', // Windows Python Launcher
121
+ 'py -3 --version', // Windows Python Launcher (any 3.x)
114
122
  ];
115
123
  let lastVersion = '';
116
124
  let lastStatus = 'missing';
117
125
  for (const cmd of probes) {
118
126
  try {
119
- const out = execSyncFn(cmd, { encoding: 'utf-8', timeout: 2000 }).trim();
127
+ const out = execSyncFn(cmd, {
128
+ encoding: 'utf-8',
129
+ timeout: 2000,
130
+ stdio: ['ignore', 'pipe', 'ignore'],
131
+ }).trim();
120
132
  const version = out.replace('Python ', '');
121
133
  const [maj, min] = version.split('.').map(Number);
122
134
  if (maj === 3 && min === 12)
@@ -905,6 +917,24 @@ export async function startRepl(program, resumeMode) {
905
917
  .replace(/^python3?\s/, `${py12} `)
906
918
  .replace(/^(python3|python)$/, py12);
907
919
  }
920
+ else if (process.platform === 'win32') {
921
+ // Windows: the binary is `python` (not `python3`). Python Launcher `py -3`
922
+ // is also common. Rewrite `python3 xyz` → `python xyz` or `py -3 xyz` so
923
+ // students who followed Unix-oriented practical-question hints don't get
924
+ // "'python3' is not recognized". Prefer `py -3` if the launcher exists
925
+ // (handles multi-version installs); fall back to plain `python`.
926
+ const pyCmd = (() => {
927
+ try {
928
+ execSyncFn('py -3 --version', { stdio: ['ignore', 'ignore', 'ignore'], timeout: 1500 });
929
+ return 'py -3';
930
+ }
931
+ catch { }
932
+ return 'python';
933
+ })();
934
+ resolvedInput = resolvedInput
935
+ .replace(/^python3?(\.\d+)?\s/, `${pyCmd} `)
936
+ .replace(/^python3?(\.\d+)?$/, pyCmd);
937
+ }
908
938
  else {
909
939
  // Linux/WSL: python → python3 (or python3.12 if available)
910
940
  const py12 = (() => { try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icoa-cli",
3
- "version": "2.19.95",
3
+ "version": "2.19.96",
4
4
  "description": "ICOA CLI — The world's first CLI-native CTF competition terminal",
5
5
  "type": "module",
6
6
  "bin": {