A file-based task manager

FIXED BASIC PARSING

+31 -23
+31 -23
src/task.rs
··· 63 63 let state_last = state.last().cloned(); 64 64 match stream.next() { 65 65 // there will always be an op code in the stack 66 - Some((pos, c)) => { 66 + Some((_, c)) => { 67 + out.push(c); 68 + let end = out.len()-1; 67 69 if c == '\n' || c == '\r' { 68 70 state.clear(); 69 71 } ··· 71 73 ('=', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(Highlight(hl))) => { 72 74 state.pop(); 73 75 out.replace_range( 74 - hl..pos, 75 - &out.get(hl + 1..pos - 1)?.reversed().to_string(), 76 + hl..end, 77 + &out.get(hl + 1..out.len() - 2)?.reversed().to_string(), 76 78 ); 77 79 } 78 80 (' ' | '\r' | '\n', '=', _) => { 79 - state.push(Highlight(pos)); 81 + state.push(Highlight(end)); 80 82 } 81 83 ('[', '[', _) => { 82 - state.push(InternalLink(pos)); 84 + state.push(InternalLink(end)); 83 85 } 84 86 (']', ']', Some(InternalLink(il))) => { 85 87 state.pop(); 86 - let contents = out.get(il + 1..pos - 1)?; 88 + let contents = out.get(il + 1..out.len() - 2)?; 87 89 if let Ok(id) = Id::from_str(&contents) { 88 90 let linktext = format!( 89 91 "{}{}", 90 92 contents.purple(), 91 93 super_num(links.len() + 1).purple() 92 94 ); 93 - out.replace_range(il..pos, &linktext); 95 + out.replace_range(il..out.len()-1, &linktext); 94 96 links.push(ParsedLink::Internal(id)); 95 97 } else { 96 98 panic!("Internal link is not a valid id: {contents}"); 97 99 } 98 100 } 99 101 (' ' | '\r' | '\n', '[', _) => { 100 - state.push(Linktext(pos)); 102 + state.push(Linktext(end)); 101 103 } 102 104 (']', '(', Some(Linktext(_))) => { 103 - state.push(Link(pos)); 105 + state.push(Link(end)); 104 106 } 105 107 (')', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(Link(_))) => { 106 108 let linkpos = if let Link(lp) = state.pop().unwrap() { ··· 117 119 }; 118 120 let linktext = format!( 119 121 "{}{}", 120 - out.get(linktextpos + 1..linkpos - 1)?.blue(), 122 + out.get(linktextpos + 1..linkpos-1)?.blue(), 121 123 super_num(links.len() + 1).purple() 122 124 ); 123 - let link = out.get(linkpos + 1..pos - 1)?; 125 + let link = out.get(linkpos + 1..out.len() - 2)?; 124 126 if let Ok(url) = Url::parse(link) { 125 127 links.push(ParsedLink::External(url)); 126 - out.replace_range(linktextpos..pos - 1, &linktext); 128 + out.replace_range(linktextpos..end, &linktext); 127 129 } 128 130 } 129 131 (' ' | '\r' | '\n', '*', _) => { 130 - state.push(Italics(pos)); 132 + state.push(Italics(end)); 131 133 } 132 134 ('*', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(Italics(il))) => { 133 135 state.pop(); 134 - out.replace_range(il..pos, &out.get(il + 1..pos - 1)?.italic().to_string()); 136 + out.replace_range( 137 + il..end, 138 + &out.get(il + 1..out.len() - 2)?.italic().to_string(), 139 + ); 135 140 } 136 141 (' ' | '\r' | '\n', '!', _) => { 137 - state.push(Bold(pos)); 142 + state.push(Bold(end)); 138 143 } 139 144 ('!', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(Bold(il))) => { 140 145 state.pop(); 141 - out.replace_range(il..pos, &out.get(il + 1..pos - 1)?.bold().to_string()); 146 + out.replace_range( 147 + il..end, 148 + &out.get(il + 1..out.len() - 2)?.bold().to_string(), 149 + ); 142 150 } 143 151 (' ' | '\r' | '\n', '_', _) => { 144 - state.push(Underline(pos)); 152 + state.push(Underline(end)); 145 153 } 146 154 ('_', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(Underline(il))) => { 147 155 state.pop(); 148 156 out.replace_range( 149 - il..pos, 150 - &out.get(il + 1..pos - 1)?.underline().to_string(), 157 + il..end, 158 + &out.get(il + 1..out.len() - 2)?.underline().to_string(), 151 159 ); 152 160 } 153 161 (' ' | '\r' | '\n', '~', _) => { 154 - state.push(Strikethrough(pos)); 162 + state.push(Strikethrough(end)); 155 163 } 156 164 ('~', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(Strikethrough(il))) => { 157 165 state.pop(); 158 166 out.replace_range( 159 - il..pos, 160 - &out.get(il + 1..pos - 1)?.strikethrough().to_string(), 167 + il..end, 168 + &out.get(il + 1..out.len() - 2)?.strikethrough().to_string(), 161 169 ); 162 170 } 163 171 _ => (), ··· 327 335 328 336 #[test] 329 337 fn test_multiple_styles() { 330 - let input = "hello *world* ~world~ !world!\n"; 338 + let input = "hello *italic* ~strikethrough~ !bold!\n"; 331 339 let output = parse(input).expect("parse to work"); 332 340 assert_eq!( 333 341 "hello \u{1b}[3mworld\u{1b}[0m \u{1b}[9mworld\u{1b}[0m \u{1b}[1mworld\u{1b}[0m\n",