@rhseung/ps-cli 1.8.0 → 1.9.1

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.
@@ -1,253 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- openBrowser
4
- } from "../chunk-QGMWUOJ3.js";
5
- import {
6
- defineFlags
7
- } from "../chunk-PY6GW22W.js";
8
- import {
9
- Command,
10
- CommandBuilder,
11
- CommandDef,
12
- detectProblemIdFromPath,
13
- findSolutionFile,
14
- resolveLanguage,
15
- resolveProblemContext
16
- } from "../chunk-JPDN34C7.js";
17
- import {
18
- __decorateClass,
19
- getSupportedLanguagesString
20
- } from "../chunk-7MQMPJ3X.js";
21
-
22
- // src/commands/submit.tsx
23
- import { Badge, StatusMessage, Alert } from "@inkjs/ui";
24
- import { Spinner } from "@inkjs/ui";
25
- import { Text, Box } from "ink";
26
-
27
- // src/hooks/use-submit.ts
28
- import { readFile } from "fs/promises";
29
- import { useEffect, useState } from "react";
30
-
31
- // src/utils/clipboard.ts
32
- import { execa, execaCommand } from "execa";
33
- async function copyToClipboard(text) {
34
- try {
35
- if (process.platform === "win32") {
36
- await execaCommand("clip", {
37
- shell: true,
38
- input: text
39
- });
40
- } else if (process.platform === "darwin") {
41
- await execaCommand("pbcopy", {
42
- shell: false,
43
- input: text
44
- });
45
- } else {
46
- try {
47
- await execa("xclip", ["-selection", "clipboard"], {
48
- input: text
49
- });
50
- } catch {
51
- try {
52
- await execa("xsel", ["--clipboard", "--input"], {
53
- input: text
54
- });
55
- } catch {
56
- return false;
57
- }
58
- }
59
- }
60
- return true;
61
- } catch {
62
- return false;
63
- }
64
- }
65
-
66
- // src/hooks/use-submit.ts
67
- var BOJ_BASE_URL = "https://www.acmicpc.net";
68
- function useSubmit({
69
- problemId,
70
- language: _language,
71
- sourcePath,
72
- onComplete
73
- }) {
74
- const [status, setStatus] = useState(
75
- "loading"
76
- );
77
- const [message, setMessage] = useState("\uC81C\uCD9C \uC900\uBE44 \uC911...");
78
- const [error, setError] = useState(null);
79
- const [submitUrl, setSubmitUrl] = useState("");
80
- const [clipboardSuccess, setClipboardSuccess] = useState(false);
81
- const [clipboardError, setClipboardError] = useState(null);
82
- useEffect(() => {
83
- async function submit() {
84
- try {
85
- setMessage("\uC18C\uC2A4 \uCF54\uB4DC\uB97C \uC77D\uB294 \uC911...");
86
- const sourceCode = await readFile(sourcePath, "utf-8");
87
- setMessage("\uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uBCF5\uC0AC\uD558\uB294 \uC911...");
88
- const clipboardResult = await copyToClipboard(sourceCode);
89
- setClipboardSuccess(clipboardResult);
90
- if (!clipboardResult) {
91
- setClipboardError("\uD074\uB9BD\uBCF4\uB4DC \uBCF5\uC0AC\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
92
- }
93
- const url = `${BOJ_BASE_URL}/submit/${problemId}`;
94
- setSubmitUrl(url);
95
- setMessage("\uBE0C\uB77C\uC6B0\uC800\uB97C \uC5EC\uB294 \uC911...");
96
- await openBrowser(url);
97
- setStatus("success");
98
- setTimeout(() => {
99
- onComplete();
100
- }, 2e3);
101
- } catch (err) {
102
- setStatus("error");
103
- setError(err instanceof Error ? err.message : String(err));
104
- setTimeout(() => {
105
- onComplete();
106
- }, 2e3);
107
- }
108
- }
109
- void submit();
110
- }, [problemId, sourcePath, onComplete]);
111
- return {
112
- status,
113
- message,
114
- error,
115
- submitUrl,
116
- clipboardSuccess,
117
- clipboardError
118
- };
119
- }
120
-
121
- // src/commands/submit.tsx
122
- import { jsx, jsxs } from "react/jsx-runtime";
123
- var submitFlagsSchema = {
124
- language: {
125
- type: "string",
126
- shortFlag: "l",
127
- description: `\uC5B8\uC5B4 \uC120\uD0DD (\uC9C0\uC815 \uC2DC \uC790\uB3D9 \uAC10\uC9C0 \uBB34\uC2DC)
128
- \uC9C0\uC6D0 \uC5B8\uC5B4: ${getSupportedLanguagesString()}`
129
- }
130
- };
131
- function SubmitView({
132
- problemId,
133
- language,
134
- sourcePath,
135
- onComplete
136
- }) {
137
- const {
138
- status,
139
- message,
140
- error,
141
- submitUrl,
142
- clipboardSuccess,
143
- clipboardError
144
- } = useSubmit({
145
- problemId,
146
- language,
147
- sourcePath,
148
- onComplete
149
- });
150
- if (status === "loading") {
151
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
152
- /* @__PURE__ */ jsx(Spinner, { label: message }),
153
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
154
- "\uBB38\uC81C #",
155
- problemId
156
- ] }) })
157
- ] });
158
- }
159
- if (status === "error") {
160
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
161
- /* @__PURE__ */ jsxs(Alert, { variant: "error", children: [
162
- "\uC624\uB958 \uBC1C\uC0DD: ",
163
- error
164
- ] }),
165
- submitUrl && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
166
- "URL: ",
167
- submitUrl
168
- ] }) })
169
- ] });
170
- }
171
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: "100%", children: [
172
- /* @__PURE__ */ jsx(StatusMessage, { variant: "success", children: "\uC81C\uCD9C \uD398\uC774\uC9C0\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4!" }),
173
- /* @__PURE__ */ jsxs(
174
- Box,
175
- {
176
- flexDirection: "column",
177
- borderStyle: "round",
178
- borderColor: "gray",
179
- marginTop: 1,
180
- paddingX: 1,
181
- paddingY: 0,
182
- alignSelf: "flex-start",
183
- children: [
184
- /* @__PURE__ */ jsxs(Text, { children: [
185
- /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\uBB38\uC81C \uBC88\uD638:" }),
186
- " ",
187
- problemId
188
- ] }),
189
- /* @__PURE__ */ jsxs(Text, { children: [
190
- /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\uC5B8\uC5B4:" }),
191
- " ",
192
- /* @__PURE__ */ jsx(Text, { color: "gray", children: language })
193
- ] }),
194
- /* @__PURE__ */ jsxs(Text, { children: [
195
- /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "URL:" }),
196
- " ",
197
- /* @__PURE__ */ jsx(Text, { color: "blue", underline: true, children: submitUrl })
198
- ] }),
199
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: clipboardSuccess ? /* @__PURE__ */ jsx(Badge, { color: "green", children: "\uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uBCF5\uC0AC\uB428" }) : /* @__PURE__ */ jsx(Badge, { color: "yellow", children: "\uD074\uB9BD\uBCF4\uB4DC \uBCF5\uC0AC \uC2E4\uD328" }) }),
200
- clipboardError && !clipboardSuccess && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Alert, { variant: "warning", children: clipboardError }) })
201
- ]
202
- }
203
- )
204
- ] });
205
- }
206
- var SubmitCommand = class extends Command {
207
- async execute(args, flags) {
208
- const context = await resolveProblemContext(args, { requireId: true });
209
- const sourcePath = await findSolutionFile(context.archiveDir);
210
- const detectedLanguage = await resolveLanguage(
211
- context.archiveDir,
212
- flags.language
213
- );
214
- let finalProblemId = context.problemId;
215
- if (finalProblemId === null) {
216
- finalProblemId = detectProblemIdFromPath(context.archiveDir);
217
- }
218
- if (finalProblemId === null) {
219
- throw new Error(
220
- "\uBB38\uC81C \uBC88\uD638\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uBB38\uC81C \uBC88\uD638\uB97C \uC778\uC790\uB85C \uC804\uB2EC\uD558\uAC70\uB098 \uBB38\uC81C \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C \uC2E4\uD589\uD574\uC8FC\uC138\uC694."
221
- );
222
- }
223
- await this.renderView(SubmitView, {
224
- problemId: finalProblemId,
225
- language: detectedLanguage,
226
- sourcePath
227
- });
228
- }
229
- };
230
- SubmitCommand = __decorateClass([
231
- CommandDef({
232
- name: "submit",
233
- description: `\uBC31\uC900 \uC81C\uCD9C \uD398\uC774\uC9C0\uB97C \uBE0C\uB77C\uC6B0\uC800\uB85C \uC5F4\uACE0 \uC18C\uC2A4 \uCF54\uB4DC\uB97C \uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uBCF5\uC0AC\uD569\uB2C8\uB2E4.
234
- - \uBB38\uC81C \uBC88\uD638\uB97C \uC778\uC790\uB85C \uC804\uB2EC\uD558\uAC70\uB098 \uBB38\uC81C \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C \uC2E4\uD589\uD558\uBA74 \uC790\uB3D9\uC73C\uB85C \uBB38\uC81C \uBC88\uD638\uB97C \uCD94\uB860
235
- - solution.* \uD30C\uC77C\uC744 \uC790\uB3D9\uC73C\uB85C \uCC3E\uC544 \uC5B8\uC5B4 \uAC10\uC9C0
236
- - \uC18C\uC2A4 \uCF54\uB4DC\uB97C \uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uC790\uB3D9 \uBCF5\uC0AC
237
- - \uC81C\uCD9C \uD398\uC774\uC9C0\uB97C \uBE0C\uB77C\uC6B0\uC800\uB85C \uC790\uB3D9 \uC5F4\uAE30`,
238
- flags: defineFlags(submitFlagsSchema),
239
- autoDetectProblemId: true,
240
- autoDetectLanguage: true,
241
- requireProblemId: true,
242
- examples: [
243
- "submit # \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C \uC81C\uCD9C",
244
- "submit 1000 # 1000\uBC88 \uBB38\uC81C \uC81C\uCD9C",
245
- "submit --language python # Python\uC73C\uB85C \uC81C\uCD9C"
246
- ]
247
- })
248
- ], SubmitCommand);
249
- var submit_default = CommandBuilder.fromClass(SubmitCommand);
3
+ SubmitCommand,
4
+ SubmitView,
5
+ submit_default
6
+ } from "../chunk-3H74PQRX.js";
7
+ import "../chunk-QGMWUOJ3.js";
8
+ import "../chunk-Q5NECGFA.js";
250
9
  export {
251
10
  SubmitCommand,
11
+ SubmitView,
252
12
  submit_default as default
253
13
  };
