Changeset 319b736 in gignore
- Timestamp:
- 7 Dec 2025, 16:25:36 (5 months ago)
- Branches:
- error_handling, file_locations, help, json_tlib, logging, man, multi_arg, trunk, visibility
- Children:
- b6c2333
- Parents:
- 48d7b95
- Files:
-
- 1 added
- 1 deleted
- 3 edited
-
.gitignore (modified) (1 diff)
-
Cargo.toml (modified) (1 diff)
-
src/lib.rs (modified) (9 diffs)
-
src/template.rs (added)
-
test_gitignore (deleted)
Legend:
- Unmodified
- Added
- Removed
-
.gitignore
r48d7b95 r319b736 1 1 target/ 2 *.swp3 */*.swp4 2 Cargo.lock 3 **.swp 4 test.txt 5 python.txt 6 rust.txt 7 mutants.out 8 vi.txt 9 html.txt -
Cargo.toml
r48d7b95 r319b736 6 6 [dependencies] 7 7 clap = { version = "4.5.53", features = ["derive"] } 8 home = "0.5.12" -
src/lib.rs
r48d7b95 r319b736 1 1 #![warn(clippy::unwrap_used)] 2 3 mod template; 2 4 3 5 use clap::{Subcommand, Parser}; … … 9 11 process::exit, 10 12 io, 13 path::Path, 11 14 }; 15 16 trait HandleErr { 17 type OkType; 18 19 fn handle_err(self, _: &str) -> Self::OkType; 20 } 21 22 impl<T, E: std::fmt::Display> HandleErr for Result<T, E> { 23 type OkType = T; 24 25 fn handle_err(self, operation: &str) -> Self::OkType { 26 match self { 27 Ok(val) => val, 28 Err(e) => { 29 eprintln!("Error {operation}: {e}"); 30 exit(1); 31 }, 32 } 33 } 34 } 35 impl<T> HandleErr for Option<T> { 36 type OkType = T; 37 38 fn handle_err(self, none_message: &str) -> Self::OkType { 39 match self { 40 Some(val) => val, 41 None => { 42 eprintln!("{none_message}"); 43 exit(1); 44 }, 45 } 46 } 47 } 48 12 49 #[derive(Parser)] 13 50 #[command(about = ".gitignore manipulator tool.", long_about = None, version)] … … 33 70 /// Lists items within .gitignore 34 71 List { 72 /// Print contents on one line, separated by whitespace. 35 73 #[arg(long)] 36 74 oneline: bool, 37 75 }, 76 77 /// Add, remove, or use templates. 78 Template { 79 #[command(subcommand)] 80 operation: TemplateCommand, 81 }, 82 } 83 84 #[derive(Subcommand)] 85 pub enum TemplateCommand { 86 /// Add template names and source files to the library 87 Add { 88 /// Name to add to library 89 name: String, 90 /// Source file to add to library 91 source_file: String, 92 93 #[arg(long, short)] 94 /// Append template to .gitignore when using (rather than truncating) 95 append: bool, 96 }, 97 98 /// Remove templates from the library 99 Remove { 100 /// Name to remove from library 101 name: String, 102 }, 103 104 /// Use templates 105 Use { 106 /// Name to write to gitignore 107 name: String, 108 }, 109 110 /// List entries in library 111 List { 112 #[arg(long)] 113 /// Print entries on one line 114 oneline: bool 115 }, 116 117 /// Clear template library 118 Clear, 38 119 } 39 120 … … 45 126 } => { 46 127 let Some(path) = path else { 47 File::create("test_gitignore").unwrap_or_else(|e| { 48 println!("Error creating file: {e}"); 49 exit(1); 50 }); 128 File::create(".gitignore").handle_err("creating file"); 51 129 52 130 std::process::exit(0); 53 131 }; 54 132 55 let mut append_handle = open_append("test_gitignore").unwrap_or_else(|e| { 56 println!("Error opening file for append: {e}"); 57 exit(1); 58 }); 59 60 append_handle.write_all(format!("{}\n", path.trim()).as_bytes()).unwrap_or_else(|e| { 61 println!("Error writing to file: {e}"); 62 exit(1); 63 }); 133 if fs::read_to_string(".gitignore") 134 .handle_err("reading file") 135 .lines() 136 .collect::<Vec<&str>>() 137 .contains(&&path[..]) { 138 println!("That path already exists in .gitignore!"); 139 exit(1); 140 } 141 142 let mut append_handle = open_append(".gitignore".as_ref()).handle_err("opening file for append"); 143 144 append_handle.write_all(format!("{}\n", path.trim()).as_bytes()).handle_err("writing to file"); 64 145 }, 65 146 OperCommand::Remove { … … 67 148 } => { 68 149 let Some(path) = path else { 69 println!("This will permanently remove .gitignore!"); 70 71 loop { 72 println!("Do you really want to do this? y/N"); 73 let mut s = String::new(); 74 io::stdin() 75 .read_line(&mut s) 76 .unwrap_or_else(|e| { 77 println!("Error reading from stdin: {e}"); 78 exit(1); 79 }); 80 81 match &s.trim().to_lowercase()[..] { 82 "" | "n" => break, 83 "y" => { 84 println!("Removing .gitignore..."); 85 86 fs::remove_file("test_gitignore").unwrap_or_else(|e| { 87 eprintln!("Error while removing the file: {e}"); 88 exit(1); 89 }); 90 91 exit(0); 150 if fs::exists(".gitignore").handle_err("searching for file") { 151 loop { 152 println!("This will permanently remove .gitignore!"); 153 println!("Do you really want to do this? y/N"); 154 let mut s = String::new(); 155 io::stdin() 156 .read_line(&mut s) 157 .handle_err("reading stdin"); 158 159 match &s.trim().to_lowercase()[..] { 160 "" | "n" => break, 161 "y" => { 162 println!("Removing .gitignore..."); 163 164 fs::remove_file(".gitignore").handle_err("removing file"); 165 166 exit(0); 167 } 168 _ => continue, 92 169 } 93 _ => continue,94 170 } 171 exit(0); 172 } else { 173 println!("File is already removed."); 174 exit(1); 95 175 } 96 exit(0);97 176 }; 98 177 99 let contents = fs::read_to_string("test_gitignore").unwrap_or_else(|e| { 100 eprintln!("Error reading contents of file: {e}"); 101 exit(1); 102 }); 178 let contents = fs::read_to_string(".gitignore").handle_err("reading file"); 103 179 104 180 let mut lines: Vec<&str> = contents.lines().collect(); … … 113 189 drop(extracted); 114 190 191 open_truncate(".gitignore".as_ref()).handle_err("opening file for truncate").write_all(b"").handle_err("writing to file"); 192 115 193 // Re-add lines to file, without [PATH]. 116 194 for line in lines { 117 File::create("test_gitignore").unwrap_or_else(|e| { 118 eprintln!("{e}"); 119 exit(1); 120 }) 121 .write_all(format!("{}\n", line).as_bytes()) 122 .unwrap_or_else(|e| { 123 eprintln!("{e}"); 124 exit(1); 125 }); 195 open_append(".gitignore".as_ref()).handle_err("opening file for append") 196 .write_all( 197 format!("{line}\n").as_bytes() 198 ).handle_err("writing to file"); 126 199 } 127 200 }, … … 130 203 oneline 131 204 } => { 132 let result = fs::read_to_string(" test_gitignore");205 let result = fs::read_to_string(".gitignore"); 133 206 134 207 if let Err(e) = result { … … 151 224 152 225 println!("{}", result.trim()); 226 }, 227 228 OperCommand::Template { 229 operation: TemplateCommand::Add { 230 name, 231 source_file, 232 append, 233 } 234 } => { 235 template::add(template::Template::new(source_file.as_ref(), name, *append)); 236 } 237 238 OperCommand::Template { 239 operation: TemplateCommand::Remove { 240 name, 241 } 242 } => { 243 template::remove(name); 244 }, 245 246 OperCommand::Template { 247 operation: TemplateCommand::List { 248 oneline, 249 } 250 } => { 251 template::list(*oneline); 252 }, 253 254 OperCommand::Template { 255 operation: TemplateCommand::Use { 256 name, 257 } 258 } => { 259 template::gitignore_write(name); 260 }, 261 262 OperCommand::Template { 263 operation: TemplateCommand::Clear 264 } => { 265 template::clear(); 153 266 } 154 267 }; 155 268 } 156 269 157 fn open_append(path: & str) -> Result<File, Box<dyn Error>> {270 fn open_append(path: &Path) -> Result<File, Box<dyn Error>> { 158 271 Ok( 159 272 OpenOptions::new() … … 163 276 ) 164 277 } 278 fn open_truncate(path: &Path) -> Result<File, Box<dyn Error>> { 279 Ok( 280 OpenOptions::new() 281 .create(true) 282 .write(true) 283 .truncate(true) 284 .open(path)? 285 ) 286 }
Note:
See TracChangeset
for help on using the changeset viewer.
