MingaEditor.UI.Theme (Minga v0.1.0)

Copy Markdown View Source

Unified color theme for the entire editor.

A theme holds every color the UI needs, organized into semantic groups: syntax highlighting, editor chrome, modeline, gutter, picker, minibuffer, search highlights, and popups.

Built-in themes are shipped as bundled theme pack extensions under Minga.Extensions.ThemePacks. The core retains a single minimal theme (:minga_default) for tests and explicit use, but startup does not silently fall back to it when the configured theme is unavailable.

Usage in config

use Minga.Config
set :theme, :catppuccin_mocha

Summary

Types

RGB color as a non-negative integer (e.g., 0xFF6C6B).

Source that contributed registry entries.

Optional per-filetype icon color overrides, keyed by filetype atom (e.g. :rust) with a special :directory key for folder icons. Unset filetypes fall back to the language's default icon_color. nil/empty means "use defaults everywhere".

A style keyword list compatible with MingaEditor.Frontend.Protocol.style().

Syntax theme: tree-sitter capture name → style.

t()

Functions

Returns a syntax theme map customized for the agent chat buffer.

Returns the agent theme section, falling back to a basic default.

Returns all available theme name atoms (fallback + packs + user-defined).

Returns the dashboard theme section, falling back to a basic default.

Returns the configured default theme name atom. Startup fails if this theme is unavailable.

The theme-independent default icon color for a filetype (or :directory), used when no theme override applies. Equivalent to icon_color/2 against a theme with no :icon overrides.

Returns the theme struct for the given name atom.

Returns the theme struct for the given name, raising on invalid name.

Returns the TODO keyword faces, falling back to Doom One-compatible defaults.

Resolves the icon color for a filetype, preferring the theme's :icon overrides over the language's default icon_color. The special :directory key colors folder icons. Themes without overrides fall back to language/folder defaults.

Registers themes with explicit source ownership. Wraps raw theme structs in LoadedTheme.

Registers user-defined themes loaded from disk.

Returns the style for a tree-sitter capture name, using suffix fallback.

Removes every theme contributed by a source while keeping the core fallback available.

Returns theme source ownership metadata.

Returns the map of registered themes.

Types

color()

@type color() :: non_neg_integer()

RGB color as a non-negative integer (e.g., 0xFF6C6B).

contribution_source()

@type contribution_source() :: :builtin | :config | {:extension, atom()}

Source that contributed registry entries.

icon_overrides()

@type icon_overrides() :: %{required(atom()) => color()}

Optional per-filetype icon color overrides, keyed by filetype atom (e.g. :rust) with a special :directory key for folder icons. Unset filetypes fall back to the language's default icon_color. nil/empty means "use defaults everywhere".

register_error()

@type register_error() ::
  {:duplicate_name, atom(), existing_source :: contribution_source(),
   attempted_source :: contribution_source()}

style()

@type style() :: keyword()

A style keyword list compatible with MingaEditor.Frontend.Protocol.style().

syntax()

@type syntax() :: %{required(String.t()) => style()}

Syntax theme: tree-sitter capture name → style.

t()

@type t() :: %MingaEditor.UI.Theme{
  agent: MingaEditor.UI.Theme.Agent.t() | nil,
  dashboard: MingaEditor.UI.Theme.Dashboard.t() | nil,
  editor: MingaEditor.UI.Theme.Editor.t(),
  git: MingaEditor.UI.Theme.Git.t(),
  gutter: MingaEditor.UI.Theme.Gutter.t(),
  hl_todo: %{required(atom()) => Minga.Core.Face.t()} | nil,
  icon: icon_overrides() | nil,
  minibuffer: MingaEditor.UI.Theme.Minibuffer.t(),
  modeline: MingaEditor.UI.Theme.Modeline.t(),
  name: atom(),
  picker: MingaEditor.UI.Theme.Picker.t(),
  popup: MingaEditor.UI.Theme.Popup.t(),
  search: MingaEditor.UI.Theme.Search.t(),
  syntax: syntax(),
  tab_bar: MingaEditor.UI.Theme.TabBar.t() | nil,
  tree: MingaEditor.UI.Theme.Tree.t()
}

