Packages
Terminal emulation and driver infrastructure for Raxol. ANSI parsing, screen buffers, command processing, cursor management, input handling, session management, and termbox2 NIF integration.
Current section
Files
Jump to
Current section
Files
lib/raxol/terminal/plugin/dependency_resolver.ex
defmodule Raxol.Terminal.Plugin.DependencyResolver do
@moduledoc """
Handles plugin dependency resolution for the terminal emulator.
This module extracts the plugin dependency resolution logic from the main emulator.
"""
@doc """
Resolves plugin dependencies and returns the load order.
"""
@spec resolve_plugin_dependencies(map()) :: [String.t()]
def resolve_plugin_dependencies(plugin_manager) do
# Extract plugin dependencies
plugins = Map.get(plugin_manager, :plugins, [])
dependencies = extract_plugin_dependencies(plugins)
# Perform topological sort
case topological_sort(dependencies) do
{:ok, sorted_plugins} ->
sorted_plugins
{:error, _reason} ->
# If there are circular dependencies, return plugins in original order
Enum.map(plugins, & &1.name)
end
end
@doc """
Extracts dependencies from a list of plugins.
"""
@spec extract_plugin_dependencies([map()]) :: map()
def extract_plugin_dependencies(plugins) do
Enum.map(plugins, fn plugin ->
{plugin.name, Map.get(plugin, :dependencies, [])}
end)
|> Map.new()
end
@doc """
Performs topological sorting on plugin dependencies.
"""
@spec topological_sort(map()) :: {:ok, [String.t()]} | {:error, atom()}
def topological_sort(dependencies) do
# Kahn's algorithm for topological sorting
nodes = Map.keys(dependencies)
in_degree = calculate_in_degree(dependencies, nodes)
# Find nodes with no incoming edges
queue = Enum.filter(nodes, fn node -> Map.get(in_degree, node, 0) == 0 end)
case topological_sort_helper(dependencies, in_degree, queue, []) do
sorted when length(sorted) == length(nodes) -> {:ok, sorted}
_ -> {:error, :circular_dependency}
end
end
@doc """
Calculates the in-degree for each node in the dependency graph.
"""
@spec calculate_in_degree(map(), [String.t()]) :: map()
def calculate_in_degree(dependencies, nodes) do
Enum.reduce(nodes, %{}, fn node, acc ->
in_degree =
Enum.count(dependencies, fn {_name, deps} ->
Enum.member?(deps, node)
end)
Map.put(acc, node, in_degree)
end)
end
@doc """
Helper function for topological sorting using Kahn's algorithm.
"""
@spec topological_sort_helper(map(), map(), [String.t()], [String.t()]) :: [
String.t()
]
def topological_sort_helper(_dependencies, _in_degree, [], result) do
result
end
def topological_sort_helper(dependencies, in_degree, [node | queue], result) do
# Remove node and its outgoing edges
new_in_degree =
Enum.reduce(dependencies[node] || [], in_degree, fn dep, acc ->
Map.update(acc, dep, 0, &(&1 - 1))
end)
# Add nodes with no incoming edges to queue
new_queue =
queue ++
Enum.filter(dependencies[node] || [], fn dep ->
Map.get(new_in_degree, dep, 0) == 0
end)
topological_sort_helper(dependencies, new_in_degree, new_queue, [
node | result
])
end
end