1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use super::Command;
use crate::Error;
use async_trait::async_trait;
use clap::{Arg, ArgMatches, Command as ClapCommand};
pub struct EditCommand;
pub const CODE_START: &str = r#"// @lc code=start"#;
pub const CODE_END: &str = r#"// @lc code=end"#;
#[async_trait]
impl Command for EditCommand {
fn usage<'a>() -> ClapCommand<'a> {
ClapCommand::new("edit")
.about("Edit question by id")
.visible_alias("e")
.arg(
Arg::with_name("lang")
.short('l')
.long("lang")
.takes_value(true)
.help("Edit with specific language"),
)
.arg(
Arg::with_name("id")
.takes_value(true)
.required(true)
.help("question id"),
)
.arg(
Arg::with_name("test")
.long("test")
.short('t')
.required(false)
.help("write test file"),
)
}
async fn handler(m: &ArgMatches) -> Result<(), crate::Error> {
use crate::{cache::models::Question, Cache};
use std::fs::File;
use std::io::Write;
use std::path::Path;
let id: i32 = m.value_of("id").ok_or(Error::NoneError)?.parse()?;
let cache = Cache::new()?;
let problem = cache.get_problem(id)?;
let mut conf = cache.to_owned().0.conf;
let test_flag = m.contains_id("test");
let p_desc_comment = problem.desc_comment();
if m.contains_id("lang") {
conf.code.lang = m.value_of("lang").ok_or(Error::NoneError)?.to_string();
conf.sync()?;
}
let lang = conf.code.lang;
let path = crate::helper::code_path(&problem, Some(lang.to_owned()))?;
if !Path::new(&path).exists() {
let mut qr = serde_json::from_str(&problem.desc);
if qr.is_err() {
qr = Ok(cache.get_question(id).await?);
}
let question: Question = qr?;
let mut file_code = File::create(&path)?;
let question_desc = question.desc_comment() + "\n";
let test_path = crate::helper::test_cases_path(&problem)?;
let mut file_tests = File::create(&test_path)?;
let mut flag = false;
for d in question.defs.0 {
if d.value == lang {
flag = true;
file_code.write_all(p_desc_comment.as_bytes())?;
file_code.write_all(question_desc.as_bytes())?;
file_code.write_all((CODE_START.to_string() + "\n").as_bytes())?;
file_code.write_all((d.code.to_string() + "\n").as_bytes())?;
file_code.write_all((CODE_END.to_string() + "\n").as_bytes())?;
if test_flag {
file_tests.write_all(question.all_cases.as_bytes())?;
}
}
}
if !flag {
std::fs::remove_file(&path)?;
if test_flag {
std::fs::remove_file(&test_path)?;
}
return Err(crate::Error::FeatureError(format!(
"This question doesn't support {}, please try another",
&lang
)));
}
}
let mut args: Vec<String> = Default::default();
if let Some(editor_args) = conf.code.editor_args {
args.extend_from_slice(&editor_args);
}
args.push(path);
std::process::Command::new(conf.code.editor)
.args(args)
.status()?;
Ok(())
}
}