Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 35 additions & 5 deletions src/leetcode_api_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,22 @@ pub struct LeetcodeApiRunner {
}

impl LeetcodeApiRunner {
pub async fn new(rcs: &RuntimeConfigSetup) -> Self {
let api = UserApi::new(&rcs.config.leetcode_token).await.unwrap();
LeetcodeApiRunner {
pub async fn new(rcs: &RuntimeConfigSetup) -> Result<Self, io::Error> {
Ok(LeetcodeApiRunner {
rcs: rcs.clone(),
api,
}
api: UserApi::new(&rcs.config.leetcode_token).await.map_err(
|_| {
io::Error::new(
io::ErrorKind::NotConnected,
format!(
"An error occurred while creating the API client. \
Check your token in your configuration file: {}",
rcs.config_file.display()
),
)
},
)?,
})
}

pub async fn get_problem_info(&self, id: u32) -> io::Result<String> {
Expand All @@ -46,6 +56,26 @@ impl LeetcodeApiRunner {
Ok(format!("{} {}: {}\n{}", id, difficulty, title, description))
}

/// Fetches the problem name by its ID.
pub async fn get_problem_name(&self, id: u32) -> io::Result<String> {
let pb = self.api.set_problem_by_id(id).await.unwrap();
Ok(pb.description().unwrap().name.clone())
}

/// Fetches the available languages for a given problem ID.
pub async fn get_available_languages(
&self, id: &u32,
) -> io::Result<Vec<String>> {
let problem = self.api.set_problem_by_id(*id).await?;

Ok(problem
.code_snippets()
.expect("No code snippets found.")
.iter()
.map(|snippet| snippet.langSlug.clone())
.collect::<Vec<_>>())
}

pub async fn start_problem(
&self, id: u32, language: ProgrammingLanguage,
) -> io::Result<String> {
Expand Down
29 changes: 24 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use clap::Parser;
use leetcode_cli::{
utils::{
parse_programming_language,
prompt_for_language,
spin_the_spinner,
},
Cli,
Expand All @@ -15,7 +16,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
let mut rcs = RuntimeConfigSetup::new();
rcs.status()?;
let api_runner = LeetcodeApiRunner::new(&rcs).await;
let api_runner = LeetcodeApiRunner::new(&rcs).await?;

match &cli.command {
Commands::Info {
Expand All @@ -33,11 +34,29 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
id,
language,
} => {
let default = &rcs.config.default_language.unwrap();
let lang = match language {
Some(lang) => parse_programming_language(lang)?,
None => parse_programming_language(default)?,
let default_lang = rcs
.config
.default_language
.clone()
.unwrap_or_else(|| "not found".to_string());
let mut lang = match language {
Some(lang) => parse_programming_language(lang),
None => parse_programming_language(&default_lang),
};
let mut spin = spin_the_spinner("Gathering problem info...");
let problem_name = api_runner.get_problem_name(*id).await?;
let available_languages =
api_runner.get_available_languages(&id).await?;
spin.stop();
while lang.is_err() {
lang = prompt_for_language(
id,
&problem_name,
&available_languages,
)
.and_then(|lang| parse_programming_language(&lang));
}
let lang = lang.unwrap();
let mut spin = spin_the_spinner("Starting problem setup...");
let start_problem = api_runner.start_problem(*id, lang).await;
spin.stop();
Expand Down
31 changes: 29 additions & 2 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub fn write_to_file(

pub fn parse_programming_language(
lang: &str,
) -> Result<leetcoderustapi::ProgrammingLanguage, String> {
) -> Result<leetcoderustapi::ProgrammingLanguage, std::io::Error> {
match lang.to_ascii_lowercase().as_str() {
"cpp" | "c++" => Ok(leetcoderustapi::ProgrammingLanguage::CPP),
"java" => Ok(leetcoderustapi::ProgrammingLanguage::Java),
Expand Down Expand Up @@ -62,7 +62,10 @@ pub fn parse_programming_language(
"dart" => Ok(leetcoderustapi::ProgrammingLanguage::Dart),
"pandas" => Ok(leetcoderustapi::ProgrammingLanguage::Pandas),
"react" => Ok(leetcoderustapi::ProgrammingLanguage::React),
_ => Err(format!("Unsupported language: {}", lang)),
_ => Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("Unsupported language: {}", lang),
)),
}
}

Expand Down Expand Up @@ -159,3 +162,27 @@ pub fn extension_programming_language(
pub fn spin_the_spinner(message: &str) -> spinners::Spinner {
spinners::Spinner::new(spinners::Spinners::Dots12, message.to_string())
}

pub fn prompt_for_language(
id: &u32, problem_name: &str, available_languages: &[String],
) -> Result<String, io::Error> {
println!(
"\nPlease enter a valid Leetcode programming language.\nHere is a \
list of available languages for the problem {} - {}\n{}",
id,
problem_name,
available_languages
.iter()
.map(|l| l.to_string())
.collect::<Vec<_>>()
.join(", ")
);
let mut input = String::new();
io::stdin().read_line(&mut input)?;
let trimmed = input.trim().to_string();
if trimmed.is_empty() {
Err(io::Error::new(io::ErrorKind::InvalidInput, "No language entered"))
} else {
Ok(trimmed)
}
}