A file-based task manager

ADD: show command, cleanup

+44 -14
+14 -1
src/main.rs
··· 86 86 full_id: bool, 87 87 }, 88 88 89 + Show { 90 + /// The [TSK-]ID of the task to display 91 + #[command(flatten)] 92 + task_id: TaskId, 93 + }, 94 + 89 95 /// Drops the task on the top of the stack and archives it. 90 96 Drop, 91 97 ··· 187 193 Commands::Push { edit, body, title } => command_push(dir, edit, body, title), 188 194 Commands::List { all, count } => command_list(dir, all, count), 189 195 Commands::Swap => command_swap(dir), 196 + Commands::Show { task_id } => command_show(dir, task_id), 190 197 Commands::Edit { task_id } => command_edit(dir, task_id), 191 198 Commands::Completion { shell } => command_completion(shell), 192 199 Commands::Drop => command_drop(dir), ··· 221 228 let mut body = body.unwrap_or_default(); 222 229 if body == "-" { 223 230 // add newline so you can type directly in the shell 224 - eprintln!(""); 231 + //eprintln!(""); 225 232 body.clear(); 226 233 std::io::stdin().read_to_string(&mut body)?; 227 234 } ··· 314 321 fn command_reprioritize(dir: PathBuf, task_id: TaskId) -> Result<()> { 315 322 Workspace::from_path(dir)?.reprioritize(task_id.into()) 316 323 } 324 + 325 + fn command_show(dir: PathBuf, task_id: TaskId) -> Result<()> { 326 + let task = Workspace::from_path(dir)?.task(task_id.into())?; 327 + println!("{task}"); 328 + Ok(()) 329 + }
+30 -13
src/workspace.rs
··· 157 157 drop(reader); 158 158 Ok(Task { 159 159 id, 160 - title, 161 - body, 160 + title: title.trim().to_string(), 161 + body: body.trim().to_string(), 162 162 file, 163 163 }) 164 164 } ··· 277 277 pub file: Flock<File>, 278 278 } 279 279 280 - /// A task container without a file handle 281 - pub struct BareTask { 282 - pub id: Id, 283 - pub title: String, 284 - pub body: String, 280 + impl Display for Task { 281 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 282 + write!(f, "{}\n\n{}", self.title, &self.body) 283 + } 285 284 } 286 285 287 286 impl Task { ··· 295 294 Ok(()) 296 295 } 297 296 298 - fn bare(self) -> BareTask { 299 - BareTask { 297 + fn bare(self) -> SearchTask { 298 + SearchTask { 300 299 id: self.id, 301 300 title: self.title, 302 301 body: self.body, ··· 304 303 } 305 304 } 306 305 307 - impl FromStr for BareTask { 306 + /// A task container without a file handle 307 + pub struct SearchTask { 308 + pub id: Id, 309 + pub title: String, 310 + pub body: String, 311 + } 312 + 313 + impl FromStr for SearchTask { 308 314 type Err = Error; 309 315 310 316 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { ··· 322 328 } 323 329 } 324 330 325 - impl Display for BareTask { 331 + impl Display for SearchTask { 326 332 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 327 333 write!( 328 334 f, ··· 340 346 } 341 347 342 348 impl<'a> Iterator for LazyTaskLoader<'a> { 343 - type Item = BareTask; 349 + type Item = SearchTask; 344 350 345 351 fn next(&mut self) -> Option<Self::Item> { 346 352 let stack_item = self.files.next()?; ··· 358 364 359 365 #[test] 360 366 fn test_bare_task_display() { 361 - let task = BareTask { 367 + let task = SearchTask { 362 368 id: Id(123), 363 369 title: "Hello, world".to_string(), 364 370 body: "The body of the task.\nAnother line\r\nis here.".to_string(), ··· 367 373 "tsk-123\tHello, world\tThe body of the task. Another line is here.", 368 374 task.to_string() 369 375 ); 376 + } 377 + 378 + #[test] 379 + fn test_task_display() { 380 + let task = Task { 381 + id: Id(123), 382 + title: "Hello, world".to_string(), 383 + body: "The body of the task.".to_string(), 384 + file: util::flopen("/dev/null".into(), FlockArg::LockShared).unwrap(), 385 + }; 386 + assert_eq!("Hello, world\n\nThe body of the task.", task.to_string()); 370 387 } 371 388 }