Skip to content

Commit 4467cc0

Browse files
committed
feat: Add file status indicators to list command (v0.4.7)
- Add file status indicators showing source code file existence: 🎯 Problem solved and source file exists locally 🚧 Source file exists locally but problem not solved yet 🌐 Problem solved but no local source file (blank) Problem not solved and no local source file - Add --refresh-files flag to update file status cache by scanning local files - Auto-update file status when creating files via edit command - Database schema enhancement with `fstatus` field for efficient file status caching - Improved performance by caching file status in database instead of scanning filesystem on each list command
1 parent bd7576c commit 4467cc0

File tree

9 files changed

+95
-3
lines changed

9 files changed

+95
-3
lines changed

β€ŽCHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
## v0.4.7
2+
3+
- Add file status indicators to list command showing source code file existence
4+
- 🎯 Problem solved and source file exists locally
5+
- 🚧 Source file exists locally but problem not solved yet
6+
- 🌐 Problem solved but no local source file
7+
- No indicator: Problem not solved and no local source file
8+
- Add `--refresh-files` flag to update file status cache by scanning local files
9+
- Auto-update file status when creating files via edit command
10+
- Database schema enhancement with `fstatus` field for efficient file status caching
11+
112
## v0.4.1
213

314
- Search problems by name

β€ŽCargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ path = "src/bin/lc.rs"
44

55
[package]
66
name = "leetcode-cli"
7-
version = "0.4.6"
7+
version = "0.4.7"
88
authors = ["clearloop <tianyi.gc@gmail.com>", "yousiki <you.siki@outlook.com>"]
99
edition = "2021"
1010
description = "Leetcode command-line interface in rust. Forked by yousiki."

β€Žsrc/cache/mod.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,50 @@ impl Cache {
384384
Ok(res)
385385
}
386386

387+
/// Update file status for a single problem
388+
pub fn update_problem_file_status(
389+
&self,
390+
problem_id: i32,
391+
file_exists: bool,
392+
) -> Result<(), Error> {
393+
let mut c = self.conn()?;
394+
let target = problems.filter(id.eq(problem_id));
395+
let file_status = if file_exists { "exists" } else { "missing" };
396+
diesel::update(target)
397+
.set(fstatus.eq(file_status))
398+
.execute(&mut c)?;
399+
Ok(())
400+
}
401+
402+
/// Batch update file status for all problems
403+
pub fn update_all_file_status(&self) -> Result<(), Error> {
404+
use crate::helper::code_path;
405+
use std::path::Path;
406+
407+
let mut c = self.conn()?;
408+
let all_problems: Vec<Problem> = problems.load(&mut c)?;
409+
410+
for problem in all_problems {
411+
// Skip non-algorithm problems
412+
if problem.category != "algorithms" {
413+
continue;
414+
}
415+
416+
let file_exists = match code_path(&problem, None) {
417+
Ok(path) => Path::new(&path).exists(),
418+
Err(_) => false,
419+
};
420+
421+
let file_status = if file_exists { "exists" } else { "missing" };
422+
let target = problems.filter(id.eq(problem.id));
423+
diesel::update(target)
424+
.set(fstatus.eq(file_status))
425+
.execute(&mut c)?;
426+
}
427+
428+
Ok(())
429+
}
430+
387431
/// New cache
388432
pub fn new() -> Result<Self, Error> {
389433
let conf = Config::locate()?;

β€Žsrc/cache/models.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub struct Problem {
3030
pub starred: bool,
3131
pub status: String,
3232
pub desc: String,
33+
pub fstatus: String,
3334
}
3435

3536
impl Problem {
@@ -51,6 +52,15 @@ impl Problem {
5152

5253
res + "\n"
5354
}
55+
56+
pub fn file_status_indicator(&self) -> &str {
57+
match (self.status.as_str(), self.fstatus.as_str()) {
58+
("ac", "exists") => "🎯", // Solved and file exists
59+
(_, "exists") => "🚧", // File exists but not solved
60+
("ac", _) => "🌐", // Solved but no local file
61+
_ => " ", // Not solved and no local file
62+
}
63+
}
5464
}
5565

5666
static DONE: &str = " βœ”";
@@ -134,10 +144,14 @@ impl std::fmt::Display for Problem {
134144
if pct.len() < 5 {
135145
pct.push_str(&"0".repeat(5 - pct.len()));
136146
}
147+
148+
let file_status_indicator = self.file_status_indicator();
149+
137150
write!(
138151
f,
139-
" {} {} [{}] {} {} ({} %)",
152+
" {} {} {} [{}] {} {} ({} %)",
140153
lock,
154+
file_status_indicator,
141155
done,
142156
id,
143157
name,

β€Žsrc/cache/parser.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub fn problem(problems: &mut Vec<Problem>, v: Value) -> Option<()> {
3535
starred: p.get("is_favor")?.as_bool()?,
3636
status: p.get("status")?.as_str().unwrap_or("Null").to_string(),
3737
desc: String::new(),
38+
fstatus: String::from("unknown"),
3839
});
3940
}
4041

β€Žsrc/cache/schemas.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ table! {
1212
starred -> Bool,
1313
status -> Text,
1414
desc -> Text,
15+
fstatus -> Text,
1516
}
1617
}
1718

β€Žsrc/cache/sql.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ pub static CREATE_PROBLEMS_IF_NOT_EXISTS: &str = r#"
1010
slug TEXT NOT NULL,
1111
starred BOOLEAN NOT NULL DEFAULT 0,
1212
status TEXT NOT NULL,
13-
desc TEXT NOT NULL DEFAULT ""
13+
desc TEXT NOT NULL DEFAULT "",
14+
fstatus TEXT NOT NULL DEFAULT "unknown"
1415
)
1516
"#;
1617

β€Žsrc/cmds/edit.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ impl Command for EditCommand {
221221
.envs(envs)
222222
.args(args)
223223
.status()?;
224+
225+
// Update file status since we just created/edited the file
226+
cache.update_problem_file_status(problem.id, true)?;
227+
224228
Ok(())
225229
}
226230
}

β€Žsrc/cmds/list.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ static LIST_AFTER_HELP: &str = r#"EXAMPLES:
6666
leetcode list -q eD List questions that with easy level and not done
6767
leetcode list -t linked-list List questions that under tag "linked-list"
6868
leetcode list -r 50 100 List questions that has id in between 50 and 100
69+
leetcode list -f List questions with updated file status
6970
"#;
7071

7172
/// implement Command trait for `list`
@@ -125,6 +126,13 @@ impl Command for ListCommand {
125126
.num_args(1)
126127
.help("Keyword in select query"),
127128
)
129+
.arg(
130+
Arg::new("refresh-files")
131+
.short('f')
132+
.long("refresh-files")
133+
.help("Update file status cache by scanning local files")
134+
.action(ArgAction::SetTrue),
135+
)
128136
}
129137

130138
/// `list` command handler
@@ -144,6 +152,14 @@ impl Command for ListCommand {
144152
return Self::handler(m).await;
145153
}
146154

155+
// refresh file status if requested
156+
if m.contains_id("refresh-files") {
157+
info!("Refreshing file status cache...");
158+
cache.update_all_file_status()?;
159+
// Reload problems to get updated file status
160+
ps = cache.get_problems()?;
161+
}
162+
147163
// filtering...
148164
// pym scripts
149165
#[cfg(feature = "pym")]

0 commit comments

Comments
Β (0)