defmodule GitGud.Themes.Editor do
@moduledoc """
Curated subset of Lumis themes exposed in the UI as "editor theme."
Lumis ships ~250 Neovim-derived themes. Surfacing the entire list in
a select makes it useless; this module fences the choice to the
classic palettes most users will recognize. If you want something
exotic, set the column directly.
Falls back to a known-good theme if the user's stored choice isn't
in the curated list (e.g. someone bumped Lumis and a theme got
renamed).
"""
# Theme ids match Lumis's `available_themes/0` exactly. Run
# `Lumis.available_themes() |> Enum.sort()` in iex to confirm
# before editing — names like "solarized_dark" or "rose_pine" don't
# exist; the actual ids are `neosolarized_*` and `rosepine_*`.
@themes [
{"OneDark", "onedark"},
{"Dracula", "dracula"},
{"Solarized Dark", "neosolarized_dark"},
{"Solarized Light", "neosolarized_light"},
{"Monokai", "monokai"},
{"Monokai Pro", "monokai_pro"},
{"GitHub Dark", "github_dark"},
{"GitHub Light", "github_light"},
{"Gruvbox Dark", "gruvbox_dark"},
{"Gruvbox Light", "gruvbox_light"},
{"Nord", "nord"},
{"Tokyo Night (Storm)", "tokyonight_storm"},
{"Tokyo Night", "tokyonight_night"},
{"Tokyo Night (Day)", "tokyonight_day"},
{"Catppuccin Mocha", "catppuccin_mocha"},
{"Catppuccin Frappé", "catppuccin_frappe"},
{"Catppuccin Macchiato", "catppuccin_macchiato"},
{"Catppuccin Latte", "catppuccin_latte"},
{"Rose Pine", "rosepine_dark"},
{"Rose Pine Dawn", "rosepine_dawn"}
]
@default "onedark"
require Logger
@doc "List of `{label, value}` tuples suitable for a select input."
def options, do: @themes
@doc "All valid theme ids."
def ids, do: Enum.map(@themes, fn {_, id} -> id end)
@doc "App default theme used when a user hasn't picked one."
def default, do: @default
@doc """
Resolve a user's theme choice to a valid Lumis id, falling back to
the default when the stored value is nil or no longer recognized.
"""
def resolve(nil), do: @default
def resolve(theme) when is_binary(theme) do
if theme in ids() do
theme
else
Logger.warning(
"editor theme #{inspect(theme)} not in curated list; falling back to #{@default}"
)
@default
end
end
def resolve(_), do: @default
@doc "True if `theme` is in the curated list."
def valid?(theme) when is_binary(theme), do: theme in ids()
def valid?(_), do: false
@doc """
Resolve the editor theme from a LiveView's `current_scope`. Anonymous
visitors get the app default; authed users get their stored choice
(falling back to the default if it's nil or no longer valid).
"""
def for_scope(%{user: %{editor_theme: theme}}), do: resolve(theme)
def for_scope(_), do: @default
end
2.8 KiB · text
5af55d9