diff --git a/lib/Block.ml b/lib/Block.ml index dac57ca..f8cd17a 100644 --- a/lib/Block.ml +++ b/lib/Block.ml @@ -1,43 +1,40 @@ type 'a t = Common of 'a | Changed of { mine : 'a list; their : 'a list } let of_hunk (hunk : 'a Patch.hunk) : 'a t list = - let rec process_hunk acc current_mine current_their = function + let rec aux acc current_mine current_their lines = + match lines with | [] -> if current_mine <> [] || current_their <> [] then - Changed - { mine = List.rev current_mine; their = List.rev current_their } - :: acc + Changed { mine = current_mine; their = current_their } :: acc else acc | `Common line :: rest -> let acc' = if current_mine <> [] || current_their <> [] then - Changed - { mine = List.rev current_mine; their = List.rev current_their } - :: acc + Changed { mine = current_mine; their = current_their } :: acc else acc in - process_hunk (Common line :: acc') [] [] rest - | `Mine line :: rest -> - process_hunk acc (line :: current_mine) current_their rest - | `Their line :: rest -> - process_hunk acc current_mine (line :: current_their) rest + aux (Common line :: acc') [] [] rest + | `Mine line :: rest -> aux acc (line :: current_mine) current_their rest + | `Their line :: rest -> aux acc current_mine (line :: current_their) rest in - List.rev (process_hunk [] [] [] hunk.lines) + List.rev (aux [] [] [] hunk.lines) let to_hunk (blocks : 'a t list) : 'a Patch.hunk = - let lines, mine_len, their_len = - List.fold_left - (fun (lines, mine_len, their_len) block -> - match block with - | Common line -> (`Common line :: lines, mine_len + 1, their_len + 1) - | Changed { mine; their } -> - let mine_lines = List.map (fun line -> `Mine line) mine in - let their_lines = List.map (fun line -> `Their line) their in - ( mine_lines @ their_lines @ lines, - mine_len + List.length mine, - their_len + List.length their )) - ([], 0, 0) blocks + let rec aux lines mine_len their_len blocks = + match blocks with + | [] -> (lines, mine_len, their_len) + | Common line :: rest -> + aux (`Common line :: lines) (mine_len + 1) (their_len + 1) rest + | Changed { mine; their } :: rest -> + let mine_lines = List.map (fun line -> `Mine line) mine in + let their_lines = List.map (fun line -> `Their line) their in + aux + (mine_lines @ their_lines @ lines) + (mine_len + List.length mine) + (their_len + List.length their) + rest in + let lines, mine_len, their_len = aux [] 0 0 blocks in { mine_start = 0; mine_len;