1use clap::Parser;
2use std::fs;
3use std::path::PathBuf;
4
5pub mod api;
6pub mod clues;
7pub mod configs;
8pub mod model_collection;
9
10mod json;
11
12#[derive(Parser)]
14#[command(version, about, long_about = None)]
15pub struct Args {
16 #[arg(short, long = "get-models")]
18 pub get: bool,
19
20 #[arg(short, long = "set-models", default_missing_value = "interactive", num_args = 0..)]
22 pub models: Option<Vec<String>>,
23
24 #[arg(short, long, value_name = "FILE")]
26 pub output: Option<PathBuf>,
27
28 #[arg(short, long = "token-usage")]
30 pub token: bool,
31
32 #[arg(required_unless_present = "get")]
34 pub to_link: Option<PathBuf>,
35
36 #[arg(required_unless_present = "get")]
38 pub to_avoid: Option<PathBuf>,
39}
40
41pub fn read_words_from_file(path: &PathBuf) -> Result<Vec<String>, Box<dyn std::error::Error>> {
42 let contents = fs::read_to_string(path)
43 .map_err(|_| format!("Cannot find file: {}", path.to_string_lossy()))?;
44
45 let words: Vec<String> = contents
46 .lines()
47 .map(|line| line.trim().to_string())
48 .filter(|line| !line.is_empty())
49 .collect();
50
51 if words.is_empty() {
52 Err(format!("File is empty: {}", path.to_string_lossy()).into())
53 } else {
54 Ok(words)
55 }
56}
57
58pub fn write_content_to_file(
59 path: &PathBuf,
60 content: String,
61) -> Result<(), Box<dyn std::error::Error>> {
62 if let Ok(existing_content) = fs::read_to_string(path) {
63 if !existing_content.is_empty() {
64 return Err(format!("File is not empty: {}", path.to_string_lossy()).into());
65 }
66 }
67
68 fs::write(path, content)
69 .map_err(|_| format!("Failed to write to file: {}", path.to_string_lossy()))?;
70
71 Ok(())
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use tempfile::tempdir;
78
79 #[test]
80 fn test_read_words_from_file() {
81 let to_link = read_words_from_file(&PathBuf::from("examples/link.txt"));
82 assert!(to_link.is_ok());
83 let to_avoid = read_words_from_file(&PathBuf::from("examples/avoid.txt"));
84 assert!(to_avoid.is_ok());
85 }
86
87 #[test]
88 fn test_write_content_to_file() {
89 let write_result = write_content_to_file(
91 &PathBuf::from("/none/existent/path/lol"),
92 String::from("useless text"),
93 );
94 assert!(write_result.is_err());
95
96 let temp_dir = tempdir().unwrap();
98 let temp_file = temp_dir.path().join("temp.txt");
99 write_content_to_file(&temp_file, String::from("some text")).unwrap();
100 assert_eq!(fs::read_to_string(&temp_file).unwrap(), "some text");
101
102 let write_result = write_content_to_file(&temp_file, String::from("some text again"));
104 assert!(write_result.is_err());
105 }
106}