Skip to content

Commit

Permalink
Really messy, but tag add and remove should be functional now!
Browse files Browse the repository at this point in the history
  • Loading branch information
MickHarrigan committed Sep 29, 2023
1 parent cb23c2c commit 33d52b7
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 49 deletions.
7 changes: 7 additions & 0 deletions src/commands/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,10 @@ where
println!("Input was parsed from: {} into {:?}", input, output);
Ok((input, output))
}

pub fn get_lc_dir() -> Result<String> {
use std::env;
let key = "LEETCODE_DIR";
// val is the top level directory for the leetcode directory
env::var(key).map_err(|e| e.into())
}
11 changes: 3 additions & 8 deletions src/commands/new.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{io::Write, str::FromStr};

use super::common::{GQL_ENDPOINT, SESSION, TOKEN};

use super::common::{GQL_ENDPOINT, SESSION, TOKEN, get_lc_dir};
use anyhow::Result;
use regex::Regex;
use reqwest::Url;
Expand Down Expand Up @@ -234,13 +235,7 @@ pub fn parse_from_json_to_problem(json: serde_json::Value) -> Result<Problem> {
}

pub fn create_entry(prob: Problem) -> Result<()> {
// this should do all of the OS things like making a directory and editing files
// reference the old bash script for this
//
use std::env;
let key = "LEETCODE_DIR";
// val is the top level directory for the leetcode directory
let lc_dir = env::var(key)?;
let lc_dir = get_lc_dir()?;

// first check if the problem exists already in the Cargo.toml
let cargo_path = format!("{}{}", lc_dir, "/Cargo.toml");
Expand Down
107 changes: 107 additions & 0 deletions src/commands/tag.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
use anyhow::Result;
use clap::{Parser, ValueEnum};
use regex::Regex;
use std::{
fs::File,
io::{BufReader, Write},
};
use strum::{EnumString, IntoStaticStr};

use super::common::{get_lc_dir, prompt_for_input};

#[derive(Debug, Clone, Parser, EnumString, IntoStaticStr)]
pub enum TagType {
// #[strum(serialize = "stack", serialize = "<other name>")]
Expand Down Expand Up @@ -45,3 +53,102 @@ impl ValueEnum for TagCommand {
&[Self::Add, Self::Remove, Self::Edit, Self::Search]
}
}

impl std::fmt::Display for TagType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}

pub fn tag_subcommands(cmd: &TagCommand) -> Result<()> {
match cmd {
TagCommand::Add => {
// FLAGS
// ************************************************************
// Add should take a number and a tag/[tags]
// to apply to a problem referenced by the number provided
//
// PROMPTS
// ************************************************************
// should prompt for a tag and a problem number
let lc_dir = get_lc_dir()?;
let (_input_tag, tag) = prompt_for_input::<TagType>("Enter Tag to add: ")?;

let (_input_num, num) =
prompt_for_input::<usize>("Enter Problem Number to add Tag to: ")?;

let problem_dir = format!("{}{}{}", lc_dir, "src/", num);
let tag_path = format!("{}{}", problem_dir, "/TAGS");
let tag_file = std::fs::read_to_string(tag_path.clone())?;

// search for that tag in the problem, if it already exists, return an error of that
let re = Regex::new(format!(r"{}", tag).as_str()).unwrap();
if let Some(_a) = re.captures(tag_file.as_str()) {
return Err(anyhow::Error::msg(format!(
"Tag `{tag}` already exists for this problem!"
)));
} else {
let mut file = std::fs::OpenOptions::new().append(true).open(tag_path)?;
writeln!(file, "{}", tag.to_string())?;
}

println!("Tag: {tag:?} was added to Problem: {num}");
Ok(())
}
TagCommand::Remove => {
// FLAGS
// ************************************************************
// should take a number and a tag/[tags] to remove the tags from said problem
//
// PROMPTS
// ************************************************************
// should prompt for a tag and a problem number

let lc_dir = get_lc_dir()?;

let (_input_num, num) =
prompt_for_input::<usize>("Enter Problem Number to remove a Tag from: ")?;

let prompt = format!("Enter Tag to remove from Problem {}: ", num);
let (_input_tag, tag) = prompt_for_input::<TagType>(prompt.as_str())?;

let problem_dir = format!("{}{}{}", lc_dir, "src/", num);
let tag_path = format!("{}{}", problem_dir, "/TAGS");
let tag_file = std::fs::read_to_string(tag_path.clone())?;

// file contents without the tag that is to be removed
let mut buf = Vec::new();
for line in tag_file.lines() {
if line.to_string() != tag.to_string() {
buf.push(line);
}
}
let buf = buf.join("\n");

let re = Regex::new(format!(r"{}", tag).as_str()).unwrap();

if let Some(_a) = re.captures(tag_file.as_str()) {
let mut file = std::fs::OpenOptions::new()
.write(true)
.truncate(true)
.open(tag_path)?;
writeln!(file, "{}", buf)?;
} else {
return Err(anyhow::Error::msg(format!(
"Tag `{tag}` doesn't exist for this problem!"
)));
}
println!("Tag: {tag:?} was removed from Problem: {num}");
Ok(())
}
TagCommand::Edit => {
// should just take a number and then give a list of all tags for that problem that
// the user can adjust
todo!();
}
TagCommand::Search => {
// given a tag, finds all problems that have that tag
todo!();
}
}
}
45 changes: 4 additions & 41 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,54 +12,17 @@ async fn main() -> Result<()> {
let args = Cli::parse();
match &args.command {
Commands::New { link } => {
let _ = commands::new::run(link).await; // <--- Remove this ; later as it should return all the way up to
// main
commands::new::run(link).await? // <--- Remove this ; later as it should return all the way up to
// main
}

Commands::Edit { num } => {
// takes a number then allows the user to edit the solution
// this is the mutating version of Commands::Info.
let _ = commands::edit::run(num);
commands::edit::run(num)?
}

Commands::Tag { cmd } => match cmd {
TagCommand::Add => {
// FLAGS
// ************************************************************
// Add should take a number and a tag/[tags]
// to apply to a problem referenced by the number provided
//
// PROMPTS
// ************************************************************
// should prompt for a tag and a problem number
let (_input_tag, tag) = prompt_for_input::<TagType>("Enter Tag to add: ")?;

let (_input_num, num) =
prompt_for_input::<usize>("Enter Problem Number to add Tag to: ")?;
println!("Tag: {tag:?} was added to Problem: {num}");
}
TagCommand::Remove => {
// FLAGS
// ************************************************************
// should take a number and a tag/[tags] to remove the tags from said problem
//
// PROMPTS
// ************************************************************
// should prompt for a tag and a problem number
let (_input_tag, tag) = prompt_for_input::<TagType>("Enter Tag to add: ")?;

let (_input_num, num) =
prompt_for_input::<usize>("Enter Problem Number to remove Tag from: ")?;
println!("Tag: {tag:?} was removed from Problem: {num}");
}
TagCommand::Edit => {
// should just take a number and then give a list of all tags for that problem that
// the user can adjust
}
TagCommand::Search => {
// given a tag, finds all problems that have that tag
}
},
Commands::Tag { cmd } => tag_subcommands(cmd)?,
Commands::Info { num } => {
// takes a number and prints a bunch of info about the problem
}
Expand Down

0 comments on commit 33d52b7

Please sign in to comment.