From 0eebee8555e9ce13faa273ddec1bf5b36997056c Mon Sep 17 00:00:00 2001
From: Dzuchun <Infernodambik@gmail.com>
Date: Thu, 16 Jan 2025 05:00:14 +0200
Subject: [PATCH 1/3] add `--daily` cli option for `e`, `t` and `x`

---
 src/cmds/edit.rs | 33 +++++++++++++++++++++++++++++----
 src/cmds/exec.rs | 30 ++++++++++++++++++++++++++++--
 src/cmds/test.rs | 36 +++++++++++++++++++++++++++++++-----
 3 files changed, 88 insertions(+), 11 deletions(-)

diff --git a/src/cmds/edit.rs b/src/cmds/edit.rs
index 7a39ee9..f611d6c 100644
--- a/src/cmds/edit.rs
+++ b/src/cmds/edit.rs
@@ -3,7 +3,7 @@ use super::Command;
 use crate::{Error, Result};
 use anyhow::anyhow;
 use async_trait::async_trait;
-use clap::{Arg, ArgMatches, Command as ClapCommand};
+use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command as ClapCommand};
 use std::collections::HashMap;
 
 /// Abstract `edit` command
@@ -29,7 +29,7 @@ impl Command for EditCommand {
     /// `edit` usage
     fn usage() -> ClapCommand {
         ClapCommand::new("edit")
-            .about("Edit question by id")
+            .about("Edit question")
             .visible_alias("e")
             .arg(
                 Arg::new("lang")
@@ -41,10 +41,22 @@ impl Command for EditCommand {
             .arg(
                 Arg::new("id")
                     .num_args(1)
-                    .required(true)
                     .value_parser(clap::value_parser!(i32))
                     .help("question id"),
             )
+            .arg(
+                Arg::new("daily")
+                    .short('d')
+                    .long("daily")
+                    .help("Edit today's daily challenge")
+                    .action(ArgAction::SetTrue),
+            )
+            .group(
+                ArgGroup::new("question-id")
+                    .args(["id", "daily"])
+                    .multiple(false)
+                    .required(true),
+            )
     }
 
     /// `edit` handler
@@ -54,8 +66,21 @@ impl Command for EditCommand {
         use std::io::Write;
         use std::path::Path;
 
-        let id = *m.get_one::<i32>("id").ok_or(Error::NoneError)?;
         let cache = Cache::new()?;
+
+        let daily = m.get_one::<bool>("daily").unwrap_or(&false);
+        let daily_id = if *daily {
+            Some(cache.get_daily_problem_id().await?)
+        } else {
+            None
+        };
+
+        let id = m
+            .get_one::<i32>("id")
+            .copied()
+            .or(daily_id)
+            .ok_or(Error::NoneError)?;
+
         let problem = cache.get_problem(id)?;
         let mut conf = cache.to_owned().0.conf;
 
diff --git a/src/cmds/exec.rs b/src/cmds/exec.rs
index 137a712..4c2fc4b 100644
--- a/src/cmds/exec.rs
+++ b/src/cmds/exec.rs
@@ -2,7 +2,7 @@
 use super::Command;
 use crate::{Error, Result};
 use async_trait::async_trait;
-use clap::{Arg, ArgMatches, Command as ClapCommand};
+use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command as ClapCommand};
 
 /// Abstract Exec Command
 ///
@@ -36,14 +36,40 @@ impl Command for ExecCommand {
                     .value_parser(clap::value_parser!(i32))
                     .help("question id"),
             )
+            .arg(
+                Arg::new("daily")
+                    .short('d')
+                    .long("daily")
+                    .help("Edit today's daily challenge")
+                    .action(ArgAction::SetTrue),
+            )
+            .group(
+                ArgGroup::new("question-id")
+                    .args(["id", "daily"])
+                    .multiple(false)
+                    .required(true),
+            )
     }
 
     /// `exec` handler
     async fn handler(m: &ArgMatches) -> Result<()> {
         use crate::cache::{Cache, Run};
 
-        let id: i32 = *m.get_one::<i32>("id").ok_or(Error::NoneError)?;
         let cache = Cache::new()?;
+
+        let daily = m.get_one::<bool>("daily").unwrap_or(&false);
+        let daily_id = if *daily {
+            Some(cache.get_daily_problem_id().await?)
+        } else {
+            None
+        };
+
+        let id = m
+            .get_one::<i32>("id")
+            .copied()
+            .or(daily_id)
+            .ok_or(Error::NoneError)?;
+
         let res = cache.exec_problem(id, Run::Submit, None).await?;
 
         println!("{}", res);
diff --git a/src/cmds/test.rs b/src/cmds/test.rs
index e8a5011..6d36920 100644
--- a/src/cmds/test.rs
+++ b/src/cmds/test.rs
@@ -2,7 +2,7 @@
 use super::Command;
 use crate::{Error, Result};
 use async_trait::async_trait;
-use clap::{Arg, ArgMatches, Command as ClapCommand};
+use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command as ClapCommand};
 
 /// Abstract Test Command
 ///
@@ -27,12 +27,11 @@ impl Command for TestCommand {
     /// `test` usage
     fn usage() -> ClapCommand {
         ClapCommand::new("test")
-            .about("Test question by id")
+            .about("Test a question")
             .visible_alias("t")
             .arg(
                 Arg::new("id")
                     .num_args(1)
-                    .required(true)
                     .value_parser(clap::value_parser!(i32))
                     .help("question id"),
             )
@@ -42,18 +41,45 @@ impl Command for TestCommand {
                     .required(false)
                     .help("custom testcase"),
             )
+            .arg(
+                Arg::new("daily")
+                    .short('d')
+                    .long("daily")
+                    .help("Test today's daily challenge")
+                    .action(ArgAction::SetTrue),
+            )
+            .group(
+                ArgGroup::new("question-id")
+                    .args(["id", "daily"])
+                    .multiple(false)
+                    .required(true),
+            )
     }
 
     /// `test` handler
     async fn handler(m: &ArgMatches) -> Result<()> {
         use crate::cache::{Cache, Run};
-        let id: i32 = *m.get_one::<i32>("id").ok_or(Error::NoneError)?;
+
+        let cache = Cache::new()?;
+
+        let daily = m.get_one::<bool>("daily").unwrap_or(&false);
+        let daily_id = if *daily {
+            Some(cache.get_daily_problem_id().await?)
+        } else {
+            None
+        };
+
+        let id = m
+            .get_one::<i32>("id")
+            .copied()
+            .or(daily_id)
+            .ok_or(Error::NoneError)?;
+
         let testcase = m.get_one::<String>("testcase");
         let case_str: Option<String> = match testcase {
             Some(case) => Option::from(case.replace("\\n", "\n")),
             _ => None,
         };
-        let cache = Cache::new()?;
         let res = cache.exec_problem(id, Run::Test, case_str).await?;
 
         println!("{}", res);

From 08ee00bd43b58fb189660071616402bb3fdb44f4 Mon Sep 17 00:00:00 2001
From: Dzuchun <Infernodambik@gmail.com>
Date: Thu, 16 Jan 2025 11:50:04 +0200
Subject: [PATCH 2/3] Bump version to 0.4.6

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 734ace8..cc2bf6d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -876,7 +876,7 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "leetcode-cli"
-version = "0.4.5"
+version = "0.4.6"
 dependencies = [
  "anyhow",
  "async-trait",
diff --git a/Cargo.toml b/Cargo.toml
index a12b9f9..96e067c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,7 +4,7 @@ path = "src/bin/lc.rs"
 
 [package]
 name = "leetcode-cli"
-version = "0.4.5"
+version = "0.4.6"
 authors = ["clearloop <tianyi.gc@gmail.com>"]
 edition = "2021"
 description = "Leetcode command-line interface in rust."

From 51d856ced13105d1c6d665d50bd18f3668f73939 Mon Sep 17 00:00:00 2001
From: Dzuchun <Infernodambik@gmail.com>
Date: Thu, 16 Jan 2025 11:53:37 +0200
Subject: [PATCH 3/3] Fix description typo

---
 src/cmds/exec.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/cmds/exec.rs b/src/cmds/exec.rs
index 4c2fc4b..d6538f8 100644
--- a/src/cmds/exec.rs
+++ b/src/cmds/exec.rs
@@ -40,7 +40,7 @@ impl Command for ExecCommand {
                 Arg::new("daily")
                     .short('d')
                     .long("daily")
-                    .help("Edit today's daily challenge")
+                    .help("Exec today's daily challenge")
                     .action(ArgAction::SetTrue),
             )
             .group(