@night-slayer18/leetcode-cli 1.0.1 → 1.1.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 +74 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +241 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -117,6 +117,42 @@ leetcode submit 20.valid-parentheses.java
|
|
|
117
117
|
|
|
118
118
|
# Using full path
|
|
119
119
|
leetcode test ./Easy/String/20.valid-parentheses.java
|
|
120
|
+
|
|
121
|
+
# With custom test case
|
|
122
|
+
leetcode test 20 -c "[1,2,3]\n4"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Random Problem
|
|
126
|
+
|
|
127
|
+
Fetch and solve a random problem.
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# Get random problem
|
|
131
|
+
leetcode random
|
|
132
|
+
|
|
133
|
+
# Filter by difficulty
|
|
134
|
+
leetcode random -d hard
|
|
135
|
+
|
|
136
|
+
# Filter by topic tag
|
|
137
|
+
leetcode random -t dp
|
|
138
|
+
|
|
139
|
+
# Pick immediately
|
|
140
|
+
leetcode random -d medium --pick
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### View & Download Submissions
|
|
144
|
+
|
|
145
|
+
View past submissions and download code.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# List last 20 submissions
|
|
149
|
+
leetcode submissions 1
|
|
150
|
+
|
|
151
|
+
# View details of last accepted submission
|
|
152
|
+
leetcode submissions 1 --last
|
|
153
|
+
|
|
154
|
+
# Download last accepted solution
|
|
155
|
+
leetcode submissions 1 --download
|
|
120
156
|
```
|
|
121
157
|
|
|
122
158
|
### Configuration
|
|
@@ -200,6 +236,44 @@ Config is stored at `~/.leetcode/config.json`:
|
|
|
200
236
|
|
|
201
237
|
- Node.js >= 20.0.0
|
|
202
238
|
|
|
239
|
+
## Docker Usage
|
|
240
|
+
|
|
241
|
+
You can run the CLI using Docker without installing Node.js.
|
|
242
|
+
|
|
243
|
+
### Method 1: Pre-built Image (Recommended)
|
|
244
|
+
|
|
245
|
+
1. **Pull the image**:
|
|
246
|
+
```bash
|
|
247
|
+
docker pull nightslayer/leetcode-cli:latest
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
2. **Setup Alias** (Add to your `~/.zshrc` or `~/.bashrc`):
|
|
251
|
+
```bash
|
|
252
|
+
alias leetcode="docker run -it --rm -v \$(pwd)/leetcode:/root/leetcode -v ~/.leetcode:/root/.leetcode nightslayer/leetcode-cli:latest"
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
3. **Usage**:
|
|
256
|
+
```bash
|
|
257
|
+
leetcode list
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Method 2: Build Locally
|
|
261
|
+
|
|
262
|
+
1. **Build the image**:
|
|
263
|
+
```bash
|
|
264
|
+
docker build -t leetcode-cli .
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
2. **Run commands**:
|
|
268
|
+
```bash
|
|
269
|
+
# Run 'list' command
|
|
270
|
+
docker run -it --rm \
|
|
271
|
+
-v $(pwd)/leetcode:/root/leetcode \
|
|
272
|
+
-v ~/.leetcode:/root/.leetcode \
|
|
273
|
+
leetcode-cli list
|
|
274
|
+
```
|
|
275
|
+
*Note: We mount `~/.leetcode` to persist login credentials and `leetcode` folder to save solution files.*
|
|
276
|
+
|
|
203
277
|
## License
|
|
204
278
|
|
|
205
279
|
Apache-2.0 © [night-slayer18](https://github.com/night-slayer18)
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
export { }
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
1
|
// src/index.ts
|
|
4
2
|
import { Command } from "commander";
|
|
5
|
-
import
|
|
3
|
+
import chalk13 from "chalk";
|
|
6
4
|
|
|
7
5
|
// src/commands/login.ts
|
|
8
6
|
import inquirer from "inquirer";
|
|
@@ -121,6 +119,41 @@ var DAILY_CHALLENGE_QUERY = `
|
|
|
121
119
|
}
|
|
122
120
|
}
|
|
123
121
|
`;
|
|
122
|
+
var SUBMISSION_LIST_QUERY = `
|
|
123
|
+
query submissionList($questionSlug: String!, $limit: Int, $offset: Int) {
|
|
124
|
+
questionSubmissionList(
|
|
125
|
+
questionSlug: $questionSlug
|
|
126
|
+
limit: $limit
|
|
127
|
+
offset: $offset
|
|
128
|
+
) {
|
|
129
|
+
submissions {
|
|
130
|
+
id
|
|
131
|
+
statusDisplay
|
|
132
|
+
lang
|
|
133
|
+
runtime
|
|
134
|
+
timestamp
|
|
135
|
+
memory
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
`;
|
|
140
|
+
var RANDOM_PROBLEM_QUERY = `
|
|
141
|
+
query randomQuestion($categorySlug: String, $filters: QuestionListFilterInput) {
|
|
142
|
+
randomQuestion(categorySlug: $categorySlug, filters: $filters) {
|
|
143
|
+
titleSlug
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
`;
|
|
147
|
+
var SUBMISSION_DETAILS_QUERY = `
|
|
148
|
+
query submissionDetails($submissionId: Int!) {
|
|
149
|
+
submissionDetails(submissionId: $submissionId) {
|
|
150
|
+
code
|
|
151
|
+
lang {
|
|
152
|
+
name
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
`;
|
|
124
157
|
|
|
125
158
|
// src/api/client.ts
|
|
126
159
|
var LEETCODE_BASE_URL = "https://leetcode.com";
|
|
@@ -210,6 +243,20 @@ var LeetCodeClient = class {
|
|
|
210
243
|
const data = await this.graphql(DAILY_CHALLENGE_QUERY);
|
|
211
244
|
return data.activeDailyCodingChallengeQuestion;
|
|
212
245
|
}
|
|
246
|
+
async getRandomProblem(filters = {}) {
|
|
247
|
+
const variables = {
|
|
248
|
+
categorySlug: "",
|
|
249
|
+
filters: {}
|
|
250
|
+
};
|
|
251
|
+
if (filters.difficulty) {
|
|
252
|
+
variables.filters.difficulty = filters.difficulty;
|
|
253
|
+
}
|
|
254
|
+
if (filters.tags?.length) {
|
|
255
|
+
variables.filters.tags = filters.tags;
|
|
256
|
+
}
|
|
257
|
+
const data = await this.graphql(RANDOM_PROBLEM_QUERY, variables);
|
|
258
|
+
return data.randomQuestion.titleSlug;
|
|
259
|
+
}
|
|
213
260
|
async getUserProfile(username) {
|
|
214
261
|
const data = await this.graphql(USER_PROFILE_QUERY, { username });
|
|
215
262
|
const user = data.matchedUser;
|
|
@@ -222,6 +269,14 @@ var LeetCodeClient = class {
|
|
|
222
269
|
totalActiveDays: user.userCalendar.totalActiveDays
|
|
223
270
|
};
|
|
224
271
|
}
|
|
272
|
+
async getSubmissionList(slug, limit = 20, offset = 0) {
|
|
273
|
+
const data = await this.graphql(SUBMISSION_LIST_QUERY, { questionSlug: slug, limit, offset });
|
|
274
|
+
return data.questionSubmissionList.submissions;
|
|
275
|
+
}
|
|
276
|
+
async getSubmissionDetails(submissionId) {
|
|
277
|
+
const data = await this.graphql(SUBMISSION_DETAILS_QUERY, { submissionId });
|
|
278
|
+
return data.submissionDetails;
|
|
279
|
+
}
|
|
225
280
|
async testSolution(titleSlug, code, lang, testcases, questionId) {
|
|
226
281
|
const response = await this.client.post(`problems/${titleSlug}/interpret_solution/`, {
|
|
227
282
|
json: {
|
|
@@ -633,6 +688,33 @@ function formatStatus(status) {
|
|
|
633
688
|
return chalk2.gray("-");
|
|
634
689
|
}
|
|
635
690
|
}
|
|
691
|
+
function displaySubmissionsList(submissions) {
|
|
692
|
+
const table = new Table({
|
|
693
|
+
head: [
|
|
694
|
+
chalk2.cyan("ID"),
|
|
695
|
+
chalk2.cyan("Status"),
|
|
696
|
+
chalk2.cyan("Lang"),
|
|
697
|
+
chalk2.cyan("Runtime"),
|
|
698
|
+
chalk2.cyan("Memory"),
|
|
699
|
+
chalk2.cyan("Date")
|
|
700
|
+
],
|
|
701
|
+
colWidths: [12, 18, 15, 12, 12, 25],
|
|
702
|
+
style: { head: [], border: [] }
|
|
703
|
+
});
|
|
704
|
+
for (const s of submissions) {
|
|
705
|
+
const isAC = s.statusDisplay === "Accepted";
|
|
706
|
+
const cleanTime = new Date(parseInt(s.timestamp) * 1e3).toLocaleString();
|
|
707
|
+
table.push([
|
|
708
|
+
s.id,
|
|
709
|
+
isAC ? chalk2.green(s.statusDisplay) : chalk2.red(s.statusDisplay),
|
|
710
|
+
s.lang,
|
|
711
|
+
s.runtime,
|
|
712
|
+
s.memory,
|
|
713
|
+
cleanTime
|
|
714
|
+
]);
|
|
715
|
+
}
|
|
716
|
+
console.log(table.toString());
|
|
717
|
+
}
|
|
636
718
|
|
|
637
719
|
// src/commands/list.ts
|
|
638
720
|
async function listCommand(options) {
|
|
@@ -1253,9 +1335,135 @@ async function dailyCommand(options) {
|
|
|
1253
1335
|
}
|
|
1254
1336
|
}
|
|
1255
1337
|
|
|
1338
|
+
// src/commands/random.ts
|
|
1339
|
+
import ora9 from "ora";
|
|
1340
|
+
import chalk10 from "chalk";
|
|
1341
|
+
async function randomCommand(options) {
|
|
1342
|
+
const credentials = config.getCredentials();
|
|
1343
|
+
if (credentials) {
|
|
1344
|
+
leetcodeClient.setCredentials(credentials);
|
|
1345
|
+
}
|
|
1346
|
+
const spinner = ora9("Fetching random problem...").start();
|
|
1347
|
+
try {
|
|
1348
|
+
const filters = {};
|
|
1349
|
+
if (options.difficulty) {
|
|
1350
|
+
const diffMap = {
|
|
1351
|
+
easy: "EASY",
|
|
1352
|
+
e: "EASY",
|
|
1353
|
+
medium: "MEDIUM",
|
|
1354
|
+
m: "MEDIUM",
|
|
1355
|
+
hard: "HARD",
|
|
1356
|
+
h: "HARD"
|
|
1357
|
+
};
|
|
1358
|
+
const diff = diffMap[options.difficulty.toLowerCase()];
|
|
1359
|
+
if (diff) {
|
|
1360
|
+
filters.difficulty = diff;
|
|
1361
|
+
} else {
|
|
1362
|
+
spinner.fail(`Invalid difficulty: ${options.difficulty}`);
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
if (options.tag) {
|
|
1367
|
+
filters.tags = [options.tag];
|
|
1368
|
+
}
|
|
1369
|
+
const titleSlug = await leetcodeClient.getRandomProblem(filters);
|
|
1370
|
+
spinner.succeed("Found random problem!");
|
|
1371
|
+
console.log();
|
|
1372
|
+
if (options.pick) {
|
|
1373
|
+
await pickCommand(titleSlug, { open: options.open ?? true });
|
|
1374
|
+
} else {
|
|
1375
|
+
await showCommand(titleSlug);
|
|
1376
|
+
console.log(chalk10.gray("Run following to start solving:"));
|
|
1377
|
+
console.log(chalk10.cyan(` leetcode pick ${titleSlug}`));
|
|
1378
|
+
}
|
|
1379
|
+
} catch (error) {
|
|
1380
|
+
spinner.fail("Failed to fetch random problem");
|
|
1381
|
+
if (error instanceof Error) {
|
|
1382
|
+
console.log(chalk10.red(error.message));
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
// src/commands/submissions.ts
|
|
1388
|
+
import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
1389
|
+
import { existsSync as existsSync4 } from "fs";
|
|
1390
|
+
import { join as join5 } from "path";
|
|
1391
|
+
import ora10 from "ora";
|
|
1392
|
+
import chalk11 from "chalk";
|
|
1393
|
+
async function submissionsCommand(idOrSlug, options) {
|
|
1394
|
+
const credentials = config.getCredentials();
|
|
1395
|
+
if (!credentials) {
|
|
1396
|
+
console.log(chalk11.red("Please login first to view submissions."));
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1399
|
+
leetcodeClient.setCredentials(credentials);
|
|
1400
|
+
const spinner = ora10("Fetching problem info...").start();
|
|
1401
|
+
try {
|
|
1402
|
+
let problem;
|
|
1403
|
+
if (/^\d+$/.test(idOrSlug)) {
|
|
1404
|
+
problem = await leetcodeClient.getProblemById(idOrSlug);
|
|
1405
|
+
} else {
|
|
1406
|
+
problem = await leetcodeClient.getProblem(idOrSlug);
|
|
1407
|
+
}
|
|
1408
|
+
if (!problem) {
|
|
1409
|
+
spinner.fail(`Problem "${idOrSlug}" not found`);
|
|
1410
|
+
return;
|
|
1411
|
+
}
|
|
1412
|
+
const slug = problem.titleSlug;
|
|
1413
|
+
spinner.text = "Fetching submissions...";
|
|
1414
|
+
const limit = options.limit ? parseInt(options.limit, 10) : 20;
|
|
1415
|
+
const submissions = await leetcodeClient.getSubmissionList(slug, limit);
|
|
1416
|
+
spinner.stop();
|
|
1417
|
+
if (submissions.length === 0) {
|
|
1418
|
+
console.log(chalk11.yellow("No submissions found."));
|
|
1419
|
+
return;
|
|
1420
|
+
}
|
|
1421
|
+
if (options.last) {
|
|
1422
|
+
const lastAC = submissions.find((s) => s.statusDisplay === "Accepted");
|
|
1423
|
+
if (lastAC) {
|
|
1424
|
+
console.log(chalk11.bold("Last Accepted Submission:"));
|
|
1425
|
+
displaySubmissionsList([lastAC]);
|
|
1426
|
+
} else {
|
|
1427
|
+
console.log(chalk11.yellow("No accepted submissions found in recent history."));
|
|
1428
|
+
}
|
|
1429
|
+
} else {
|
|
1430
|
+
displaySubmissionsList(submissions);
|
|
1431
|
+
}
|
|
1432
|
+
if (options.download) {
|
|
1433
|
+
const downloadSpinner = ora10("Downloading submission...").start();
|
|
1434
|
+
const lastAC = submissions.find((s) => s.statusDisplay === "Accepted");
|
|
1435
|
+
if (!lastAC) {
|
|
1436
|
+
downloadSpinner.fail("No accepted submission found to download.");
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
const details = await leetcodeClient.getSubmissionDetails(parseInt(lastAC.id, 10));
|
|
1440
|
+
const workDir = config.getWorkDir();
|
|
1441
|
+
const difficulty = problem.difficulty;
|
|
1442
|
+
const category = problem.topicTags.length > 0 ? problem.topicTags[0].name.replace(/[^\w\s-]/g, "").trim() : "Uncategorized";
|
|
1443
|
+
const targetDir = join5(workDir, difficulty, category);
|
|
1444
|
+
if (!existsSync4(targetDir)) {
|
|
1445
|
+
await mkdir2(targetDir, { recursive: true });
|
|
1446
|
+
}
|
|
1447
|
+
const langSlug = details.lang.name;
|
|
1448
|
+
const supportedLang = LANG_SLUG_MAP[langSlug] ?? "txt";
|
|
1449
|
+
const ext = LANGUAGE_EXTENSIONS[supportedLang] ?? langSlug;
|
|
1450
|
+
const fileName = `${problem.questionFrontendId}.${problem.titleSlug}.submission-${lastAC.id}.${ext}`;
|
|
1451
|
+
const filePath = join5(targetDir, fileName);
|
|
1452
|
+
await writeFile2(filePath, details.code, "utf-8");
|
|
1453
|
+
downloadSpinner.succeed(`Downloaded to ${chalk11.green(fileName)}`);
|
|
1454
|
+
console.log(chalk11.gray(`Path: ${filePath}`));
|
|
1455
|
+
}
|
|
1456
|
+
} catch (error) {
|
|
1457
|
+
spinner.fail("Failed to fetch submissions");
|
|
1458
|
+
if (error instanceof Error) {
|
|
1459
|
+
console.log(chalk11.red(error.message));
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1256
1464
|
// src/commands/config.ts
|
|
1257
1465
|
import inquirer2 from "inquirer";
|
|
1258
|
-
import
|
|
1466
|
+
import chalk12 from "chalk";
|
|
1259
1467
|
var SUPPORTED_LANGUAGES = [
|
|
1260
1468
|
"typescript",
|
|
1261
1469
|
"javascript",
|
|
@@ -1277,20 +1485,20 @@ async function configCommand(options) {
|
|
|
1277
1485
|
if (options.lang) {
|
|
1278
1486
|
const lang = options.lang.toLowerCase();
|
|
1279
1487
|
if (!SUPPORTED_LANGUAGES.includes(lang)) {
|
|
1280
|
-
console.log(
|
|
1281
|
-
console.log(
|
|
1488
|
+
console.log(chalk12.red(`Unsupported language: ${options.lang}`));
|
|
1489
|
+
console.log(chalk12.gray(`Supported: ${SUPPORTED_LANGUAGES.join(", ")}`));
|
|
1282
1490
|
return;
|
|
1283
1491
|
}
|
|
1284
1492
|
config.setLanguage(lang);
|
|
1285
|
-
console.log(
|
|
1493
|
+
console.log(chalk12.green(`\u2713 Default language set to ${lang}`));
|
|
1286
1494
|
}
|
|
1287
1495
|
if (options.editor) {
|
|
1288
1496
|
config.setEditor(options.editor);
|
|
1289
|
-
console.log(
|
|
1497
|
+
console.log(chalk12.green(`\u2713 Editor set to ${options.editor}`));
|
|
1290
1498
|
}
|
|
1291
1499
|
if (options.workdir) {
|
|
1292
1500
|
config.setWorkDir(options.workdir);
|
|
1293
|
-
console.log(
|
|
1501
|
+
console.log(chalk12.green(`\u2713 Work directory set to ${options.workdir}`));
|
|
1294
1502
|
}
|
|
1295
1503
|
}
|
|
1296
1504
|
async function configInteractiveCommand() {
|
|
@@ -1320,40 +1528,41 @@ async function configInteractiveCommand() {
|
|
|
1320
1528
|
config.setEditor(answers.editor);
|
|
1321
1529
|
config.setWorkDir(answers.workDir);
|
|
1322
1530
|
console.log();
|
|
1323
|
-
console.log(
|
|
1531
|
+
console.log(chalk12.green("\u2713 Configuration saved"));
|
|
1324
1532
|
showCurrentConfig();
|
|
1325
1533
|
}
|
|
1326
1534
|
function showCurrentConfig() {
|
|
1327
1535
|
const currentConfig = config.getConfig();
|
|
1328
1536
|
const credentials = config.getCredentials();
|
|
1329
1537
|
console.log();
|
|
1330
|
-
console.log(
|
|
1331
|
-
console.log(
|
|
1538
|
+
console.log(chalk12.bold("LeetCode CLI Configuration"));
|
|
1539
|
+
console.log(chalk12.gray("\u2500".repeat(40)));
|
|
1332
1540
|
console.log();
|
|
1333
|
-
console.log(
|
|
1541
|
+
console.log(chalk12.gray("Config file:"), config.getPath());
|
|
1334
1542
|
console.log();
|
|
1335
|
-
console.log(
|
|
1336
|
-
console.log(
|
|
1337
|
-
console.log(
|
|
1338
|
-
console.log(
|
|
1543
|
+
console.log(chalk12.gray("Language: "), chalk12.white(currentConfig.language));
|
|
1544
|
+
console.log(chalk12.gray("Editor: "), chalk12.white(currentConfig.editor ?? "(not set)"));
|
|
1545
|
+
console.log(chalk12.gray("Work Dir: "), chalk12.white(currentConfig.workDir));
|
|
1546
|
+
console.log(chalk12.gray("Logged in: "), credentials ? chalk12.green("Yes") : chalk12.yellow("No"));
|
|
1339
1547
|
}
|
|
1340
1548
|
|
|
1341
1549
|
// src/index.ts
|
|
1342
1550
|
var program = new Command();
|
|
1343
1551
|
program.configureHelp({
|
|
1344
1552
|
sortSubcommands: true,
|
|
1345
|
-
subcommandTerm: (cmd) =>
|
|
1346
|
-
subcommandDescription: (cmd) =>
|
|
1347
|
-
optionTerm: (option) =>
|
|
1348
|
-
optionDescription: (option) =>
|
|
1553
|
+
subcommandTerm: (cmd) => chalk13.cyan(cmd.name()) + (cmd.alias() ? chalk13.gray(`|${cmd.alias()}`) : ""),
|
|
1554
|
+
subcommandDescription: (cmd) => chalk13.white(cmd.description()),
|
|
1555
|
+
optionTerm: (option) => chalk13.yellow(option.flags),
|
|
1556
|
+
optionDescription: (option) => chalk13.white(option.description)
|
|
1349
1557
|
});
|
|
1350
|
-
program.name("leetcode").usage("[command] [options]").description(
|
|
1351
|
-
${
|
|
1352
|
-
${
|
|
1353
|
-
${
|
|
1354
|
-
${
|
|
1355
|
-
${
|
|
1356
|
-
${
|
|
1558
|
+
program.name("leetcode").usage("[command] [options]").description(chalk13.bold.cyan("\u{1F525} A modern LeetCode CLI built with TypeScript")).version("1.1.0", "-v, --version", "Output the version number").helpOption("-h, --help", "Display help for command").addHelpText("after", `
|
|
1559
|
+
${chalk13.yellow("Examples:")}
|
|
1560
|
+
${chalk13.cyan("$ leetcode login")} Login to LeetCode
|
|
1561
|
+
${chalk13.cyan("$ leetcode list -d easy")} List easy problems
|
|
1562
|
+
${chalk13.cyan("$ leetcode random -d medium")} Get random medium problem
|
|
1563
|
+
${chalk13.cyan("$ leetcode pick 1")} Start solving "Two Sum"
|
|
1564
|
+
${chalk13.cyan("$ leetcode test 1")} Test your solution
|
|
1565
|
+
${chalk13.cyan("$ leetcode submit 1")} Submit your solution
|
|
1357
1566
|
`);
|
|
1358
1567
|
program.command("login").description("Login to LeetCode with browser cookies").action(loginCommand);
|
|
1359
1568
|
program.command("logout").description("Clear stored credentials").action(logoutCommand);
|
|
@@ -1361,9 +1570,11 @@ program.command("whoami").description("Check current login status").action(whoam
|
|
|
1361
1570
|
program.command("list").alias("l").description("List LeetCode problems").option("-d, --difficulty <level>", "Filter by difficulty (easy/medium/hard)").option("-s, --status <status>", "Filter by status (todo/solved/attempted)").option("-t, --tag <tags...>", "Filter by topic tags").option("-q, --search <keywords>", "Search by keywords").option("-n, --limit <number>", "Number of problems to show", "20").option("-p, --page <number>", "Page number", "1").action(listCommand);
|
|
1362
1571
|
program.command("show <id>").alias("s").description("Show problem description").action(showCommand);
|
|
1363
1572
|
program.command("daily").alias("d").description("Show today's daily challenge").action(dailyCommand);
|
|
1573
|
+
program.command("random").alias("r").description("Get a random problem").option("-d, --difficulty <level>", "Filter by difficulty (easy/medium/hard)").option("-t, --tag <tag>", "Filter by topic tag").option("--pick", "Auto-generate solution file").option("--no-open", "Do not open file in editor").action(randomCommand);
|
|
1364
1574
|
program.command("pick <id>").alias("p").description("Generate solution file for a problem").option("-l, --lang <language>", "Programming language for the solution").option("--no-open", "Do not open file in editor").action(pickCommand);
|
|
1365
1575
|
program.command("test <file>").alias("t").description("Test solution against sample test cases").option("-c, --testcase <testcase>", "Custom test case").action(testCommand);
|
|
1366
1576
|
program.command("submit <file>").alias("x").description("Submit solution to LeetCode").action(submitCommand);
|
|
1577
|
+
program.command("submissions <id>").description("View past submissions").option("-n, --limit <number>", "Number of submissions to show", "20").option("--last", "Show details of the last accepted submission").option("--download", "Download the last accepted submission code").action(submissionsCommand);
|
|
1367
1578
|
program.command("stat [username]").description("Show user statistics").action(statCommand);
|
|
1368
1579
|
program.command("config").description("View or set configuration").option("-l, --lang <language>", "Set default programming language").option("-e, --editor <editor>", "Set editor command").option("-w, --workdir <path>", "Set working directory for solutions").option("-i, --interactive", "Interactive configuration").action(async (options) => {
|
|
1369
1580
|
if (options.interactive) {
|
|
@@ -1376,8 +1587,8 @@ program.showHelpAfterError("(add --help for additional information)");
|
|
|
1376
1587
|
program.parse();
|
|
1377
1588
|
if (!process.argv.slice(2).length) {
|
|
1378
1589
|
console.log();
|
|
1379
|
-
console.log(
|
|
1380
|
-
console.log(
|
|
1590
|
+
console.log(chalk13.bold.cyan(" \u{1F525} LeetCode CLI"));
|
|
1591
|
+
console.log(chalk13.gray(" A modern command-line interface for LeetCode"));
|
|
1381
1592
|
console.log();
|
|
1382
1593
|
program.outputHelp();
|
|
1383
1594
|
}
|