1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
use crate::*; use bogobble::*; #[derive(Debug)] pub enum Item { Hits(usize), Recent(u64), Path(String), Cmd(String), } parser! {(File->Vec<Item>) (star(("\n ,".istar(),PItem).last()),("\n ,".istar(),EOI)).first() } parser! {(PItem->Item) or!( ("h",common::UInt).map(|(_,n)|Item::Hits(n)), ("r",common::UInt).map(|(_,n)|Item::Recent(n as u64)), ("p",Quoted).map(|(_,s)|Item::Path(s)), ("c",Quoted).map(|(_,s)|Item::Cmd(s)), ) } parser! {(Quoted->String) ('\"',chars_until(or!( ("\\n").asv('\n'), ("\\\"").asv('"'), ("\\\\").asv('\\'), Any.one(), ),'"')).map(|(_,(b,_))|b) } pub fn parse_onto(h: &mut HistoryStore, s: &str) -> anyhow::Result<()> { let mut pr = File.parse_s(s).map_err(|e| e.strung())?.into_iter(); let mut cmd = read_to_command(&mut pr, &mut CommandData::new()); while let Some(c) = cmd { match h.mp.get_mut(&c) { Some(v) => cmd = read_to_command(&mut pr, v), None => { let mut cdat = CommandData::new(); let new_command = c.to_string(); cmd = read_to_command(&mut pr, &mut cdat); h.mp.insert(new_command, cdat); } } } Ok(()) } pub fn read_to_command<I: Iterator<Item = Item>>( i: &mut I, cd: &mut CommandData, ) -> Option<String> { let mut hits = 0; let mut recent = 0; while let Some(c) = i.next() { match c { Item::Cmd(c) => return Some(c), Item::Hits(h) => { cd.hits += h; hits = h; } Item::Recent(r) => recent = r, Item::Path(p) => { if recent > cd.recent { cd.recent = recent; } match cd.paths.get_mut(&p) { Some(hi) => { hi.hits += hits; hi.recent = recent; } None => drop(cd.paths.insert( p, HistoryItem { recent, hits, r_hits: 0, }, )), } } } } None }