@rhseung/ps-cli 1.7.5 → 1.9.0

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,400 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- scrapeProblem
4
- } from "../chunk-4ISG24GW.js";
5
- import {
6
- getProblem
7
- } from "../chunk-A6STXEAE.js";
8
- import {
9
- Command,
10
- CommandBuilder,
11
- CommandDef,
12
- getAutoOpenEditor,
13
- getEditor,
14
- getSolvingDirPath,
15
- getTierColor,
16
- getTierImageUrl,
17
- getTierName,
18
- resolveProblemContext
19
- } from "../chunk-F4LZ6ENP.js";
20
- import {
21
- __decorateClass,
22
- getLanguageConfig,
23
- getSupportedLanguages,
24
- getSupportedLanguagesString
25
- } from "../chunk-7MQMPJ3X.js";
26
-
27
- // src/commands/fetch.tsx
28
- import { StatusMessage, Alert } from "@inkjs/ui";
29
- import { Spinner } from "@inkjs/ui";
30
- import { Box as Box2 } from "ink";
31
-
32
- // src/components/problem-dashboard.tsx
33
- import { Box, Text } from "ink";
34
- import { jsx, jsxs } from "react/jsx-runtime";
35
- function ProblemDashboard({ problem }) {
36
- const tierName = getTierName(problem.level);
37
- const tierColor = getTierColor(problem.level);
38
- const borderColorString = typeof tierColor === "string" ? tierColor : "#ff7ca8";
39
- const textColorString = borderColorString;
40
- return /* @__PURE__ */ jsx(
41
- Box,
42
- {
43
- flexDirection: "column",
44
- borderStyle: "round",
45
- borderColor: borderColorString,
46
- paddingX: 1,
47
- alignSelf: "flex-start",
48
- children: /* @__PURE__ */ jsxs(Text, { bold: true, color: textColorString, children: [
49
- tierName,
50
- " ",
51
- /* @__PURE__ */ jsxs(Text, { color: "white", children: [
52
- "#",
53
- problem.id,
54
- ": ",
55
- problem.title
56
- ] })
57
- ] })
58
- }
59
- );
60
- }
61
-
62
- // src/hooks/use-fetch-problem.ts
63
- import { execaCommand } from "execa";
64
- import { useEffect, useState } from "react";
65
-
66
- // src/services/file-generator.ts
67
- import { mkdir, writeFile, readFile } from "fs/promises";
68
- import { join, dirname } from "path";
69
- import { fileURLToPath } from "url";
70
- function parseTimeLimitToMs(timeLimit) {
71
- if (!timeLimit) return void 0;
72
- const match = timeLimit.match(/([\d.]+)/);
73
- if (!match) return void 0;
74
- const seconds = parseFloat(match[1]);
75
- if (Number.isNaN(seconds)) return void 0;
76
- return Math.round(seconds * 1e3);
77
- }
78
- function ensureTrailingNewline(content) {
79
- if (!content || content.trim().length === 0) {
80
- return content;
81
- }
82
- const trimmed = content.trimEnd();
83
- if (trimmed.length === 0) {
84
- return content;
85
- }
86
- const lines = trimmed.split("\n");
87
- const lastLine = lines[lines.length - 1];
88
- const isListItem = /^[\s]*[-*]\s/.test(lastLine) || /^[\s]*\d+[.)]\s/.test(lastLine);
89
- const isTableRow = /^\s*\|.+\|\s*$/.test(lastLine);
90
- const isCodeBlock = trimmed.endsWith("```");
91
- if (isListItem || isTableRow || isCodeBlock) {
92
- return trimmed + "\n";
93
- }
94
- if (!content.endsWith("\n")) {
95
- return content + "\n";
96
- }
97
- return content;
98
- }
99
- function getProjectRoot() {
100
- const __filename = fileURLToPath(import.meta.url);
101
- const __dirname = dirname(__filename);
102
- if (__dirname.includes("dist")) {
103
- return join(__dirname, "../..");
104
- }
105
- return join(__dirname, "../..");
106
- }
107
- async function generateProblemFiles(problem, language = "python") {
108
- const problemDir = getSolvingDirPath(problem.id, process.cwd(), problem);
109
- await mkdir(problemDir, { recursive: true });
110
- const langConfig = getLanguageConfig(language);
111
- const projectRoot = getProjectRoot();
112
- const templatePath = join(projectRoot, "templates", langConfig.templateFile);
113
- const solutionPath = join(problemDir, `solution.${langConfig.extension}`);
114
- try {
115
- const templateContent = await readFile(templatePath, "utf-8");
116
- await writeFile(solutionPath, templateContent, "utf-8");
117
- } catch {
118
- await writeFile(
119
- solutionPath,
120
- `// Problem ${problem.id}: ${problem.title}
121
- `,
122
- "utf-8"
123
- );
124
- }
125
- const testcasesDir = join(problemDir, "testcases");
126
- for (let i = 0; i < problem.testCases.length; i++) {
127
- const testCase = problem.testCases[i];
128
- const caseDir = join(testcasesDir, String(i + 1));
129
- await mkdir(caseDir, { recursive: true });
130
- const inputPath = join(caseDir, "input.txt");
131
- const outputPath = join(caseDir, "output.txt");
132
- await writeFile(inputPath, testCase.input, "utf-8");
133
- await writeFile(outputPath, testCase.output, "utf-8");
134
- }
135
- const tierName = getTierName(problem.level);
136
- const tierImageUrl = getTierImageUrl(problem.level);
137
- const tags = problem.tags.length > 0 ? problem.tags.join(", ") : "\uC5C6\uC74C";
138
- const headers = [];
139
- const values = [];
140
- headers.push("\uB09C\uC774\uB3C4");
141
- values.push(`<img src="${tierImageUrl}" alt="${tierName}" width="20" />`);
142
- if (problem.timeLimit) {
143
- headers.push("\uC2DC\uAC04 \uC81C\uD55C");
144
- values.push(problem.timeLimit);
145
- }
146
- if (problem.memoryLimit) {
147
- headers.push("\uBA54\uBAA8\uB9AC \uC81C\uD55C");
148
- values.push(problem.memoryLimit);
149
- }
150
- if (problem.submissions) {
151
- headers.push("\uC81C\uCD9C");
152
- values.push(problem.submissions);
153
- }
154
- if (problem.accepted) {
155
- headers.push("\uC815\uB2F5");
156
- values.push(problem.accepted);
157
- }
158
- if (problem.acceptedUsers) {
159
- headers.push("\uB9DE\uD78C \uC0AC\uB78C");
160
- values.push(problem.acceptedUsers);
161
- }
162
- if (problem.acceptedRate) {
163
- headers.push("\uC815\uB2F5 \uBE44\uC728");
164
- values.push(problem.acceptedRate);
165
- }
166
- let infoTable = "";
167
- if (headers.length > 0) {
168
- const headerRow = `| ${headers.join(" | ")} |`;
169
- const separatorRow = `|${headers.map(() => "---").join("|")}|`;
170
- const valueRow = `| ${values.join(" | ")} |`;
171
- infoTable = `
172
- ${headerRow}
173
- ${separatorRow}
174
- ${valueRow}
175
- `;
176
- }
177
- const description = ensureTrailingNewline(problem.description || "\uC124\uBA85 \uC5C6\uC74C");
178
- const inputFormat = ensureTrailingNewline(
179
- problem.inputFormat || "\uC785\uB825 \uD615\uC2DD \uC5C6\uC74C"
180
- );
181
- const outputFormat = ensureTrailingNewline(
182
- problem.outputFormat || "\uCD9C\uB825 \uD615\uC2DD \uC5C6\uC74C"
183
- );
184
- const readmeContent = `# [${problem.id}: ${problem.title}](https://www.acmicpc.net/problem/${problem.id})
185
-
186
- ${infoTable}## \uBB38\uC81C \uC124\uBA85
187
- ${description}## \uC785\uB825
188
- ${inputFormat}## \uCD9C\uB825
189
- ${outputFormat}
190
-
191
- ## \uC608\uC81C
192
- ${problem.testCases.map(
193
- (tc, i) => `### \uC608\uC81C ${i + 1}
194
-
195
- **\uC785\uB825:**
196
- \`\`\`
197
- ${tc.input.trimEnd()}
198
- \`\`\`
199
-
200
- **\uCD9C\uB825:**
201
- \`\`\`
202
- ${tc.output.trimEnd()}
203
- \`\`\`
204
- `
205
- ).join("\n")}
206
-
207
- ## \uD0DC\uADF8
208
- ${tags}
209
- `;
210
- const readmePath = join(problemDir, "README.md");
211
- await writeFile(readmePath, readmeContent, "utf-8");
212
- const meta = {
213
- id: problem.id,
214
- title: problem.title,
215
- level: problem.level,
216
- tags: problem.tags,
217
- timeLimit: problem.timeLimit,
218
- timeLimitMs: parseTimeLimitToMs(problem.timeLimit),
219
- memoryLimit: problem.memoryLimit
220
- };
221
- const metaPath = join(problemDir, "meta.json");
222
- await writeFile(metaPath, JSON.stringify(meta, null, 2), "utf-8");
223
- return problemDir;
224
- }
225
-
226
- // src/hooks/use-fetch-problem.ts
227
- function useFetchProblem({
228
- problemId,
229
- language,
230
- onComplete
231
- }) {
232
- const [status, setStatus] = useState(
233
- "loading"
234
- );
235
- const [problem, setProblem] = useState(null);
236
- const [error, setError] = useState(null);
237
- const [message, setMessage] = useState("\uBB38\uC81C \uC815\uBCF4\uB97C \uAC00\uC838\uC624\uB294 \uC911...");
238
- useEffect(() => {
239
- async function fetchProblem() {
240
- try {
241
- setMessage("Solved.ac\uC5D0\uC11C \uBB38\uC81C \uC815\uBCF4\uB97C \uAC00\uC838\uC624\uB294 \uC911...");
242
- const solvedAcData = await getProblem(problemId);
243
- setMessage("BOJ\uC5D0\uC11C \uBB38\uC81C \uC0C1\uC138 \uC815\uBCF4\uB97C \uAC00\uC838\uC624\uB294 \uC911...");
244
- const scrapedData = await scrapeProblem(problemId);
245
- if (!scrapedData.title && !solvedAcData.titleKo) {
246
- throw new Error(
247
- `\uBB38\uC81C ${problemId}\uC758 \uC81C\uBAA9\uC744 \uAC00\uC838\uC62C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uBB38\uC81C\uAC00 \uC874\uC7AC\uD558\uC9C0 \uC54A\uAC70\uB098 \uC811\uADFC\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`
248
- );
249
- }
250
- const combinedProblem = {
251
- id: problemId,
252
- title: solvedAcData.titleKo || scrapedData.title,
253
- level: solvedAcData.level,
254
- tier: getTierName(solvedAcData.level),
255
- tags: solvedAcData.tags.map(
256
- (tag) => tag.displayNames.find((d) => d.language === "ko")?.name || tag.displayNames[0]?.name || tag.key
257
- ),
258
- timeLimit: scrapedData.timeLimit,
259
- memoryLimit: scrapedData.memoryLimit,
260
- submissions: scrapedData.submissions,
261
- accepted: scrapedData.accepted,
262
- acceptedUsers: scrapedData.acceptedUsers,
263
- acceptedRate: scrapedData.acceptedRate,
264
- description: scrapedData.description,
265
- inputFormat: scrapedData.inputFormat,
266
- outputFormat: scrapedData.outputFormat,
267
- testCases: scrapedData.testCases
268
- };
269
- setProblem(combinedProblem);
270
- setMessage("\uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uB294 \uC911...");
271
- const problemDir = await generateProblemFiles(
272
- combinedProblem,
273
- language
274
- );
275
- setStatus("success");
276
- setMessage(`\uBB38\uC81C \uD30C\uC77C\uC774 \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4: ${problemDir}`);
277
- if (getAutoOpenEditor()) {
278
- try {
279
- const editor = getEditor();
280
- await execaCommand(`${editor} ${problemDir}`, {
281
- shell: true,
282
- detached: true,
283
- stdio: "ignore"
284
- });
285
- setMessage(
286
- `\uBB38\uC81C \uD30C\uC77C\uC774 \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4: ${problemDir}
287
- ${editor}\uB85C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4.`
288
- );
289
- } catch (err) {
290
- console.warn(
291
- `\uC5D0\uB514\uD130\uB97C \uC5F4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${err instanceof Error ? err.message : String(err)}`
292
- );
293
- }
294
- }
295
- setTimeout(() => {
296
- onComplete?.();
297
- }, 2e3);
298
- } catch (err) {
299
- setStatus("error");
300
- setError(err instanceof Error ? err.message : String(err));
301
- setTimeout(() => {
302
- onComplete?.();
303
- }, 2e3);
304
- }
305
- }
306
- void fetchProblem();
307
- }, [problemId, language, onComplete]);
308
- return {
309
- status,
310
- problem,
311
- error,
312
- message
313
- };
314
- }
315
-
316
- // src/commands/fetch.tsx
317
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
318
- function FetchView({
319
- problemId,
320
- language = "python",
321
- onComplete
322
- }) {
323
- const { status, problem, error, message } = useFetchProblem({
324
- problemId,
325
- language,
326
- onComplete
327
- });
328
- if (status === "loading") {
329
- return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
330
- /* @__PURE__ */ jsx2(Spinner, { label: message }),
331
- problem && /* @__PURE__ */ jsx2(ProblemDashboard, { problem })
332
- ] });
333
- }
334
- if (status === "error") {
335
- return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: /* @__PURE__ */ jsxs2(Alert, { variant: "error", children: [
336
- "\uC624\uB958 \uBC1C\uC0DD: ",
337
- error
338
- ] }) });
339
- }
340
- return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: "100%", children: [
341
- problem && /* @__PURE__ */ jsx2(Box2, { alignSelf: "flex-start", children: /* @__PURE__ */ jsx2(ProblemDashboard, { problem }) }),
342
- /* @__PURE__ */ jsx2(StatusMessage, { variant: "success", children: message })
343
- ] });
344
- }
345
- var FetchCommand = class extends Command {
346
- async execute(args, flags) {
347
- const context = await resolveProblemContext(args, { requireId: true });
348
- if (context.problemId === null) {
349
- console.error("\uC624\uB958: \uBB38\uC81C \uBC88\uD638\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694.");
350
- console.error(`\uC0AC\uC6A9\uBC95: ps fetch <\uBB38\uC81C\uBC88\uD638> [\uC635\uC158]`);
351
- console.error(`\uB3C4\uC6C0\uB9D0: ps fetch --help`);
352
- console.error(
353
- `\uD78C\uD2B8: problems/{\uBB38\uC81C\uBC88\uD638} \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C \uC2E4\uD589\uD558\uBA74 \uC790\uB3D9\uC73C\uB85C \uBB38\uC81C \uBC88\uD638\uB97C \uCD94\uB860\uD569\uB2C8\uB2E4.`
354
- );
355
- process.exit(1);
356
- return;
357
- }
358
- const validLanguages = getSupportedLanguages();
359
- const language = flags.language;
360
- if (language && !validLanguages.includes(language)) {
361
- console.error(
362
- `\uC624\uB958: \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC5B8\uC5B4\uC785\uB2C8\uB2E4. (${getSupportedLanguagesString()})`
363
- );
364
- process.exit(1);
365
- return;
366
- }
367
- await this.renderView(FetchView, {
368
- problemId: context.problemId,
369
- language: language || "python"
370
- });
371
- }
372
- };
373
- FetchCommand = __decorateClass([
374
- CommandDef({
375
- name: "fetch",
376
- description: `\uBC31\uC900 \uBB38\uC81C\uB97C \uAC00\uC838\uC640\uC11C \uB85C\uCEEC\uC5D0 \uD30C\uC77C\uC744 \uC0DD\uC131\uD569\uB2C8\uB2E4.
377
- - Solved.ac API\uC640 BOJ \uD06C\uB864\uB9C1\uC744 \uD1B5\uD574 \uBB38\uC81C \uC815\uBCF4 \uC218\uC9D1
378
- - \uBB38\uC81C \uC124\uBA85, \uC785\uCD9C\uB825 \uD615\uC2DD, \uC608\uC81C \uC785\uCD9C\uB825 \uD30C\uC77C \uC790\uB3D9 \uC0DD\uC131
379
- - \uC120\uD0DD\uD55C \uC5B8\uC5B4\uC758 \uC194\uB8E8\uC158 \uD15C\uD50C\uB9BF \uD30C\uC77C \uC0DD\uC131
380
- - README.md\uC5D0 \uBB38\uC81C \uC815\uBCF4, \uD1B5\uACC4, \uD0DC\uADF8 \uB4F1 \uD3EC\uD568`,
381
- flags: [
382
- {
383
- name: "language",
384
- options: {
385
- shortFlag: "l",
386
- description: `\uC5B8\uC5B4 \uC120\uD0DD (${getSupportedLanguagesString()})
387
- \uAE30\uBCF8\uAC12: python`
388
- }
389
- }
390
- ],
391
- autoDetectProblemId: false,
392
- requireProblemId: true,
393
- examples: ["fetch 1000", "fetch 1000 --language python", "fetch 1000 -l cpp"]
394
- })
395
- ], FetchCommand);
396
- var fetch_default = CommandBuilder.fromClass(FetchCommand);
3
+ FetchCommand,
4
+ FetchView,
5
+ fetch_default
6
+ } from "../chunk-SBBC4CBS.js";
7
+ import "../chunk-YH6VDCNG.js";
8
+ import "../chunk-JZK2464U.js";
397
9
  export {
398
10
  FetchCommand,
11
+ FetchView,
399
12
  fetch_default as default
400
13
  };
@@ -3,18 +3,18 @@ import {
3
3
  Command,
4
4
  CommandBuilder,
5
5
  CommandDef,
6
+ __decorateClass,
6
7
  getArchiveDir,
7
8
  getArchiveStrategy,
8
9
  getAutoOpenEditor,
9
10
  getDefaultLanguage,
10
11
  getEditor,
12
+ getIncludeTag,
11
13
  getSolvedAcHandle,
12
- getSolvingDir
13
- } from "../chunk-F4LZ6ENP.js";
14
- import {
15
- __decorateClass,
16
- getSupportedLanguages
17
- } from "../chunk-7MQMPJ3X.js";
14
+ getSolvingDir,
15
+ getSupportedLanguages,
16
+ icons
17
+ } from "../chunk-JZK2464U.js";
18
18
 
19
19
  // src/commands/init.tsx
20
20
  import {
@@ -42,6 +42,7 @@ function useInit({ onComplete }) {
42
42
  const [language, setLanguage] = useState(getDefaultLanguage());
43
43
  const [editor, setEditorValue] = useState(getEditor());
44
44
  const [autoOpen, setAutoOpen] = useState(getAutoOpenEditor());
45
+ const [includeTag, setIncludeTag] = useState(getIncludeTag());
45
46
  const [handle, setHandle] = useState(getSolvedAcHandle() || "");
46
47
  const [handleInputMode, setHandleInputMode] = useState(false);
47
48
  const [created, setCreated] = useState([]);
@@ -82,6 +83,8 @@ function useInit({ onComplete }) {
82
83
  if (projectConfig.editor) setEditorValue(projectConfig.editor);
83
84
  if (projectConfig.autoOpenEditor !== void 0)
84
85
  setAutoOpen(projectConfig.autoOpenEditor);
86
+ if (projectConfig.includeTag !== void 0)
87
+ setIncludeTag(projectConfig.includeTag);
85
88
  if (projectConfig.solvedAcHandle)
86
89
  setHandle(projectConfig.solvedAcHandle);
87
90
  } catch {
@@ -105,6 +108,8 @@ function useInit({ onComplete }) {
105
108
  return "\uC5D0\uB514\uD130 \uC124\uC815";
106
109
  case "auto-open":
107
110
  return "\uC790\uB3D9 \uC5D0\uB514\uD130 \uC5F4\uAE30";
111
+ case "include-tag":
112
+ return "README\uC5D0 \uC54C\uACE0\uB9AC\uC998 \uBD84\uB958 \uD3EC\uD568";
108
113
  case "handle":
109
114
  return "Solved.ac \uD578\uB4E4 (\uC120\uD0DD)";
110
115
  default:
@@ -133,6 +138,8 @@ function useInit({ onComplete }) {
133
138
  return editor;
134
139
  case "auto-open":
135
140
  return autoOpen ? "\uC608" : "\uC544\uB2C8\uC624";
141
+ case "include-tag":
142
+ return includeTag ? "\uC608" : "\uC544\uB2C8\uC624";
136
143
  case "handle":
137
144
  return handle || "(\uC2A4\uD0B5)";
138
145
  default:
@@ -145,6 +152,7 @@ function useInit({ onComplete }) {
145
152
  language,
146
153
  editor,
147
154
  autoOpen,
155
+ includeTag,
148
156
  handle,
149
157
  archiveStrategy
150
158
  ]
@@ -160,7 +168,8 @@ function useInit({ onComplete }) {
160
168
  archiveStrategy,
161
169
  defaultLanguage: language,
162
170
  editor,
163
- autoOpenEditor: autoOpen
171
+ autoOpenEditor: autoOpen,
172
+ includeTag
164
173
  };
165
174
  const handleToUse = overrideHandle ?? handle;
166
175
  if (handleToUse && typeof handleToUse === "string" && handleToUse.trim().length > 0) {
@@ -286,6 +295,7 @@ ${gitignorePatterns.join("\n")}
286
295
  language,
287
296
  editor,
288
297
  autoOpen,
298
+ includeTag,
289
299
  handle,
290
300
  onComplete
291
301
  ]
@@ -306,6 +316,7 @@ ${gitignorePatterns.join("\n")}
306
316
  "language",
307
317
  "editor",
308
318
  "auto-open",
319
+ "include-tag",
309
320
  "handle",
310
321
  "done"
311
322
  ];
@@ -335,6 +346,7 @@ ${gitignorePatterns.join("\n")}
335
346
  language,
336
347
  editor,
337
348
  autoOpen,
349
+ includeTag,
338
350
  handle,
339
351
  handleInputMode,
340
352
  created,
@@ -345,6 +357,7 @@ ${gitignorePatterns.join("\n")}
345
357
  setLanguage,
346
358
  setEditorValue,
347
359
  setAutoOpen,
360
+ setIncludeTag,
348
361
  setHandle,
349
362
  setHandleInputMode,
350
363
  setConfirmExit,
@@ -389,6 +402,7 @@ function InitView({ onComplete }) {
389
402
  setLanguage,
390
403
  setEditorValue,
391
404
  setAutoOpen,
405
+ setIncludeTag,
392
406
  setHandle,
393
407
  setHandleInputMode,
394
408
  setConfirmExit,
@@ -563,6 +577,28 @@ function InitView({ onComplete }) {
563
577
  )
564
578
  );
565
579
  }
580
+ case "include-tag": {
581
+ const options = [
582
+ { label: "\uC608", value: "true" },
583
+ { label: "\uC544\uB2C8\uC624", value: "false" }
584
+ ];
585
+ return renderQuestionCard(
586
+ getStepLabel(currentStep),
587
+ /* @__PURE__ */ jsx(
588
+ Select,
589
+ {
590
+ options,
591
+ onChange: (value) => {
592
+ setIncludeTag(value === "true");
593
+ moveToNextStep(
594
+ value === "true" ? "\uC608" : "\uC544\uB2C8\uC624",
595
+ getStepLabel(currentStep)
596
+ );
597
+ }
598
+ }
599
+ )
600
+ );
601
+ }
566
602
  case "handle": {
567
603
  if (handleInputMode) {
568
604
  return renderQuestionCard(
@@ -610,7 +646,7 @@ function InitView({ onComplete }) {
610
646
  case "done": {
611
647
  const createdItemsText = created.length > 0 ? `
