Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7ea48b8

Browse files
fix issue 80 (clearloop#81)
* fix: clippy warning for rust 1.61 stable * feat: upgrade dep version, and use Rust 2021 Edition * fix: issue 80 1. use code.test config to open/close writing test file 2. use code.comment_leading to comment the desc 3. use code.comment_problem_desc to open/close the description about the problem 4. use code.start_marker to mark the code begin 5. use code.end_marker to mark the code end * fix: create empty test file * revert: use superscript and subscript, not ^ and _ * fix: not generate leetcode_tmp.toml * fix: clippy warning * chore: upgrade dep * backwark compability * cfg marker trun on/off
1 parent 3621ba0 commit 7ea48b8

File tree

8 files changed

+155
-64
lines changed

8 files changed

+155
-64
lines changed

β€ŽCargo.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@ readme = './README.md'
1717

1818
[dependencies]
1919
async-trait = "0.1.56"
20-
tokio = { version = "1", features = ["full"] }
21-
clap = { version = "3.2.8", features = ["cargo"] }
20+
tokio = { version = "1.19.2", features = ["full"] }
21+
clap = { version = "3.2.10", features = ["cargo"] }
2222
colored = "2.0.0"
2323
dirs = "4.0.0"
2424
env_logger = "0.9.0"
25-
keyring = "1.1.2"
25+
keyring = "1.2.0"
2626
log = "0.4.17"
27-
openssl = "0.10.40"
27+
openssl = "0.10.41"
2828
pyo3 = { version = "0.16.5", optional = true }
2929
rand = "0.8.5"
30-
serde = { version = "1.0.138", features = ["derive"] }
30+
serde = { version = "1.0.139", features = ["derive"] }
3131
serde_json = "1.0.82"
3232
toml = "0.5.9"
33-
regex = "1.5.6"
33+
regex = "1.6.0"
3434
scraper = "0.13.0"
3535

3636
[dependencies.diesel]

β€Žsrc/cache/mod.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ mod sql;
66
use self::models::*;
77
use self::schemas::{problems::dsl::*, tags::dsl::*};
88
use self::sql::*;
9-
use crate::cmds::{CODE_END, CODE_START};
109
use crate::helper::test_cases_path;
1110
use crate::{cfg, err::Error, plugins::LeetCode};
1211
use colored::Colorize;
@@ -285,10 +284,16 @@ impl Cache {
285284

286285
File::open(code_path(&p, None)?)?.read_to_string(&mut code)?;
287286

288-
let begin = code.find(CODE_START).unwrap_or(0);
289-
let end = code.find(CODE_END).unwrap_or(code.len());
290-
let code = if let Some(solution) = code.get(begin..end) {
291-
solution.to_string()
287+
let code = if conf.code.edit_code_marker {
288+
let begin = code.find(&conf.code.start_marker);
289+
let end = code.find(&conf.code.end_marker);
290+
if let (Some(l), Some(r)) = (begin, end) {
291+
code.get((l + conf.code.start_marker.len())..r)
292+
.map(|s| s.to_string())
293+
.unwrap_or_else(|| code)
294+
} else {
295+
code
296+
}
292297
} else {
293298
code
294299
};

β€Žsrc/cache/models.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@ impl Problem {
3939
_ => "Unknown",
4040
}
4141
}
42-
pub fn desc_comment(&self) -> String {
42+
pub fn desc_comment(&self,conf:&Config) -> String {
4343
let mut res = String::new();
44-
res += format!("// Category: {}\n", self.category).as_str();
45-
res += format!("// Level: {}\n", self.display_level(),).as_str();
46-
res += format!("// Percent: {}%\n\n", self.percent).as_str();
44+
let comment_leading = &conf.code.comment_leading;
45+
res += format!("{} Category: {}\n", comment_leading, self.category).as_str();
46+
res += format!("{} Level: {}\n", comment_leading, self.display_level(),).as_str();
47+
res += format!("{} Percent: {}%\n\n", comment_leading, self.percent).as_str();
4748

4849
res + "\n"
4950
}
@@ -148,13 +149,13 @@ impl Question {
148149
self.content.render()
149150
}
150151

151-
pub fn desc_comment(&self) -> String {
152+
pub fn desc_comment(&self,conf:&Config) -> String {
152153
let desc = self.content.render();
153154

154-
let mut res = desc
155-
.lines()
156-
.fold("/*\n".to_string(), |acc, e| acc + " * " + e + "\n");
157-
res += " */\n";
155+
let mut res = desc.lines().fold("\n".to_string(), |acc, e| {
156+
acc + " " + conf.code.comment_leading.as_str() + " " + e + "\n"
157+
});
158+
res += " \n";
158159

159160
res
160161
}
@@ -481,7 +482,9 @@ impl std::fmt::Display for VerifyResult {
481482
}
482483
}
483484

485+
use crate::Config;
484486
use verify::*;
487+
485488
mod verify {
486489
use super::super::parser::ssr;
487490
use serde::Deserialize;

β€Žsrc/cfg.rs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::Error;
99
use serde::{Deserialize, Serialize};
1010
use std::{collections::HashMap, fs, path::PathBuf};
1111

12-
const DEFAULT_CONFIG: &str = r##"
12+
pubconst DEFAULT_CONFIG: &str = r##"
1313
# usually you don't wanna change those
1414
[sys]
1515
categories = [
@@ -57,6 +57,12 @@ favorite_delete = "https://leetcode.com/list/api/questions/$hash/$id"
5757
[code]
5858
editor = "vim"
5959
lang = "rust"
60+
edit_code_marker = false
61+
comment_problem_desc = false
62+
comment_leading = "///"
63+
start_marker = "@lc code=start"
64+
end_marker = "@lc code=start"
65+
test = true
6066
pick = "${fid}.${slug}"
6167
submission = "${fid}.${slug}.${sid}.${ac}"
6268
@@ -66,10 +72,10 @@ session = ""
6672
6773
[storage]
6874
root = "~/.leetcode"
69-
cache = "Problems"
7075
scripts = "scripts"
71-
# absolutely path for the code, other use root as parent dir
7276
code = "code"
77+
# absolutely path for the cache, other use root as parent dir
78+
cache = "~/.cache/leetcode"
7379
"##;
7480

7581
/// Sync with `~/.leetcode/config.toml`
@@ -134,6 +140,12 @@ pub struct Code {
134140
pub editor: String,
135141
#[serde(rename(serialize = "editor-args", deserialize = "editor-args"))]
136142
pub editor_args: Option<Vec<String>>,
143+
pub edit_code_marker: bool,
144+
pub start_marker: String,
145+
pub end_marker: String,
146+
pub comment_problem_desc: bool,
147+
pub comment_leading: String,
148+
pub test: bool,
137149
pub lang: String,
138150
pub pick: String,
139151
pub submission: String,
@@ -163,16 +175,23 @@ impl Storage {
163175

164176
/// get cache path
165177
pub fn cache(&self) -> Result<String, crate::Error> {
166-
let root = &self.root()?;
167-
Ok(PathBuf::from(root)
168-
.join(&self.cache)
178+
let home = dirs::home_dir()
179+
.ok_or(Error::NoneError)?
169180
.to_string_lossy()
170-
.to_string())
181+
.to_string();
182+
let path = PathBuf::from(self.cache.replace('~', &home));
183+
if !path.is_dir() {
184+
info!("Generate cache dir at {:?}.", &path);
185+
fs::DirBuilder::new().recursive(true).create(&path)?;
186+
}
187+
188+
Ok(path.join("Problems").to_string_lossy().to_string())
171189
}
172190

173191
/// get code path
174192
pub fn code(&self) -> Result<String, crate::Error> {
175-
let p = PathBuf::from(&self.code);
193+
let root = &self.root()?;
194+
let p = PathBuf::from(root).join(&self.code);
176195
if !PathBuf::from(&p).exists() {
177196
fs::create_dir(&p)?
178197
}

β€Žsrc/cmds/edit.rs

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ use clap::{Arg, ArgMatches, Command as ClapCommand};
2222
/// ```
2323
pub struct EditCommand;
2424

25-
pub const CODE_START: &str = r#"// @lc code=start"#;
26-
pub const CODE_END: &str = r#"// @lc code=end"#;
27-
2825
#[async_trait]
2926
impl Command for EditCommand {
3027
/// `edit` usage
@@ -45,13 +42,6 @@ impl Command for EditCommand {
4542
.required(true)
4643
.help("question id"),
4744
)
48-
.arg(
49-
Arg::with_name("test")
50-
.long("test")
51-
.short('t')
52-
.required(false)
53-
.help("write test file"),
54-
)
5545
}
5646

5747
/// `edit` handler
@@ -66,16 +56,16 @@ impl Command for EditCommand {
6656
let problem = cache.get_problem(id)?;
6757
let mut conf = cache.to_owned().0.conf;
6858

69-
let test_flag = m.contains_id("test");
59+
let test_flag = conf.code.test;
7060

71-
let p_desc_comment = problem.desc_comment();
61+
let p_desc_comment = problem.desc_comment(&conf);
7262
// condition language
7363
if m.contains_id("lang") {
7464
conf.code.lang = m.value_of("lang").ok_or(Error::NoneError)?.to_string();
7565
conf.sync()?;
7666
}
7767

78-
let lang = conf.code.lang;
68+
let lang = &conf.code.lang;
7969
let path = crate::helper::code_path(&problem, Some(lang.to_owned()))?;
8070

8171
if !Path::new(&path).exists() {
@@ -87,22 +77,40 @@ impl Command for EditCommand {
8777
let question: Question = qr?;
8878

8979
let mut file_code = File::create(&path)?;
90-
let question_desc = question.desc_comment() + "\n";
80+
let question_desc = question.desc_comment(&conf) + "\n";
9181

9282
let test_path = crate::helper::test_cases_path(&problem)?;
93-
let mut file_tests = File::create(&test_path)?;
9483

9584
let mut flag = false;
9685
for d in question.defs.0 {
97-
if d.value == lang {
86+
if d.value == *lang {
9887
flag = true;
99-
file_code.write_all(p_desc_comment.as_bytes())?;
100-
file_code.write_all(question_desc.as_bytes())?;
101-
file_code.write_all((CODE_START.to_string() + "\n").as_bytes())?;
88+
if conf.code.comment_problem_desc {
89+
file_code.write_all(p_desc_comment.as_bytes())?;
90+
file_code.write_all(question_desc.as_bytes())?;
91+
}
92+
if conf.code.edit_code_marker {
93+
file_code.write_all(
94+
(conf.code.comment_leading.clone()
95+
+ " "
96+
+ &conf.code.start_marker
97+
+ "\n")
98+
.as_bytes(),
99+
)?;
100+
}
102101
file_code.write_all((d.code.to_string() + "\n").as_bytes())?;
103-
file_code.write_all((CODE_END.to_string() + "\n").as_bytes())?;
102+
if conf.code.edit_code_marker {
103+
file_code.write_all(
104+
(conf.code.comment_leading.clone()
105+
+ " "
106+
+ &conf.code.end_marker
107+
+ "\n")
108+
.as_bytes(),
109+
)?;
110+
}
104111

105112
if test_flag {
113+
let mut file_tests = File::create(&test_path)?;
106114
file_tests.write_all(question.all_cases.as_bytes())?;
107115
}
108116
}

β€Žsrc/cmds/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,3 @@ pub use list::ListCommand;
3838
pub use pick::PickCommand;
3939
pub use stat::StatCommand;
4040
pub use test::TestCommand;
41-
42-
pub use edit::{CODE_END, CODE_START};

β€Žsrc/err.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! Errors in leetcode-cli
2+
use crate::cfg::{root, DEFAULT_CONFIG};
23
use crate::cmds::{Command, DataCommand};
34
use colored::Colorize;
45
use std::fmt;
@@ -98,19 +99,31 @@ impl std::convert::From<serde_json::error::Error> for Error {
9899

99100
// toml
100101
impl std::convert::From<toml::de::Error> for Error {
101-
fn from(err: toml::de::Error) -> Self {
102-
Error::ParseError(format!(
103-
"{}, {}{}{}{}{}{}{}{}",
104-
err,
102+
fn from(_err: toml::de::Error) -> Self {
103+
let conf = root().unwrap().join("leetcode_tmp.toml");
104+
std::fs::write(&conf, &DEFAULT_CONFIG[1..]).unwrap();
105+
#[cfg(debug_assertions)]
106+
let err_msg = format!(
107+
"{}, {}{}{}{}{}{}",
108+
_err,
105109
"Parse config file failed, ",
106110
"leetcode-cli has just generated a new leetcode.toml at ",
107111
"~/.leetcode/leetcode_tmp.toml,".green().bold().underline(),
108112
" the current one at ",
109113
"~/.leetcode/leetcode.toml".yellow().bold().underline(),
110-
"seems missing some keys, please compare to ",
111-
"the tmp one and add them up : )\n",
112-
".",
113-
))
114+
" seems missing some keys, Please compare the new file and add the missing keys.\n",
115+
);
116+
#[cfg(not(debug_assertions))]
117+
let err_msg = format!(
118+
"{}{}{}{}{}{}",
119+
"Parse config file failed, ",
120+
"leetcode-cli has just generated a new leetcode.toml at ",
121+
"~/.leetcode/leetcode_tmp.toml,".green().bold().underline(),
122+
" the current one at ",
123+
"~/.leetcode/leetcode.toml".yellow().bold().underline(),
124+
" seems missing some keys, Please compare the new file and add the missing keys.\n",
125+
);
126+
Error::ParseError(err_msg)
114127
}
115128
}
116129

β€Žsrc/helper.rs

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,22 +90,67 @@ mod filter {
9090
}
9191
}
9292

93+
pub fn superscript(n: u8) -> String {
94+
match n {
95+
x if x >= 10 => format!("{}{}", superscript(n / 10), superscript(n % 10)),
96+
0 => "0".to_string(),
97+
1 => "1".to_string(),
98+
2 => "2".to_string(),
99+
3 => "3".to_string(),
100+
4 => "4".to_string(),
101+
5 => "5".to_string(),
102+
6 => "6".to_string(),
103+
7 => "7".to_string(),
104+
8 => "8".to_string(),
105+
9 => "9".to_string(),
106+
_ => n.to_string(),
107+
}
108+
}
109+
110+
pub fn subscript(n: u8) -> String {
111+
match n {
112+
x if x >= 10 => format!("{}{}", subscript(n / 10), subscript(n % 10)),
113+
0 => "0".to_string(),
114+
1 => "1".to_string(),
115+
2 => "2".to_string(),
116+
3 => "3".to_string(),
117+
4 => "4".to_string(),
118+
5 => "5".to_string(),
119+
6 => "6".to_string(),
120+
7 => "7".to_string(),
121+
8 => "8".to_string(),
122+
9 => "9".to_string(),
123+
_ => n.to_string(),
124+
}
125+
}
126+
93127
/// Render html to command-line
94128
mod html {
129+
use crate::helper::{subscript, superscript};
130+
use regex::Captures;
95131
use scraper::Html;
132+
96133
/// Html render plugin
97134
pub trait HTML {
98135
fn render(&self) -> String;
99136
}
100137

101138
impl HTML for String {
102139
fn render(&self) -> String {
103-
let rep = self
104-
.replace(r#"</sup>"#, "")
105-
.replace(r#"<sup>"#, "^")
106-
.replace(r#"</sub>"#, "")
107-
.replace(r#"<sub>"#, "_");
108-
let frag = Html::parse_fragment(rep.as_str());
140+
let sup_re = regex::Regex::new(r"<sup>(?P<num>[0-9]*)</sup>").unwrap();
141+
let sub_re = regex::Regex::new(r"<sub>(?P<num>[0-9]*)</sub>").unwrap();
142+
143+
let res = sup_re.replace_all(self, |cap: &Captures| {
144+
let num: u8 = cap["num"].to_string().parse().unwrap();
145+
superscript(num)
146+
});
147+
148+
let res = sub_re.replace_all(&res, |cap: &Captures| {
149+
let num: u8 = cap["num"].to_string().parse().unwrap();
150+
subscript(num)
151+
});
152+
153+
let frag = Html::parse_fragment(&res);
109154

110155
let res = frag
111156
.root_element()

0 commit comments

Comments
(0)

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /