@rhseung/ps-cli 1.7.5 → 1.8.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/README.md +18 -5
- package/dist/{chunk-GCOFFYJ3.js → chunk-3LR2NGRC.js} +12 -4
- package/dist/{chunk-F4LZ6ENP.js → chunk-JPDN34C7.js} +67 -3
- package/dist/chunk-PY6GW22W.js +13 -0
- package/dist/{chunk-A6STXEAE.js → chunk-QB2R47PW.js} +8 -1
- package/dist/commands/archive.js +25 -14
- package/dist/commands/config.js +56 -2
- package/dist/commands/fetch.js +14 -12
- package/dist/commands/init.js +1 -1
- package/dist/commands/open.js +56 -12
- package/dist/commands/run.js +18 -18
- package/dist/commands/search.js +51 -19
- package/dist/commands/stats.js +119 -37
- package/dist/commands/submit.js +13 -11
- package/dist/commands/test.js +19 -19
- package/dist/index.js +77 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -188,7 +188,7 @@ ps submit --language python # Python으로 제출
|
|
|
188
188
|
|
|
189
189
|
### `archive` - 아카이빙
|
|
190
190
|
|
|
191
|
-
solving 디렉토리의 문제를 archive 디렉토리로 이동하고 Git 커밋을 생성합니다.
|
|
191
|
+
solving 디렉토리의 문제를 archive 디렉토리로 이동하고 (선택적으로) Git 커밋을 생성합니다.
|
|
192
192
|
|
|
193
193
|
**사용법:**
|
|
194
194
|
|
|
@@ -206,31 +206,42 @@ ps archive # 현재 디렉토리에서 문제 번호 자동
|
|
|
206
206
|
**설명:**
|
|
207
207
|
|
|
208
208
|
- solving 디렉토리에서 문제를 찾아 archive 디렉토리로 이동
|
|
209
|
-
- Git add 및 commit 실행
|
|
210
|
-
- 커밋 메시지: "solve: {
|
|
209
|
+
- 설정에 따라 Git add 및 commit 실행
|
|
210
|
+
- 기본 커밋 메시지: "solve: {id} - {title}"
|
|
211
|
+
- `archive-auto-commit` 이 `true` 인 경우, **archive 디렉토리로 이동 후** Git 커밋을 시도하며, 커밋 실패 시 다시 원래 위치로 되돌림 (롤백)
|
|
212
|
+
- `archive-auto-commit` 이 `false` 인 경우, Git 커밋 없이 디렉토리만 이동
|
|
211
213
|
|
|
212
214
|
---
|
|
213
215
|
|
|
214
216
|
### `open` - 문제 페이지 열기
|
|
215
217
|
|
|
216
|
-
백준 문제 페이지를 브라우저로 엽니다.
|
|
218
|
+
백준 문제 페이지 또는 문제집 페이지를 브라우저로 엽니다.
|
|
217
219
|
|
|
218
220
|
**사용법:**
|
|
219
221
|
|
|
220
222
|
```bash
|
|
221
223
|
ps open [문제번호]
|
|
224
|
+
ps open --workbook <문제집ID>
|
|
225
|
+
ps open -w <문제집ID>
|
|
222
226
|
```
|
|
223
227
|
|
|
228
|
+
**옵션:**
|
|
229
|
+
|
|
230
|
+
- `--workbook`, `-w`: 문제집 ID를 지정하여 해당 문제집 페이지를 엽니다
|
|
231
|
+
|
|
224
232
|
**예제:**
|
|
225
233
|
|
|
226
234
|
```bash
|
|
227
235
|
ps open 1000 # 1000번 문제 열기
|
|
228
236
|
ps open # 문제 디렉토리에서 실행 시 자동 추론
|
|
237
|
+
ps open --workbook 25052 # 문제집 25052 열기
|
|
238
|
+
ps open -w 25052 # 문제집 25052 열기 (단축 옵션)
|
|
229
239
|
```
|
|
230
240
|
|
|
231
241
|
**설명:**
|
|
232
242
|
|
|
233
243
|
- 문제 번호를 인자로 전달하거나 문제 디렉토리에서 실행하면 자동으로 문제 번호를 추론
|
|
244
|
+
- `--workbook` 또는 `-w` 옵션으로 문제집 페이지를 열 수 있습니다
|
|
234
245
|
|
|
235
246
|
---
|
|
236
247
|
|
|
@@ -347,6 +358,8 @@ ps config clear # .ps-cli.json 파일 삭제
|
|
|
347
358
|
- `archive-dir`: 아카이브된 문제 디렉토리 (기본값: problems)
|
|
348
359
|
- `solving-dir`: 푸는 중인 문제 디렉토리 (기본값: solving)
|
|
349
360
|
- `archive-strategy`: 아카이빙 전략
|
|
361
|
+
- `archive-auto-commit`: archive 실행 시 Git 커밋 자동 실행 여부 (true/false, 기본값: true)
|
|
362
|
+
- `archive-commit-message`: archive 시 사용할 Git 커밋 메시지 템플릿 (`{id}`, `{title}` 사용 가능, 기본값: `solve: {id} - {title}`)
|
|
350
363
|
|
|
351
364
|
### 아카이빙 전략
|
|
352
365
|
|
|
@@ -416,7 +429,7 @@ node dist/index.js init
|
|
|
416
429
|
```bash
|
|
417
430
|
# 프로젝트 디렉토리에서
|
|
418
431
|
bun run build
|
|
419
|
-
|
|
432
|
+
bun link
|
|
420
433
|
|
|
421
434
|
# 외부 폴더에서 테스트
|
|
422
435
|
cd /path/to/test-project
|
|
@@ -8,6 +8,7 @@ import { useEffect, useState } from "react";
|
|
|
8
8
|
var BOJ_BASE_URL = "https://www.acmicpc.net";
|
|
9
9
|
function useOpenBrowser({
|
|
10
10
|
problemId,
|
|
11
|
+
workbookId,
|
|
11
12
|
onComplete
|
|
12
13
|
}) {
|
|
13
14
|
const [status, setStatus] = useState(
|
|
@@ -18,9 +19,16 @@ function useOpenBrowser({
|
|
|
18
19
|
useEffect(() => {
|
|
19
20
|
async function handleOpenBrowser() {
|
|
20
21
|
try {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
let targetUrl;
|
|
23
|
+
if (workbookId !== void 0) {
|
|
24
|
+
targetUrl = `${BOJ_BASE_URL}/workbook/view/${workbookId}`;
|
|
25
|
+
} else if (problemId !== void 0) {
|
|
26
|
+
targetUrl = `${BOJ_BASE_URL}/problem/${problemId}`;
|
|
27
|
+
} else {
|
|
28
|
+
throw new Error("\uBB38\uC81C \uBC88\uD638 \uB610\uB294 \uBB38\uC81C\uC9D1 ID\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.");
|
|
29
|
+
}
|
|
30
|
+
setUrl(targetUrl);
|
|
31
|
+
await openBrowser(targetUrl);
|
|
24
32
|
setStatus("success");
|
|
25
33
|
setTimeout(() => {
|
|
26
34
|
onComplete?.();
|
|
@@ -34,7 +42,7 @@ function useOpenBrowser({
|
|
|
34
42
|
}
|
|
35
43
|
}
|
|
36
44
|
void handleOpenBrowser();
|
|
37
|
-
}, [problemId, onComplete]);
|
|
45
|
+
}, [problemId, workbookId, onComplete]);
|
|
38
46
|
return {
|
|
39
47
|
status,
|
|
40
48
|
error,
|
|
@@ -9926,8 +9926,9 @@ var config = new Conf({
|
|
|
9926
9926
|
solvedAcHandle: void 0,
|
|
9927
9927
|
archiveDir: "problems",
|
|
9928
9928
|
// 기본값: problems 디렉토리
|
|
9929
|
-
solvingDir: "solving"
|
|
9929
|
+
solvingDir: "solving",
|
|
9930
9930
|
// 기본값: solving 디렉토리
|
|
9931
|
+
archiveAutoCommit: true
|
|
9931
9932
|
}
|
|
9932
9933
|
});
|
|
9933
9934
|
var projectConfigCache = null;
|
|
@@ -10030,6 +10031,24 @@ function getArchiveStrategy() {
|
|
|
10030
10031
|
}
|
|
10031
10032
|
return config.get("archiveStrategy") ?? "flat";
|
|
10032
10033
|
}
|
|
10034
|
+
function getArchiveAutoCommit() {
|
|
10035
|
+
const projectConfig = getProjectConfigSync();
|
|
10036
|
+
if (projectConfig?.archiveAutoCommit !== void 0) {
|
|
10037
|
+
return projectConfig.archiveAutoCommit;
|
|
10038
|
+
}
|
|
10039
|
+
const globalValue = config.get("archiveAutoCommit");
|
|
10040
|
+
if (globalValue !== void 0) {
|
|
10041
|
+
return globalValue;
|
|
10042
|
+
}
|
|
10043
|
+
return true;
|
|
10044
|
+
}
|
|
10045
|
+
function getArchiveCommitMessage() {
|
|
10046
|
+
const projectConfig = getProjectConfigSync();
|
|
10047
|
+
if (projectConfig?.archiveCommitMessage !== void 0) {
|
|
10048
|
+
return projectConfig.archiveCommitMessage;
|
|
10049
|
+
}
|
|
10050
|
+
return config.get("archiveCommitMessage");
|
|
10051
|
+
}
|
|
10033
10052
|
|
|
10034
10053
|
// src/utils/tier.ts
|
|
10035
10054
|
import gradient from "gradient-string";
|
|
@@ -10067,6 +10086,40 @@ var TIER_NAMES = [
|
|
|
10067
10086
|
"Ruby I",
|
|
10068
10087
|
"Master"
|
|
10069
10088
|
];
|
|
10089
|
+
var TIER_SHORT_NAMES = [
|
|
10090
|
+
void 0,
|
|
10091
|
+
"B5",
|
|
10092
|
+
"B4",
|
|
10093
|
+
"B3",
|
|
10094
|
+
"B2",
|
|
10095
|
+
"B1",
|
|
10096
|
+
"S5",
|
|
10097
|
+
"S4",
|
|
10098
|
+
"S3",
|
|
10099
|
+
"S2",
|
|
10100
|
+
"S1",
|
|
10101
|
+
"G5",
|
|
10102
|
+
"G4",
|
|
10103
|
+
"G3",
|
|
10104
|
+
"G2",
|
|
10105
|
+
"G1",
|
|
10106
|
+
"P5",
|
|
10107
|
+
"P4",
|
|
10108
|
+
"P3",
|
|
10109
|
+
"P2",
|
|
10110
|
+
"P1",
|
|
10111
|
+
"D5",
|
|
10112
|
+
"D4",
|
|
10113
|
+
"D3",
|
|
10114
|
+
"D2",
|
|
10115
|
+
"D1",
|
|
10116
|
+
"R5",
|
|
10117
|
+
"R4",
|
|
10118
|
+
"R3",
|
|
10119
|
+
"R2",
|
|
10120
|
+
"R1",
|
|
10121
|
+
"M"
|
|
10122
|
+
];
|
|
10070
10123
|
var TIER_COLORS = [
|
|
10071
10124
|
void 0,
|
|
10072
10125
|
"#9d4900",
|
|
@@ -10213,6 +10266,13 @@ function getTierName(level) {
|
|
|
10213
10266
|
}
|
|
10214
10267
|
return "Unrated";
|
|
10215
10268
|
}
|
|
10269
|
+
function getTierShortName(level) {
|
|
10270
|
+
if (level === 0) return "UR";
|
|
10271
|
+
if (level >= 1 && level < TIER_SHORT_NAMES.length) {
|
|
10272
|
+
return TIER_SHORT_NAMES[level] || "UR";
|
|
10273
|
+
}
|
|
10274
|
+
return "UR";
|
|
10275
|
+
}
|
|
10216
10276
|
function getTierColor(level) {
|
|
10217
10277
|
if (level === 0) return "#2d2d2d";
|
|
10218
10278
|
if (level === 31) {
|
|
@@ -10248,7 +10308,7 @@ function getArchiveSubPath(problemId, strategy = "flat", problem) {
|
|
|
10248
10308
|
return String(range).padStart(5, "0");
|
|
10249
10309
|
}
|
|
10250
10310
|
case "by-tier": {
|
|
10251
|
-
if (!problem) {
|
|
10311
|
+
if (!problem || problem.level === void 0) {
|
|
10252
10312
|
return "";
|
|
10253
10313
|
}
|
|
10254
10314
|
return getTierDirName(problem.level);
|
|
@@ -10508,7 +10568,8 @@ var CommandBuilder = class {
|
|
|
10508
10568
|
return {
|
|
10509
10569
|
name: finalMetadata.name,
|
|
10510
10570
|
help,
|
|
10511
|
-
execute: wrappedExecute
|
|
10571
|
+
execute: wrappedExecute,
|
|
10572
|
+
metadata: finalMetadata
|
|
10512
10573
|
};
|
|
10513
10574
|
}
|
|
10514
10575
|
/**
|
|
@@ -10597,9 +10658,12 @@ export {
|
|
|
10597
10658
|
getArchiveDir,
|
|
10598
10659
|
getSolvingDir,
|
|
10599
10660
|
getArchiveStrategy,
|
|
10661
|
+
getArchiveAutoCommit,
|
|
10662
|
+
getArchiveCommitMessage,
|
|
10600
10663
|
getNextTierMinRating,
|
|
10601
10664
|
calculateTierProgress,
|
|
10602
10665
|
getTierName,
|
|
10666
|
+
getTierShortName,
|
|
10603
10667
|
getTierColor,
|
|
10604
10668
|
getTierImageUrl,
|
|
10605
10669
|
detectProblemIdFromPath,
|
|
@@ -47,8 +47,15 @@ async function getUserStats(handle) {
|
|
|
47
47
|
const data = await response.json();
|
|
48
48
|
return data;
|
|
49
49
|
}
|
|
50
|
+
async function getUserTop100(handle) {
|
|
51
|
+
const url = `${BASE_URL}/user/top_100?handle=${handle}`;
|
|
52
|
+
const response = await fetchWithRetry(url);
|
|
53
|
+
const data = await response.json();
|
|
54
|
+
return data.items || [];
|
|
55
|
+
}
|
|
50
56
|
|
|
51
57
|
export {
|
|
52
58
|
getProblem,
|
|
53
|
-
getUserStats
|
|
59
|
+
getUserStats,
|
|
60
|
+
getUserTop100
|
|
54
61
|
};
|
package/dist/commands/archive.js
CHANGED
|
@@ -4,11 +4,13 @@ import {
|
|
|
4
4
|
CommandBuilder,
|
|
5
5
|
CommandDef,
|
|
6
6
|
findProjectRoot,
|
|
7
|
+
getArchiveAutoCommit,
|
|
8
|
+
getArchiveCommitMessage,
|
|
7
9
|
getArchiveDirPath,
|
|
8
10
|
getSolvingDir,
|
|
9
11
|
getSolvingDirPath,
|
|
10
12
|
resolveProblemContext
|
|
11
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-JPDN34C7.js";
|
|
12
14
|
import {
|
|
13
15
|
__decorateClass
|
|
14
16
|
} from "../chunk-7MQMPJ3X.js";
|
|
@@ -82,11 +84,33 @@ function useArchive({
|
|
|
82
84
|
throw err;
|
|
83
85
|
}
|
|
84
86
|
}
|
|
87
|
+
const autoCommit = getArchiveAutoCommit();
|
|
88
|
+
const template = getArchiveCommitMessage() ?? "solve: {id} - {title}";
|
|
89
|
+
const commitMessage = template.replace("{id}", String(problemId)).replace("{title}", problemTitle);
|
|
85
90
|
const archiveDirParent = dirname(archiveDir);
|
|
86
91
|
setMessage("\uC544\uCE74\uC774\uBE0C \uB514\uB809\uD1A0\uB9AC\uB97C \uC900\uBE44\uD558\uB294 \uC911...");
|
|
87
92
|
await mkdir(archiveDirParent, { recursive: true });
|
|
88
93
|
setMessage("\uBB38\uC81C\uB97C archive \uB514\uB809\uD1A0\uB9AC\uB85C \uC774\uB3D9\uD558\uB294 \uC911...");
|
|
89
94
|
await rename(solvingDir, archiveDir);
|
|
95
|
+
if (autoCommit) {
|
|
96
|
+
try {
|
|
97
|
+
setMessage("Git \uCEE4\uBC0B\uC744 \uC2E4\uD589\uD558\uB294 \uC911...");
|
|
98
|
+
await execa("git", ["add", archiveDir], { cwd: projectRoot });
|
|
99
|
+
await execa("git", ["commit", "-m", commitMessage], {
|
|
100
|
+
cwd: projectRoot
|
|
101
|
+
});
|
|
102
|
+
} catch (gitError) {
|
|
103
|
+
setMessage("\uCEE4\uBC0B \uC2E4\uD328\uB85C \uC778\uD574 \uB864\uBC31\uD558\uB294 \uC911...");
|
|
104
|
+
try {
|
|
105
|
+
await rename(archiveDir, solvingDir);
|
|
106
|
+
} catch (rollbackError) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
`Git \uCEE4\uBC0B \uC2E4\uD328 \uBC0F \uB864\uBC31 \uC2E4\uD328: ${gitError instanceof Error ? gitError.message : String(gitError)}. \uB864\uBC31 \uC5D0\uB7EC: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}. \uC218\uB3D9\uC73C\uB85C \uD30C\uC77C\uC744 \uD655\uC778\uD574\uC8FC\uC138\uC694.`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
throw gitError;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
90
114
|
setMessage("\uBE48 \uB514\uB809\uD1A0\uB9AC \uC815\uB9AC \uC911...");
|
|
91
115
|
try {
|
|
92
116
|
const solvingDirConfig = getSolvingDir();
|
|
@@ -109,19 +133,6 @@ function useArchive({
|
|
|
109
133
|
}
|
|
110
134
|
} catch {
|
|
111
135
|
}
|
|
112
|
-
setMessage("Git \uCEE4\uBC0B\uC744 \uC2E4\uD589\uD558\uB294 \uC911...");
|
|
113
|
-
try {
|
|
114
|
-
await execa("git", ["add", archiveDir], { cwd: projectRoot });
|
|
115
|
-
const commitMessage = `solve: ${problemId} - ${problemTitle}`;
|
|
116
|
-
await execa("git", ["commit", "-m", commitMessage], {
|
|
117
|
-
cwd: projectRoot
|
|
118
|
-
});
|
|
119
|
-
} catch (gitError) {
|
|
120
|
-
console.warn(
|
|
121
|
-
"Git \uCEE4\uBC0B \uC2E4\uD328:",
|
|
122
|
-
gitError instanceof Error ? gitError.message : String(gitError)
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
136
|
setStatus("success");
|
|
126
137
|
setMessage(`\uBB38\uC81C ${problemId}\uB97C \uC544\uCE74\uC774\uBE0C\uD588\uC2B5\uB2C8\uB2E4: ${archiveDir}`);
|
|
127
138
|
setTimeout(() => {
|
package/dist/commands/config.js
CHANGED
|
@@ -3,13 +3,15 @@ import {
|
|
|
3
3
|
Command,
|
|
4
4
|
CommandBuilder,
|
|
5
5
|
CommandDef,
|
|
6
|
+
getArchiveAutoCommit,
|
|
7
|
+
getArchiveCommitMessage,
|
|
6
8
|
getArchiveDir,
|
|
7
9
|
getArchiveStrategy,
|
|
8
10
|
getAutoOpenEditor,
|
|
9
11
|
getDefaultLanguage,
|
|
10
12
|
getEditor,
|
|
11
13
|
getSolvedAcHandle
|
|
12
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-JPDN34C7.js";
|
|
13
15
|
import {
|
|
14
16
|
__decorateClass,
|
|
15
17
|
getSupportedLanguages,
|
|
@@ -117,6 +119,19 @@ function useConfig({
|
|
|
117
119
|
updatedConfig.archiveStrategy = value;
|
|
118
120
|
break;
|
|
119
121
|
}
|
|
122
|
+
case "archive-auto-commit": {
|
|
123
|
+
if (value !== "true" && value !== "false") {
|
|
124
|
+
console.error(
|
|
125
|
+
`archive-auto-commit \uAC12\uC740 true \uB610\uB294 false \uC5EC\uC57C \uD569\uB2C8\uB2E4: ${value}`
|
|
126
|
+
);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
updatedConfig.archiveAutoCommit = value === "true";
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
case "archive-commit-message":
|
|
133
|
+
updatedConfig.archiveCommitMessage = value;
|
|
134
|
+
break;
|
|
120
135
|
default:
|
|
121
136
|
console.error(`\uC54C \uC218 \uC5C6\uB294 \uC124\uC815 \uD0A4: ${configKey}`);
|
|
122
137
|
process.exit(1);
|
|
@@ -161,6 +176,8 @@ function getConfigHelp() {
|
|
|
161
176
|
solved-ac-handle Solved.ac \uD578\uB4E4 (stats \uBA85\uB839\uC5B4\uC6A9)
|
|
162
177
|
archive-dir \uC544\uCE74\uC774\uBE0C \uB514\uB809\uD1A0\uB9AC \uACBD\uB85C (\uAE30\uBCF8\uAC12: problems, "." \uB610\uB294 ""\uB294 \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8)
|
|
163
178
|
archive-strategy \uC544\uCE74\uC774\uBE59 \uC804\uB7B5 (flat, by-range, by-tier, by-tag)
|
|
179
|
+
archive-auto-commit archive \uC2DC Git \uCEE4\uBC0B \uC790\uB3D9 \uC2E4\uD589 \uC5EC\uBD80 (true/false)
|
|
180
|
+
archive-commit-message archive \uCEE4\uBC0B \uBA54\uC2DC\uC9C0 \uD15C\uD50C\uB9BF ({id}, {title} \uC0AC\uC6A9 \uAC00\uB2A5)
|
|
164
181
|
|
|
165
182
|
\uC635\uC158:
|
|
166
183
|
--help, -h \uB3C4\uC6C0\uB9D0 \uD45C\uC2DC
|
|
@@ -181,7 +198,9 @@ var CONFIG_KEYS = [
|
|
|
181
198
|
{ label: "auto-open-editor", value: "auto-open-editor" },
|
|
182
199
|
{ label: "solved-ac-handle", value: "solved-ac-handle" },
|
|
183
200
|
{ label: "archive-dir", value: "archive-dir" },
|
|
184
|
-
{ label: "archive-strategy", value: "archive-strategy" }
|
|
201
|
+
{ label: "archive-strategy", value: "archive-strategy" },
|
|
202
|
+
{ label: "archive-auto-commit", value: "archive-auto-commit" },
|
|
203
|
+
{ label: "archive-commit-message", value: "archive-commit-message" }
|
|
185
204
|
];
|
|
186
205
|
function ConfigView({
|
|
187
206
|
configKey,
|
|
@@ -215,6 +234,8 @@ function ConfigView({
|
|
|
215
234
|
const handle = config?.solvedAcHandle ?? getSolvedAcHandle();
|
|
216
235
|
const archiveDir = config?.archiveDir ?? getArchiveDir();
|
|
217
236
|
const archiveStrategy = config?.archiveStrategy ?? getArchiveStrategy();
|
|
237
|
+
const archiveAutoCommit = config?.archiveAutoCommit ?? getArchiveAutoCommit();
|
|
238
|
+
const archiveCommitMessage = config?.archiveCommitMessage ?? getArchiveCommitMessage();
|
|
218
239
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
219
240
|
/* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u2699\uFE0F \uD604\uC7AC \uC124\uC815 (.ps-cli.json)" }) }),
|
|
220
241
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
@@ -247,6 +268,23 @@ function ConfigView({
|
|
|
247
268
|
/* @__PURE__ */ jsx(Text, { color: "gray", children: "archive-strategy:" }),
|
|
248
269
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
249
270
|
/* @__PURE__ */ jsx(Text, { bold: true, children: archiveStrategy })
|
|
271
|
+
] }),
|
|
272
|
+
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
273
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "archive-auto-commit:" }),
|
|
274
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
275
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: archiveAutoCommit ? "green" : "gray", children: archiveAutoCommit ? "true" : "false" })
|
|
276
|
+
] }),
|
|
277
|
+
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
278
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "archive-commit-message:" }),
|
|
279
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
280
|
+
/* @__PURE__ */ jsx(
|
|
281
|
+
Text,
|
|
282
|
+
{
|
|
283
|
+
bold: true,
|
|
284
|
+
color: archiveCommitMessage && archiveCommitMessage.length > 0 ? "cyan" : "gray",
|
|
285
|
+
children: archiveCommitMessage || "(\uC124\uC815 \uC548 \uB428)"
|
|
286
|
+
}
|
|
287
|
+
)
|
|
250
288
|
] })
|
|
251
289
|
] })
|
|
252
290
|
] });
|
|
@@ -272,6 +310,12 @@ function ConfigView({
|
|
|
272
310
|
case "archive-strategy":
|
|
273
311
|
configValue = config?.archiveStrategy ?? getArchiveStrategy();
|
|
274
312
|
break;
|
|
313
|
+
case "archive-auto-commit":
|
|
314
|
+
configValue = config?.archiveAutoCommit !== void 0 ? String(config.archiveAutoCommit) : String(getArchiveAutoCommit());
|
|
315
|
+
break;
|
|
316
|
+
case "archive-commit-message":
|
|
317
|
+
configValue = config?.archiveCommitMessage ?? getArchiveCommitMessage();
|
|
318
|
+
break;
|
|
275
319
|
default:
|
|
276
320
|
console.error(`\uC54C \uC218 \uC5C6\uB294 \uC124\uC815 \uD0A4: ${configKey}`);
|
|
277
321
|
process.exit(1);
|
|
@@ -444,6 +488,10 @@ var ConfigCommand = class extends Command {
|
|
|
444
488
|
return "\uC544\uCE74\uC774\uBE0C \uB514\uB809\uD1A0\uB9AC \uACBD\uB85C \uC785\uB825";
|
|
445
489
|
case "archive-strategy":
|
|
446
490
|
return "\uC544\uCE74\uC774\uBE59 \uC804\uB7B5 \uC785\uB825 (flat, by-range, by-tier, by-tag)";
|
|
491
|
+
case "archive-auto-commit":
|
|
492
|
+
return "true \uB610\uB294 false \uC785\uB825";
|
|
493
|
+
case "archive-commit-message":
|
|
494
|
+
return "\uCEE4\uBC0B \uBA54\uC2DC\uC9C0 \uD15C\uD50C\uB9BF \uC785\uB825 (\uC608: solve: {id} - {title})";
|
|
447
495
|
default:
|
|
448
496
|
return "\uAC12 \uC785\uB825";
|
|
449
497
|
}
|
|
@@ -462,6 +510,10 @@ var ConfigCommand = class extends Command {
|
|
|
462
510
|
return '\uC544\uCE74\uC774\uBE0C \uB514\uB809\uD1A0\uB9AC \uACBD\uB85C (\uAE30\uBCF8\uAC12: "problems", \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8: ".")';
|
|
463
511
|
case "archive-strategy":
|
|
464
512
|
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)";
|
|
513
|
+
case "archive-auto-commit":
|
|
514
|
+
return "archive \uBA85\uB839 \uC2E4\uD589 \uC2DC Git \uCEE4\uBC0B\uC744 \uC790\uB3D9\uC73C\uB85C \uC218\uD589\uD560\uC9C0 \uC5EC\uBD80";
|
|
515
|
+
case "archive-commit-message":
|
|
516
|
+
return "archive \uC2DC \uC0AC\uC6A9\uD560 Git \uCEE4\uBC0B \uBA54\uC2DC\uC9C0 \uD15C\uD50C\uB9BF ({id}, {title} \uC0AC\uC6A9 \uAC00\uB2A5)";
|
|
465
517
|
default:
|
|
466
518
|
return "";
|
|
467
519
|
}
|
|
@@ -478,6 +530,8 @@ var ConfigCommand = class extends Command {
|
|
|
478
530
|
return ["problems", ".", ""];
|
|
479
531
|
case "archive-strategy":
|
|
480
532
|
return ["flat", "by-range", "by-tier", "by-tag"];
|
|
533
|
+
case "archive-auto-commit":
|
|
534
|
+
return ["true", "false"];
|
|
481
535
|
default:
|
|
482
536
|
return [];
|
|
483
537
|
}
|
package/dist/commands/fetch.js
CHANGED
|
@@ -4,7 +4,10 @@ import {
|
|
|
4
4
|
} from "../chunk-4ISG24GW.js";
|
|
5
5
|
import {
|
|
6
6
|
getProblem
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-QB2R47PW.js";
|
|
8
|
+
import {
|
|
9
|
+
defineFlags
|
|
10
|
+
} from "../chunk-PY6GW22W.js";
|
|
8
11
|
import {
|
|
9
12
|
Command,
|
|
10
13
|
CommandBuilder,
|
|
@@ -16,7 +19,7 @@ import {
|
|
|
16
19
|
getTierImageUrl,
|
|
17
20
|
getTierName,
|
|
18
21
|
resolveProblemContext
|
|
19
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-JPDN34C7.js";
|
|
20
23
|
import {
|
|
21
24
|
__decorateClass,
|
|
22
25
|
getLanguageConfig,
|
|
@@ -315,6 +318,14 @@ ${editor}\uB85C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4.`
|
|
|
315
318
|
|
|
316
319
|
// src/commands/fetch.tsx
|
|
317
320
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
321
|
+
var fetchFlagsSchema = {
|
|
322
|
+
language: {
|
|
323
|
+
type: "string",
|
|
324
|
+
shortFlag: "l",
|
|
325
|
+
description: `\uC5B8\uC5B4 \uC120\uD0DD (${getSupportedLanguagesString()})
|
|
326
|
+
\uAE30\uBCF8\uAC12: python`
|
|
327
|
+
}
|
|
328
|
+
};
|
|
318
329
|
function FetchView({
|
|
319
330
|
problemId,
|
|
320
331
|
language = "python",
|
|
@@ -378,16 +389,7 @@ FetchCommand = __decorateClass([
|
|
|
378
389
|
- \uBB38\uC81C \uC124\uBA85, \uC785\uCD9C\uB825 \uD615\uC2DD, \uC608\uC81C \uC785\uCD9C\uB825 \uD30C\uC77C \uC790\uB3D9 \uC0DD\uC131
|
|
379
390
|
- \uC120\uD0DD\uD55C \uC5B8\uC5B4\uC758 \uC194\uB8E8\uC158 \uD15C\uD50C\uB9BF \uD30C\uC77C \uC0DD\uC131
|
|
380
391
|
- 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
|
-
],
|
|
392
|
+
flags: defineFlags(fetchFlagsSchema),
|
|
391
393
|
autoDetectProblemId: false,
|
|
392
394
|
requireProblemId: true,
|
|
393
395
|
examples: ["fetch 1000", "fetch 1000 --language python", "fetch 1000 -l cpp"]
|
package/dist/commands/init.js
CHANGED
package/dist/commands/open.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
useOpenBrowser
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-3LR2NGRC.js";
|
|
5
5
|
import "../chunk-QGMWUOJ3.js";
|
|
6
|
+
import {
|
|
7
|
+
defineFlags
|
|
8
|
+
} from "../chunk-PY6GW22W.js";
|
|
6
9
|
import {
|
|
7
10
|
Command,
|
|
8
11
|
CommandBuilder,
|
|
9
12
|
CommandDef,
|
|
10
13
|
resolveProblemContext
|
|
11
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-JPDN34C7.js";
|
|
12
15
|
import {
|
|
13
16
|
__decorateClass
|
|
14
17
|
} from "../chunk-7MQMPJ3X.js";
|
|
@@ -18,17 +21,30 @@ import { StatusMessage, Alert } from "@inkjs/ui";
|
|
|
18
21
|
import { Spinner } from "@inkjs/ui";
|
|
19
22
|
import { Text, Box } from "ink";
|
|
20
23
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
21
|
-
|
|
24
|
+
var openFlagsSchema = {
|
|
25
|
+
workbook: {
|
|
26
|
+
type: "number",
|
|
27
|
+
shortFlag: "w",
|
|
28
|
+
description: "\uBB38\uC81C\uC9D1 ID\uB97C \uC9C0\uC815\uD558\uC5EC \uD574\uB2F9 \uBB38\uC81C\uC9D1 \uD398\uC774\uC9C0\uB97C \uC5FD\uB2C8\uB2E4"
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
function OpenView({ problemId, workbookId, onComplete }) {
|
|
22
32
|
const { status, error, url } = useOpenBrowser({
|
|
23
33
|
problemId,
|
|
34
|
+
workbookId,
|
|
24
35
|
onComplete
|
|
25
36
|
});
|
|
37
|
+
const displayId = workbookId !== void 0 ? workbookId : problemId;
|
|
38
|
+
const displayType = workbookId !== void 0 ? "\uBB38\uC81C\uC9D1" : "\uBB38\uC81C";
|
|
26
39
|
if (status === "loading") {
|
|
27
40
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
28
41
|
/* @__PURE__ */ jsx(Spinner, { label: "\uBE0C\uB77C\uC6B0\uC800\uB97C \uC5EC\uB294 \uC911..." }),
|
|
29
42
|
/* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
30
|
-
|
|
31
|
-
|
|
43
|
+
displayType,
|
|
44
|
+
" ",
|
|
45
|
+
workbookId !== void 0 ? "ID" : "#",
|
|
46
|
+
": ",
|
|
47
|
+
displayId
|
|
32
48
|
] }) })
|
|
33
49
|
] });
|
|
34
50
|
}
|
|
@@ -45,12 +61,21 @@ function OpenView({ problemId, onComplete }) {
|
|
|
45
61
|
] });
|
|
46
62
|
}
|
|
47
63
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: "100%", children: [
|
|
48
|
-
/* @__PURE__ */
|
|
64
|
+
/* @__PURE__ */ jsxs(StatusMessage, { variant: "success", children: [
|
|
65
|
+
"\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C ",
|
|
66
|
+
displayType,
|
|
67
|
+
" \uD398\uC774\uC9C0\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4!"
|
|
68
|
+
] }),
|
|
49
69
|
/* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
|
|
50
70
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
51
|
-
/* @__PURE__ */
|
|
71
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
|
|
72
|
+
displayType,
|
|
73
|
+
" ",
|
|
74
|
+
workbookId !== void 0 ? "ID" : "\uBC88\uD638",
|
|
75
|
+
":"
|
|
76
|
+
] }),
|
|
52
77
|
" ",
|
|
53
|
-
|
|
78
|
+
displayId
|
|
54
79
|
] }),
|
|
55
80
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
56
81
|
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "URL:" }),
|
|
@@ -61,11 +86,26 @@ function OpenView({ problemId, onComplete }) {
|
|
|
61
86
|
] });
|
|
62
87
|
}
|
|
63
88
|
var OpenCommand = class extends Command {
|
|
64
|
-
async execute(args,
|
|
89
|
+
async execute(args, flags) {
|
|
90
|
+
const workbookId = flags.workbook ? parseInt(String(flags.workbook), 10) : null;
|
|
91
|
+
if (workbookId !== null) {
|
|
92
|
+
if (isNaN(workbookId) || workbookId <= 0) {
|
|
93
|
+
console.error("\uC624\uB958: \uC720\uD6A8\uD55C \uBB38\uC81C\uC9D1 ID\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694.");
|
|
94
|
+
console.error(`\uC0AC\uC6A9\uBC95: ps open --workbook <\uBB38\uC81C\uC9D1ID>`);
|
|
95
|
+
console.error(`\uB3C4\uC6C0\uB9D0: ps open --help`);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
await this.renderView(OpenView, {
|
|
100
|
+
workbookId
|
|
101
|
+
});
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
65
104
|
const context = await resolveProblemContext(args, { requireId: true });
|
|
66
105
|
if (context.problemId === null) {
|
|
67
106
|
console.error("\uC624\uB958: \uBB38\uC81C \uBC88\uD638\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694.");
|
|
68
107
|
console.error(`\uC0AC\uC6A9\uBC95: ps open <\uBB38\uC81C\uBC88\uD638>`);
|
|
108
|
+
console.error(` ps open --workbook <\uBB38\uC81C\uC9D1ID>`);
|
|
69
109
|
console.error(`\uB3C4\uC6C0\uB9D0: ps open --help`);
|
|
70
110
|
console.error(
|
|
71
111
|
`\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.`
|
|
@@ -81,14 +121,18 @@ var OpenCommand = class extends Command {
|
|
|
81
121
|
OpenCommand = __decorateClass([
|
|
82
122
|
CommandDef({
|
|
83
123
|
name: "open",
|
|
84
|
-
description: `\uBC31\uC900 \uBB38\uC81C \uD398\uC774\uC9C0\uB97C \uBE0C\uB77C\uC6B0\uC800\uB85C \uC5FD\uB2C8\uB2E4.
|
|
124
|
+
description: `\uBC31\uC900 \uBB38\uC81C \uD398\uC774\uC9C0 \uB610\uB294 \uBB38\uC81C\uC9D1 \uD398\uC774\uC9C0\uB97C \uBE0C\uB77C\uC6B0\uC800\uB85C \uC5FD\uB2C8\uB2E4.
|
|
85
125
|
- \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
|
|
126
|
+
- \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.
|
|
127
|
+
- --workbook \uC635\uC158\uC73C\uB85C \uBB38\uC81C\uC9D1 ID\uB97C \uC9C0\uC815\uD558\uBA74 \uBB38\uC81C\uC9D1 \uD398\uC774\uC9C0\uB97C \uC5FD\uB2C8\uB2E4.`,
|
|
87
128
|
autoDetectProblemId: true,
|
|
88
|
-
requireProblemId:
|
|
129
|
+
requireProblemId: false,
|
|
130
|
+
flags: defineFlags(openFlagsSchema),
|
|
89
131
|
examples: [
|
|
90
132
|
"open 1000 # 1000\uBC88 \uBB38\uC81C \uC5F4\uAE30",
|
|
91
133
|
"open # \uBB38\uC81C \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C \uC2E4\uD589 \uC2DC \uC790\uB3D9 \uCD94\uB860",
|
|
134
|
+
"open --workbook 25052 # \uBB38\uC81C\uC9D1 25052 \uC5F4\uAE30",
|
|
135
|
+
"open -w 25052 # \uBB38\uC81C\uC9D1 25052 \uC5F4\uAE30 (\uB2E8\uCD95 \uC635\uC158)",
|
|
92
136
|
"open --help # \uB3C4\uC6C0\uB9D0 \uD45C\uC2DC"
|
|
93
137
|
]
|
|
94
138
|
})
|
package/dist/commands/run.js
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runSolution
|
|
4
4
|
} from "../chunk-VIHXBCOZ.js";
|
|
5
|
+
import {
|
|
6
|
+
defineFlags
|
|
7
|
+
} from "../chunk-PY6GW22W.js";
|
|
5
8
|
import {
|
|
6
9
|
Command,
|
|
7
10
|
CommandBuilder,
|
|
8
11
|
CommandDef,
|
|
9
12
|
resolveLanguage,
|
|
10
13
|
resolveProblemContext
|
|
11
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-JPDN34C7.js";
|
|
12
15
|
import {
|
|
13
16
|
__decorateClass,
|
|
14
17
|
getSupportedLanguagesString
|
|
@@ -63,6 +66,19 @@ function useRunSolution({
|
|
|
63
66
|
|
|
64
67
|
// src/commands/run.tsx
|
|
65
68
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
69
|
+
var runFlagsSchema = {
|
|
70
|
+
language: {
|
|
71
|
+
type: "string",
|
|
72
|
+
shortFlag: "l",
|
|
73
|
+
description: `\uC5B8\uC5B4 \uC120\uD0DD (\uC9C0\uC815 \uC2DC \uC790\uB3D9 \uAC10\uC9C0 \uBB34\uC2DC)
|
|
74
|
+
\uC9C0\uC6D0 \uC5B8\uC5B4: ${getSupportedLanguagesString()}`
|
|
75
|
+
},
|
|
76
|
+
input: {
|
|
77
|
+
type: "string",
|
|
78
|
+
shortFlag: "i",
|
|
79
|
+
description: "\uC785\uB825 \uD30C\uC77C \uC9C0\uC815 (\uC608: 1 \uB610\uB294 testcases/1/input.txt)"
|
|
80
|
+
}
|
|
81
|
+
};
|
|
66
82
|
function RunView({
|
|
67
83
|
problemDir,
|
|
68
84
|
language,
|
|
@@ -171,23 +187,7 @@ RunCommand = __decorateClass([
|
|
|
171
187
|
- --input \uC635\uC158\uC73C\uB85C \uC785\uB825 \uD30C\uC77C \uC9C0\uC815 \uAC00\uB2A5 (\uC608: testcases/1/input.txt)
|
|
172
188
|
- \uC635\uC158 \uC5C6\uC774 \uC2E4\uD589 \uC2DC \uD45C\uC900 \uC785\uB825\uC73C\uB85C \uC785\uB825 \uBC1B\uAE30
|
|
173
189
|
- \uD14C\uC2A4\uD2B8 \uCF00\uC774\uC2A4 \uAC80\uC99D \uC5C6\uC774 \uB2E8\uC21C \uC2E4\uD589`,
|
|
174
|
-
flags:
|
|
175
|
-
{
|
|
176
|
-
name: "language",
|
|
177
|
-
options: {
|
|
178
|
-
shortFlag: "l",
|
|
179
|
-
description: `\uC5B8\uC5B4 \uC120\uD0DD (\uC9C0\uC815 \uC2DC \uC790\uB3D9 \uAC10\uC9C0 \uBB34\uC2DC)
|
|
180
|
-
\uC9C0\uC6D0 \uC5B8\uC5B4: ${getSupportedLanguagesString()}`
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
name: "input",
|
|
185
|
-
options: {
|
|
186
|
-
shortFlag: "i",
|
|
187
|
-
description: "\uC785\uB825 \uD30C\uC77C \uC9C0\uC815 (\uC608: 1 \uB610\uB294 testcases/1/input.txt)"
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
],
|
|
190
|
+
flags: defineFlags(runFlagsSchema),
|
|
191
191
|
autoDetectProblemId: true,
|
|
192
192
|
autoDetectLanguage: true,
|
|
193
193
|
examples: [
|
package/dist/commands/search.js
CHANGED
|
@@ -7,11 +7,14 @@ import {
|
|
|
7
7
|
} from "../chunk-4ISG24GW.js";
|
|
8
8
|
import {
|
|
9
9
|
getProblem
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-QB2R47PW.js";
|
|
11
11
|
import {
|
|
12
12
|
useOpenBrowser
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-3LR2NGRC.js";
|
|
14
14
|
import "../chunk-QGMWUOJ3.js";
|
|
15
|
+
import {
|
|
16
|
+
defineFlags
|
|
17
|
+
} from "../chunk-PY6GW22W.js";
|
|
15
18
|
import {
|
|
16
19
|
Command,
|
|
17
20
|
CommandBuilder,
|
|
@@ -19,7 +22,7 @@ import {
|
|
|
19
22
|
getArchiveDirPath,
|
|
20
23
|
getTierColor,
|
|
21
24
|
getTierName
|
|
22
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-JPDN34C7.js";
|
|
23
26
|
import {
|
|
24
27
|
__decorateClass
|
|
25
28
|
} from "../chunk-7MQMPJ3X.js";
|
|
@@ -48,20 +51,20 @@ function ProblemSelector({
|
|
|
48
51
|
const solvedText = problem.solvedCount ? ` (${problem.solvedCount.toLocaleString()}\uBA85` : "";
|
|
49
52
|
const triesText = problem.averageTries ? `, \uD3C9\uADE0 ${problem.averageTries}\uD68C` : "";
|
|
50
53
|
const suffix = solvedText + triesText + (solvedText ? ")" : "");
|
|
51
|
-
const solvedMark = problem.isSolved ? "
|
|
54
|
+
const solvedMark = problem.isSolved ? ` ${source_default.bold.green("\u2713")}` : "";
|
|
52
55
|
let tierText = "";
|
|
53
56
|
if (problem.level) {
|
|
54
57
|
const tierName = getTierName(problem.level);
|
|
55
58
|
const tierColor = getTierColor(problem.level);
|
|
56
59
|
if (typeof tierColor === "string") {
|
|
57
|
-
tierText =
|
|
60
|
+
tierText = `${source_default.bold.hex(tierColor)(tierName)} `;
|
|
58
61
|
} else {
|
|
59
|
-
tierText =
|
|
62
|
+
tierText = `${tierColor(source_default.bold(tierName))} `;
|
|
60
63
|
}
|
|
61
64
|
}
|
|
62
65
|
const problemText = `${problem.problemId} - ${problem.title}`;
|
|
63
66
|
options.push({
|
|
64
|
-
label: `${tierText}
|
|
67
|
+
label: `${tierText}${problemText}${suffix}${solvedMark}`,
|
|
65
68
|
value: `problem:${problem.problemId}`
|
|
66
69
|
});
|
|
67
70
|
});
|
|
@@ -180,6 +183,13 @@ async function scrapeWorkbook(workbookId) {
|
|
|
180
183
|
|
|
181
184
|
// src/commands/search.tsx
|
|
182
185
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
186
|
+
var searchFlagsSchema = {
|
|
187
|
+
workbook: {
|
|
188
|
+
type: "number",
|
|
189
|
+
shortFlag: "w",
|
|
190
|
+
description: "\uBB38\uC81C\uC9D1 ID\uB97C \uC9C0\uC815\uD558\uC5EC \uD574\uB2F9 \uBB38\uC81C\uC9D1\uC758 \uBB38\uC81C \uBAA9\uB85D\uC744 \uD45C\uC2DC"
|
|
191
|
+
}
|
|
192
|
+
};
|
|
183
193
|
async function enrichProblemsWithTiers(problems) {
|
|
184
194
|
const BATCH_SIZE = 10;
|
|
185
195
|
const DELAY_MS = 200;
|
|
@@ -191,7 +201,10 @@ async function enrichProblemsWithTiers(problems) {
|
|
|
191
201
|
const solvedAcData = await getProblem(problem.problemId);
|
|
192
202
|
return {
|
|
193
203
|
...problem,
|
|
194
|
-
level: solvedAcData.level
|
|
204
|
+
level: solvedAcData.level,
|
|
205
|
+
tags: solvedAcData.tags.map(
|
|
206
|
+
(t) => t.displayNames.find((n) => n.language === "ko")?.name || t.key
|
|
207
|
+
)
|
|
195
208
|
};
|
|
196
209
|
} catch (error) {
|
|
197
210
|
console.warn(
|
|
@@ -270,7 +283,10 @@ function WorkbookSearchView({
|
|
|
270
283
|
] });
|
|
271
284
|
}
|
|
272
285
|
const problemsWithSolvedStatus = problems.map((problem) => {
|
|
273
|
-
const problemDirPath = getArchiveDirPath(problem.problemId)
|
|
286
|
+
const problemDirPath = getArchiveDirPath(problem.problemId, process.cwd(), {
|
|
287
|
+
level: problem.level,
|
|
288
|
+
tags: problem.tags
|
|
289
|
+
});
|
|
274
290
|
const isSolved = existsSync(problemDirPath);
|
|
275
291
|
return {
|
|
276
292
|
problemId: problem.problemId,
|
|
@@ -360,12 +376,34 @@ function SearchView({ query, onComplete }) {
|
|
|
360
376
|
setLoading(true);
|
|
361
377
|
setError(null);
|
|
362
378
|
const searchResults = await searchProblems(query, currentPage);
|
|
379
|
+
const enrichedProblems = await enrichProblemsWithTiers(
|
|
380
|
+
searchResults.problems.map((p) => ({
|
|
381
|
+
problemId: p.problemId,
|
|
382
|
+
title: p.title,
|
|
383
|
+
order: 0
|
|
384
|
+
// SearchResult에는 order가 없으므로 0으로 설정
|
|
385
|
+
}))
|
|
386
|
+
);
|
|
363
387
|
const resultsWithSolvedStatus = searchResults.problems.map(
|
|
364
388
|
(problem) => {
|
|
365
|
-
const
|
|
389
|
+
const enriched = enrichedProblems.find(
|
|
390
|
+
(ep) => ep.problemId === problem.problemId
|
|
391
|
+
);
|
|
392
|
+
const level = enriched?.level ?? problem.level;
|
|
393
|
+
const tags = enriched?.tags ?? problem.tags;
|
|
394
|
+
const problemDirPath = getArchiveDirPath(
|
|
395
|
+
problem.problemId,
|
|
396
|
+
process.cwd(),
|
|
397
|
+
{
|
|
398
|
+
level,
|
|
399
|
+
tags
|
|
400
|
+
}
|
|
401
|
+
);
|
|
366
402
|
const isSolved = existsSync(problemDirPath);
|
|
367
403
|
return {
|
|
368
404
|
...problem,
|
|
405
|
+
level,
|
|
406
|
+
tags,
|
|
369
407
|
isSolved
|
|
370
408
|
};
|
|
371
409
|
}
|
|
@@ -483,14 +521,7 @@ SearchCommand = __decorateClass([
|
|
|
483
521
|
- \uBB38\uC81C \uBAA9\uB85D\uC5D0\uC11C \uC120\uD0DD\uD558\uBA74 \uC790\uB3D9\uC73C\uB85C \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uBB38\uC81C \uD398\uC774\uC9C0\uB97C \uC5FD\uB2C8\uB2E4.
|
|
484
522
|
- \uD398\uC774\uC9C0\uB124\uC774\uC158\uC744 \uD1B5\uD574 \uC5EC\uB7EC \uD398\uC774\uC9C0\uC758 \uACB0\uACFC\uB97C \uD0D0\uC0C9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.
|
|
485
523
|
- --workbook \uC635\uC158\uC73C\uB85C \uBC31\uC900 \uBB38\uC81C\uC9D1\uC758 \uBB38\uC81C \uBAA9\uB85D\uC744 \uBCFC \uC218 \uC788\uC2B5\uB2C8\uB2E4.`,
|
|
486
|
-
flags:
|
|
487
|
-
{
|
|
488
|
-
name: "workbook",
|
|
489
|
-
options: {
|
|
490
|
-
description: "\uBB38\uC81C\uC9D1 ID\uB97C \uC9C0\uC815\uD558\uC5EC \uD574\uB2F9 \uBB38\uC81C\uC9D1\uC758 \uBB38\uC81C \uBAA9\uB85D\uC744 \uD45C\uC2DC"
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
],
|
|
524
|
+
flags: defineFlags(searchFlagsSchema),
|
|
494
525
|
autoDetectProblemId: false,
|
|
495
526
|
requireProblemId: false,
|
|
496
527
|
examples: [
|
|
@@ -499,7 +530,8 @@ SearchCommand = __decorateClass([
|
|
|
499
530
|
'search "#dp" # DP \uD0DC\uADF8 \uBB38\uC81C \uAC80\uC0C9',
|
|
500
531
|
'search "tag:dp" # DP \uD0DC\uADF8 \uBB38\uC81C \uAC80\uC0C9 (tag: \uBB38\uBC95)',
|
|
501
532
|
'search "*g1...g5 #dp" # Gold 1-5 \uD2F0\uC5B4\uC758 DP \uD0DC\uADF8 \uBB38\uC81C \uAC80\uC0C9',
|
|
502
|
-
"search --workbook 25052 # \uBB38\uC81C\uC9D1 25052\uC758 \uBB38\uC81C \uBAA9\uB85D \uD45C\uC2DC"
|
|
533
|
+
"search --workbook 25052 # \uBB38\uC81C\uC9D1 25052\uC758 \uBB38\uC81C \uBAA9\uB85D \uD45C\uC2DC",
|
|
534
|
+
"search -w 25052 # \uBB38\uC81C\uC9D1 25052\uC758 \uBB38\uC81C \uBAA9\uB85D \uD45C\uC2DC (\uB2E8\uCD95 \uC635\uC158)"
|
|
503
535
|
]
|
|
504
536
|
})
|
|
505
537
|
], SearchCommand);
|
package/dist/commands/stats.js
CHANGED
|
@@ -3,18 +3,26 @@ import {
|
|
|
3
3
|
source_default
|
|
4
4
|
} from "../chunk-ASMT3CRD.js";
|
|
5
5
|
import {
|
|
6
|
-
getUserStats
|
|
7
|
-
|
|
6
|
+
getUserStats,
|
|
7
|
+
getUserTop100
|
|
8
|
+
} from "../chunk-QB2R47PW.js";
|
|
9
|
+
import {
|
|
10
|
+
defineFlags
|
|
11
|
+
} from "../chunk-PY6GW22W.js";
|
|
8
12
|
import {
|
|
9
13
|
Command,
|
|
10
14
|
CommandBuilder,
|
|
11
15
|
CommandDef,
|
|
12
16
|
calculateTierProgress,
|
|
17
|
+
findProjectRoot,
|
|
18
|
+
getArchiveDir,
|
|
13
19
|
getNextTierMinRating,
|
|
14
20
|
getSolvedAcHandle,
|
|
21
|
+
getSolvingDir,
|
|
15
22
|
getTierColor,
|
|
16
|
-
getTierName
|
|
17
|
-
|
|
23
|
+
getTierName,
|
|
24
|
+
getTierShortName
|
|
25
|
+
} from "../chunk-JPDN34C7.js";
|
|
18
26
|
import {
|
|
19
27
|
__decorateClass
|
|
20
28
|
} from "../chunk-7MQMPJ3X.js";
|
|
@@ -25,40 +33,98 @@ import { Spinner } from "@inkjs/ui";
|
|
|
25
33
|
import { Box, Text, Transform } from "ink";
|
|
26
34
|
|
|
27
35
|
// src/hooks/use-user-stats.ts
|
|
36
|
+
import { existsSync } from "fs";
|
|
37
|
+
import { readdir, stat } from "fs/promises";
|
|
38
|
+
import { join } from "path";
|
|
28
39
|
import { useEffect, useState } from "react";
|
|
40
|
+
async function countProblems(dir) {
|
|
41
|
+
let count = 0;
|
|
42
|
+
try {
|
|
43
|
+
if (!existsSync(dir)) return 0;
|
|
44
|
+
const entries = await readdir(dir);
|
|
45
|
+
for (const entry of entries) {
|
|
46
|
+
if (entry.startsWith(".")) continue;
|
|
47
|
+
const fullPath = join(dir, entry);
|
|
48
|
+
const s = await stat(fullPath);
|
|
49
|
+
if (s.isDirectory()) {
|
|
50
|
+
if (existsSync(join(fullPath, "meta.json"))) {
|
|
51
|
+
count++;
|
|
52
|
+
} else {
|
|
53
|
+
count += await countProblems(fullPath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
} catch {
|
|
58
|
+
}
|
|
59
|
+
return count;
|
|
60
|
+
}
|
|
29
61
|
function useUserStats({
|
|
30
62
|
handle,
|
|
31
|
-
onComplete
|
|
63
|
+
onComplete,
|
|
64
|
+
fetchLocalCount = false
|
|
32
65
|
}) {
|
|
33
66
|
const [status, setStatus] = useState(
|
|
34
67
|
"loading"
|
|
35
68
|
);
|
|
36
69
|
const [user, setUser] = useState(null);
|
|
70
|
+
const [top100, setTop100] = useState(null);
|
|
71
|
+
const [localSolvedCount, setLocalSolvedCount] = useState(null);
|
|
37
72
|
const [error, setError] = useState(null);
|
|
38
73
|
useEffect(() => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
74
|
+
async function fetchData() {
|
|
75
|
+
try {
|
|
76
|
+
const [userData, top100Data] = await Promise.all([
|
|
77
|
+
getUserStats(handle),
|
|
78
|
+
getUserTop100(handle)
|
|
79
|
+
]);
|
|
80
|
+
setUser(userData);
|
|
81
|
+
setTop100(top100Data);
|
|
82
|
+
if (fetchLocalCount) {
|
|
83
|
+
const projectRoot = findProjectRoot();
|
|
84
|
+
if (projectRoot) {
|
|
85
|
+
const archiveDir = getArchiveDir();
|
|
86
|
+
const solvingDir = getSolvingDir();
|
|
87
|
+
const archivePath = join(projectRoot, archiveDir);
|
|
88
|
+
const solvingPath = join(projectRoot, solvingDir);
|
|
89
|
+
const [archiveCount, solvingCount] = await Promise.all([
|
|
90
|
+
countProblems(archivePath),
|
|
91
|
+
countProblems(solvingPath)
|
|
92
|
+
]);
|
|
93
|
+
setLocalSolvedCount(archiveCount + solvingCount);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
setStatus("success");
|
|
97
|
+
setTimeout(() => {
|
|
98
|
+
onComplete();
|
|
99
|
+
}, 5e3);
|
|
100
|
+
} catch (err) {
|
|
101
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
102
|
+
setStatus("error");
|
|
103
|
+
setTimeout(() => {
|
|
104
|
+
onComplete();
|
|
105
|
+
}, 3e3);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
void fetchData();
|
|
52
109
|
}, [handle, onComplete]);
|
|
53
110
|
return {
|
|
54
111
|
status,
|
|
55
112
|
user,
|
|
113
|
+
top100,
|
|
114
|
+
localSolvedCount,
|
|
56
115
|
error
|
|
57
116
|
};
|
|
58
117
|
}
|
|
59
118
|
|
|
60
119
|
// src/commands/stats.tsx
|
|
61
120
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
121
|
+
var statsFlagsSchema = {
|
|
122
|
+
handle: {
|
|
123
|
+
type: "string",
|
|
124
|
+
shortFlag: "h",
|
|
125
|
+
description: "Solved.ac \uD578\uB4E4 (\uC124\uC815\uC5D0 \uC800\uC7A5\uB41C \uAC12 \uC0AC\uC6A9 \uAC00\uB2A5)"
|
|
126
|
+
}
|
|
127
|
+
};
|
|
62
128
|
function ProgressBarWithColor({ value, colorFn }) {
|
|
63
129
|
const width = process.stdout.columns || 40;
|
|
64
130
|
const barWidth = Math.max(10, Math.min(30, width - 20));
|
|
@@ -69,10 +135,11 @@ function ProgressBarWithColor({ value, colorFn }) {
|
|
|
69
135
|
const barText = filledBar + emptyBar;
|
|
70
136
|
return /* @__PURE__ */ jsx(Transform, { transform: (output) => colorFn(output), children: /* @__PURE__ */ jsx(Text, { children: barText }) });
|
|
71
137
|
}
|
|
72
|
-
function StatsView({ handle, onComplete }) {
|
|
73
|
-
const { status, user, error } = useUserStats({
|
|
138
|
+
function StatsView({ handle, onComplete, showLocalStats }) {
|
|
139
|
+
const { status, user, top100, localSolvedCount, error } = useUserStats({
|
|
74
140
|
handle,
|
|
75
|
-
onComplete
|
|
141
|
+
onComplete,
|
|
142
|
+
fetchLocalCount: showLocalStats
|
|
76
143
|
});
|
|
77
144
|
if (status === "loading") {
|
|
78
145
|
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsx(Spinner, { label: "\uD1B5\uACC4\uB97C \uBD88\uB7EC\uC624\uB294 \uC911..." }) });
|
|
@@ -90,10 +157,16 @@ function StatsView({ handle, onComplete }) {
|
|
|
90
157
|
const nextTierMin = getNextTierMinRating(user.tier);
|
|
91
158
|
const progress = user.tier === 31 ? 100 : calculateTierProgress(user.rating, user.tier);
|
|
92
159
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
93
|
-
/* @__PURE__ */
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
160
|
+
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [
|
|
161
|
+
/* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
|
|
162
|
+
"\u2728 ",
|
|
163
|
+
user.handle
|
|
164
|
+
] }),
|
|
165
|
+
/* @__PURE__ */ jsxs(Text, { color: "blue", underline: true, children: [
|
|
166
|
+
"https://solved.ac/profile/",
|
|
167
|
+
user.handle
|
|
168
|
+
] })
|
|
169
|
+
] }),
|
|
97
170
|
/* @__PURE__ */ jsx(Box, { marginBottom: 1, flexDirection: "row", gap: 1, children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
98
171
|
tierColorFn(tierName),
|
|
99
172
|
" ",
|
|
@@ -113,7 +186,12 @@ function StatsView({ handle, onComplete }) {
|
|
|
113
186
|
"\uD574\uACB0\uD55C \uBB38\uC81C:",
|
|
114
187
|
" ",
|
|
115
188
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: user.solvedCount.toLocaleString() }),
|
|
116
|
-
"\uAC1C"
|
|
189
|
+
"\uAC1C",
|
|
190
|
+
localSolvedCount !== null && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
191
|
+
" (\uB85C\uCEEC: ",
|
|
192
|
+
localSolvedCount,
|
|
193
|
+
"\uAC1C)"
|
|
194
|
+
] })
|
|
117
195
|
] }),
|
|
118
196
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
119
197
|
"\uD074\uB798\uC2A4: ",
|
|
@@ -132,7 +210,17 @@ function StatsView({ handle, onComplete }) {
|
|
|
132
210
|
] })
|
|
133
211
|
] })
|
|
134
212
|
}
|
|
135
|
-
)
|
|
213
|
+
),
|
|
214
|
+
top100 && top100.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
215
|
+
/* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "\u{1F3C6} \uC0C1\uC704 100\uBB38\uC81C \uD2F0\uC5B4 \uBD84\uD3EC" }) }),
|
|
216
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children: Array.from({ length: Math.ceil(top100.length / 10) }).map(
|
|
217
|
+
(_, rowIndex) => /* @__PURE__ */ jsx(Box, { flexDirection: "row", children: top100.slice(rowIndex * 10, (rowIndex + 1) * 10).map((p, colIndex) => {
|
|
218
|
+
const tierColor2 = getTierColor(p.level);
|
|
219
|
+
const tierColorFn2 = typeof tierColor2 === "string" ? source_default.hex(tierColor2) : tierColor2.multiline;
|
|
220
|
+
return /* @__PURE__ */ jsx(Box, { width: 4, children: /* @__PURE__ */ jsx(Text, { children: tierColorFn2(getTierShortName(p.level)) }) }, colIndex);
|
|
221
|
+
}) }, rowIndex)
|
|
222
|
+
) })
|
|
223
|
+
] })
|
|
136
224
|
] });
|
|
137
225
|
}
|
|
138
226
|
return null;
|
|
@@ -153,8 +241,10 @@ var StatsCommand = class extends Command {
|
|
|
153
241
|
process.exit(1);
|
|
154
242
|
return;
|
|
155
243
|
}
|
|
244
|
+
const showLocalStats = !args[0] && !flags.handle;
|
|
156
245
|
await this.renderView(StatsView, {
|
|
157
|
-
handle
|
|
246
|
+
handle,
|
|
247
|
+
showLocalStats
|
|
158
248
|
});
|
|
159
249
|
}
|
|
160
250
|
};
|
|
@@ -164,15 +254,7 @@ StatsCommand = __decorateClass([
|
|
|
164
254
|
description: `Solved.ac\uC5D0\uC11C \uC0AC\uC6A9\uC790 \uD1B5\uACC4\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4.
|
|
165
255
|
- \uD2F0\uC5B4, \uB808\uC774\uD305, \uD574\uACB0\uD55C \uBB38\uC81C \uC218 \uB4F1 \uD45C\uC2DC
|
|
166
256
|
- \uADF8\uB77C\uB370\uC774\uC158\uC73C\uB85C \uC2DC\uAC01\uC801\uC73C\uB85C \uD45C\uC2DC`,
|
|
167
|
-
flags:
|
|
168
|
-
{
|
|
169
|
-
name: "handle",
|
|
170
|
-
options: {
|
|
171
|
-
shortFlag: "h",
|
|
172
|
-
description: "Solved.ac \uD578\uB4E4 (\uC124\uC815\uC5D0 \uC800\uC7A5\uB41C \uAC12 \uC0AC\uC6A9 \uAC00\uB2A5)"
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
],
|
|
257
|
+
flags: defineFlags(statsFlagsSchema),
|
|
176
258
|
autoDetectProblemId: false,
|
|
177
259
|
examples: ["stats myhandle", "stats --handle myhandle"]
|
|
178
260
|
})
|
package/dist/commands/submit.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
openBrowser
|
|
4
4
|
} from "../chunk-QGMWUOJ3.js";
|
|
5
|
+
import {
|
|
6
|
+
defineFlags
|
|
7
|
+
} from "../chunk-PY6GW22W.js";
|
|
5
8
|
import {
|
|
6
9
|
Command,
|
|
7
10
|
CommandBuilder,
|
|
@@ -10,7 +13,7 @@ import {
|
|
|
10
13
|
findSolutionFile,
|
|
11
14
|
resolveLanguage,
|
|
12
15
|
resolveProblemContext
|
|
13
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-JPDN34C7.js";
|
|
14
17
|
import {
|
|
15
18
|
__decorateClass,
|
|
16
19
|
getSupportedLanguagesString
|
|
@@ -117,6 +120,14 @@ function useSubmit({
|
|
|
117
120
|
|
|
118
121
|
// src/commands/submit.tsx
|
|
119
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
|
+
};
|
|
120
131
|
function SubmitView({
|
|
121
132
|
problemId,
|
|
122
133
|
language,
|
|
@@ -224,16 +235,7 @@ SubmitCommand = __decorateClass([
|
|
|
224
235
|
- solution.* \uD30C\uC77C\uC744 \uC790\uB3D9\uC73C\uB85C \uCC3E\uC544 \uC5B8\uC5B4 \uAC10\uC9C0
|
|
225
236
|
- \uC18C\uC2A4 \uCF54\uB4DC\uB97C \uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uC790\uB3D9 \uBCF5\uC0AC
|
|
226
237
|
- \uC81C\uCD9C \uD398\uC774\uC9C0\uB97C \uBE0C\uB77C\uC6B0\uC800\uB85C \uC790\uB3D9 \uC5F4\uAE30`,
|
|
227
|
-
flags:
|
|
228
|
-
{
|
|
229
|
-
name: "language",
|
|
230
|
-
options: {
|
|
231
|
-
shortFlag: "l",
|
|
232
|
-
description: `\uC5B8\uC5B4 \uC120\uD0DD (\uC9C0\uC815 \uC2DC \uC790\uB3D9 \uAC10\uC9C0 \uBB34\uC2DC)
|
|
233
|
-
\uC9C0\uC6D0 \uC5B8\uC5B4: ${getSupportedLanguagesString()}`
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
],
|
|
238
|
+
flags: defineFlags(submitFlagsSchema),
|
|
237
239
|
autoDetectProblemId: true,
|
|
238
240
|
autoDetectLanguage: true,
|
|
239
241
|
requireProblemId: true,
|
package/dist/commands/test.js
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runSolution
|
|
4
4
|
} from "../chunk-VIHXBCOZ.js";
|
|
5
|
+
import {
|
|
6
|
+
defineFlags
|
|
7
|
+
} from "../chunk-PY6GW22W.js";
|
|
5
8
|
import {
|
|
6
9
|
Command,
|
|
7
10
|
CommandBuilder,
|
|
8
11
|
CommandDef,
|
|
9
12
|
resolveLanguage,
|
|
10
13
|
resolveProblemContext
|
|
11
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-JPDN34C7.js";
|
|
12
15
|
import {
|
|
13
16
|
__decorateClass,
|
|
14
17
|
getSupportedLanguagesString
|
|
@@ -281,6 +284,20 @@ function useTestRunner({
|
|
|
281
284
|
|
|
282
285
|
// src/commands/test.tsx
|
|
283
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
|
+
};
|
|
284
301
|
function TestView({
|
|
285
302
|
problemDir,
|
|
286
303
|
language,
|
|
@@ -342,24 +359,7 @@ TestCommand = __decorateClass([
|
|
|
342
359
|
- testcases/{\uBC88\uD638}/input.txt\uC640 testcases/{\uBC88\uD638}/output.txt \uD30C\uC77C\uC744 \uAE30\uBC18\uC73C\uB85C \uD14C\uC2A4\uD2B8
|
|
343
360
|
- \uBB38\uC81C\uC758 \uC2DC\uAC04 \uC81C\uD55C\uC744 \uC790\uB3D9\uC73C\uB85C \uC801\uC6A9
|
|
344
361
|
- --watch \uC635\uC158\uC73C\uB85C \uD30C\uC77C \uBCC0\uACBD \uC2DC \uC790\uB3D9 \uC7AC\uD14C\uC2A4\uD2B8`,
|
|
345
|
-
flags:
|
|
346
|
-
{
|
|
347
|
-
name: "language",
|
|
348
|
-
options: {
|
|
349
|
-
shortFlag: "l",
|
|
350
|
-
description: `\uC5B8\uC5B4 \uC120\uD0DD (\uC9C0\uC815 \uC2DC \uC790\uB3D9 \uAC10\uC9C0 \uBB34\uC2DC)
|
|
351
|
-
\uC9C0\uC6D0 \uC5B8\uC5B4: ${getSupportedLanguagesString()}`
|
|
352
|
-
}
|
|
353
|
-
},
|
|
354
|
-
{
|
|
355
|
-
name: "watch",
|
|
356
|
-
options: {
|
|
357
|
-
shortFlag: "w",
|
|
358
|
-
description: `watch \uBAA8\uB4DC (\uD30C\uC77C \uBCC0\uACBD \uC2DC \uC790\uB3D9 \uC7AC\uD14C\uC2A4\uD2B8)
|
|
359
|
-
solution.*, testcases/**/*.txt \uD30C\uC77C \uBCC0\uACBD \uAC10\uC9C0`
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
],
|
|
362
|
+
flags: defineFlags(testFlagsSchema),
|
|
363
363
|
autoDetectProblemId: true,
|
|
364
364
|
autoDetectLanguage: true,
|
|
365
365
|
examples: [
|
package/dist/index.js
CHANGED
|
@@ -9471,7 +9471,8 @@ async function main() {
|
|
|
9471
9471
|
if (!commands) {
|
|
9472
9472
|
commands = await loadCommands();
|
|
9473
9473
|
}
|
|
9474
|
-
const [command, ...
|
|
9474
|
+
const [command, ...initialArgs] = cli.input;
|
|
9475
|
+
let rawArgs = initialArgs;
|
|
9475
9476
|
if (command === "help" || !command && cli.flags.help) {
|
|
9476
9477
|
const helpText = generateHelpText(commands);
|
|
9477
9478
|
console.log(helpText.trim());
|
|
@@ -9493,6 +9494,80 @@ async function main() {
|
|
|
9493
9494
|
process.exit(1);
|
|
9494
9495
|
return;
|
|
9495
9496
|
}
|
|
9497
|
+
let finalFlags = cli.flags;
|
|
9498
|
+
const commandIndex = process.argv.findIndex((arg) => arg === command);
|
|
9499
|
+
const commandArgs = commandIndex >= 0 ? process.argv.slice(commandIndex + 1) : process.argv.slice(2);
|
|
9500
|
+
if (commandDef.metadata?.flags) {
|
|
9501
|
+
const commandFlags = {};
|
|
9502
|
+
for (const flagDef of commandDef.metadata.flags) {
|
|
9503
|
+
const flagConfig = {
|
|
9504
|
+
type: flagDef.options?.type || "string"
|
|
9505
|
+
};
|
|
9506
|
+
if (flagDef.options?.shortFlag) {
|
|
9507
|
+
flagConfig.shortFlag = flagDef.options.shortFlag;
|
|
9508
|
+
}
|
|
9509
|
+
if (flagDef.options?.default !== void 0) {
|
|
9510
|
+
flagConfig.default = flagDef.options.default;
|
|
9511
|
+
}
|
|
9512
|
+
commandFlags[flagDef.name] = flagConfig;
|
|
9513
|
+
}
|
|
9514
|
+
const commandCli = meow("", {
|
|
9515
|
+
importMeta: import.meta,
|
|
9516
|
+
argv: commandArgs,
|
|
9517
|
+
autoHelp: false,
|
|
9518
|
+
// 기본 help 출력 비활성화 (우리가 직접 처리)
|
|
9519
|
+
flags: {
|
|
9520
|
+
help: {
|
|
9521
|
+
type: "boolean",
|
|
9522
|
+
shortFlag: "h",
|
|
9523
|
+
default: false
|
|
9524
|
+
},
|
|
9525
|
+
...commandFlags
|
|
9526
|
+
}
|
|
9527
|
+
});
|
|
9528
|
+
if (commandCli.flags.help) {
|
|
9529
|
+
if (commandDef.help && commandDef.help.trim()) {
|
|
9530
|
+
console.log(commandDef.help.trim());
|
|
9531
|
+
} else {
|
|
9532
|
+
console.log(`\uBA85\uB839\uC5B4: ${commandDef.name}`);
|
|
9533
|
+
if (commandDef.metadata?.description) {
|
|
9534
|
+
console.log(`\uC124\uBA85: ${commandDef.metadata.description}`);
|
|
9535
|
+
}
|
|
9536
|
+
}
|
|
9537
|
+
process.exit(0);
|
|
9538
|
+
return;
|
|
9539
|
+
}
|
|
9540
|
+
rawArgs = commandCli.input;
|
|
9541
|
+
finalFlags = { ...cli.flags, ...commandCli.flags };
|
|
9542
|
+
} else {
|
|
9543
|
+
const commandCli = meow("", {
|
|
9544
|
+
importMeta: import.meta,
|
|
9545
|
+
argv: commandArgs,
|
|
9546
|
+
autoHelp: false,
|
|
9547
|
+
// 기본 help 출력 비활성화 (우리가 직접 처리)
|
|
9548
|
+
flags: {
|
|
9549
|
+
help: {
|
|
9550
|
+
type: "boolean",
|
|
9551
|
+
shortFlag: "h",
|
|
9552
|
+
default: false
|
|
9553
|
+
}
|
|
9554
|
+
}
|
|
9555
|
+
});
|
|
9556
|
+
if (commandCli.flags.help) {
|
|
9557
|
+
if (commandDef.help && commandDef.help.trim()) {
|
|
9558
|
+
console.log(commandDef.help.trim());
|
|
9559
|
+
} else {
|
|
9560
|
+
console.log(`\uBA85\uB839\uC5B4: ${commandDef.name}`);
|
|
9561
|
+
if (commandDef.metadata?.description) {
|
|
9562
|
+
console.log(`\uC124\uBA85: ${commandDef.metadata.description}`);
|
|
9563
|
+
}
|
|
9564
|
+
}
|
|
9565
|
+
process.exit(0);
|
|
9566
|
+
return;
|
|
9567
|
+
}
|
|
9568
|
+
rawArgs = commandCli.input;
|
|
9569
|
+
finalFlags = { ...cli.flags, ...commandCli.flags };
|
|
9570
|
+
}
|
|
9496
9571
|
if (command !== "init") {
|
|
9497
9572
|
let currentDir = process.cwd();
|
|
9498
9573
|
let found = false;
|
|
@@ -9517,7 +9592,7 @@ async function main() {
|
|
|
9517
9592
|
return;
|
|
9518
9593
|
}
|
|
9519
9594
|
}
|
|
9520
|
-
await commandDef.execute(
|
|
9595
|
+
await commandDef.execute(rawArgs, finalFlags);
|
|
9521
9596
|
}
|
|
9522
9597
|
main().catch((error) => {
|
|
9523
9598
|
console.error("\uC624\uB958:", error.message);
|