612
648
  \uC0DD\uC131\uB41C \uD56D\uBAA9:
613
- ${created.map((item) => `\u2022 ${item}`).join("\n")}` : "";
649
+ ${created.map((item) => `${icons.solving} ${item}`).join("\n")}` : "";
614
650
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
615
651
  /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Alert, { variant: "success", children: [
616
652
  "\uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654 \uC644\uB8CC",
@@ -635,7 +671,10 @@ ${created.map((item) => `\u2022 ${item}`).join("\n")}` : "";
635
671
  const version = getVersion();
636
672
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
637
673
  /* @__PURE__ */ jsxs(Box, { marginBottom: completedSteps.length > 0 ? 1 : 0, children: [
638
- /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u{1F680} ps-cli \uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654" }),
674
+ /* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
675
+ icons.init,
676
+ " ps-cli \uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654"
677
+ ] }),
639
678
  version && /* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
640
679
  " ",
641
680
  "v",
@@ -660,7 +699,8 @@ InitCommand = __decorateClass([
660
699
  name: "init",
661
700
  description: `\uD604\uC7AC \uB514\uB809\uD1A0\uB9AC\uB97C ps-cli \uD504\uB85C\uC81D\uD2B8\uB85C \uB300\uD654\uD615\uC73C\uB85C \uCD08\uAE30\uD654\uD569\uB2C8\uB2E4.
662
701
  - \uB2E8\uACC4\uBCC4\uB85C \uC124\uC815\uC744 \uBB3C\uC5B4\uBD05\uB2C8\uB2E4
663
- - \uBB38\uC81C \uB514\uB809\uD1A0\uB9AC, \uAE30\uBCF8 \uC5B8\uC5B4, \uC5D0\uB514\uD130 \uB4F1\uC744 \uC124\uC815\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4`,
702
+ - \uBB38\uC81C \uB514\uB809\uD1A0\uB9AC, \uAE30\uBCF8 \uC5B8\uC5B4, \uC5D0\uB514\uD130, \uD0DC\uADF8 \uD3EC\uD568 \uC5EC\uBD80 \uB4F1\uC744 \uC124\uC815\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4`,
703
+ flags: [],
664
704
  autoDetectProblemId: false,
665
705
  examples: ["init"]
666
706
  })
