83 lines
2.5 KiB
Elixir
83 lines
2.5 KiB
Elixir
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
|