1structure tailbuffer :> tailbuffer = 2struct 3 4type t = {v : string Vector.vector, i: int, full : bool, s : string, max : int, 5 patterns : (string * bool) list} 6 7fun new {numlines,patterns} : t = 8 if numlines < 1 then raise Fail "tailbuffer.new: numlines <= 0" 9 else 10 let 11 val v = Vector.tabulate(numlines, (fn _ => "")) 12 in 13 {v = v, i = 0, full = false, s = "", max = numlines, 14 patterns = List.map (fn p => (p, false)) patterns} 15 end 16 17fun front_last l = 18 let 19 fun recurse acc l = 20 case l of 21 [] => NONE 22 | [h] => SOME (List.rev acc, h) 23 | h::t => recurse (h::acc) t 24 in 25 recurse [] l 26 end 27 28fun fill1 (news, {v,i,full,s,max,patterns} : t) : t = 29 let 30 val newline = s^news 31 in 32 {v = Vector.update(v,i,newline), 33 i = (i + 1) mod max, 34 full = full orelse i + 1 = max, 35 s = "", 36 max = max, 37 patterns = 38 List.map (fn pat as (_, true) => pat 39 | (p, _) => (p, String.isSubstring p newline)) patterns} 40 end 41 42fun add_incomplete_line l ({v,i,full,s,max,patterns}:t) : t = 43 {v = v, i = i, full = full, max = max, patterns = patterns, s = s ^ l} 44 45fun append s' (tb:t) : t = 46 let 47 val lines = String.fields (fn c => c = #"\n") s' 48 in 49 case front_last lines of 50 NONE => raise Fail "tailbuffer.append: can't happen" 51 | SOME(lines, line) => 52 let 53 val tb' = List.foldl fill1 tb lines 54 in 55 add_incomplete_line line tb' 56 end 57 end 58 59fun last_line ({v,i,full,max,...} : t) = 60 if not full andalso i = 0 then NONE 61 else SOME (Vector.sub(v,(i - 1) mod max)) 62 63fun output ({v,i,full,s,max,patterns,...}:t) = 64 let 65 val patterns_seen = List.map #1 (List.filter #2 patterns) 66 in 67 if not full andalso i = 0 then 68 { fulllines = [], lastpartial = s, patterns_seen = patterns_seen } 69 else 70 let 71 val limit = if full then i else 0 72 fun recurse acc j = 73 if j = limit then 74 Vector.sub(v, j)::acc 75 else recurse (Vector.sub(v,j)::acc) ((j - 1) mod max) 76 in 77 { fulllines = recurse [] ((i - 1) mod max), lastpartial = s, 78 patterns_seen = patterns_seen } 79 end 80 end 81 82end 83