@@ -1,100 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- useOpenBrowser
4
- } from "../chunk-GCOFFYJ3.js";
3
+ OpenCommand,
4
+ OpenView,
5
+ open_default
6
+ } from "../chunk-XV6UUPQC.js";
5
7
  import "../chunk-QGMWUOJ3.js";
6
- import {
7
- Command,
8
- CommandBuilder,
9
- CommandDef,
10
- resolveProblemContext
11
- } from "../chunk-F4LZ6ENP.js";
12
- import {
13
- __decorateClass
14
- } from "../chunk-7MQMPJ3X.js";
15
-
16
- // src/commands/open.tsx
17
- import { StatusMessage, Alert } from "@inkjs/ui";
18
- import { Spinner } from "@inkjs/ui";
19
- import { Text, Box } from "ink";
20
- import { jsx, jsxs } from "react/jsx-runtime";
21
- function OpenView({ problemId, onComplete }) {
22
- const { status, error, url } = useOpenBrowser({
23
- problemId,
24
- onComplete
25
- });
26
- if (status === "loading") {
27
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
28
- /* @__PURE__ */ jsx(Spinner, { label: "\uBE0C\uB77C\uC6B0\uC800\uB97C \uC5EC\uB294 \uC911..." }),
29
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
30
- "\uBB38\uC81C #",
31
- problemId
32
- ] }) })
33
- ] });
34
- }
35
- if (status === "error") {
36
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
37
- /* @__PURE__ */ jsxs(Alert, { variant: "error", children: [
38
- "\uBE0C\uB77C\uC6B0\uC800\uB97C \uC5F4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ",
39
- error
40
- ] }),
41
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
42
- "URL: ",
43
- url
44
- ] }) })
45
- ] });
46
- }
47
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: "100%", children: [
48
- /* @__PURE__ */ jsx(StatusMessage, { variant: "success", children: "\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uBB38\uC81C \uD398\uC774\uC9C0\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4!" }),
49
- /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
50
- /* @__PURE__ */ jsxs(Text, { children: [
51
- /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\uBB38\uC81C \uBC88\uD638:" }),
52
- " ",
53
- problemId
54
- ] }),
55
- /* @__PURE__ */ jsxs(Text, { children: [
56
- /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "URL:" }),
57
- " ",
58
- /* @__PURE__ */ jsx(Text, { color: "blue", underline: true, children: url })
59
- ] })
60
- ] })
61
- ] });
62
- }
63
- var OpenCommand = class extends Command {
64
- async execute(args, _flags) {
65
- const context = await resolveProblemContext(args, { requireId: true });
66
- if (context.problemId === null) {
67
- console.error("\uC624\uB958: \uBB38\uC81C \uBC88\uD638\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694.");
68
- console.error(`\uC0AC\uC6A9\uBC95: ps open <\uBB38\uC81C\uBC88\uD638>`);
69
- console.error(`\uB3C4\uC6C0\uB9D0: ps open --help`);
70
- console.error(
71
- `\uD78C\uD2B8: problems/{\uBB38\uC81C\uBC88\uD638} \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C \uC2E4\uD589\uD558\uBA74 \uC790\uB3D9\uC73C\uB85C \uBB38\uC81C \uBC88\uD638\uB97C \uCD94\uB860\uD569\uB2C8\uB2E4.`
72
- );
73
- process.exit(1);
74
- return;
75
- }
76
- await this.renderView(OpenView, {
77
- problemId: context.problemId
78
- });
79
- }
80
- };
81
- OpenCommand = __decorateClass([
82
- CommandDef({
83
- name: "open",
84
- description: `\uBC31\uC900 \uBB38\uC81C \uD398\uC774\uC9C0\uB97C \uBE0C\uB77C\uC6B0\uC800\uB85C \uC5FD\uB2C8\uB2E4.
85
- - \uBB38\uC81C \uBC88\uD638\uB97C \uC778\uC790\uB85C \uC804\uB2EC\uD558\uAC70\uB098
86
- - \uBB38\uC81C \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C \uC2E4\uD589\uD558\uBA74 \uC790\uB3D9\uC73C\uB85C \uBB38\uC81C \uBC88\uD638\uB97C \uCD94\uB860\uD569\uB2C8\uB2E4.`,
87
- autoDetectProblemId: true,
88
- requireProblemId: true,
89
- examples: [
90
- "open 1000 # 1000\uBC88 \uBB38\uC81C \uC5F4\uAE30",
91
- "open # \uBB38\uC81C \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C \uC2E4\uD589 \uC2DC \uC790\uB3D9 \uCD94\uB860",
92
- "open --help # \uB3C4\uC6C0\uB9D0 \uD45C\uC2DC"
93
- ]
94
- })
95
- ], OpenCommand);
96
- var open_default = CommandBuilder.fromClass(OpenCommand);
8
+ import "../chunk-JZK2464U.js";
97
9
  export {
98
10
  OpenCommand,
11
+ OpenView,
99
12
  open_default as default
100
13
  };