defmodule Outlook.InternalTree.TunitModifications do alias Outlook.InternalTree.{InternalNode,TranslationUnit} def modifiers do [ %{ name: "unite_with_next", fn: &unite_with_next/2, label: "Unite with next", description: "unite selected translation unit with (unselected) next" }, # %{ # name: "split_tunit", # fn: &split_tunit/2, # label: "Split Translation unit", # description: "split translation unit into two" # } ] end # Modifier functions defp unite_with_next(nodelist, tu_ids) when is_list(tu_ids) do ids_to_process = Enum.reverse(tu_ids) Enum.reduce(ids_to_process, nodelist, fn id, nodes -> unite_with_next(nodes, id) end) end defp unite_with_next(nodelist, tu_id) do ind = Enum.find_index(nodelist, fn n -> n.nid == tu_id end) nodes = Enum.slice(nodelist, ind, 2) unite_with_next(nodelist, ind, nodes) end defp unite_with_next(nodelist, ind, [unit,next]) do nunit = %TranslationUnit{unit | content: unit.content <> next.content} nodelist |> List.replace_at(ind, nunit) |> List.delete_at(ind + 1) end defp unite_with_next(nodelist, _, [_]) do nodelist end defp split_tunit(_nodelist, _tu_ids) do end # Function and helpers to apply modifiers def apply_modifier([ %InternalNode{} = node | rest ], modifier, tu_ids) when node.type == :element do content = case List.first(node.content) do %TranslationUnit{} -> process_tunit_list(node.content, modifier, tu_ids) _ -> apply_modifier(node.content, modifier, tu_ids) end [%InternalNode{node| content: content} | apply_modifier(rest, modifier, tu_ids)] end def apply_modifier([node | rest], modifier, tu_ids), do: [node | apply_modifier(rest, modifier, tu_ids)] def apply_modifier([],_, _), do: [] def process_tunit_list(tunits, modifier, tu_ids) do modi_fun = get_modi_fun(modifier) ids_to_process = get_ids_to_process(tunits, tu_ids) case length(ids_to_process) do 0 -> tunits _ -> modi_fun.(tunits, ids_to_process) end end @doc false def get_ids_to_process(tunits, tu_ids) do present_ids = Enum.map(tunits, fn u -> u.nid end) found_ids = MapSet.new(present_ids) |> MapSet.intersection(MapSet.new(tu_ids)) |> MapSet.to_list() # make sure to return ids in the order they occur in tunits Enum.filter(present_ids, fn pres -> pres in found_ids end) end defp get_modi_fun(modifier) do modifiers() |> Enum.find(fn m -> m.name == modifier end) |> Map.get(:fn) end end