use crate::{
get_save_backup_file_path, load_textareas, save_textareas, EditorClipboard, ThemeMode,
ThothConfig,
};
use anyhow::{bail, Result};
use std::{
fs::File,
io::{BufRead, BufReader, Write},
};
use std::env;
use clap::{Parser, Subcommand};
use crate::get_save_file_path;
#[derive(Parser)]
#[command(author = env!("CARGO_PKG_AUTHORS"), version = env!("CARGO_PKG_VERSION"), about, long_about = None, rename_all = "snake_case")]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Commands>,
}
#[derive(Subcommand)]
#[command(rename_all = "snake_case")]
pub enum Commands {
Add {
name: String,
content: Option<String>,
},
List,
LoadBackup,
ReadClipboard,
Delete {
name: String,
},
View {
name: String,
},
Copy {
name: String,
},
Theme {
mode: String,
},
GetTheme,
}
pub fn set_theme(mode: &str) -> Result<()> {
let mode_lowercase = mode.to_lowercase();
let mut config = ThothConfig::load()?;
match mode_lowercase.as_str() {
"light" => {
config.set_theme(ThemeMode::Light)?;
println!("Theme set to light mode");
}
"dark" => {
config.set_theme(ThemeMode::Dark)?;
println!("Theme set to dark mode");
}
_ => {
bail!("Invalid theme mode. Use 'light' or 'dark'");
}
}
Ok(())
}
pub fn get_theme() -> Result<()> {
let config = ThothConfig::load()?;
match config.theme {
ThemeMode::Light => println!("Current theme: light"),
ThemeMode::Dark => println!("Current theme: dark"),
}
Ok(())
}
pub fn read_clipboard_backup() -> Result<()> {
let file_path = crate::get_clipboard_backup_file_path();
if !file_path.exists() {
println!("No clipboard backup file found at {}", file_path.display());
return Ok(());
}
let content = std::fs::read_to_string(&file_path)?;
if content.is_empty() {
println!("Clipboard backup file exists but is empty.");
} else {
println!("{}", content);
}
Ok(())
}
pub fn add_block(name: &str, content: &str) -> Result<()> {
let mut file = std::fs::OpenOptions::new()
.append(true)
.create(true)
.open(get_save_file_path())?;
writeln!(file, "# {}", name)?;
writeln!(file, "{}", content)?;
writeln!(file)?;
println!("Block '{}' added successfully.", name);
Ok(())
}
pub fn list_blocks() -> Result<()> {
let file = File::open(get_save_file_path())?;
let reader = BufReader::new(file);
for line in reader.lines() {
let line = line?;
if let Some(strip) = line.strip_prefix("# ") {
println!("{}", strip);
}
}
Ok(())
}
pub fn replace_from_backup() -> Result<()> {
let (backup_textareas, backup_textareas_titles) = load_textareas(get_save_backup_file_path())?;
save_textareas(
&backup_textareas,
&backup_textareas_titles,
get_save_file_path(),
)
}
pub fn view_block(name: &str) -> Result<()> {
let file = File::open(get_save_file_path())?;
let reader = BufReader::new(file);
let mut blocks = Vec::new();
let mut current_block = Vec::new();
let mut current_name = String::new();
for line in reader.lines() {
let line = line?;
if let Some(strip) = line.strip_prefix("# ") {
if !current_name.is_empty() {
blocks.push((current_name, current_block));
current_block = Vec::new();
}
current_name = strip.to_string();
} else {
current_block.push(line);
}
}
if !current_name.is_empty() {
blocks.push((current_name, current_block));
}
for (block_name, block_content) in blocks {
if block_name == name {
for line in block_content {
println!("{}", line);
}
}
}
Ok(())
}
pub fn copy_block(name: &str) -> Result<()> {
let file = File::open(get_save_file_path())?;
let reader = BufReader::new(file);
let mut blocks = Vec::new();
let mut current_block = Vec::new();
let mut current_name = String::new();
let mut matched_name: Option<String> = None;
for line in reader.lines() {
let line = line?;
if let Some(strip) = line.strip_prefix("# ") {
if !current_name.is_empty() {
blocks.push((current_name, current_block));
current_block = Vec::new();
}
current_name = strip.to_string();
} else {
current_block.push(line);
}
}
if !current_name.is_empty() {
blocks.push((current_name, current_block));
}
for (block_name, block_content) in blocks {
if block_name == name {
let result_ctx = EditorClipboard::new();
if result_ctx.is_err() {
bail!("Failed to create clipboard context for copy block");
}
let mut ctx = result_ctx.unwrap();
let is_success = ctx.set_contents(block_content.join("\n"));
if is_success.is_err() {
bail!(format!(
"Failed to copy contents of block {} to system clipboard",
block_name
));
}
matched_name = Some(block_name);
break;
}
}
match matched_name {
Some(name) => println!("Successfully copied contents from block {}", name),
None => println!("Didn't find the block. Please try again. You can use `thoth list` to find the name of all blocks")
};
Ok(())
}
pub fn delete_block(name: &str) -> Result<()> {
let file = File::open(get_save_file_path())?;
let reader = BufReader::new(file);
let mut blocks = Vec::new();
let mut current_block = Vec::new();
let mut current_name = String::new();
for line in reader.lines() {
let line = line?;
if let Some(strip) = line.strip_prefix("# ") {
if !current_name.is_empty() {
blocks.push((current_name, current_block));
current_block = Vec::new();
}
current_name = strip.to_string();
} else {
current_block.push(line);
}
}
if !current_name.is_empty() {
blocks.push((current_name, current_block));
}
let mut file = File::create(get_save_file_path())?;
let mut deleted = false;
for (block_name, block_content) in blocks {
if block_name != name {
writeln!(file, "# {}", block_name)?;
for line in block_content {
writeln!(file, "{}", line)?;
}
writeln!(file)?;
} else {
deleted = true;
}
}
if deleted {
println!("Block '{}' deleted successfully.", name);
} else {
println!("Block '{}' not found.", name);
}
Ok(())
}