@rhseung/ps-cli 1.5.0 → 1.7.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.
- package/dist/{chunk-HDNNR5OY.js → chunk-ASMT3CRD.js} +1 -202
- package/dist/{chunk-7SVCS23X.js → chunk-TNGUME4H.js} +376 -27
- package/dist/commands/config.js +32 -2
- package/dist/commands/fetch.js +13 -15
- package/dist/commands/init.js +247 -100
- package/dist/commands/open.js +1 -1
- package/dist/commands/run.js +1 -1
- package/dist/commands/search.js +367 -103
- package/dist/commands/solve.js +201 -0
- package/dist/commands/stats.js +9 -9
- package/dist/commands/submit.js +1 -1
- package/dist/commands/test.js +1 -1
- package/package.json +1 -1
package/dist/commands/config.js
CHANGED
|
@@ -3,12 +3,13 @@ import {
|
|
|
3
3
|
Command,
|
|
4
4
|
CommandBuilder,
|
|
5
5
|
CommandDef,
|
|
6
|
+
getArchiveStrategy,
|
|
6
7
|
getAutoOpenEditor,
|
|
7
8
|
getDefaultLanguage,
|
|
8
9
|
getEditor,
|
|
9
10
|
getProblemDir,
|
|
10
11
|
getSolvedAcHandle
|
|
11
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-TNGUME4H.js";
|
|
12
13
|
import {
|
|
13
14
|
__decorateClass,
|
|
14
15
|
getSupportedLanguages,
|
|
@@ -104,6 +105,18 @@ function useConfig({
|
|
|
104
105
|
case "problem-dir":
|
|
105
106
|
updatedConfig.problemDir = value;
|
|
106
107
|
break;
|
|
108
|
+
case "archive-strategy": {
|
|
109
|
+
const validStrategies = ["flat", "by-range", "by-tier", "by-tag"];
|
|
110
|
+
if (!validStrategies.includes(value)) {
|
|
111
|
+
console.error(
|
|
112
|
+
`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC544\uCE74\uC774\uBE59 \uC804\uB7B5\uC785\uB2C8\uB2E4: ${value}
|
|
113
|
+
\uC9C0\uC6D0 \uC804\uB7B5: ${validStrategies.join(", ")}`
|
|
114
|
+
);
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
updatedConfig.archiveStrategy = value;
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
107
120
|
default:
|
|
108
121
|
console.error(`\uC54C \uC218 \uC5C6\uB294 \uC124\uC815 \uD0A4: ${configKey}`);
|
|
109
122
|
process.exit(1);
|
|
@@ -147,6 +160,7 @@ function getConfigHelp() {
|
|
|
147
160
|
auto-open-editor fetch \uD6C4 \uC790\uB3D9\uC73C\uB85C \uC5D0\uB514\uD130 \uC5F4\uAE30 (true/false)
|
|
148
161
|
solved-ac-handle Solved.ac \uD578\uB4E4 (stats \uBA85\uB839\uC5B4\uC6A9)
|
|
149
162
|
problem-dir \uBB38\uC81C \uB514\uB809\uD1A0\uB9AC \uACBD\uB85C (\uAE30\uBCF8\uAC12: problems, "." \uB610\uB294 ""\uB294 \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8)
|
|
163
|
+
archive-strategy \uC544\uCE74\uC774\uBE59 \uC804\uB7B5 (flat, by-range, by-tier, by-tag)
|
|
150
164
|
|
|
151
165
|
\uC635\uC158:
|
|
152
166
|
--help, -h \uB3C4\uC6C0\uB9D0 \uD45C\uC2DC
|
|
@@ -166,7 +180,8 @@ var CONFIG_KEYS = [
|
|
|
166
180
|
{ label: "editor", value: "editor" },
|
|
167
181
|
{ label: "auto-open-editor", value: "auto-open-editor" },
|
|
168
182
|
{ label: "solved-ac-handle", value: "solved-ac-handle" },
|
|
169
|
-
{ label: "problem-dir", value: "problem-dir" }
|
|
183
|
+
{ label: "problem-dir", value: "problem-dir" },
|
|
184
|
+
{ label: "archive-strategy", value: "archive-strategy" }
|
|
170
185
|
];
|
|
171
186
|
function ConfigView({
|
|
172
187
|
configKey,
|
|
@@ -199,6 +214,7 @@ function ConfigView({
|
|
|
199
214
|
const autoOpen = config?.autoOpenEditor ?? getAutoOpenEditor();
|
|
200
215
|
const handle = config?.solvedAcHandle ?? getSolvedAcHandle();
|
|
201
216
|
const problemDir = config?.problemDir ?? getProblemDir();
|
|
217
|
+
const archiveStrategy = config?.archiveStrategy ?? getArchiveStrategy();
|
|
202
218
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
203
219
|
/* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2699\uFE0F \uD604\uC7AC \uC124\uC815 (.ps-cli.json)" }) }),
|
|
204
220
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
@@ -226,6 +242,11 @@ function ConfigView({
|
|
|
226
242
|
/* @__PURE__ */ jsx(Text, { color: "gray", children: "problem-dir:" }),
|
|
227
243
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
228
244
|
/* @__PURE__ */ jsx(Text, { bold: true, children: problemDir })
|
|
245
|
+
] }),
|
|
246
|
+
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
247
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "archive-strategy:" }),
|
|
248
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
249
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: archiveStrategy })
|
|
229
250
|
] })
|
|
230
251
|
] })
|
|
231
252
|
] });
|
|
@@ -248,6 +269,9 @@ function ConfigView({
|
|
|
248
269
|
case "problem-dir":
|
|
249
270
|
configValue = config?.problemDir ?? getProblemDir();
|
|
250
271
|
break;
|
|
272
|
+
case "archive-strategy":
|
|
273
|
+
configValue = config?.archiveStrategy ?? getArchiveStrategy();
|
|
274
|
+
break;
|
|
251
275
|
default:
|
|
252
276
|
console.error(`\uC54C \uC218 \uC5C6\uB294 \uC124\uC815 \uD0A4: ${configKey}`);
|
|
253
277
|
process.exit(1);
|
|
@@ -418,6 +442,8 @@ var ConfigCommand = class extends Command {
|
|
|
418
442
|
return "Solved.ac \uD578\uB4E4 \uC785\uB825";
|
|
419
443
|
case "problem-dir":
|
|
420
444
|
return "\uBB38\uC81C \uB514\uB809\uD1A0\uB9AC \uACBD\uB85C \uC785\uB825";
|
|
445
|
+
case "archive-strategy":
|
|
446
|
+
return "\uC544\uCE74\uC774\uBE59 \uC804\uB7B5 \uC785\uB825 (flat, by-range, by-tier, by-tag)";
|
|
421
447
|
default:
|
|
422
448
|
return "\uAC12 \uC785\uB825";
|
|
423
449
|
}
|
|
@@ -434,6 +460,8 @@ var ConfigCommand = class extends Command {
|
|
|
434
460
|
return "Solved.ac \uC0AC\uC6A9\uC790 \uD578\uB4E4";
|
|
435
461
|
case "problem-dir":
|
|
436
462
|
return '\uBB38\uC81C \uB514\uB809\uD1A0\uB9AC \uACBD\uB85C (\uAE30\uBCF8\uAC12: "problems", \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8: ".")';
|
|
463
|
+
case "archive-strategy":
|
|
464
|
+
return "\uC544\uCE74\uC774\uBE59 \uC804\uB7B5: flat (\uD3C9\uBA74), by-range (1000\uBC88\uB300 \uBB36\uAE30), by-tier (\uD2F0\uC5B4\uBCC4), by-tag (\uD0DC\uADF8\uBCC4)";
|
|
437
465
|
default:
|
|
438
466
|
return "";
|
|
439
467
|
}
|
|
@@ -448,6 +476,8 @@ var ConfigCommand = class extends Command {
|
|
|
448
476
|
return ["true", "false"];
|
|
449
477
|
case "problem-dir":
|
|
450
478
|
return ["problems", ".", ""];
|
|
479
|
+
case "archive-strategy":
|
|
480
|
+
return ["flat", "by-range", "by-tier", "by-tag"];
|
|
451
481
|
default:
|
|
452
482
|
return [];
|
|
453
483
|
}
|
package/dist/commands/fetch.js
CHANGED
|
@@ -5,21 +5,18 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
getProblem
|
|
7
7
|
} from "../chunk-A6STXEAE.js";
|
|
8
|
-
import {
|
|
9
|
-
getTierColor,
|
|
10
|
-
getTierImageUrl,
|
|
11
|
-
getTierName,
|
|
12
|
-
source_default
|
|
13
|
-
} from "../chunk-HDNNR5OY.js";
|
|
14
8
|
import {
|
|
15
9
|
Command,
|
|
16
10
|
CommandBuilder,
|
|
17
11
|
CommandDef,
|
|
18
12
|
getAutoOpenEditor,
|
|
19
13
|
getEditor,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
getProblemId,
|
|
15
|
+
getSolvingDirPath,
|
|
16
|
+
getTierColor,
|
|
17
|
+
getTierImageUrl,
|
|
18
|
+
getTierName
|
|
19
|
+
} from "../chunk-TNGUME4H.js";
|
|
23
20
|
import {
|
|
24
21
|
__decorateClass,
|
|
25
22
|
getLanguageConfig,
|
|
@@ -33,14 +30,14 @@ import { Spinner } from "@inkjs/ui";
|
|
|
33
30
|
import { Box as Box2 } from "ink";
|
|
34
31
|
|
|
35
32
|
// src/components/problem-dashboard.tsx
|
|
36
|
-
import { Box, Text
|
|
33
|
+
import { Box, Text } from "ink";
|
|
37
34
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
38
35
|
function ProblemDashboard({ problem }) {
|
|
39
36
|
const tierName = getTierName(problem.level);
|
|
40
37
|
const tierColor = getTierColor(problem.level);
|
|
41
|
-
const tierColorFn = typeof tierColor === "string" ? source_default.hex(tierColor) : tierColor.multiline;
|
|
42
38
|
const borderColorString = typeof tierColor === "string" ? tierColor : "#ff7ca8";
|
|
43
|
-
|
|
39
|
+
const textColorString = borderColorString;
|
|
40
|
+
return /* @__PURE__ */ jsx(
|
|
44
41
|
Box,
|
|
45
42
|
{
|
|
46
43
|
flexDirection: "column",
|
|
@@ -48,7 +45,7 @@ function ProblemDashboard({ problem }) {
|
|
|
48
45
|
borderColor: borderColorString,
|
|
49
46
|
paddingX: 1,
|
|
50
47
|
alignSelf: "flex-start",
|
|
51
|
-
children: /* @__PURE__ */ jsxs(Text, { bold: true, children: [
|
|
48
|
+
children: /* @__PURE__ */ jsxs(Text, { bold: true, color: textColorString, children: [
|
|
52
49
|
tierName,
|
|
53
50
|
" ",
|
|
54
51
|
/* @__PURE__ */ jsxs(Text, { color: "white", children: [
|
|
@@ -59,7 +56,7 @@ function ProblemDashboard({ problem }) {
|
|
|
59
56
|
] })
|
|
60
57
|
] })
|
|
61
58
|
}
|
|
62
|
-
)
|
|
59
|
+
);
|
|
63
60
|
}
|
|
64
61
|
|
|
65
62
|
// src/hooks/use-fetch-problem.ts
|
|
@@ -87,7 +84,7 @@ function getProjectRoot() {
|
|
|
87
84
|
return join(__dirname, "../..");
|
|
88
85
|
}
|
|
89
86
|
async function generateProblemFiles(problem, language = "python") {
|
|
90
|
-
const problemDir =
|
|
87
|
+
const problemDir = getSolvingDirPath(problem.id, process.cwd(), problem);
|
|
91
88
|
await mkdir(problemDir, { recursive: true });
|
|
92
89
|
const langConfig = getLanguageConfig(language);
|
|
93
90
|
const projectRoot = getProjectRoot();
|
|
@@ -189,6 +186,7 @@ ${tags}
|
|
|
189
186
|
id: problem.id,
|
|
190
187
|
title: problem.title,
|
|
191
188
|
level: problem.level,
|
|
189
|
+
tags: problem.tags,
|
|
192
190
|
timeLimit: problem.timeLimit,
|
|
193
191
|
timeLimitMs: parseTimeLimitToMs(problem.timeLimit),
|
|
194
192
|
memoryLimit: problem.memoryLimit
|
package/dist/commands/init.js
CHANGED
|
@@ -3,12 +3,14 @@ import {
|
|
|
3
3
|
Command,
|
|
4
4
|
CommandBuilder,
|
|
5
5
|
CommandDef,
|
|
6
|
+
getArchiveStrategy,
|
|
6
7
|
getAutoOpenEditor,
|
|
7
8
|
getDefaultLanguage,
|
|
8
9
|
getEditor,
|
|
9
10
|
getProblemDir,
|
|
10
|
-
getSolvedAcHandle
|
|
11
|
-
|
|
11
|
+
getSolvedAcHandle,
|
|
12
|
+
getSolvingDir
|
|
13
|
+
} from "../chunk-TNGUME4H.js";
|
|
12
14
|
import {
|
|
13
15
|
__decorateClass,
|
|
14
16
|
getSupportedLanguages
|
|
@@ -35,6 +37,8 @@ function useInit({ onComplete }) {
|
|
|
35
37
|
const [confirmExit, setConfirmExit] = useState(false);
|
|
36
38
|
const [initialized, setInitialized] = useState(false);
|
|
37
39
|
const [problemDir, setProblemDirValue] = useState(getProblemDir());
|
|
40
|
+
const [solvingDir, setSolvingDirValue] = useState(getSolvingDir());
|
|
41
|
+
const [archiveStrategy, setArchiveStrategy] = useState(getArchiveStrategy());
|
|
38
42
|
const [language, setLanguage] = useState(getDefaultLanguage());
|
|
39
43
|
const [editor, setEditorValue] = useState(getEditor());
|
|
40
44
|
const [autoOpen, setAutoOpen] = useState(getAutoOpenEditor());
|
|
@@ -69,6 +73,10 @@ function useInit({ onComplete }) {
|
|
|
69
73
|
const projectConfig = JSON.parse(configContent);
|
|
70
74
|
if (projectConfig.problemDir)
|
|
71
75
|
setProblemDirValue(projectConfig.problemDir);
|
|
76
|
+
if (projectConfig.solvingDir)
|
|
77
|
+
setSolvingDirValue(projectConfig.solvingDir);
|
|
78
|
+
if (projectConfig.archiveStrategy)
|
|
79
|
+
setArchiveStrategy(projectConfig.archiveStrategy);
|
|
72
80
|
if (projectConfig.defaultLanguage)
|
|
73
81
|
setLanguage(projectConfig.defaultLanguage);
|
|
74
82
|
if (projectConfig.editor) setEditorValue(projectConfig.editor);
|
|
@@ -86,7 +94,11 @@ function useInit({ onComplete }) {
|
|
|
86
94
|
const getStepLabel = useCallback((step) => {
|
|
87
95
|
switch (step) {
|
|
88
96
|
case "problem-dir":
|
|
89
|
-
return "\uBB38\uC81C \uB514\uB809\uD1A0\uB9AC \uC124\uC815";
|
|
97
|
+
return "\uBB38\uC81C \uB514\uB809\uD1A0\uB9AC \uC124\uC815 (\uC544\uCE74\uC774\uBE0C\uB41C \uBB38\uC81C)";
|
|
98
|
+
case "solving-dir":
|
|
99
|
+
return "Solving \uB514\uB809\uD1A0\uB9AC \uC124\uC815 (\uD478\uB294 \uC911\uC778 \uBB38\uC81C)";
|
|
100
|
+
case "archive-strategy":
|
|
101
|
+
return "\uC544\uCE74\uC774\uBE59 \uC804\uB7B5 \uC124\uC815";
|
|
90
102
|
case "language":
|
|
91
103
|
return "\uAE30\uBCF8 \uC5B8\uC5B4 \uC124\uC815";
|
|
92
104
|
case "editor":
|
|
@@ -104,6 +116,17 @@ function useInit({ onComplete }) {
|
|
|
104
116
|
switch (step) {
|
|
105
117
|
case "problem-dir":
|
|
106
118
|
return problemDir === "." ? "\uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8" : problemDir;
|
|
119
|
+
case "solving-dir":
|
|
120
|
+
return solvingDir === "." ? "\uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8" : solvingDir;
|
|
121
|
+
case "archive-strategy": {
|
|
122
|
+
const strategyLabels = {
|
|
123
|
+
flat: "\uD3C9\uBA74 (\uC804\uBD80 \uB098\uC5F4)",
|
|
124
|
+
"by-range": "1000\uBC88\uB300 \uBB36\uAE30",
|
|
125
|
+
"by-tier": "\uD2F0\uC5B4\uBCC4",
|
|
126
|
+
"by-tag": "\uD0DC\uADF8\uBCC4"
|
|
127
|
+
};
|
|
128
|
+
return strategyLabels[archiveStrategy] || archiveStrategy;
|
|
129
|
+
}
|
|
107
130
|
case "language":
|
|
108
131
|
return language;
|
|
109
132
|
case "editor":
|
|
@@ -116,121 +139,170 @@ function useInit({ onComplete }) {
|
|
|
116
139
|
return "";
|
|
117
140
|
}
|
|
118
141
|
},
|
|
119
|
-
[
|
|
142
|
+
[
|
|
143
|
+
problemDir,
|
|
144
|
+
solvingDir,
|
|
145
|
+
archiveStrategy,
|
|
146
|
+
language,
|
|
147
|
+
editor,
|
|
148
|
+
autoOpen,
|
|
149
|
+
handle
|
|
150
|
+
]
|
|
120
151
|
);
|
|
121
|
-
const executeInit = useCallback(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
"
|
|
136
|
-
|
|
137
|
-
setCreated((prev) => [...prev, ".ps-cli.json"]);
|
|
138
|
-
if (problemDir !== "." && problemDir !== "") {
|
|
139
|
-
const problemDirPath = join(cwd, problemDir);
|
|
140
|
-
try {
|
|
141
|
-
await mkdir(problemDirPath, { recursive: true });
|
|
142
|
-
setCreated((prev) => [...prev, `${problemDir}/`]);
|
|
143
|
-
} catch (err) {
|
|
144
|
-
const error = err;
|
|
145
|
-
if (error.code !== "EEXIST") {
|
|
146
|
-
throw err;
|
|
147
|
-
}
|
|
152
|
+
const executeInit = useCallback(
|
|
153
|
+
async (overrideHandle) => {
|
|
154
|
+
try {
|
|
155
|
+
const cwd = process.cwd();
|
|
156
|
+
const projectConfigPath = join(cwd, ".ps-cli.json");
|
|
157
|
+
const projectConfig = {
|
|
158
|
+
problemDir,
|
|
159
|
+
solvingDir,
|
|
160
|
+
archiveStrategy,
|
|
161
|
+
defaultLanguage: language,
|
|
162
|
+
editor,
|
|
163
|
+
autoOpenEditor: autoOpen
|
|
164
|
+
};
|
|
165
|
+
const handleToUse = overrideHandle ?? handle;
|
|
166
|
+
if (handleToUse && typeof handleToUse === "string" && handleToUse.trim().length > 0) {
|
|
167
|
+
projectConfig.solvedAcHandle = handleToUse.trim();
|
|
148
168
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
await
|
|
159
|
-
setCreated((prev) => [...prev,
|
|
169
|
+
await writeFile(
|
|
170
|
+
projectConfigPath,
|
|
171
|
+
JSON.stringify(projectConfig, null, 2),
|
|
172
|
+
"utf-8"
|
|
173
|
+
);
|
|
174
|
+
setCreated((prev) => [...prev, ".ps-cli.json"]);
|
|
175
|
+
if (problemDir !== "." && problemDir !== "") {
|
|
176
|
+
const problemDirPath = join(cwd, problemDir);
|
|
177
|
+
try {
|
|
178
|
+
await mkdir(problemDirPath, { recursive: true });
|
|
179
|
+
setCreated((prev) => [...prev, `${problemDir}/`]);
|
|
180
|
+
} catch (err) {
|
|
181
|
+
const error = err;
|
|
182
|
+
if (error.code !== "EEXIST") {
|
|
183
|
+
throw err;
|
|
184
|
+
}
|
|
160
185
|
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
} else {
|
|
173
|
-
console.warn(".gitignore \uC5C5\uB370\uC774\uD2B8 \uC2E4\uD328:", error.message);
|
|
186
|
+
}
|
|
187
|
+
if (solvingDir !== "." && solvingDir !== "") {
|
|
188
|
+
const solvingDirPath = join(cwd, solvingDir);
|
|
189
|
+
try {
|
|
190
|
+
await mkdir(solvingDirPath, { recursive: true });
|
|
191
|
+
setCreated((prev) => [...prev, `${solvingDir}/`]);
|
|
192
|
+
} catch (err) {
|
|
193
|
+
const error = err;
|
|
194
|
+
if (error.code !== "EEXIST") {
|
|
195
|
+
throw err;
|
|
196
|
+
}
|
|
174
197
|
}
|
|
175
198
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
try {
|
|
181
|
-
await access(gitDir);
|
|
182
|
-
isGitRepo = true;
|
|
183
|
-
} catch {
|
|
199
|
+
const gitignorePath = join(cwd, ".gitignore");
|
|
200
|
+
const gitignorePatterns = [];
|
|
201
|
+
if (solvingDir !== "." && solvingDir !== "") {
|
|
202
|
+
gitignorePatterns.push(`${solvingDir}/`);
|
|
184
203
|
}
|
|
185
|
-
if (
|
|
186
|
-
|
|
187
|
-
|
|
204
|
+
if (gitignorePatterns.length > 0) {
|
|
205
|
+
try {
|
|
206
|
+
const gitignoreContent = await readFile(gitignorePath, "utf-8");
|
|
207
|
+
let updatedContent = gitignoreContent.trim();
|
|
208
|
+
let hasChanges = false;
|
|
209
|
+
for (const pattern of gitignorePatterns) {
|
|
210
|
+
if (!gitignoreContent.includes(pattern)) {
|
|
211
|
+
updatedContent += (updatedContent ? "\n" : "") + `# ps-cli \uBB38\uC81C \uB514\uB809\uD1A0\uB9AC
|
|
212
|
+
${pattern}`;
|
|
213
|
+
hasChanges = true;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (hasChanges) {
|
|
217
|
+
await writeFile(gitignorePath, updatedContent + "\n", "utf-8");
|
|
218
|
+
setCreated((prev) => [...prev, ".gitignore \uC5C5\uB370\uC774\uD2B8"]);
|
|
219
|
+
}
|
|
220
|
+
} catch (err) {
|
|
221
|
+
const error = err;
|
|
222
|
+
if (error.code === "ENOENT") {
|
|
223
|
+
const content = `# ps-cli \uBB38\uC81C \uB514\uB809\uD1A0\uB9AC
|
|
224
|
+
${gitignorePatterns.join("\n")}
|
|
225
|
+
`;
|
|
226
|
+
await writeFile(gitignorePath, content, "utf-8");
|
|
227
|
+
setCreated((prev) => [...prev, ".gitignore \uC0DD\uC131"]);
|
|
228
|
+
} else {
|
|
229
|
+
console.warn(".gitignore \uC5C5\uB370\uC774\uD2B8 \uC2E4\uD328:", error.message);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
188
232
|
}
|
|
189
|
-
const filesToAdd = [".ps-cli.json"];
|
|
190
|
-
const gitignorePath = join(cwd, ".gitignore");
|
|
191
233
|
try {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
} catch {
|
|
195
|
-
}
|
|
196
|
-
if (filesToAdd.length > 0) {
|
|
197
|
-
await execa("git", ["add", ...filesToAdd], { cwd });
|
|
234
|
+
const gitDir = join(cwd, ".git");
|
|
235
|
+
let isGitRepo = false;
|
|
198
236
|
try {
|
|
199
|
-
await
|
|
237
|
+
await access(gitDir);
|
|
238
|
+
isGitRepo = true;
|
|
200
239
|
} catch {
|
|
201
|
-
await execa(
|
|
202
|
-
"git",
|
|
203
|
-
["commit", "-m", "chore: ps-cli \uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654"],
|
|
204
|
-
{ cwd }
|
|
205
|
-
);
|
|
206
|
-
setCreated((prev) => [...prev, "\uCD08\uAE30 \uCEE4\uBC0B \uC0DD\uC131"]);
|
|
207
240
|
}
|
|
241
|
+
if (!isGitRepo) {
|
|
242
|
+
await execaCommand("git init", { cwd });
|
|
243
|
+
setCreated((prev) => [...prev, "Git \uC800\uC7A5\uC18C \uCD08\uAE30\uD654"]);
|
|
244
|
+
}
|
|
245
|
+
const filesToAdd = [".ps-cli.json"];
|
|
246
|
+
const gitignorePath2 = join(cwd, ".gitignore");
|
|
247
|
+
try {
|
|
248
|
+
await access(gitignorePath2);
|
|
249
|
+
filesToAdd.push(".gitignore");
|
|
250
|
+
} catch {
|
|
251
|
+
}
|
|
252
|
+
if (filesToAdd.length > 0) {
|
|
253
|
+
await execa("git", ["add", ...filesToAdd], { cwd });
|
|
254
|
+
try {
|
|
255
|
+
await execa("git", ["rev-parse", "--verify", "HEAD"], { cwd });
|
|
256
|
+
} catch {
|
|
257
|
+
await execa(
|
|
258
|
+
"git",
|
|
259
|
+
["commit", "-m", "chore: ps-cli \uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654"],
|
|
260
|
+
{ cwd }
|
|
261
|
+
);
|
|
262
|
+
setCreated((prev) => [...prev, "\uCD08\uAE30 \uCEE4\uBC0B \uC0DD\uC131"]);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
} catch (err) {
|
|
266
|
+
const error = err;
|
|
267
|
+
console.warn("Git \uC5F0\uB3D9 \uC2E4\uD328:", error.message);
|
|
208
268
|
}
|
|
269
|
+
setTimeout(() => {
|
|
270
|
+
onComplete();
|
|
271
|
+
}, 3e3);
|
|
209
272
|
} catch (err) {
|
|
210
273
|
const error = err;
|
|
211
|
-
console.
|
|
274
|
+
console.error("\uCD08\uAE30\uD654 \uC911 \uC624\uB958 \uBC1C\uC0DD:", error.message);
|
|
275
|
+
setCancelled(true);
|
|
276
|
+
setCurrentStep("cancelled");
|
|
277
|
+
setTimeout(() => {
|
|
278
|
+
onComplete();
|
|
279
|
+
}, 2e3);
|
|
212
280
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}, [problemDir, language, editor, autoOpen, handle, onComplete]);
|
|
281
|
+
},
|
|
282
|
+
[
|
|
283
|
+
problemDir,
|
|
284
|
+
solvingDir,
|
|
285
|
+
archiveStrategy,
|
|
286
|
+
language,
|
|
287
|
+
editor,
|
|
288
|
+
autoOpen,
|
|
289
|
+
handle,
|
|
290
|
+
onComplete
|
|
291
|
+
]
|
|
292
|
+
);
|
|
226
293
|
const moveToNextStep = useCallback(
|
|
227
|
-
(selectedValue, stepLabel) => {
|
|
294
|
+
(selectedValue, stepLabel, handleValue) => {
|
|
228
295
|
setCompletedSteps((prev) => [
|
|
229
296
|
...prev,
|
|
230
297
|
{ label: stepLabel, value: selectedValue }
|
|
231
298
|
]);
|
|
299
|
+
if (currentStep === "handle" && handleValue !== void 0) {
|
|
300
|
+
setHandle(handleValue);
|
|
301
|
+
}
|
|
232
302
|
const stepOrder = [
|
|
233
303
|
"problem-dir",
|
|
304
|
+
"solving-dir",
|
|
305
|
+
"archive-strategy",
|
|
234
306
|
"language",
|
|
235
307
|
"editor",
|
|
236
308
|
"auto-open",
|
|
@@ -242,11 +314,25 @@ ${gitignorePattern}
|
|
|
242
314
|
const nextStep = stepOrder[currentIndex + 1];
|
|
243
315
|
setCurrentStep(nextStep);
|
|
244
316
|
if (nextStep === "done") {
|
|
245
|
-
void
|
|
317
|
+
if (currentStep === "handle" && handleValue !== void 0) {
|
|
318
|
+
void executeInit(handleValue.trim());
|
|
319
|
+
} else {
|
|
320
|
+
void executeInit();
|
|
321
|
+
}
|
|
246
322
|
}
|
|
247
323
|
}
|
|
248
324
|
},
|
|
249
|
-
[
|
|
325
|
+
[
|
|
326
|
+
currentStep,
|
|
327
|
+
executeInit,
|
|
328
|
+
problemDir,
|
|
329
|
+
solvingDir,
|
|
330
|
+
archiveStrategy,
|
|
331
|
+
language,
|
|
332
|
+
editor,
|
|
333
|
+
autoOpen,
|
|
334
|
+
onComplete
|
|
335
|
+
]
|
|
250
336
|
);
|
|
251
337
|
return {
|
|
252
338
|
currentStep,
|
|
@@ -254,6 +340,8 @@ ${gitignorePattern}
|
|
|
254
340
|
confirmExit,
|
|
255
341
|
initialized,
|
|
256
342
|
problemDir,
|
|
343
|
+
solvingDir,
|
|
344
|
+
archiveStrategy,
|
|
257
345
|
language,
|
|
258
346
|
editor,
|
|
259
347
|
autoOpen,
|
|
@@ -262,6 +350,8 @@ ${gitignorePattern}
|
|
|
262
350
|
created,
|
|
263
351
|
cancelled,
|
|
264
352
|
setProblemDirValue,
|
|
353
|
+
setSolvingDirValue,
|
|
354
|
+
setArchiveStrategy,
|
|
265
355
|
setLanguage,
|
|
266
356
|
setEditorValue,
|
|
267
357
|
setAutoOpen,
|
|
@@ -288,6 +378,8 @@ function InitView({ onComplete }) {
|
|
|
288
378
|
created,
|
|
289
379
|
cancelled,
|
|
290
380
|
setProblemDirValue,
|
|
381
|
+
setSolvingDirValue,
|
|
382
|
+
setArchiveStrategy,
|
|
291
383
|
setLanguage,
|
|
292
384
|
setEditorValue,
|
|
293
385
|
setAutoOpen,
|
|
@@ -352,6 +444,56 @@ function InitView({ onComplete }) {
|
|
|
352
444
|
)
|
|
353
445
|
);
|
|
354
446
|
}
|
|
447
|
+
case "solving-dir": {
|
|
448
|
+
const options = [
|
|
449
|
+
{ label: "solving", value: "solving" },
|
|
450
|
+
{ label: ". (\uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8)", value: "." }
|
|
451
|
+
];
|
|
452
|
+
return renderQuestionCard(
|
|
453
|
+
getStepLabel(currentStep),
|
|
454
|
+
/* @__PURE__ */ jsx(
|
|
455
|
+
Select,
|
|
456
|
+
{
|
|
457
|
+
options,
|
|
458
|
+
onChange: (value) => {
|
|
459
|
+
setSolvingDirValue(value);
|
|
460
|
+
const displayValue = value === "." ? "\uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8" : value;
|
|
461
|
+
moveToNextStep(displayValue, getStepLabel(currentStep));
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
)
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
case "archive-strategy": {
|
|
468
|
+
const options = [
|
|
469
|
+
{ label: "\uD3C9\uBA74 (\uC804\uBD80 \uB098\uC5F4)", value: "flat" },
|
|
470
|
+
{ label: "1000\uBC88\uB300 \uBB36\uAE30", value: "by-range" },
|
|
471
|
+
{ label: "\uD2F0\uC5B4\uBCC4", value: "by-tier" },
|
|
472
|
+
{ label: "\uD0DC\uADF8\uBCC4", value: "by-tag" }
|
|
473
|
+
];
|
|
474
|
+
return renderQuestionCard(
|
|
475
|
+
getStepLabel(currentStep),
|
|
476
|
+
/* @__PURE__ */ jsx(
|
|
477
|
+
Select,
|
|
478
|
+
{
|
|
479
|
+
options,
|
|
480
|
+
onChange: (value) => {
|
|
481
|
+
setArchiveStrategy(value);
|
|
482
|
+
const strategyLabels = {
|
|
483
|
+
flat: "\uD3C9\uBA74 (\uC804\uBD80 \uB098\uC5F4)",
|
|
484
|
+
"by-range": "1000\uBC88\uB300 \uBB36\uAE30",
|
|
485
|
+
"by-tier": "\uD2F0\uC5B4\uBCC4",
|
|
486
|
+
"by-tag": "\uD0DC\uADF8\uBCC4"
|
|
487
|
+
};
|
|
488
|
+
moveToNextStep(
|
|
489
|
+
strategyLabels[value] || value,
|
|
490
|
+
getStepLabel(currentStep)
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
)
|
|
495
|
+
);
|
|
496
|
+
}
|
|
355
497
|
case "language": {
|
|
356
498
|
const supportedLanguages = getSupportedLanguages();
|
|
357
499
|
const options = supportedLanguages.map((lang) => ({
|
|
@@ -424,9 +566,14 @@ function InitView({ onComplete }) {
|
|
|
424
566
|
{
|
|
425
567
|
placeholder: "\uD578\uB4E4 \uC785\uB825",
|
|
426
568
|
onSubmit: (value) => {
|
|
427
|
-
|
|
569
|
+
const handleValue = value.trim();
|
|
570
|
+
setHandle(handleValue);
|
|
428
571
|
setHandleInputMode(false);
|
|
429
|
-
moveToNextStep(
|
|
572
|
+
moveToNextStep(
|
|
573
|
+
handleValue || "(\uC2A4\uD0B5)",
|
|
574
|
+
getStepLabel(currentStep),
|
|
575
|
+
handleValue
|
|
576
|
+
);
|
|
430
577
|
}
|
|
431
578
|
}
|
|
432
579
|
) })
|
package/dist/commands/open.js
CHANGED