Functions

agent_syntax(theme)

@spec agent_syntax(t()) :: syntax()

Returns a syntax theme map customized for the agent chat buffer.

Overrides delimiter and punctuation captures to use the agent theme's delimiter_dim color, so tree-sitter naturally dims markdown syntax characters (**, *, `, #, ```, brackets, list markers). Link text uses link_fg and URLs use delimiter_dim.

The base syntax map comes from the editor's global theme; only the agent-specific overrides are merged on top.

agent_theme(theme)

@spec agent_theme(t()) :: MingaEditor.UI.Theme.Agent.t()

Returns the agent theme section, falling back to a basic default.

available()

@spec available() :: [atom()]

Returns all available theme name atoms (fallback + packs + user-defined).

dashboard_theme(theme)

@spec dashboard_theme(t()) :: MingaEditor.UI.Theme.Dashboard.t()

Returns the dashboard theme section, falling back to a basic default.

default()

@spec default() :: atom()

Returns the configured default theme name atom. Startup fails if this theme is unavailable.

default_icon_color(filetype)

@spec default_icon_color(atom()) :: color()

The theme-independent default icon color for a filetype (or :directory), used when no theme override applies. Equivalent to icon_color/2 against a theme with no :icon overrides.

get(name)

@spec get(atom()) :: {:ok, t()} | :error

Returns the theme struct for the given name atom.

Checks registered themes (extension packs + user themes) first, then the core fallback.

get!(name)

@spec get!(atom()) :: t()

Returns the theme struct for the given name, raising on invalid name.

hl_todo_faces(theme)

@spec hl_todo_faces(t()) :: %{required(atom()) => Minga.Core.Face.t()}

Returns the TODO keyword faces, falling back to Doom One-compatible defaults.

icon_color(theme, filetype)

@spec icon_color(t(), atom()) :: color()

Resolves the icon color for a filetype, preferring the theme's :icon overrides over the language's default icon_color. The special :directory key colors folder icons. Themes without overrides fall back to language/folder defaults.

register_themes(themes, source)

@spec register_themes(
  %{required(atom()) => t() | MingaEditor.UI.Theme.Loader.loaded_theme()},
  contribution_source()
) :: :ok | {:error, register_error()}

Registers themes with explicit source ownership. Wraps raw theme structs in LoadedTheme.

register_user_themes(themes)

@spec register_user_themes(%{
  required(atom()) => MingaEditor.UI.Theme.Loader.loaded_theme()
}) ::
  :ok | {:error, register_error()}

Registers user-defined themes loaded from disk.

Called by the theme loader at startup and on reload. Stores themes in :persistent_term for fast reads on the render path.

style_for_capture(syntax, name)

@spec style_for_capture(t() | syntax(), String.t()) :: style()

Returns the style for a tree-sitter capture name, using suffix fallback.

Tries exact match first. If not found, strips the last .segment and retries. Returns [] if no match is found.

Examples

iex> theme = MingaEditor.UI.Theme.get!(:doom_one)
iex> style = MingaEditor.UI.Theme.style_for_capture(theme, "keyword")
iex> Keyword.get(style, :bold)
true

iex> theme = MingaEditor.UI.Theme.get!(:doom_one)
iex> MingaEditor.UI.Theme.style_for_capture(theme, "nonexistent")
[]

unregister_source(source)

@spec unregister_source(contribution_source()) :: :ok

Removes every theme contributed by a source while keeping the core fallback available.

user_theme_sources()

@spec user_theme_sources() :: %{required(atom()) => contribution_source()}

Returns theme source ownership metadata.

user_themes()

@spec user_themes() :: %{
  required(atom()) => MingaEditor.UI.Theme.Loader.loaded_theme()
}

Returns the map of registered themes.