@@ -1,377 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- runSolution
4
- } from "../chunk-VIHXBCOZ.js";
5
- import {
6
- defineFlags
7
- } from "../chunk-PY6GW22W.js";
8
- import {
9
- Command,
10
- CommandBuilder,
11
- CommandDef,
12
- resolveLanguage,
13
- resolveProblemContext
14
- } from "../chunk-JPDN34C7.js";
15
- import {
16
- __decorateClass,
17
- getSupportedLanguagesString
18
- } from "../chunk-7MQMPJ3X.js";
19
-
20
- // src/commands/test.tsx
21
- import { Alert } from "@inkjs/ui";
22
- import { Spinner } from "@inkjs/ui";
23
- import { Box as Box2, Text as Text2 } from "ink";
24
-
25
- // src/components/test-result.tsx
26
- import { Badge, StatusMessage } from "@inkjs/ui";
27
- import { Box, Text } from "ink";
28
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
29
- function truncate(text = "", max = 200) {
30
- return text.length > max ? `${text.slice(0, max)}...` : text;
31
- }
32
- function formatDuration(ms) {
33
- if (ms < 1e3) return `${ms}ms`;
34
- return `${(ms / 1e3).toFixed(2)}s`;
35
- }
36
- function ResultRow({ result }) {
37
- const badgeColor = result.status === "pass" ? "green" : result.status === "fail" ? "red" : "yellow";
38
- const statusText = result.status === "pass" ? "PASS" : result.status === "fail" ? "FAIL" : "ERROR";
39
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
40
- /* @__PURE__ */ jsxs(Box, { children: [
41
- /* @__PURE__ */ jsx(Badge, { color: badgeColor, children: statusText }),
42
- /* @__PURE__ */ jsx(Text, { children: " " }),
43
- /* @__PURE__ */ jsxs(Text, { children: [
44
- "\uCF00\uC774\uC2A4 ",
45
- result.caseId
46
- ] }),
47
- result.durationMs !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
48
- /* @__PURE__ */ jsx(Text, { children: " " }),
49
- /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
50
- "(",
51
- formatDuration(result.durationMs),
52
- ")"
53
- ] })
54
- ] })
55
- ] }),
56
- result.status === "fail" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 3, marginTop: 1, children: [
57
- /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
58
- /* @__PURE__ */ jsx(Text, { color: "gray", children: "\uAE30\uB300\uAC12:" }),
59
- /* @__PURE__ */ jsx(Text, { children: truncate(result.expected ?? "") })
60
- ] }),
61
- /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
62
- /* @__PURE__ */ jsx(Text, { color: "gray", children: "\uC2E4\uC81C\uAC12:" }),
63
- /* @__PURE__ */ jsx(Text, { children: truncate(result.actual ?? "") })
64
- ] })
65
- ] }),
66
- result.status === "error" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 3, marginTop: 1, children: [
67
- /* @__PURE__ */ jsx(Text, { color: "yellow", children: result.error ?? "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958" }),
68
- result.stderr && /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: truncate(result.stderr) })
69
- ] })
70
- ] });
71
- }
72
- function TestResultView({ summary, results }) {
73
- const allPassed = summary.failed === 0 && summary.errored === 0;
74
- const summaryVariant = allPassed ? "success" : "error";
75
- const summaryText = `\uCD1D ${summary.total}\uAC1C | Pass ${summary.passed}${summary.failed > 0 ? ` | Fail ${summary.failed}` : ""}${summary.errored > 0 ? ` | Error ${summary.errored}` : ""}`;
76
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
77
- /* @__PURE__ */ jsxs(StatusMessage, { variant: summaryVariant, children: [
78
- "\uD14C\uC2A4\uD2B8 \uACB0\uACFC: ",
79
- summaryText
80
- ] }),
81
- /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: results.map((r) => /* @__PURE__ */ jsx(ResultRow, { result: r }, r.caseId)) })
82
- ] });
83
- }
84
-
85
- // src/hooks/use-test-runner.ts
86
- import { join as join2 } from "path";
87
- import chokidar from "chokidar";
88
- import { useEffect, useState, useCallback } from "react";
89
-
90
- // src/services/test-runner.ts
91
- import { readdir, readFile } from "fs/promises";
92
- import { join } from "path";
93
-
94
- // src/services/diff-checker.ts
95
- function normalizeOutput(output) {
96
- return output.replace(/\r\n/g, "\n").split("\n").map((line) => line.trimEnd()).join("\n").trimEnd();
97
- }
98
- function compareOutput(expected, actual) {
99
- const expectedNorm = normalizeOutput(expected);
100
- const actualNorm = normalizeOutput(actual);
101
- return {
102
- pass: expectedNorm === actualNorm,
103
- expected: expectedNorm,
104
- actual: actualNorm
105
- };
106
- }
107
-
108
- // src/services/test-runner.ts
109
- function buildSummary(results) {
110
- const summary = {
111
- total: results.length,
112
- passed: 0,
113
- failed: 0,
114
- errored: 0
115
- };
116
- for (const r of results) {
117
- if (r.status === "pass") summary.passed += 1;
118
- else if (r.status === "fail") summary.failed += 1;
119
- else summary.errored += 1;
120
- }
121
- return summary;
122
- }
123
- async function runAllTests({
124
- problemDir,
125
- language,
126
- timeoutMs
127
- }) {
128
- const testcasesDir = join(problemDir, "testcases");
129
- let caseDirs = [];
130
- try {
131
- const entries = await readdir(testcasesDir);
132
- caseDirs = entries.filter((entry) => /^\d+$/.test(entry)).sort((a, b) => Number(a) - Number(b)).map((entry) => join(testcasesDir, entry));
133
- } catch {
134
- return { results: [], summary: buildSummary([]) };
135
- }
136
- const results = [];
137
- let effectiveTimeout = timeoutMs;
138
- if (effectiveTimeout == null) {
139
- try {
140
- const metaRaw = await readFile(join(problemDir, "meta.json"), "utf-8");
141
- const meta = JSON.parse(metaRaw);
142
- if (typeof meta.timeLimitMs === "number") {
143
- effectiveTimeout = meta.timeLimitMs;
144
- } else if (typeof meta.timeLimit === "string") {
145
- const match = meta.timeLimit.match(/([\d.]+)/);
146
- if (match) {
147
- const seconds = parseFloat(match[1]);
148
- if (!Number.isNaN(seconds)) {
149
- effectiveTimeout = Math.round(seconds * 1e3);
150
- }
151
- }
152
- }
153
- } catch {
154
- }
155
- }
156
- if (effectiveTimeout == null) {
157
- effectiveTimeout = 5e3;
158
- }
159
- for (const caseDir of caseDirs) {
160
- const caseId = Number(join(caseDir).split("/").pop() || "0");
161
- const inputPath = join(caseDir, "input.txt");
162
- const outputPath = join(caseDir, "output.txt");
163
- let expected;
164
- try {
165
- expected = await readFile(outputPath, "utf-8");
166
- } catch {
167
- results.push({
168
- caseId,
169
- inputPath,
170
- status: "error",
171
- error: "\uAE30\uB300 \uCD9C\uB825(output.txt)\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."
172
- });
173
- continue;
174
- }
175
- const runResult = await runSolution({
176
- problemDir,
177
- language,
178
- inputPath,
179
- timeoutMs: effectiveTimeout
180
- });
181
- if (runResult.exitCode !== 0 || runResult.timedOut) {
182
- results.push({
183
- caseId,
184
- inputPath,
185
- expected,
186
- actual: runResult.stdout,
187
- error: runResult.timedOut ? `\uC2DC\uAC04 \uCD08\uACFC (timeout ${effectiveTimeout}ms)` : runResult.stderr || "\uC2E4\uD589 \uC5D0\uB7EC",
188
- status: "error",
189
- durationMs: runResult.durationMs
190
- });
191
- continue;
192
- }
193
- const diff = compareOutput(expected ?? "", runResult.stdout);
194
- results.push({
195
- caseId,
196
- inputPath,
197
- expected: diff.expected,
198
- actual: diff.actual,
199
- status: diff.pass ? "pass" : "fail",
200
- durationMs: runResult.durationMs
201
- });
202
- }
203
- return { results, summary: buildSummary(results) };
204
- }
205
-
206
- // src/hooks/use-test-runner.ts
207
- function useTestRunner({
208
- problemDir,
209
- language,
210
- watch,
211
- timeoutMs,
212
- onComplete
213
- }) {
214
- const [status, setStatus] = useState("loading");
215
- const [results, setResults] = useState([]);
216
- const [summary, setSummary] = useState({
217
- total: 0,
218
- passed: 0,
219
- failed: 0,
220
- errored: 0
221
- });
222
- const [error, setError] = useState(null);
223
- const runTests = useCallback(
224
- (isWatchTrigger = false) => {
225
- if (isWatchTrigger && watch) {
226
- console.clear();
227
- }
228
- setStatus("loading");
229
- void runAllTests({
230
- problemDir,
231
- language,
232
- timeoutMs
233
- }).then(({ results: results2, summary: summary2 }) => {
234
- setResults(results2);
235
- setSummary(summary2);
236
- setStatus("ready");
237
- }).catch((err) => {
238
- setError(err instanceof Error ? err.message : String(err));
239
- setStatus("error");
240
- });
241
- },
242
- [problemDir, language, timeoutMs, watch]
243
- );
244
- useEffect(() => {
245
- const timer = setTimeout(() => {
246
- void runTests();
247
- }, 0);
248
- return () => clearTimeout(timer);
249
- }, [runTests]);
250
- useEffect(() => {
251
- if (!watch) {
252
- return void 0;
253
- }
254
- const watcher = chokidar.watch(
255
- [
256
- join2(problemDir, "solution.*"),
257
- join2(problemDir, "testcases", "**", "*.txt")
258
- ],
259
- {
260
- ignoreInitial: true
261
- }
262
- );
263
- watcher.on("change", () => {
264
- runTests(true);
265
- });
266
- return () => {
267
- void watcher.close();
268
- };
269
- }, [problemDir, watch, runTests]);
270
- useEffect(() => {
271
- if (!watch && status === "ready") {
272
- const timer = setTimeout(() => onComplete(), 200);
273
- return () => clearTimeout(timer);
274
- }
275
- return void 0;
276
- }, [status, watch, onComplete]);
277
- return {
278
- status,
279
- results,
280
- summary,
281
- error
282
- };
283
- }
284
-
285
- // src/commands/test.tsx
286
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
287
- var testFlagsSchema = {
288
- language: {
289
- type: "string",
290
- shortFlag: "l",
291
- description: `\uC5B8\uC5B4 \uC120\uD0DD (\uC9C0\uC815 \uC2DC \uC790\uB3D9 \uAC10\uC9C0 \uBB34\uC2DC)
292
- \uC9C0\uC6D0 \uC5B8\uC5B4: ${getSupportedLanguagesString()}`
293
- },
294
- watch: {
295
- type: "boolean",
296
- shortFlag: "w",
297
- description: `watch \uBAA8\uB4DC (\uD30C\uC77C \uBCC0\uACBD \uC2DC \uC790\uB3D9 \uC7AC\uD14C\uC2A4\uD2B8)
298
- solution.*, testcases/**/*.txt \uD30C\uC77C \uBCC0\uACBD \uAC10\uC9C0`
299
- }
300
- };
301
- function TestView({
302
- problemDir,
303
- language,
304
- watch,
305
- timeoutMs,
306
- onComplete
307
- }) {
308
- const { status, results, summary, error } = useTestRunner({
309
- problemDir,
310
- language,
311
- watch,
312
- timeoutMs,
313
- onComplete
314
- });
315
- if (status === "loading") {
316
- return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: /* @__PURE__ */ jsx2(Spinner, { label: "\uD14C\uC2A4\uD2B8 \uC2E4\uD589 \uC911..." }) });
317
- }
318
- if (status === "error") {
319
- return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: /* @__PURE__ */ jsxs2(Alert, { variant: "error", children: [
320
- "\uD14C\uC2A4\uD2B8 \uC2E4\uD589 \uC2E4\uD328",
321
- error ? `: ${error}` : ""
322
- ] }) });
323
- }
324
- return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
325
- /* @__PURE__ */ jsxs2(Box2, { marginBottom: 1, children: [
326
- /* @__PURE__ */ jsx2(Text2, { color: "cyan", bold: true, children: "\uD14C\uC2A4\uD2B8 \uC2E4\uD589 \uC911" }),
327
- /* @__PURE__ */ jsx2(Text2, { children: " " }),
328
- /* @__PURE__ */ jsxs2(Text2, { color: "gray", children: [
329
- problemDir,
330
- " \u2022 ",
331
- language,
332
- watch && " \u2022 watch"
333
- ] })
334
- ] }),
335
- /* @__PURE__ */ jsx2(TestResultView, { results, summary })
336
- ] });
337
- }
338
- var TestCommand = class extends Command {
339
- async execute(args, flags) {
340
- const context = await resolveProblemContext(args);
341
- const language = await resolveLanguage(
342
- context.archiveDir,
343
- flags.language
344
- );
345
- await this.renderView(TestView, {
346
- problemDir: context.archiveDir,
347
- language,
348
- watch: Boolean(flags.watch),
349
- timeoutMs: flags.timeoutMs
350
- });
351
- }
352
- };
353
- TestCommand = __decorateClass([
354
- CommandDef({
355
- name: "test",
356
- description: `\uC608\uC81C \uC785\uCD9C\uB825 \uAE30\uBC18\uC73C\uB85C \uB85C\uCEEC \uD14C\uC2A4\uD2B8\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4.
357
- - \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC \uB610\uB294 \uC9C0\uC815\uD55C \uBB38\uC81C \uBC88\uD638\uC758 \uD14C\uC2A4\uD2B8 \uC2E4\uD589
358
- - solution.* \uD30C\uC77C\uC744 \uC790\uB3D9\uC73C\uB85C \uCC3E\uC544 \uC5B8\uC5B4 \uAC10\uC9C0
359
- - testcases/{\uBC88\uD638}/input.txt\uC640 testcases/{\uBC88\uD638}/output.txt \uD30C\uC77C\uC744 \uAE30\uBC18\uC73C\uB85C \uD14C\uC2A4\uD2B8
360
- - \uBB38\uC81C\uC758 \uC2DC\uAC04 \uC81C\uD55C\uC744 \uC790\uB3D9\uC73C\uB85C \uC801\uC6A9
361
- - --watch \uC635\uC158\uC73C\uB85C \uD30C\uC77C \uBCC0\uACBD \uC2DC \uC790\uB3D9 \uC7AC\uD14C\uC2A4\uD2B8`,
362
- flags: defineFlags(testFlagsSchema),
363
- autoDetectProblemId: true,
364
- autoDetectLanguage: true,
365
- examples: [
366
- "test # \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C \uD14C\uC2A4\uD2B8",
367
- "test 1000 # 1000\uBC88 \uBB38\uC81C \uD14C\uC2A4\uD2B8",
368
- "test --watch # watch \uBAA8\uB4DC\uB85C \uD14C\uC2A4\uD2B8",
369
- "test 1000 --watch # 1000\uBC88 \uBB38\uC81C\uB97C watch \uBAA8\uB4DC\uB85C \uD14C\uC2A4\uD2B8"
370
- ]
371
- })
372
- ], TestCommand);
373
- var test_default = CommandBuilder.fromClass(TestCommand);
3
+ TestCommand,
4
+ TestView,
5
+ test_default
6
+ } from "../chunk-2YSOO6AM.js";
7
+ import "../chunk-YZUGYJA4.js";
8
+ import "../chunk-Q5NECGFA.js";
374
9
  export {
375
10
  TestCommand,
11
+ TestView,
376
12
  test_default as default
377
13
  };