A file-based task manager
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Don't panic on unresolvable wiki-style links

[[some text]] that doesn't parse as either an internal id (tsk-N) or a
foreign id (prefix-N) used to crash the parser. tsk edit / show / list
all run task::parse, so any task body containing one such bracketed
phrase made the binary unusable.

Now we leave the bracketed text in the output unchanged and don't
register a link. Adds two regression tests, and flips the existing
test_foreign_link_bad_no_number from #[should_panic] to assert the
non-panicking contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

+29 -19
+29 -19
src/task.rs
··· 100 100 ); 101 101 out.replace_range(il - 1..out.len(), &linktext); 102 102 links.push(ParsedLink::Internal(id)); 103 - } else if let Some((prefix, id_str)) = contents.split_once('-') { 104 - if let Ok(id) = id_str.parse::<u32>() { 105 - let linktext = format!( 106 - "{}{}", 107 - contents.cyan(), 108 - super_num(links.len() + 1).cyan() 109 - ); 110 - out.replace_range(il - 1..out.len(), &linktext); 111 - links.push(ParsedLink::Foreign { 112 - prefix: prefix.to_string(), 113 - id, 114 - }); 115 - } else { 116 - panic!("Internal link is not a valid id: {contents}"); 117 - } 118 - } else { 119 - panic!("Internal link is not a valid id: {contents}"); 103 + } else if let Some((prefix, id_str)) = contents.split_once('-') 104 + && let Ok(id) = id_str.parse::<u32>() 105 + { 106 + let linktext = 107 + format!("{}{}", contents.cyan(), super_num(links.len() + 1).cyan()); 108 + out.replace_range(il - 1..out.len(), &linktext); 109 + links.push(ParsedLink::Foreign { 110 + prefix: prefix.to_string(), 111 + id, 112 + }); 120 113 } 114 + // If the bracketed text isn't a valid id, leave it in 115 + // the output as-is (no link registered, no panic). 121 116 } 122 117 (last, '[', _) if is_boundary(last) => { 123 118 state.push(Linktext(end, char_pos)); ··· 496 491 ); 497 492 } 498 493 494 + /// `[[jira-abc]]` looks like a foreign link but the id portion isn't 495 + /// numeric. The parser must not panic; the bracketed text is left as plain 496 + /// content and no link is registered. 499 497 #[test] 500 - #[should_panic(expected = "Internal link is not a valid id")] 501 498 fn test_foreign_link_bad_no_number() { 502 499 setup(); 503 500 let input = "see [[jira-abc]]\n"; 504 - let _output = parse(input).expect("parse to work"); 501 + let output = parse(input).expect("parse to work"); 502 + assert!(output.links.is_empty()); 503 + assert_eq!(input, output.content); 504 + } 505 + 506 + /// `[[plain text]]` doesn't match any link form. Same as above: no panic, 507 + /// content preserved, no link registered. 508 + #[test] 509 + fn test_internal_link_unparseable_contents() { 510 + setup(); 511 + let input = "see [[not a link]]\n"; 512 + let output = parse(input).expect("parse to work"); 513 + assert!(output.links.is_empty()); 514 + assert_eq!(input, output.content); 505 515 } 506 516 }