A file-based task manager

ADD: link following

+103 -1
+37
Cargo.lock
··· 351 ] 352 353 [[package]] 354 name = "is_terminal_polyfill" 355 version = "1.70.1" 356 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 397 version = "1.20.2" 398 source = "registry+https://github.com/rust-lang/crates.io-index" 399 checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 400 401 [[package]] 402 name = "percent-encoding" ··· 563 "colored", 564 "edit", 565 "nix", 566 "smallstr", 567 "thiserror", 568 "url",
··· 351 ] 352 353 [[package]] 354 + name = "is-docker" 355 + version = "0.2.0" 356 + source = "registry+https://github.com/rust-lang/crates.io-index" 357 + checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" 358 + dependencies = [ 359 + "once_cell", 360 + ] 361 + 362 + [[package]] 363 + name = "is-wsl" 364 + version = "0.4.0" 365 + source = "registry+https://github.com/rust-lang/crates.io-index" 366 + checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" 367 + dependencies = [ 368 + "is-docker", 369 + "once_cell", 370 + ] 371 + 372 + [[package]] 373 name = "is_terminal_polyfill" 374 version = "1.70.1" 375 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 416 version = "1.20.2" 417 source = "registry+https://github.com/rust-lang/crates.io-index" 418 checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 419 + 420 + [[package]] 421 + name = "open" 422 + version = "5.3.0" 423 + source = "registry+https://github.com/rust-lang/crates.io-index" 424 + checksum = "61a877bf6abd716642a53ef1b89fb498923a4afca5c754f9050b4d081c05c4b3" 425 + dependencies = [ 426 + "is-wsl", 427 + "libc", 428 + "pathdiff", 429 + ] 430 + 431 + [[package]] 432 + name = "pathdiff" 433 + version = "0.2.2" 434 + source = "registry+https://github.com/rust-lang/crates.io-index" 435 + checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" 436 437 [[package]] 438 name = "percent-encoding" ··· 599 "colored", 600 "edit", 601 "nix", 602 + "open", 603 "smallstr", 604 "thiserror", 605 "url",
+1
Cargo.toml
··· 13 xattr = "1.3.1" 14 colored = "2.1.0" 15 smallstr = "0.3.0" 16 17 [build-dependencies] 18 clap_mangen = "0.2.23"
··· 13 xattr = "1.3.1" 14 colored = "2.1.0" 15 smallstr = "0.3.0" 16 + open = "5.3.0" 17 18 [build-dependencies] 19 clap_mangen = "0.2.23"
+65 -1
src/main.rs
··· 11 use std::path::PathBuf; 12 use std::process::exit; 13 use std::{env::current_dir, io::Read}; 14 use workspace::{Id, TaskIdentifier, Workspace}; 15 16 //use smol; ··· 89 full_id: bool, 90 }, 91 92 - /// Prints the contents of a task. 93 Show { 94 /// Shows raw file attributes for the file 95 #[arg(short = 'x', default_value_t = false)] ··· 99 task_id: TaskId, 100 }, 101 102 /// Drops the task on the top of the stack and archives it. 103 Drop { 104 /// The [TSK-]ID of the task to drop. ··· 215 task_id, 216 show_attrs, 217 } => command_show(dir, task_id, show_attrs), 218 Commands::Edit { task_id } => command_edit(dir, task_id), 219 Commands::Completion { shell } => command_completion(shell), 220 Commands::Drop { task_id } => command_drop(dir, task_id), ··· 234 } 235 } 236 237 fn command_init(dir: PathBuf) -> Result<()> { 238 Workspace::init(dir) 239 } ··· 366 } 367 Ok(()) 368 }
··· 11 use std::path::PathBuf; 12 use std::process::exit; 13 use std::{env::current_dir, io::Read}; 14 + use task::ParsedLink; 15 use workspace::{Id, TaskIdentifier, Workspace}; 16 17 //use smol; ··· 90 full_id: bool, 91 }, 92 93 + /// Prints the contents of a task, parsing the body as rich text and formatting it using ANSI 94 + /// escape sequences. 95 Show { 96 /// Shows raw file attributes for the file 97 #[arg(short = 'x', default_value_t = false)] ··· 101 task_id: TaskId, 102 }, 103 104 + /// Follow a link that is parsed from a task body. It may be an internal or external link (ie. 105 + /// a url or a wiki-style link using double square brackets). When using the `tsk show` 106 + /// command, links that are successfully parsed get a numeric superscript that may be used to 107 + /// address the link. That number should be supplied to the -l/link_index where it will be 108 + /// subsequently followed opened or shown. 109 + Follow { 110 + /// The task whose body will be searched for links. 111 + #[command(flatten)] 112 + task_id: TaskId, 113 + /// The index of the link to open. Must be supplied. 114 + #[arg(short = 'l')] 115 + link_index: usize, 116 + /// When opening an internal link, whether to show or edit the addressed task. 117 + #[arg(short = 'e', default_value_t = false)] 118 + edit: bool, 119 + }, 120 + 121 /// Drops the task on the top of the stack and archives it. 122 Drop { 123 /// The [TSK-]ID of the task to drop. ··· 234 task_id, 235 show_attrs, 236 } => command_show(dir, task_id, show_attrs), 237 + Commands::Follow { 238 + task_id, 239 + link_index, 240 + edit, 241 + } => command_follow(dir, task_id, link_index, edit), 242 Commands::Edit { task_id } => command_edit(dir, task_id), 243 Commands::Completion { shell } => command_completion(shell), 244 Commands::Drop { task_id } => command_drop(dir, task_id), ··· 258 } 259 } 260 261 + fn taskid_from_tsk_id(tsk_id: Id) -> TaskId { 262 + TaskId { 263 + tsk_id: Some(tsk_id), 264 + id: None, 265 + relative_id: 0, 266 + find: Find { 267 + find: false, 268 + args: FindArgs { search_body: false }, 269 + }, 270 + } 271 + } 272 + 273 fn command_init(dir: PathBuf) -> Result<()> { 274 Workspace::init(dir) 275 } ··· 402 } 403 Ok(()) 404 } 405 + 406 + fn command_follow(dir: PathBuf, task_id: TaskId, link_index: usize, edit: bool) -> Result<()> { 407 + let task = Workspace::from_path(dir.clone())?.task(task_id.into())?; 408 + if let Some(parsed_task) = task::parse(&task.to_string()) { 409 + if link_index == 0 || link_index > parsed_task.links.len() { 410 + eprintln!("Link index out of bounds."); 411 + exit(1); 412 + } 413 + let link = &parsed_task.links[link_index - 1]; 414 + match link { 415 + ParsedLink::External(url) => { 416 + open::that_detached(url.as_str())?; 417 + Ok(()) 418 + } 419 + ParsedLink::Internal(id) => { 420 + let taskid = taskid_from_tsk_id(*id); 421 + if edit { 422 + command_edit(dir, taskid) 423 + } else { 424 + command_show(dir, taskid, false) 425 + } 426 + } 427 + } 428 + } else { 429 + eprintln!("Unable to parse any links from body."); 430 + exit(1); 431 + } 432 + }