@night-slayer18/leetcode-cli 1.3.2 → 1.4.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 +29 -1
- package/dist/index.js +575 -195
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,6 +18,7 @@ A modern, feature-rich LeetCode CLI built with TypeScript.
|
|
|
18
18
|
- 🎯 **Daily challenge** - Get today's problem
|
|
19
19
|
- ⚙️ **Configurable** - Set language, editor, and working directory
|
|
20
20
|
- 📂 **Smart file discovery** - Use problem ID, filename, or full path
|
|
21
|
+
- 🔄 **Git Sync** - Auto-sync solutions to GitHub/GitLab
|
|
21
22
|
|
|
22
23
|
## 📚 Documentation
|
|
23
24
|
|
|
@@ -70,7 +71,9 @@ leetcode submit 1
|
|
|
70
71
|
| `submit <id\|file>` | Submit solution to LeetCode |
|
|
71
72
|
| `submissions <id>` | View past submissions |
|
|
72
73
|
| `stat [username]` | Show user statistics |
|
|
74
|
+
| `stat [username]` | Show user statistics |
|
|
73
75
|
| `config` | View or set configuration |
|
|
76
|
+
| `sync` | Sync solutions to Git repository |
|
|
74
77
|
|
|
75
78
|
## Usage Examples
|
|
76
79
|
|
|
@@ -181,6 +184,29 @@ leetcode submissions 1 --download
|
|
|
181
184
|
# Keep personal notes
|
|
182
185
|
leetcode note 1 edit
|
|
183
186
|
```
|
|
187
|
+
|
|
188
|
+
### User Statistics
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Basic stats (solved count, rank, streak)
|
|
192
|
+
leetcode stat
|
|
193
|
+
|
|
194
|
+
# Weekly activity table (last 12 weeks)
|
|
195
|
+
leetcode stat -c
|
|
196
|
+
|
|
197
|
+
# Skill breakdown by topic tags
|
|
198
|
+
leetcode stat -s
|
|
199
|
+
|
|
200
|
+
# 7-day trend chart
|
|
201
|
+
leetcode stat -t
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Git Integration
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# Sync all solutions to your configured git repo
|
|
208
|
+
leetcode sync
|
|
209
|
+
```
|
|
184
210
|
|
|
185
211
|
### Configuration
|
|
186
212
|
|
|
@@ -195,6 +221,7 @@ leetcode config -i
|
|
|
195
221
|
leetcode config --lang python3
|
|
196
222
|
leetcode config --editor code
|
|
197
223
|
leetcode config --workdir ~/leetcode
|
|
224
|
+
leetcode config --repo https://github.com/username/leetcode-solutions.git
|
|
198
225
|
```
|
|
199
226
|
|
|
200
227
|
## Folder Structure
|
|
@@ -254,7 +281,8 @@ Config is stored at `~/.leetcode/config.json`:
|
|
|
254
281
|
"config": {
|
|
255
282
|
"language": "java",
|
|
256
283
|
"editor": "code",
|
|
257
|
-
"workDir": "/path/to/leetcode"
|
|
284
|
+
"workDir": "/path/to/leetcode",
|
|
285
|
+
"repo": "https://github.com/username/leetcode-solutions.git"
|
|
258
286
|
}
|
|
259
287
|
}
|
|
260
288
|
```
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import
|
|
5
|
+
import chalk20 from "chalk";
|
|
6
6
|
|
|
7
7
|
// src/commands/login.ts
|
|
8
8
|
import inquirer from "inquirer";
|
|
@@ -111,7 +111,8 @@ var UserProfileSchema = z.object({
|
|
|
111
111
|
}),
|
|
112
112
|
userCalendar: z.object({
|
|
113
113
|
streak: z.number(),
|
|
114
|
-
totalActiveDays: z.number()
|
|
114
|
+
totalActiveDays: z.number(),
|
|
115
|
+
submissionCalendar: z.string().optional()
|
|
115
116
|
})
|
|
116
117
|
});
|
|
117
118
|
var UserStatusSchema = z.object({
|
|
@@ -202,6 +203,30 @@ var USER_PROFILE_QUERY = `
|
|
|
202
203
|
userCalendar {
|
|
203
204
|
streak
|
|
204
205
|
totalActiveDays
|
|
206
|
+
submissionCalendar
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
`;
|
|
211
|
+
var SKILL_STATS_QUERY = `
|
|
212
|
+
query skillStats($username: String!) {
|
|
213
|
+
matchedUser(username: $username) {
|
|
214
|
+
tagProblemCounts {
|
|
215
|
+
fundamental {
|
|
216
|
+
tagName
|
|
217
|
+
tagSlug
|
|
218
|
+
problemsSolved
|
|
219
|
+
}
|
|
220
|
+
intermediate {
|
|
221
|
+
tagName
|
|
222
|
+
tagSlug
|
|
223
|
+
problemsSolved
|
|
224
|
+
}
|
|
225
|
+
advanced {
|
|
226
|
+
tagName
|
|
227
|
+
tagSlug
|
|
228
|
+
problemsSolved
|
|
229
|
+
}
|
|
205
230
|
}
|
|
206
231
|
}
|
|
207
232
|
}
|
|
@@ -381,9 +406,14 @@ var LeetCodeClient = class {
|
|
|
381
406
|
ranking: validated.profile.ranking,
|
|
382
407
|
acSubmissionNum: validated.submitStatsGlobal.acSubmissionNum,
|
|
383
408
|
streak: validated.userCalendar.streak,
|
|
384
|
-
totalActiveDays: validated.userCalendar.totalActiveDays
|
|
409
|
+
totalActiveDays: validated.userCalendar.totalActiveDays,
|
|
410
|
+
submissionCalendar: user.userCalendar.submissionCalendar
|
|
385
411
|
};
|
|
386
412
|
}
|
|
413
|
+
async getSkillStats(username) {
|
|
414
|
+
const data = await this.graphql(SKILL_STATS_QUERY, { username });
|
|
415
|
+
return data.matchedUser.tagProblemCounts;
|
|
416
|
+
}
|
|
387
417
|
async getSubmissionList(slug, limit = 20, offset = 0) {
|
|
388
418
|
const data = await this.graphql(SUBMISSION_LIST_QUERY, { questionSlug: slug, limit, offset });
|
|
389
419
|
const validated = z2.array(SubmissionSchema).parse(data.questionSubmissionList.submissions);
|
|
@@ -449,7 +479,8 @@ var schema = {
|
|
|
449
479
|
properties: {
|
|
450
480
|
language: { type: "string", default: "typescript" },
|
|
451
481
|
editor: { type: "string" },
|
|
452
|
-
workDir: { type: "string", default: join(homedir(), "leetcode") }
|
|
482
|
+
workDir: { type: "string", default: join(homedir(), "leetcode") },
|
|
483
|
+
repo: { type: "string" }
|
|
453
484
|
},
|
|
454
485
|
default: {
|
|
455
486
|
language: "typescript",
|
|
@@ -486,6 +517,12 @@ var config = {
|
|
|
486
517
|
setWorkDir(workDir) {
|
|
487
518
|
configStore.set("config.workDir", workDir);
|
|
488
519
|
},
|
|
520
|
+
setRepo(repo) {
|
|
521
|
+
configStore.set("config.repo", repo);
|
|
522
|
+
},
|
|
523
|
+
deleteRepo() {
|
|
524
|
+
configStore.delete("config.repo");
|
|
525
|
+
},
|
|
489
526
|
// Get specific config values
|
|
490
527
|
getLanguage() {
|
|
491
528
|
return configStore.get("config.language");
|
|
@@ -496,6 +533,9 @@ var config = {
|
|
|
496
533
|
getWorkDir() {
|
|
497
534
|
return configStore.get("config.workDir");
|
|
498
535
|
},
|
|
536
|
+
getRepo() {
|
|
537
|
+
return configStore.get("config.repo");
|
|
538
|
+
},
|
|
499
539
|
// Clear all config
|
|
500
540
|
clear() {
|
|
501
541
|
configStore.clear();
|
|
@@ -1427,8 +1467,121 @@ async function submitCommand(fileOrId) {
|
|
|
1427
1467
|
|
|
1428
1468
|
// src/commands/stat.ts
|
|
1429
1469
|
import ora7 from "ora";
|
|
1470
|
+
import chalk11 from "chalk";
|
|
1471
|
+
|
|
1472
|
+
// src/utils/stats-display.ts
|
|
1430
1473
|
import chalk10 from "chalk";
|
|
1431
|
-
|
|
1474
|
+
var MONTH_NAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
1475
|
+
function renderHeatmap(calendarJson) {
|
|
1476
|
+
const data = JSON.parse(calendarJson);
|
|
1477
|
+
const now = /* @__PURE__ */ new Date();
|
|
1478
|
+
const weeks = [];
|
|
1479
|
+
for (let w = 11; w >= 0; w--) {
|
|
1480
|
+
const weekStart = new Date(now);
|
|
1481
|
+
weekStart.setDate(weekStart.getDate() - w * 7 - weekStart.getDay());
|
|
1482
|
+
let weekCount = 0;
|
|
1483
|
+
let activeDays = 0;
|
|
1484
|
+
for (let d = 0; d < 7; d++) {
|
|
1485
|
+
const day = new Date(weekStart);
|
|
1486
|
+
day.setDate(day.getDate() + d);
|
|
1487
|
+
if (day > now) break;
|
|
1488
|
+
const midnight = new Date(Date.UTC(day.getFullYear(), day.getMonth(), day.getDate()));
|
|
1489
|
+
const timestamp = Math.floor(midnight.getTime() / 1e3).toString();
|
|
1490
|
+
const count = data[timestamp] || 0;
|
|
1491
|
+
weekCount += count;
|
|
1492
|
+
if (count > 0) activeDays++;
|
|
1493
|
+
}
|
|
1494
|
+
const weekEnd = new Date(weekStart);
|
|
1495
|
+
weekEnd.setDate(weekEnd.getDate() + 6);
|
|
1496
|
+
weeks.push({
|
|
1497
|
+
start: `${MONTH_NAMES[weekStart.getMonth()]} ${weekStart.getDate()}`,
|
|
1498
|
+
end: `${MONTH_NAMES[weekEnd.getMonth()]} ${weekEnd.getDate()}`,
|
|
1499
|
+
count: weekCount,
|
|
1500
|
+
days: activeDays
|
|
1501
|
+
});
|
|
1502
|
+
}
|
|
1503
|
+
const totalSubmissions = weeks.reduce((sum, w) => sum + w.count, 0);
|
|
1504
|
+
const totalActiveDays = weeks.reduce((sum, w) => sum + w.days, 0);
|
|
1505
|
+
console.log();
|
|
1506
|
+
console.log(chalk10.bold("\u{1F4C5} Activity (Last 12 Weeks)"));
|
|
1507
|
+
console.log(chalk10.gray("How many problems you submitted and days you practiced."));
|
|
1508
|
+
console.log(chalk10.gray("\u2500".repeat(50)));
|
|
1509
|
+
console.log();
|
|
1510
|
+
for (const week of weeks) {
|
|
1511
|
+
const weekLabel = `${week.start} - ${week.end}`.padEnd(18);
|
|
1512
|
+
const bar = week.count > 0 ? chalk10.green("\u2588".repeat(Math.min(week.count, 10))).padEnd(10) : chalk10.gray("\xB7").padEnd(10);
|
|
1513
|
+
const countStr = week.count > 0 ? `${week.count} subs`.padEnd(10) : "".padEnd(10);
|
|
1514
|
+
const daysStr = week.days > 0 ? `${week.days}d active` : "";
|
|
1515
|
+
console.log(` ${chalk10.white(weekLabel)} ${bar} ${chalk10.cyan(countStr)} ${chalk10.yellow(daysStr)}`);
|
|
1516
|
+
}
|
|
1517
|
+
console.log(chalk10.gray("\u2500".repeat(50)));
|
|
1518
|
+
console.log(` ${chalk10.bold.white("Total:")} ${chalk10.cyan.bold(totalSubmissions + " submissions")}, ${chalk10.yellow.bold(totalActiveDays + " days active")}`);
|
|
1519
|
+
console.log();
|
|
1520
|
+
}
|
|
1521
|
+
function renderSkillStats(fundamental, intermediate, advanced) {
|
|
1522
|
+
console.log();
|
|
1523
|
+
console.log(chalk10.bold("\u{1F3AF} Skill Breakdown"));
|
|
1524
|
+
console.log(chalk10.gray("\u2500".repeat(45)));
|
|
1525
|
+
const renderSection = (title, stats, color) => {
|
|
1526
|
+
if (stats.length === 0) return;
|
|
1527
|
+
console.log();
|
|
1528
|
+
console.log(color.bold(` ${title}`));
|
|
1529
|
+
const sorted = [...stats].sort((a, b) => b.problemsSolved - a.problemsSolved);
|
|
1530
|
+
for (const stat of sorted.slice(0, 8)) {
|
|
1531
|
+
const name = stat.tagName.padEnd(22);
|
|
1532
|
+
const bar = color("\u2588".repeat(Math.min(stat.problemsSolved, 15)));
|
|
1533
|
+
console.log(` ${chalk10.white(name)} ${bar} ${chalk10.white(stat.problemsSolved)}`);
|
|
1534
|
+
}
|
|
1535
|
+
};
|
|
1536
|
+
renderSection("Fundamental", fundamental, chalk10.green);
|
|
1537
|
+
renderSection("Intermediate", intermediate, chalk10.yellow);
|
|
1538
|
+
renderSection("Advanced", advanced, chalk10.red);
|
|
1539
|
+
console.log();
|
|
1540
|
+
}
|
|
1541
|
+
function renderTrendChart(calendarJson) {
|
|
1542
|
+
const data = JSON.parse(calendarJson);
|
|
1543
|
+
const now = /* @__PURE__ */ new Date();
|
|
1544
|
+
const dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1545
|
+
const days = [];
|
|
1546
|
+
for (let d = 6; d >= 0; d--) {
|
|
1547
|
+
const day = new Date(now);
|
|
1548
|
+
day.setDate(day.getDate() - d);
|
|
1549
|
+
const midnight = new Date(Date.UTC(day.getFullYear(), day.getMonth(), day.getDate()));
|
|
1550
|
+
const timestamp = Math.floor(midnight.getTime() / 1e3).toString();
|
|
1551
|
+
days.push({
|
|
1552
|
+
label: dayNames[day.getDay()],
|
|
1553
|
+
count: data[timestamp] || 0
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
const maxVal = Math.max(...days.map((d) => d.count), 1);
|
|
1557
|
+
const chartHeight = 6;
|
|
1558
|
+
console.log();
|
|
1559
|
+
console.log(chalk10.bold("\u{1F4C8} Submission Trend (Last 7 Days)"));
|
|
1560
|
+
console.log(chalk10.gray("\u2500".repeat(35)));
|
|
1561
|
+
console.log();
|
|
1562
|
+
for (let row = chartHeight; row >= 1; row--) {
|
|
1563
|
+
let line = ` ${row === chartHeight ? maxVal.toString().padStart(2) : " "} \u2502`;
|
|
1564
|
+
for (const day of days) {
|
|
1565
|
+
const barHeight = Math.round(day.count / maxVal * chartHeight);
|
|
1566
|
+
if (barHeight >= row) {
|
|
1567
|
+
line += chalk10.green(" \u2588\u2588 ");
|
|
1568
|
+
} else {
|
|
1569
|
+
line += " ";
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
console.log(line);
|
|
1573
|
+
}
|
|
1574
|
+
console.log(` 0 \u2514${"\u2500\u2500\u2500\u2500".repeat(7)}`);
|
|
1575
|
+
console.log(` ${days.map((d) => d.label.padEnd(4)).join("")}`);
|
|
1576
|
+
console.log(chalk10.gray(` ${days.map((d) => d.count.toString().padEnd(4)).join("")}`));
|
|
1577
|
+
const total = days.reduce((a, b) => a + b.count, 0);
|
|
1578
|
+
console.log();
|
|
1579
|
+
console.log(chalk10.white(` Total: ${total} submissions this week`));
|
|
1580
|
+
console.log();
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
// src/commands/stat.ts
|
|
1584
|
+
async function statCommand(username, options = {}) {
|
|
1432
1585
|
const { authorized, username: currentUser } = await requireAuth();
|
|
1433
1586
|
if (!authorized) return;
|
|
1434
1587
|
const spinner = ora7("Fetching statistics...").start();
|
|
@@ -1440,25 +1593,48 @@ async function statCommand(username) {
|
|
|
1440
1593
|
}
|
|
1441
1594
|
const profile = await leetcodeClient.getUserProfile(targetUsername);
|
|
1442
1595
|
spinner.stop();
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1596
|
+
if (!options.calendar && !options.skills && !options.trend) {
|
|
1597
|
+
displayUserStats(
|
|
1598
|
+
profile.username,
|
|
1599
|
+
profile.realName,
|
|
1600
|
+
profile.ranking,
|
|
1601
|
+
profile.acSubmissionNum,
|
|
1602
|
+
profile.streak,
|
|
1603
|
+
profile.totalActiveDays
|
|
1604
|
+
);
|
|
1605
|
+
return;
|
|
1606
|
+
}
|
|
1607
|
+
if (options.calendar) {
|
|
1608
|
+
if (profile.submissionCalendar) {
|
|
1609
|
+
renderHeatmap(profile.submissionCalendar);
|
|
1610
|
+
} else {
|
|
1611
|
+
console.log(chalk11.yellow("Calendar data not available."));
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
if (options.trend) {
|
|
1615
|
+
if (profile.submissionCalendar) {
|
|
1616
|
+
renderTrendChart(profile.submissionCalendar);
|
|
1617
|
+
} else {
|
|
1618
|
+
console.log(chalk11.yellow("Calendar data not available."));
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
if (options.skills) {
|
|
1622
|
+
spinner.start("Fetching skill stats...");
|
|
1623
|
+
const skills = await leetcodeClient.getSkillStats(targetUsername);
|
|
1624
|
+
spinner.stop();
|
|
1625
|
+
renderSkillStats(skills.fundamental, skills.intermediate, skills.advanced);
|
|
1626
|
+
}
|
|
1451
1627
|
} catch (error) {
|
|
1452
1628
|
spinner.fail("Failed to fetch statistics");
|
|
1453
1629
|
if (error instanceof Error) {
|
|
1454
|
-
console.log(
|
|
1630
|
+
console.log(chalk11.red(error.message));
|
|
1455
1631
|
}
|
|
1456
1632
|
}
|
|
1457
1633
|
}
|
|
1458
1634
|
|
|
1459
1635
|
// src/commands/daily.ts
|
|
1460
1636
|
import ora8 from "ora";
|
|
1461
|
-
import
|
|
1637
|
+
import chalk12 from "chalk";
|
|
1462
1638
|
async function dailyCommand() {
|
|
1463
1639
|
const { authorized } = await requireAuth();
|
|
1464
1640
|
if (!authorized) return;
|
|
@@ -1468,19 +1644,19 @@ async function dailyCommand() {
|
|
|
1468
1644
|
spinner.stop();
|
|
1469
1645
|
displayDailyChallenge(daily.date, daily.question);
|
|
1470
1646
|
console.log();
|
|
1471
|
-
console.log(
|
|
1472
|
-
console.log(
|
|
1647
|
+
console.log(chalk12.gray("Run the following to start working on this problem:"));
|
|
1648
|
+
console.log(chalk12.cyan(` leetcode pick ${daily.question.titleSlug}`));
|
|
1473
1649
|
} catch (error) {
|
|
1474
1650
|
spinner.fail("Failed to fetch daily challenge");
|
|
1475
1651
|
if (error instanceof Error) {
|
|
1476
|
-
console.log(
|
|
1652
|
+
console.log(chalk12.red(error.message));
|
|
1477
1653
|
}
|
|
1478
1654
|
}
|
|
1479
1655
|
}
|
|
1480
1656
|
|
|
1481
1657
|
// src/commands/random.ts
|
|
1482
1658
|
import ora9 from "ora";
|
|
1483
|
-
import
|
|
1659
|
+
import chalk13 from "chalk";
|
|
1484
1660
|
async function randomCommand(options) {
|
|
1485
1661
|
const { authorized } = await requireAuth();
|
|
1486
1662
|
if (!authorized) return;
|
|
@@ -1514,13 +1690,13 @@ async function randomCommand(options) {
|
|
|
1514
1690
|
await pickCommand(titleSlug, { open: options.open ?? true });
|
|
1515
1691
|
} else {
|
|
1516
1692
|
await showCommand(titleSlug);
|
|
1517
|
-
console.log(
|
|
1518
|
-
console.log(
|
|
1693
|
+
console.log(chalk13.gray("Run following to start solving:"));
|
|
1694
|
+
console.log(chalk13.cyan(` leetcode pick ${titleSlug}`));
|
|
1519
1695
|
}
|
|
1520
1696
|
} catch (error) {
|
|
1521
1697
|
spinner.fail("Failed to fetch random problem");
|
|
1522
1698
|
if (error instanceof Error) {
|
|
1523
|
-
console.log(
|
|
1699
|
+
console.log(chalk13.red(error.message));
|
|
1524
1700
|
}
|
|
1525
1701
|
}
|
|
1526
1702
|
}
|
|
@@ -1530,7 +1706,7 @@ import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
|
1530
1706
|
import { existsSync as existsSync5 } from "fs";
|
|
1531
1707
|
import { join as join4 } from "path";
|
|
1532
1708
|
import ora10 from "ora";
|
|
1533
|
-
import
|
|
1709
|
+
import chalk14 from "chalk";
|
|
1534
1710
|
async function submissionsCommand(idOrSlug, options) {
|
|
1535
1711
|
const { authorized } = await requireAuth();
|
|
1536
1712
|
if (!authorized) return;
|
|
@@ -1552,16 +1728,16 @@ async function submissionsCommand(idOrSlug, options) {
|
|
|
1552
1728
|
const submissions = await leetcodeClient.getSubmissionList(slug, limit);
|
|
1553
1729
|
spinner.stop();
|
|
1554
1730
|
if (submissions.length === 0) {
|
|
1555
|
-
console.log(
|
|
1731
|
+
console.log(chalk14.yellow("No submissions found."));
|
|
1556
1732
|
return;
|
|
1557
1733
|
}
|
|
1558
1734
|
if (options.last) {
|
|
1559
1735
|
const lastAC = submissions.find((s) => s.statusDisplay === "Accepted");
|
|
1560
1736
|
if (lastAC) {
|
|
1561
|
-
console.log(
|
|
1737
|
+
console.log(chalk14.bold("Last Accepted Submission:"));
|
|
1562
1738
|
displaySubmissionsList([lastAC]);
|
|
1563
1739
|
} else {
|
|
1564
|
-
console.log(
|
|
1740
|
+
console.log(chalk14.yellow("No accepted submissions found in recent history."));
|
|
1565
1741
|
}
|
|
1566
1742
|
} else {
|
|
1567
1743
|
displaySubmissionsList(submissions);
|
|
@@ -1592,20 +1768,20 @@ async function submissionsCommand(idOrSlug, options) {
|
|
|
1592
1768
|
const fileName = `${problem.questionFrontendId}.${problem.titleSlug}.submission-${lastAC.id}.${ext}`;
|
|
1593
1769
|
const filePath = join4(targetDir, fileName);
|
|
1594
1770
|
await writeFile2(filePath, details.code, "utf-8");
|
|
1595
|
-
downloadSpinner.succeed(`Downloaded to ${
|
|
1596
|
-
console.log(
|
|
1771
|
+
downloadSpinner.succeed(`Downloaded to ${chalk14.green(fileName)}`);
|
|
1772
|
+
console.log(chalk14.gray(`Path: ${filePath}`));
|
|
1597
1773
|
}
|
|
1598
1774
|
} catch (error) {
|
|
1599
1775
|
spinner.fail("Failed to fetch submissions");
|
|
1600
1776
|
if (error instanceof Error) {
|
|
1601
|
-
console.log(
|
|
1777
|
+
console.log(chalk14.red(error.message));
|
|
1602
1778
|
}
|
|
1603
1779
|
}
|
|
1604
1780
|
}
|
|
1605
1781
|
|
|
1606
1782
|
// src/commands/config.ts
|
|
1607
1783
|
import inquirer2 from "inquirer";
|
|
1608
|
-
import
|
|
1784
|
+
import chalk15 from "chalk";
|
|
1609
1785
|
var SUPPORTED_LANGUAGES = [
|
|
1610
1786
|
"typescript",
|
|
1611
1787
|
"javascript",
|
|
@@ -1627,21 +1803,30 @@ async function configCommand(options) {
|
|
|
1627
1803
|
if (options.lang) {
|
|
1628
1804
|
const langInput = options.lang.toLowerCase();
|
|
1629
1805
|
if (!SUPPORTED_LANGUAGES.includes(langInput)) {
|
|
1630
|
-
console.log(
|
|
1631
|
-
console.log(
|
|
1806
|
+
console.log(chalk15.red(`Unsupported language: ${options.lang}`));
|
|
1807
|
+
console.log(chalk15.gray(`Supported: ${SUPPORTED_LANGUAGES.join(", ")}`));
|
|
1632
1808
|
return;
|
|
1633
1809
|
}
|
|
1634
1810
|
const lang = langInput;
|
|
1635
1811
|
config.setLanguage(lang);
|
|
1636
|
-
console.log(
|
|
1812
|
+
console.log(chalk15.green(`\u2713 Default language set to ${lang}`));
|
|
1637
1813
|
}
|
|
1638
1814
|
if (options.editor) {
|
|
1639
1815
|
config.setEditor(options.editor);
|
|
1640
|
-
console.log(
|
|
1816
|
+
console.log(chalk15.green(`\u2713 Editor set to ${options.editor}`));
|
|
1641
1817
|
}
|
|
1642
1818
|
if (options.workdir) {
|
|
1643
1819
|
config.setWorkDir(options.workdir);
|
|
1644
|
-
console.log(
|
|
1820
|
+
console.log(chalk15.green(`\u2713 Work directory set to ${options.workdir}`));
|
|
1821
|
+
}
|
|
1822
|
+
if (options.repo !== void 0) {
|
|
1823
|
+
if (options.repo.trim() === "") {
|
|
1824
|
+
config.deleteRepo();
|
|
1825
|
+
console.log(chalk15.green("\u2713 Repository URL cleared"));
|
|
1826
|
+
} else {
|
|
1827
|
+
config.setRepo(options.repo);
|
|
1828
|
+
console.log(chalk15.green(`\u2713 Repository URL set to ${options.repo}`));
|
|
1829
|
+
}
|
|
1645
1830
|
}
|
|
1646
1831
|
}
|
|
1647
1832
|
async function configInteractiveCommand() {
|
|
@@ -1665,32 +1850,44 @@ async function configInteractiveCommand() {
|
|
|
1665
1850
|
name: "workDir",
|
|
1666
1851
|
message: "Working directory for solution files:",
|
|
1667
1852
|
default: currentConfig.workDir
|
|
1853
|
+
},
|
|
1854
|
+
{
|
|
1855
|
+
type: "input",
|
|
1856
|
+
name: "repo",
|
|
1857
|
+
message: "Git repository URL (optional):",
|
|
1858
|
+
default: currentConfig.repo
|
|
1668
1859
|
}
|
|
1669
1860
|
]);
|
|
1670
1861
|
config.setLanguage(answers.language);
|
|
1671
1862
|
config.setEditor(answers.editor);
|
|
1672
1863
|
config.setWorkDir(answers.workDir);
|
|
1864
|
+
if (answers.repo) {
|
|
1865
|
+
config.setRepo(answers.repo);
|
|
1866
|
+
} else {
|
|
1867
|
+
config.deleteRepo();
|
|
1868
|
+
}
|
|
1673
1869
|
console.log();
|
|
1674
|
-
console.log(
|
|
1870
|
+
console.log(chalk15.green("\u2713 Configuration saved"));
|
|
1675
1871
|
showCurrentConfig();
|
|
1676
1872
|
}
|
|
1677
1873
|
function showCurrentConfig() {
|
|
1678
1874
|
const currentConfig = config.getConfig();
|
|
1679
1875
|
const credentials = config.getCredentials();
|
|
1680
1876
|
console.log();
|
|
1681
|
-
console.log(
|
|
1682
|
-
console.log(
|
|
1877
|
+
console.log(chalk15.bold("LeetCode CLI Configuration"));
|
|
1878
|
+
console.log(chalk15.gray("\u2500".repeat(40)));
|
|
1683
1879
|
console.log();
|
|
1684
|
-
console.log(
|
|
1880
|
+
console.log(chalk15.gray("Config file:"), config.getPath());
|
|
1685
1881
|
console.log();
|
|
1686
|
-
console.log(
|
|
1687
|
-
console.log(
|
|
1688
|
-
console.log(
|
|
1689
|
-
console.log(
|
|
1882
|
+
console.log(chalk15.gray("Language: "), chalk15.white(currentConfig.language));
|
|
1883
|
+
console.log(chalk15.gray("Editor: "), chalk15.white(currentConfig.editor ?? "(not set)"));
|
|
1884
|
+
console.log(chalk15.gray("Work Dir: "), chalk15.white(currentConfig.workDir));
|
|
1885
|
+
console.log(chalk15.gray("Repo URL: "), chalk15.white(currentConfig.repo ?? "(not set)"));
|
|
1886
|
+
console.log(chalk15.gray("Logged in: "), credentials ? chalk15.green("Yes") : chalk15.yellow("No"));
|
|
1690
1887
|
}
|
|
1691
1888
|
|
|
1692
1889
|
// src/commands/bookmark.ts
|
|
1693
|
-
import
|
|
1890
|
+
import chalk16 from "chalk";
|
|
1694
1891
|
import Table2 from "cli-table3";
|
|
1695
1892
|
import ora11 from "ora";
|
|
1696
1893
|
|
|
@@ -1735,36 +1932,36 @@ var bookmarks = {
|
|
|
1735
1932
|
async function bookmarkCommand(action, id) {
|
|
1736
1933
|
const validActions = ["add", "remove", "list", "clear"];
|
|
1737
1934
|
if (!validActions.includes(action)) {
|
|
1738
|
-
console.log(
|
|
1739
|
-
console.log(
|
|
1935
|
+
console.log(chalk16.red(`Invalid action: ${action}`));
|
|
1936
|
+
console.log(chalk16.gray("Valid actions: add, remove, list, clear"));
|
|
1740
1937
|
return;
|
|
1741
1938
|
}
|
|
1742
1939
|
switch (action) {
|
|
1743
1940
|
case "add":
|
|
1744
1941
|
if (!id) {
|
|
1745
|
-
console.log(
|
|
1942
|
+
console.log(chalk16.red("Please provide a problem ID to bookmark"));
|
|
1746
1943
|
return;
|
|
1747
1944
|
}
|
|
1748
1945
|
if (!isProblemId(id)) {
|
|
1749
|
-
console.log(
|
|
1750
|
-
console.log(
|
|
1946
|
+
console.log(chalk16.red(`Invalid problem ID: ${id}`));
|
|
1947
|
+
console.log(chalk16.gray("Problem ID must be a positive integer"));
|
|
1751
1948
|
return;
|
|
1752
1949
|
}
|
|
1753
1950
|
if (bookmarks.add(id)) {
|
|
1754
|
-
console.log(
|
|
1951
|
+
console.log(chalk16.green(`\u2713 Bookmarked problem ${id}`));
|
|
1755
1952
|
} else {
|
|
1756
|
-
console.log(
|
|
1953
|
+
console.log(chalk16.yellow(`Problem ${id} is already bookmarked`));
|
|
1757
1954
|
}
|
|
1758
1955
|
break;
|
|
1759
1956
|
case "remove":
|
|
1760
1957
|
if (!id) {
|
|
1761
|
-
console.log(
|
|
1958
|
+
console.log(chalk16.red("Please provide a problem ID to remove"));
|
|
1762
1959
|
return;
|
|
1763
1960
|
}
|
|
1764
1961
|
if (bookmarks.remove(id)) {
|
|
1765
|
-
console.log(
|
|
1962
|
+
console.log(chalk16.green(`\u2713 Removed bookmark for problem ${id}`));
|
|
1766
1963
|
} else {
|
|
1767
|
-
console.log(
|
|
1964
|
+
console.log(chalk16.yellow(`Problem ${id} is not bookmarked`));
|
|
1768
1965
|
}
|
|
1769
1966
|
break;
|
|
1770
1967
|
case "list":
|
|
@@ -1773,10 +1970,10 @@ async function bookmarkCommand(action, id) {
|
|
|
1773
1970
|
case "clear":
|
|
1774
1971
|
const count = bookmarks.count();
|
|
1775
1972
|
if (count === 0) {
|
|
1776
|
-
console.log(
|
|
1973
|
+
console.log(chalk16.yellow("No bookmarks to clear"));
|
|
1777
1974
|
} else {
|
|
1778
1975
|
bookmarks.clear();
|
|
1779
|
-
console.log(
|
|
1976
|
+
console.log(chalk16.green(`\u2713 Cleared ${count} bookmark${count !== 1 ? "s" : ""}`));
|
|
1780
1977
|
}
|
|
1781
1978
|
break;
|
|
1782
1979
|
}
|
|
@@ -1784,12 +1981,12 @@ async function bookmarkCommand(action, id) {
|
|
|
1784
1981
|
async function listBookmarks() {
|
|
1785
1982
|
const bookmarkList = bookmarks.list();
|
|
1786
1983
|
if (bookmarkList.length === 0) {
|
|
1787
|
-
console.log(
|
|
1788
|
-
console.log(
|
|
1984
|
+
console.log(chalk16.yellow("\u{1F4CC} No bookmarked problems"));
|
|
1985
|
+
console.log(chalk16.gray('Use "leetcode bookmark add <id>" to bookmark a problem'));
|
|
1789
1986
|
return;
|
|
1790
1987
|
}
|
|
1791
1988
|
console.log();
|
|
1792
|
-
console.log(
|
|
1989
|
+
console.log(chalk16.bold.cyan(`\u{1F4CC} Bookmarked Problems (${bookmarkList.length})`));
|
|
1793
1990
|
console.log();
|
|
1794
1991
|
const { authorized } = await requireAuth();
|
|
1795
1992
|
if (authorized) {
|
|
@@ -1797,10 +1994,10 @@ async function listBookmarks() {
|
|
|
1797
1994
|
try {
|
|
1798
1995
|
const table = new Table2({
|
|
1799
1996
|
head: [
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1997
|
+
chalk16.cyan("ID"),
|
|
1998
|
+
chalk16.cyan("Title"),
|
|
1999
|
+
chalk16.cyan("Difficulty"),
|
|
2000
|
+
chalk16.cyan("Status")
|
|
1804
2001
|
],
|
|
1805
2002
|
colWidths: [8, 45, 12, 10],
|
|
1806
2003
|
style: { head: [], border: [] }
|
|
@@ -1813,35 +2010,35 @@ async function listBookmarks() {
|
|
|
1813
2010
|
problem.questionFrontendId,
|
|
1814
2011
|
problem.title.length > 42 ? problem.title.slice(0, 39) + "..." : problem.title,
|
|
1815
2012
|
colorDifficulty2(problem.difficulty),
|
|
1816
|
-
problem.status === "ac" ?
|
|
2013
|
+
problem.status === "ac" ? chalk16.green("\u2713") : chalk16.gray("-")
|
|
1817
2014
|
]);
|
|
1818
2015
|
} else {
|
|
1819
|
-
table.push([id,
|
|
2016
|
+
table.push([id, chalk16.gray("(not found)"), "-", "-"]);
|
|
1820
2017
|
}
|
|
1821
2018
|
} catch {
|
|
1822
|
-
table.push([id,
|
|
2019
|
+
table.push([id, chalk16.gray("(error fetching)"), "-", "-"]);
|
|
1823
2020
|
}
|
|
1824
2021
|
}
|
|
1825
2022
|
spinner.stop();
|
|
1826
2023
|
console.log(table.toString());
|
|
1827
2024
|
} catch {
|
|
1828
2025
|
spinner.stop();
|
|
1829
|
-
console.log(
|
|
2026
|
+
console.log(chalk16.gray("IDs: ") + bookmarkList.join(", "));
|
|
1830
2027
|
}
|
|
1831
2028
|
} else {
|
|
1832
|
-
console.log(
|
|
2029
|
+
console.log(chalk16.gray("IDs: ") + bookmarkList.join(", "));
|
|
1833
2030
|
console.log();
|
|
1834
|
-
console.log(
|
|
2031
|
+
console.log(chalk16.gray("Login to see problem details"));
|
|
1835
2032
|
}
|
|
1836
2033
|
}
|
|
1837
2034
|
function colorDifficulty2(difficulty) {
|
|
1838
2035
|
switch (difficulty.toLowerCase()) {
|
|
1839
2036
|
case "easy":
|
|
1840
|
-
return
|
|
2037
|
+
return chalk16.green(difficulty);
|
|
1841
2038
|
case "medium":
|
|
1842
|
-
return
|
|
2039
|
+
return chalk16.yellow(difficulty);
|
|
1843
2040
|
case "hard":
|
|
1844
|
-
return
|
|
2041
|
+
return chalk16.red(difficulty);
|
|
1845
2042
|
default:
|
|
1846
2043
|
return difficulty;
|
|
1847
2044
|
}
|
|
@@ -1851,11 +2048,11 @@ function colorDifficulty2(difficulty) {
|
|
|
1851
2048
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
1852
2049
|
import { join as join5 } from "path";
|
|
1853
2050
|
import { existsSync as existsSync6 } from "fs";
|
|
1854
|
-
import
|
|
2051
|
+
import chalk17 from "chalk";
|
|
1855
2052
|
async function notesCommand(problemId, action) {
|
|
1856
2053
|
if (!isProblemId(problemId)) {
|
|
1857
|
-
console.log(
|
|
1858
|
-
console.log(
|
|
2054
|
+
console.log(chalk17.red(`Invalid problem ID: ${problemId}`));
|
|
2055
|
+
console.log(chalk17.gray("Problem ID must be a positive integer"));
|
|
1859
2056
|
return;
|
|
1860
2057
|
}
|
|
1861
2058
|
const noteAction = action === "view" ? "view" : "edit";
|
|
@@ -1872,21 +2069,21 @@ async function notesCommand(problemId, action) {
|
|
|
1872
2069
|
}
|
|
1873
2070
|
async function viewNote(notePath, problemId) {
|
|
1874
2071
|
if (!existsSync6(notePath)) {
|
|
1875
|
-
console.log(
|
|
1876
|
-
console.log(
|
|
2072
|
+
console.log(chalk17.yellow(`No notes found for problem ${problemId}`));
|
|
2073
|
+
console.log(chalk17.gray(`Use "leetcode note ${problemId} edit" to create notes`));
|
|
1877
2074
|
return;
|
|
1878
2075
|
}
|
|
1879
2076
|
try {
|
|
1880
2077
|
const content = await readFile3(notePath, "utf-8");
|
|
1881
2078
|
console.log();
|
|
1882
|
-
console.log(
|
|
1883
|
-
console.log(
|
|
2079
|
+
console.log(chalk17.bold.cyan(`\u{1F4DD} Notes for Problem ${problemId}`));
|
|
2080
|
+
console.log(chalk17.gray("\u2500".repeat(50)));
|
|
1884
2081
|
console.log();
|
|
1885
2082
|
console.log(content);
|
|
1886
2083
|
} catch (error) {
|
|
1887
|
-
console.log(
|
|
2084
|
+
console.log(chalk17.red("Failed to read notes"));
|
|
1888
2085
|
if (error instanceof Error) {
|
|
1889
|
-
console.log(
|
|
2086
|
+
console.log(chalk17.gray(error.message));
|
|
1890
2087
|
}
|
|
1891
2088
|
}
|
|
1892
2089
|
}
|
|
@@ -1894,9 +2091,9 @@ async function editNote(notePath, problemId) {
|
|
|
1894
2091
|
if (!existsSync6(notePath)) {
|
|
1895
2092
|
const template = await generateNoteTemplate(problemId);
|
|
1896
2093
|
await writeFile3(notePath, template, "utf-8");
|
|
1897
|
-
console.log(
|
|
2094
|
+
console.log(chalk17.green(`\u2713 Created notes file for problem ${problemId}`));
|
|
1898
2095
|
}
|
|
1899
|
-
console.log(
|
|
2096
|
+
console.log(chalk17.gray(`Opening: ${notePath}`));
|
|
1900
2097
|
await openInEditor(notePath);
|
|
1901
2098
|
}
|
|
1902
2099
|
async function generateNoteTemplate(problemId) {
|
|
@@ -1953,7 +2150,7 @@ async function generateNoteTemplate(problemId) {
|
|
|
1953
2150
|
}
|
|
1954
2151
|
|
|
1955
2152
|
// src/commands/today.ts
|
|
1956
|
-
import
|
|
2153
|
+
import chalk18 from "chalk";
|
|
1957
2154
|
import ora12 from "ora";
|
|
1958
2155
|
async function todayCommand() {
|
|
1959
2156
|
const { authorized, username } = await requireAuth();
|
|
@@ -1968,190 +2165,373 @@ async function todayCommand() {
|
|
|
1968
2165
|
]);
|
|
1969
2166
|
spinner.stop();
|
|
1970
2167
|
console.log();
|
|
1971
|
-
console.log(
|
|
1972
|
-
console.log(
|
|
2168
|
+
console.log(chalk18.bold.cyan(`\u{1F4CA} Today's Summary`), chalk18.gray(`- ${username}`));
|
|
2169
|
+
console.log(chalk18.gray("\u2500".repeat(50)));
|
|
1973
2170
|
console.log();
|
|
1974
|
-
console.log(
|
|
1975
|
-
console.log(
|
|
2171
|
+
console.log(chalk18.yellow(`\u{1F525} Current Streak: ${profile.streak} day${profile.streak !== 1 ? "s" : ""}`));
|
|
2172
|
+
console.log(chalk18.gray(` Total Active Days: ${profile.totalActiveDays}`));
|
|
1976
2173
|
console.log();
|
|
1977
2174
|
const total = profile.acSubmissionNum.find((s) => s.difficulty === "All");
|
|
1978
2175
|
const easy = profile.acSubmissionNum.find((s) => s.difficulty === "Easy");
|
|
1979
2176
|
const medium = profile.acSubmissionNum.find((s) => s.difficulty === "Medium");
|
|
1980
2177
|
const hard = profile.acSubmissionNum.find((s) => s.difficulty === "Hard");
|
|
1981
|
-
console.log(
|
|
1982
|
-
console.log(` ${
|
|
1983
|
-
console.log(` ${
|
|
2178
|
+
console.log(chalk18.white("\u{1F4C8} Problems Solved:"));
|
|
2179
|
+
console.log(` ${chalk18.green("Easy")}: ${easy?.count ?? 0} | ${chalk18.yellow("Medium")}: ${medium?.count ?? 0} | ${chalk18.red("Hard")}: ${hard?.count ?? 0}`);
|
|
2180
|
+
console.log(` ${chalk18.bold("Total")}: ${total?.count ?? 0}`);
|
|
1984
2181
|
console.log();
|
|
1985
|
-
console.log(
|
|
2182
|
+
console.log(chalk18.bold.yellow("\u{1F3AF} Today's Challenge:"));
|
|
1986
2183
|
console.log(` ${daily.question.questionFrontendId}. ${daily.question.title}`);
|
|
1987
2184
|
console.log(` ${colorDifficulty3(daily.question.difficulty)}`);
|
|
1988
2185
|
const status = daily.question.status;
|
|
1989
2186
|
if (status === "ac") {
|
|
1990
|
-
console.log(
|
|
2187
|
+
console.log(chalk18.green(" \u2713 Completed!"));
|
|
1991
2188
|
} else if (status === "notac") {
|
|
1992
|
-
console.log(
|
|
2189
|
+
console.log(chalk18.yellow(" \u25CB Attempted"));
|
|
1993
2190
|
} else {
|
|
1994
|
-
console.log(
|
|
2191
|
+
console.log(chalk18.gray(" - Not started"));
|
|
1995
2192
|
}
|
|
1996
2193
|
console.log();
|
|
1997
|
-
console.log(
|
|
2194
|
+
console.log(chalk18.gray(` leetcode pick ${daily.question.questionFrontendId} # Start working on it`));
|
|
1998
2195
|
} catch (error) {
|
|
1999
2196
|
spinner.fail("Failed to fetch progress");
|
|
2000
2197
|
if (error instanceof Error) {
|
|
2001
|
-
console.log(
|
|
2198
|
+
console.log(chalk18.red(error.message));
|
|
2002
2199
|
}
|
|
2003
2200
|
}
|
|
2004
2201
|
}
|
|
2005
2202
|
function colorDifficulty3(difficulty) {
|
|
2006
2203
|
switch (difficulty.toLowerCase()) {
|
|
2007
2204
|
case "easy":
|
|
2008
|
-
return
|
|
2205
|
+
return chalk18.green(difficulty);
|
|
2009
2206
|
case "medium":
|
|
2010
|
-
return
|
|
2207
|
+
return chalk18.yellow(difficulty);
|
|
2011
2208
|
case "hard":
|
|
2012
|
-
return
|
|
2209
|
+
return chalk18.red(difficulty);
|
|
2013
2210
|
default:
|
|
2014
2211
|
return difficulty;
|
|
2015
2212
|
}
|
|
2016
2213
|
}
|
|
2017
2214
|
|
|
2215
|
+
// src/commands/sync.ts
|
|
2216
|
+
import { execSync } from "child_process";
|
|
2217
|
+
import { existsSync as existsSync7 } from "fs";
|
|
2218
|
+
import chalk19 from "chalk";
|
|
2219
|
+
import inquirer3 from "inquirer";
|
|
2220
|
+
import ora13 from "ora";
|
|
2221
|
+
function isGitInstalled() {
|
|
2222
|
+
try {
|
|
2223
|
+
execSync("git --version", { stdio: "ignore" });
|
|
2224
|
+
return true;
|
|
2225
|
+
} catch (error) {
|
|
2226
|
+
return false;
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
function isMapRepo(workDir) {
|
|
2230
|
+
try {
|
|
2231
|
+
execSync("git rev-parse --is-inside-work-tree", { cwd: workDir, stdio: "ignore" });
|
|
2232
|
+
return true;
|
|
2233
|
+
} catch (error) {
|
|
2234
|
+
return false;
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
function isGhInstalled() {
|
|
2238
|
+
try {
|
|
2239
|
+
execSync("gh --version", { stdio: "ignore" });
|
|
2240
|
+
return true;
|
|
2241
|
+
} catch (error) {
|
|
2242
|
+
return false;
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
function getRemoteUrl(workDir) {
|
|
2246
|
+
try {
|
|
2247
|
+
const url = execSync("git config --get remote.origin.url", { cwd: workDir, encoding: "utf-8" });
|
|
2248
|
+
return url.trim();
|
|
2249
|
+
} catch (error) {
|
|
2250
|
+
return null;
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
async function setupGitRepo(workDir) {
|
|
2254
|
+
const { init } = await inquirer3.prompt([
|
|
2255
|
+
{
|
|
2256
|
+
type: "confirm",
|
|
2257
|
+
name: "init",
|
|
2258
|
+
message: "Work directory is not a git repository. Initialize?",
|
|
2259
|
+
default: true
|
|
2260
|
+
}
|
|
2261
|
+
]);
|
|
2262
|
+
if (!init) {
|
|
2263
|
+
console.log(chalk19.yellow("Skipping basic git initialization."));
|
|
2264
|
+
return false;
|
|
2265
|
+
}
|
|
2266
|
+
const spinner = ora13("Initializing git repository...").start();
|
|
2267
|
+
try {
|
|
2268
|
+
execSync("git init", { cwd: workDir });
|
|
2269
|
+
spinner.succeed("Initialized git repository");
|
|
2270
|
+
return true;
|
|
2271
|
+
} catch (error) {
|
|
2272
|
+
spinner.fail("Failed to initialize git repository");
|
|
2273
|
+
throw error;
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
async function setupRemote(workDir) {
|
|
2277
|
+
const spinner = ora13();
|
|
2278
|
+
let repoUrl = config.getRepo();
|
|
2279
|
+
if (!repoUrl) {
|
|
2280
|
+
if (isGhInstalled()) {
|
|
2281
|
+
const { createGh } = await inquirer3.prompt([
|
|
2282
|
+
{
|
|
2283
|
+
type: "confirm",
|
|
2284
|
+
name: "createGh",
|
|
2285
|
+
message: "Create a new private GitHub repository?",
|
|
2286
|
+
default: true
|
|
2287
|
+
}
|
|
2288
|
+
]);
|
|
2289
|
+
if (createGh) {
|
|
2290
|
+
spinner.start("Creating GitHub repository...");
|
|
2291
|
+
try {
|
|
2292
|
+
const repoName = workDir.split("/").pop() || "leetcode-solutions";
|
|
2293
|
+
execSync(`gh repo create ${repoName} --private --source=. --remote=origin`, { cwd: workDir });
|
|
2294
|
+
spinner.succeed("Created and linked GitHub repository");
|
|
2295
|
+
repoUrl = getRemoteUrl(workDir) || "";
|
|
2296
|
+
if (repoUrl) {
|
|
2297
|
+
config.setRepo(repoUrl);
|
|
2298
|
+
}
|
|
2299
|
+
return repoUrl;
|
|
2300
|
+
} catch (error) {
|
|
2301
|
+
spinner.fail("Failed to create GitHub repository");
|
|
2302
|
+
console.log(chalk19.red(error));
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
if (!repoUrl) {
|
|
2307
|
+
console.log(chalk19.yellow("\nPlease create a new repository on your Git provider and copy the URL."));
|
|
2308
|
+
const { url } = await inquirer3.prompt([
|
|
2309
|
+
{
|
|
2310
|
+
type: "input",
|
|
2311
|
+
name: "url",
|
|
2312
|
+
message: "Enter remote repository URL:",
|
|
2313
|
+
validate: (input) => input.length > 0 ? true : "URL cannot be empty"
|
|
2314
|
+
}
|
|
2315
|
+
]);
|
|
2316
|
+
repoUrl = url;
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
if (repoUrl) {
|
|
2320
|
+
config.setRepo(repoUrl);
|
|
2321
|
+
}
|
|
2322
|
+
const currentRemote = getRemoteUrl(workDir);
|
|
2323
|
+
if (!currentRemote && repoUrl) {
|
|
2324
|
+
try {
|
|
2325
|
+
execSync(`git remote add origin ${repoUrl}`, { cwd: workDir });
|
|
2326
|
+
console.log(chalk19.green("\u2713 Added remote origin"));
|
|
2327
|
+
} catch (e) {
|
|
2328
|
+
console.log(chalk19.red("Failed to add remote origin"));
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
return repoUrl || "";
|
|
2332
|
+
}
|
|
2333
|
+
async function syncCommand() {
|
|
2334
|
+
const workDir = config.getWorkDir();
|
|
2335
|
+
if (!existsSync7(workDir)) {
|
|
2336
|
+
console.log(chalk19.red(`Work directory does not exist: ${workDir}`));
|
|
2337
|
+
return;
|
|
2338
|
+
}
|
|
2339
|
+
if (!isGitInstalled()) {
|
|
2340
|
+
console.log(chalk19.red("Git is not installed. Please install Git to use command."));
|
|
2341
|
+
return;
|
|
2342
|
+
}
|
|
2343
|
+
if (!isMapRepo(workDir)) {
|
|
2344
|
+
const initialized = await setupGitRepo(workDir);
|
|
2345
|
+
if (!initialized) return;
|
|
2346
|
+
}
|
|
2347
|
+
await setupRemote(workDir);
|
|
2348
|
+
const spinner = ora13("Syncing solutions...").start();
|
|
2349
|
+
try {
|
|
2350
|
+
const status = execSync("git status --porcelain", { cwd: workDir, encoding: "utf-8" });
|
|
2351
|
+
if (!status) {
|
|
2352
|
+
spinner.info("No changes to sync");
|
|
2353
|
+
return;
|
|
2354
|
+
}
|
|
2355
|
+
execSync("git add .", { cwd: workDir });
|
|
2356
|
+
const lines = status.trim().split("\n");
|
|
2357
|
+
const count = lines.length;
|
|
2358
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").substring(0, 19);
|
|
2359
|
+
const message = `Sync: ${count} solutions - ${timestamp}`;
|
|
2360
|
+
execSync(`git commit -m "${message}"`, { cwd: workDir });
|
|
2361
|
+
try {
|
|
2362
|
+
execSync("git push -u origin main", { cwd: workDir, stdio: "ignore" });
|
|
2363
|
+
} catch {
|
|
2364
|
+
try {
|
|
2365
|
+
execSync("git push -u origin master", { cwd: workDir, stdio: "ignore" });
|
|
2366
|
+
} catch (e) {
|
|
2367
|
+
throw new Error("Failed to push to remote. Please check your git credentials and branch status.");
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
spinner.succeed("Successfully synced solutions to remote");
|
|
2371
|
+
} catch (error) {
|
|
2372
|
+
spinner.fail("Sync failed");
|
|
2373
|
+
if (error.message) {
|
|
2374
|
+
console.log(chalk19.red(error.message));
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2018
2379
|
// src/index.ts
|
|
2019
2380
|
var program = new Command();
|
|
2020
2381
|
program.configureHelp({
|
|
2021
2382
|
sortSubcommands: true,
|
|
2022
|
-
subcommandTerm: (cmd) =>
|
|
2023
|
-
subcommandDescription: (cmd) =>
|
|
2024
|
-
optionTerm: (option) =>
|
|
2025
|
-
optionDescription: (option) =>
|
|
2383
|
+
subcommandTerm: (cmd) => chalk20.cyan(cmd.name()) + (cmd.alias() ? chalk20.gray(`|${cmd.alias()}`) : ""),
|
|
2384
|
+
subcommandDescription: (cmd) => chalk20.white(cmd.description()),
|
|
2385
|
+
optionTerm: (option) => chalk20.yellow(option.flags),
|
|
2386
|
+
optionDescription: (option) => chalk20.white(option.description)
|
|
2026
2387
|
});
|
|
2027
|
-
program.name("leetcode").usage("[command] [options]").description(
|
|
2028
|
-
${
|
|
2029
|
-
${
|
|
2030
|
-
${
|
|
2031
|
-
${
|
|
2032
|
-
${
|
|
2033
|
-
${
|
|
2034
|
-
${
|
|
2388
|
+
program.name("leetcode").usage("[command] [options]").description(chalk20.bold.cyan("\u{1F525} A modern LeetCode CLI built with TypeScript")).version("1.4.0", "-v, --version", "Output the version number").helpOption("-h, --help", "Display help for command").addHelpText("after", `
|
|
2389
|
+
${chalk20.yellow("Examples:")}
|
|
2390
|
+
${chalk20.cyan("$ leetcode login")} Login to LeetCode
|
|
2391
|
+
${chalk20.cyan("$ leetcode list -d easy")} List easy problems
|
|
2392
|
+
${chalk20.cyan("$ leetcode random -d medium")} Get random medium problem
|
|
2393
|
+
${chalk20.cyan("$ leetcode pick 1")} Start solving "Two Sum"
|
|
2394
|
+
${chalk20.cyan("$ leetcode test 1")} Test your solution
|
|
2395
|
+
${chalk20.cyan("$ leetcode submit 1")} Submit your solution
|
|
2035
2396
|
`);
|
|
2036
2397
|
program.command("login").description("Login to LeetCode with browser cookies").addHelpText("after", `
|
|
2037
|
-
${
|
|
2038
|
-
1. Open ${
|
|
2398
|
+
${chalk20.yellow("How to login:")}
|
|
2399
|
+
1. Open ${chalk20.cyan("https://leetcode.com")} in your browser
|
|
2039
2400
|
2. Login to your account
|
|
2040
2401
|
3. Open Developer Tools (F12) \u2192 Application \u2192 Cookies
|
|
2041
|
-
4. Copy values of ${
|
|
2402
|
+
4. Copy values of ${chalk20.green("LEETCODE_SESSION")} and ${chalk20.green("csrftoken")}
|
|
2042
2403
|
5. Paste when prompted by this command
|
|
2043
2404
|
`).action(loginCommand);
|
|
2044
2405
|
program.command("logout").description("Clear stored credentials").action(logoutCommand);
|
|
2045
2406
|
program.command("whoami").description("Check current login status").action(whoamiCommand);
|
|
2046
2407
|
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").addHelpText("after", `
|
|
2047
|
-
${
|
|
2048
|
-
${
|
|
2049
|
-
${
|
|
2050
|
-
${
|
|
2051
|
-
${
|
|
2052
|
-
${
|
|
2053
|
-
${
|
|
2408
|
+
${chalk20.yellow("Examples:")}
|
|
2409
|
+
${chalk20.cyan("$ leetcode list")} List first 20 problems
|
|
2410
|
+
${chalk20.cyan("$ leetcode list -d easy")} List easy problems only
|
|
2411
|
+
${chalk20.cyan("$ leetcode list -s solved")} List your solved problems
|
|
2412
|
+
${chalk20.cyan("$ leetcode list -t array -t string")} Filter by multiple tags
|
|
2413
|
+
${chalk20.cyan('$ leetcode list -q "two sum"')} Search by keywords
|
|
2414
|
+
${chalk20.cyan("$ leetcode list -n 50 -p 2")} Show 50 problems, page 2
|
|
2054
2415
|
`).action(listCommand);
|
|
2055
2416
|
program.command("show <id>").alias("s").description("Show problem description").addHelpText("after", `
|
|
2056
|
-
${
|
|
2057
|
-
${
|
|
2058
|
-
${
|
|
2059
|
-
${
|
|
2417
|
+
${chalk20.yellow("Examples:")}
|
|
2418
|
+
${chalk20.cyan("$ leetcode show 1")} Show by problem ID
|
|
2419
|
+
${chalk20.cyan("$ leetcode show two-sum")} Show by problem slug
|
|
2420
|
+
${chalk20.cyan("$ leetcode s 412")} Short alias
|
|
2060
2421
|
`).action(showCommand);
|
|
2061
2422
|
program.command("daily").alias("d").description("Show today's daily challenge").addHelpText("after", `
|
|
2062
|
-
${
|
|
2063
|
-
${
|
|
2064
|
-
${
|
|
2423
|
+
${chalk20.yellow("Examples:")}
|
|
2424
|
+
${chalk20.cyan("$ leetcode daily")} Show today's challenge
|
|
2425
|
+
${chalk20.cyan("$ leetcode d")} Short alias
|
|
2065
2426
|
`).action(dailyCommand);
|
|
2066
2427
|
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").addHelpText("after", `
|
|
2067
|
-
${
|
|
2068
|
-
${
|
|
2069
|
-
${
|
|
2070
|
-
${
|
|
2071
|
-
${
|
|
2072
|
-
${
|
|
2428
|
+
${chalk20.yellow("Examples:")}
|
|
2429
|
+
${chalk20.cyan("$ leetcode random")} Get any random problem
|
|
2430
|
+
${chalk20.cyan("$ leetcode random -d medium")} Random medium problem
|
|
2431
|
+
${chalk20.cyan("$ leetcode random -t array")} Random array problem
|
|
2432
|
+
${chalk20.cyan("$ leetcode random --pick")} Random + create file
|
|
2433
|
+
${chalk20.cyan("$ leetcode r -d easy --pick")} Random easy + file
|
|
2073
2434
|
`).action(randomCommand);
|
|
2074
2435
|
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").addHelpText("after", `
|
|
2075
|
-
${
|
|
2076
|
-
${
|
|
2077
|
-
${
|
|
2078
|
-
${
|
|
2079
|
-
${
|
|
2080
|
-
${
|
|
2436
|
+
${chalk20.yellow("Examples:")}
|
|
2437
|
+
${chalk20.cyan("$ leetcode pick 1")} Pick by problem ID
|
|
2438
|
+
${chalk20.cyan("$ leetcode pick two-sum")} Pick by problem slug
|
|
2439
|
+
${chalk20.cyan("$ leetcode pick 1 -l python3")} Pick with specific language
|
|
2440
|
+
${chalk20.cyan("$ leetcode pick 1 --no-open")} Create file without opening
|
|
2441
|
+
${chalk20.cyan("$ leetcode p 412")} Short alias
|
|
2081
2442
|
|
|
2082
|
-
${
|
|
2443
|
+
${chalk20.gray("Files are organized by: workDir/Difficulty/Category/")}
|
|
2083
2444
|
`).action(async (id, options) => {
|
|
2084
2445
|
await pickCommand(id, options);
|
|
2085
2446
|
});
|
|
2086
2447
|
program.command("pick-batch <ids...>").description("Generate solution files for multiple problems").option("-l, --lang <language>", "Programming language for the solutions").addHelpText("after", `
|
|
2087
|
-
${
|
|
2088
|
-
${
|
|
2089
|
-
${
|
|
2448
|
+
${chalk20.yellow("Examples:")}
|
|
2449
|
+
${chalk20.cyan("$ leetcode pick-batch 1 2 3")} Pick problems 1, 2, and 3
|
|
2450
|
+
${chalk20.cyan("$ leetcode pick-batch 1 2 3 -l py")} Pick with Python
|
|
2090
2451
|
`).action(batchPickCommand);
|
|
2091
2452
|
program.command("test <file>").alias("t").description("Test solution against sample test cases").option("-c, --testcase <testcase>", "Custom test case").addHelpText("after", `
|
|
2092
|
-
${
|
|
2093
|
-
${
|
|
2094
|
-
${
|
|
2095
|
-
${
|
|
2096
|
-
${
|
|
2097
|
-
${
|
|
2453
|
+
${chalk20.yellow("Examples:")}
|
|
2454
|
+
${chalk20.cyan("$ leetcode test 1")} Test by problem ID
|
|
2455
|
+
${chalk20.cyan("$ leetcode test two-sum")} Test by problem slug
|
|
2456
|
+
${chalk20.cyan("$ leetcode test ./path/to/file.py")} Test by file path
|
|
2457
|
+
${chalk20.cyan('$ leetcode test 1 -c "[1,2]\\n3"')} Test with custom case
|
|
2458
|
+
${chalk20.cyan("$ leetcode t 412")} Short alias
|
|
2098
2459
|
|
|
2099
|
-
${
|
|
2460
|
+
${chalk20.gray("Testcases use \\n to separate multiple inputs.")}
|
|
2100
2461
|
`).action(testCommand);
|
|
2101
2462
|
program.command("submit <file>").alias("x").description("Submit solution to LeetCode").addHelpText("after", `
|
|
2102
|
-
${
|
|
2103
|
-
${
|
|
2104
|
-
${
|
|
2105
|
-
${
|
|
2106
|
-
${
|
|
2463
|
+
${chalk20.yellow("Examples:")}
|
|
2464
|
+
${chalk20.cyan("$ leetcode submit 1")} Submit by problem ID
|
|
2465
|
+
${chalk20.cyan("$ leetcode submit two-sum")} Submit by problem slug
|
|
2466
|
+
${chalk20.cyan("$ leetcode submit ./path/to/file.py")} Submit by file path
|
|
2467
|
+
${chalk20.cyan("$ leetcode x 412")} Short alias
|
|
2107
2468
|
`).action(submitCommand);
|
|
2108
2469
|
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").addHelpText("after", `
|
|
2109
|
-
${
|
|
2110
|
-
${
|
|
2111
|
-
${
|
|
2112
|
-
${
|
|
2113
|
-
${
|
|
2470
|
+
${chalk20.yellow("Examples:")}
|
|
2471
|
+
${chalk20.cyan("$ leetcode submissions 1")} View submissions for problem
|
|
2472
|
+
${chalk20.cyan("$ leetcode submissions 1 -n 5")} Show last 5 submissions
|
|
2473
|
+
${chalk20.cyan("$ leetcode submissions 1 --last")} Show last accepted submission
|
|
2474
|
+
${chalk20.cyan("$ leetcode submissions 1 --download")} Download last accepted code
|
|
2114
2475
|
`).action(submissionsCommand);
|
|
2115
|
-
program.command("stat [username]").description("Show user statistics").addHelpText("after", `
|
|
2116
|
-
${
|
|
2117
|
-
${
|
|
2118
|
-
|
|
2119
|
-
|
|
2476
|
+
program.command("stat [username]").description("Show user statistics and analytics").option("-c, --calendar", "Weekly activity summary (submissions & active days for last 12 weeks)").option("-s, --skills", "Skill breakdown (problems solved grouped by topic tags)").option("-t, --trend", "Daily trend chart (bar graph of submissions for last 7 days)").addHelpText("after", `
|
|
2477
|
+
${chalk20.yellow("Options Explained:")}
|
|
2478
|
+
${chalk20.cyan("-c, --calendar")} Shows a table of your weekly submissions and active days
|
|
2479
|
+
for the past 12 weeks. Useful for tracking consistency.
|
|
2480
|
+
|
|
2481
|
+
${chalk20.cyan("-s, --skills")} Shows how many problems you solved per topic tag,
|
|
2482
|
+
grouped by difficulty (Fundamental/Intermediate/Advanced).
|
|
2483
|
+
Helps identify your strong and weak areas.
|
|
2484
|
+
|
|
2485
|
+
${chalk20.cyan("-t, --trend")} Shows a bar chart of daily submissions for the past week.
|
|
2486
|
+
Visualizes your recent coding activity day by day.
|
|
2487
|
+
|
|
2488
|
+
${chalk20.yellow("Examples:")}
|
|
2489
|
+
${chalk20.cyan("$ leetcode stat")} Show basic stats (solved count, rank)
|
|
2490
|
+
${chalk20.cyan("$ leetcode stat lee215")} Show another user's stats
|
|
2491
|
+
${chalk20.cyan("$ leetcode stat -c")} Weekly activity table
|
|
2492
|
+
${chalk20.cyan("$ leetcode stat -s")} Topic-wise breakdown
|
|
2493
|
+
${chalk20.cyan("$ leetcode stat -t")} 7-day trend chart
|
|
2494
|
+
`).action((username, options) => statCommand(username, options));
|
|
2120
2495
|
program.command("today").description("Show today's progress summary").addHelpText("after", `
|
|
2121
|
-
${
|
|
2122
|
-
${
|
|
2496
|
+
${chalk20.yellow("Examples:")}
|
|
2497
|
+
${chalk20.cyan("$ leetcode today")} Show streak, solved, and daily challenge
|
|
2123
2498
|
`).action(todayCommand);
|
|
2124
2499
|
program.command("bookmark <action> [id]").description("Manage problem bookmarks").addHelpText("after", `
|
|
2125
|
-
${
|
|
2126
|
-
${
|
|
2127
|
-
${
|
|
2128
|
-
${
|
|
2129
|
-
${
|
|
2500
|
+
${chalk20.yellow("Actions:")}
|
|
2501
|
+
${chalk20.cyan("add <id>")} Bookmark a problem
|
|
2502
|
+
${chalk20.cyan("remove <id>")} Remove a bookmark
|
|
2503
|
+
${chalk20.cyan("list")} List all bookmarks
|
|
2504
|
+
${chalk20.cyan("clear")} Clear all bookmarks
|
|
2130
2505
|
|
|
2131
|
-
${
|
|
2132
|
-
${
|
|
2133
|
-
${
|
|
2134
|
-
${
|
|
2506
|
+
${chalk20.yellow("Examples:")}
|
|
2507
|
+
${chalk20.cyan("$ leetcode bookmark add 1")} Bookmark problem 1
|
|
2508
|
+
${chalk20.cyan("$ leetcode bookmark remove 1")} Remove bookmark
|
|
2509
|
+
${chalk20.cyan("$ leetcode bookmark list")} List all bookmarks
|
|
2135
2510
|
`).action(bookmarkCommand);
|
|
2136
2511
|
program.command("note <id> [action]").description("View or edit notes for a problem").addHelpText("after", `
|
|
2137
|
-
${
|
|
2138
|
-
${
|
|
2139
|
-
${
|
|
2512
|
+
${chalk20.yellow("Actions:")}
|
|
2513
|
+
${chalk20.cyan("edit")} Open notes in editor (default)
|
|
2514
|
+
${chalk20.cyan("view")} Display notes in terminal
|
|
2140
2515
|
|
|
2141
|
-
${
|
|
2142
|
-
${
|
|
2143
|
-
${
|
|
2144
|
-
${
|
|
2516
|
+
${chalk20.yellow("Examples:")}
|
|
2517
|
+
${chalk20.cyan("$ leetcode note 1")} Edit notes for problem 1
|
|
2518
|
+
${chalk20.cyan("$ leetcode note 1 edit")} Edit notes (explicit)
|
|
2519
|
+
${chalk20.cyan("$ leetcode note 1 view")} View notes in terminal
|
|
2145
2520
|
`).action(notesCommand);
|
|
2146
|
-
program.command("
|
|
2147
|
-
${
|
|
2148
|
-
${
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
${
|
|
2521
|
+
program.command("sync").description("Sync solutions to Git repository").addHelpText("after", `
|
|
2522
|
+
${chalk20.yellow("Examples:")}
|
|
2523
|
+
${chalk20.cyan("$ leetcode sync")} Sync all solutions to remote
|
|
2524
|
+
`).action(syncCommand);
|
|
2525
|
+
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("-r, --repo <url>", "Set Git repository URL").option("-i, --interactive", "Interactive configuration").addHelpText("after", `
|
|
2526
|
+
${chalk20.yellow("Examples:")}
|
|
2527
|
+
${chalk20.cyan("$ leetcode config")} View current config
|
|
2528
|
+
${chalk20.cyan("$ leetcode config -l python3")} Set language to Python
|
|
2529
|
+
${chalk20.cyan('$ leetcode config -e "code"')} Set editor to VS Code
|
|
2530
|
+
${chalk20.cyan("$ leetcode config -w ~/leetcode")} Set solutions folder
|
|
2531
|
+
${chalk20.cyan("$ leetcode config -r https://...")} Set git repository
|
|
2532
|
+
${chalk20.cyan("$ leetcode config -i")} Interactive setup
|
|
2153
2533
|
|
|
2154
|
-
${
|
|
2534
|
+
${chalk20.gray("Supported languages: typescript, javascript, python3, java, cpp, c, csharp, go, rust, kotlin, swift")}
|
|
2155
2535
|
`).action(async (options) => {
|
|
2156
2536
|
if (options.interactive) {
|
|
2157
2537
|
await configInteractiveCommand();
|
|
@@ -2163,8 +2543,8 @@ program.showHelpAfterError("(add --help for additional information)");
|
|
|
2163
2543
|
program.parse();
|
|
2164
2544
|
if (!process.argv.slice(2).length) {
|
|
2165
2545
|
console.log();
|
|
2166
|
-
console.log(
|
|
2167
|
-
console.log(
|
|
2546
|
+
console.log(chalk20.bold.cyan(" \u{1F525} LeetCode CLI"));
|
|
2547
|
+
console.log(chalk20.gray(" A modern command-line interface for LeetCode"));
|
|
2168
2548
|
console.log();
|
|
2169
2549
|
program.outputHelp();
|
|
2170
2550
|
}
|