mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
palette: better uniformization of builtin vs community
This commit is contained in:
+1073
-973
File diff suppressed because it is too large
Load Diff
@@ -7,12 +7,15 @@
|
||||
|
||||
namespace noctalia::theme {
|
||||
|
||||
struct FixedPaletteMode {
|
||||
Palette palette;
|
||||
TerminalPalette terminal;
|
||||
};
|
||||
|
||||
struct BuiltinPalette {
|
||||
std::string_view name;
|
||||
Palette dark;
|
||||
Palette light;
|
||||
TerminalPalette darkTerminal;
|
||||
TerminalPalette lightTerminal;
|
||||
FixedPaletteMode dark;
|
||||
FixedPaletteMode light;
|
||||
};
|
||||
|
||||
std::span<const BuiltinPalette> builtinPalettes();
|
||||
|
||||
+9
-16
@@ -116,28 +116,21 @@ namespace noctalia::theme {
|
||||
}
|
||||
|
||||
void injectTerminalColors(TokenMap& dst, const nlohmann::json& modeJson) {
|
||||
if (!modeJson.contains("terminal") || !modeJson["terminal"].is_object())
|
||||
if (!modeJson.contains(kTerminalJsonKey) || !modeJson[kTerminalJsonKey].is_object())
|
||||
return;
|
||||
const auto& terminal = modeJson["terminal"];
|
||||
static constexpr std::pair<const char*, const char*> directKeys[] = {
|
||||
{"foreground", "terminal_foreground"},
|
||||
{"background", "terminal_background"},
|
||||
{"cursor", "terminal_cursor"},
|
||||
{"cursorText", "terminal_cursor_text"},
|
||||
{"selectionFg", "terminal_selection_fg"},
|
||||
{"selectionBg", "terminal_selection_bg"},
|
||||
};
|
||||
for (const auto& [jsonKey, flatKey] : directKeys) {
|
||||
const auto& terminal = modeJson[kTerminalJsonKey];
|
||||
for (const auto& [jsonKey, flatKey] : kTerminalDirectColorTokenKeys) {
|
||||
if (terminal.contains(jsonKey) && terminal[jsonKey].is_string())
|
||||
setToken(dst, flatKey, terminal[jsonKey].get<std::string>());
|
||||
}
|
||||
for (const char* group : {"normal", "bright"}) {
|
||||
if (!terminal.contains(group) || !terminal[group].is_object())
|
||||
for (const auto& group : kTerminalAnsiGroupTokenKeys) {
|
||||
if (!terminal.contains(group.jsonKey) || !terminal[group.jsonKey].is_object())
|
||||
continue;
|
||||
for (auto it = terminal[group].begin(); it != terminal[group].end(); ++it) {
|
||||
if (!it.value().is_string())
|
||||
for (const auto key : kTerminalAnsiColorJsonKeys) {
|
||||
const auto& groupJson = terminal[group.jsonKey];
|
||||
if (!groupJson.contains(key) || !groupJson[key].is_string())
|
||||
continue;
|
||||
setToken(dst, std::string("terminal_") + group + "_" + it.key(), it.value().get<std::string>());
|
||||
setToken(dst, std::string(group.tokenPrefix) + "_" + std::string(key), groupJson[key].get<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+48
-16
@@ -54,15 +54,49 @@ namespace noctalia::theme {
|
||||
}
|
||||
}
|
||||
|
||||
const ::Color& ansiColorForKey(const TerminalAnsiColors& colors, std::string_view key) {
|
||||
if (key == kTerminalBlackJsonKey)
|
||||
return colors.black;
|
||||
if (key == kTerminalRedJsonKey)
|
||||
return colors.red;
|
||||
if (key == kTerminalGreenJsonKey)
|
||||
return colors.green;
|
||||
if (key == kTerminalYellowJsonKey)
|
||||
return colors.yellow;
|
||||
if (key == kTerminalBlueJsonKey)
|
||||
return colors.blue;
|
||||
if (key == kTerminalMagentaJsonKey)
|
||||
return colors.magenta;
|
||||
if (key == kTerminalCyanJsonKey)
|
||||
return colors.cyan;
|
||||
return colors.white;
|
||||
}
|
||||
|
||||
const ::Color& directColorForKey(const TerminalPalette& terminal, std::string_view key) {
|
||||
if (key == kTerminalForegroundJsonKey)
|
||||
return terminal.foreground;
|
||||
if (key == kTerminalBackgroundJsonKey)
|
||||
return terminal.background;
|
||||
if (key == kTerminalCursorJsonKey)
|
||||
return terminal.cursor;
|
||||
if (key == kTerminalCursorTextJsonKey)
|
||||
return terminal.cursorText;
|
||||
if (key == kTerminalSelectionFgJsonKey)
|
||||
return terminal.selectionFg;
|
||||
return terminal.selectionBg;
|
||||
}
|
||||
|
||||
const TerminalAnsiColors& ansiGroupForKey(const TerminalPalette& terminal, std::string_view key) {
|
||||
return key == kTerminalBrightJsonKey ? terminal.bright : terminal.normal;
|
||||
}
|
||||
|
||||
void applyAnsiColors(TokenMap& tokens, std::string_view prefix, const TerminalAnsiColors& colors) {
|
||||
setToken(tokens, std::string(prefix) + "_black", colors.black);
|
||||
setToken(tokens, std::string(prefix) + "_red", colors.red);
|
||||
setToken(tokens, std::string(prefix) + "_green", colors.green);
|
||||
setToken(tokens, std::string(prefix) + "_yellow", colors.yellow);
|
||||
setToken(tokens, std::string(prefix) + "_blue", colors.blue);
|
||||
setToken(tokens, std::string(prefix) + "_magenta", colors.magenta);
|
||||
setToken(tokens, std::string(prefix) + "_cyan", colors.cyan);
|
||||
setToken(tokens, std::string(prefix) + "_white", colors.white);
|
||||
for (const auto key : kTerminalAnsiColorJsonKeys) {
|
||||
std::string tokenKey(prefix);
|
||||
tokenKey += "_";
|
||||
tokenKey += key;
|
||||
setToken(tokens, tokenKey, ansiColorForKey(colors, key));
|
||||
}
|
||||
}
|
||||
|
||||
Color interpolateColor(const Color& a, const Color& b, double t) {
|
||||
@@ -73,14 +107,12 @@ namespace noctalia::theme {
|
||||
} // namespace
|
||||
|
||||
void applyTerminalPalette(TokenMap& tokens, const TerminalPalette& terminal) {
|
||||
applyAnsiColors(tokens, "terminal_normal", terminal.normal);
|
||||
applyAnsiColors(tokens, "terminal_bright", terminal.bright);
|
||||
setToken(tokens, "terminal_foreground", terminal.foreground);
|
||||
setToken(tokens, "terminal_background", terminal.background);
|
||||
setToken(tokens, "terminal_selection_fg", terminal.selectionFg);
|
||||
setToken(tokens, "terminal_selection_bg", terminal.selectionBg);
|
||||
setToken(tokens, "terminal_cursor_text", terminal.cursorText);
|
||||
setToken(tokens, "terminal_cursor", terminal.cursor);
|
||||
for (const auto& group : kTerminalAnsiGroupTokenKeys) {
|
||||
applyAnsiColors(tokens, group.tokenPrefix, ansiGroupForKey(terminal, group.jsonKey));
|
||||
}
|
||||
for (const auto& key : kTerminalDirectColorTokenKeys) {
|
||||
setToken(tokens, key.tokenKey, directColorForKey(terminal, key.jsonKey));
|
||||
}
|
||||
}
|
||||
|
||||
void synthesizeTerminalPaletteTokens(TokenMap& tokens) {
|
||||
|
||||
@@ -3,12 +3,67 @@
|
||||
#include "theme/palette.h"
|
||||
#include "ui/palette.h"
|
||||
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace noctalia::theme {
|
||||
|
||||
using TokenMap = std::unordered_map<std::string, uint32_t>;
|
||||
|
||||
inline constexpr std::string_view kTerminalJsonKey = "terminal";
|
||||
inline constexpr std::string_view kTerminalNormalJsonKey = "normal";
|
||||
inline constexpr std::string_view kTerminalBrightJsonKey = "bright";
|
||||
inline constexpr std::string_view kTerminalBlackJsonKey = "black";
|
||||
inline constexpr std::string_view kTerminalRedJsonKey = "red";
|
||||
inline constexpr std::string_view kTerminalGreenJsonKey = "green";
|
||||
inline constexpr std::string_view kTerminalYellowJsonKey = "yellow";
|
||||
inline constexpr std::string_view kTerminalBlueJsonKey = "blue";
|
||||
inline constexpr std::string_view kTerminalMagentaJsonKey = "magenta";
|
||||
inline constexpr std::string_view kTerminalCyanJsonKey = "cyan";
|
||||
inline constexpr std::string_view kTerminalWhiteJsonKey = "white";
|
||||
inline constexpr std::string_view kTerminalForegroundJsonKey = "foreground";
|
||||
inline constexpr std::string_view kTerminalBackgroundJsonKey = "background";
|
||||
inline constexpr std::string_view kTerminalCursorJsonKey = "cursor";
|
||||
inline constexpr std::string_view kTerminalCursorTextJsonKey = "cursorText";
|
||||
inline constexpr std::string_view kTerminalSelectionFgJsonKey = "selectionFg";
|
||||
inline constexpr std::string_view kTerminalSelectionBgJsonKey = "selectionBg";
|
||||
|
||||
struct TerminalColorTokenKey {
|
||||
std::string_view jsonKey;
|
||||
std::string_view tokenKey;
|
||||
};
|
||||
|
||||
inline constexpr std::array<TerminalColorTokenKey, 6> kTerminalDirectColorTokenKeys = {{
|
||||
{kTerminalForegroundJsonKey, "terminal_foreground"},
|
||||
{kTerminalBackgroundJsonKey, "terminal_background"},
|
||||
{kTerminalCursorJsonKey, "terminal_cursor"},
|
||||
{kTerminalCursorTextJsonKey, "terminal_cursor_text"},
|
||||
{kTerminalSelectionFgJsonKey, "terminal_selection_fg"},
|
||||
{kTerminalSelectionBgJsonKey, "terminal_selection_bg"},
|
||||
}};
|
||||
|
||||
inline constexpr std::array<std::string_view, 8> kTerminalAnsiColorJsonKeys = {{
|
||||
kTerminalBlackJsonKey,
|
||||
kTerminalRedJsonKey,
|
||||
kTerminalGreenJsonKey,
|
||||
kTerminalYellowJsonKey,
|
||||
kTerminalBlueJsonKey,
|
||||
kTerminalMagentaJsonKey,
|
||||
kTerminalCyanJsonKey,
|
||||
kTerminalWhiteJsonKey,
|
||||
}};
|
||||
|
||||
struct TerminalAnsiGroupTokenKey {
|
||||
std::string_view jsonKey;
|
||||
std::string_view tokenPrefix;
|
||||
};
|
||||
|
||||
inline constexpr std::array<TerminalAnsiGroupTokenKey, 2> kTerminalAnsiGroupTokenKeys = {{
|
||||
{kTerminalNormalJsonKey, "terminal_normal"},
|
||||
{kTerminalBrightJsonKey, "terminal_bright"},
|
||||
}};
|
||||
|
||||
struct TerminalAnsiColors {
|
||||
::Color black;
|
||||
::Color red;
|
||||
|
||||
+37
-30
@@ -132,39 +132,44 @@ namespace noctalia::theme {
|
||||
|
||||
TerminalAnsiColors readAnsiJson(const nlohmann::json& obj) {
|
||||
return TerminalAnsiColors{
|
||||
.black = readColorField(obj, "black"),
|
||||
.red = readColorField(obj, "red"),
|
||||
.green = readColorField(obj, "green"),
|
||||
.yellow = readColorField(obj, "yellow"),
|
||||
.blue = readColorField(obj, "blue"),
|
||||
.magenta = readColorField(obj, "magenta"),
|
||||
.cyan = readColorField(obj, "cyan"),
|
||||
.white = readColorField(obj, "white"),
|
||||
.black = readColorField(obj, kTerminalBlackJsonKey),
|
||||
.red = readColorField(obj, kTerminalRedJsonKey),
|
||||
.green = readColorField(obj, kTerminalGreenJsonKey),
|
||||
.yellow = readColorField(obj, kTerminalYellowJsonKey),
|
||||
.blue = readColorField(obj, kTerminalBlueJsonKey),
|
||||
.magenta = readColorField(obj, kTerminalMagentaJsonKey),
|
||||
.cyan = readColorField(obj, kTerminalCyanJsonKey),
|
||||
.white = readColorField(obj, kTerminalWhiteJsonKey),
|
||||
};
|
||||
}
|
||||
|
||||
TerminalPalette readTerminalJson(const nlohmann::json& obj) {
|
||||
TerminalPalette tp{};
|
||||
if (auto it = obj.find("normal"); it != obj.end() && it->is_object()) {
|
||||
if (auto it = obj.find(kTerminalNormalJsonKey); it != obj.end() && it->is_object()) {
|
||||
tp.normal = readAnsiJson(*it);
|
||||
}
|
||||
if (auto it = obj.find("bright"); it != obj.end() && it->is_object()) {
|
||||
if (auto it = obj.find(kTerminalBrightJsonKey); it != obj.end() && it->is_object()) {
|
||||
tp.bright = readAnsiJson(*it);
|
||||
}
|
||||
tp.foreground = readColorField(obj, "foreground");
|
||||
tp.background = readColorField(obj, "background");
|
||||
tp.selectionFg = readColorField(obj, "selectionFg");
|
||||
tp.selectionBg = readColorField(obj, "selectionBg");
|
||||
tp.cursorText = readColorField(obj, "cursorText");
|
||||
tp.cursor = readColorField(obj, "cursor");
|
||||
tp.foreground = readColorField(obj, kTerminalForegroundJsonKey);
|
||||
tp.background = readColorField(obj, kTerminalBackgroundJsonKey);
|
||||
tp.selectionFg = readColorField(obj, kTerminalSelectionFgJsonKey);
|
||||
tp.selectionBg = readColorField(obj, kTerminalSelectionBgJsonKey);
|
||||
tp.cursorText = readColorField(obj, kTerminalCursorTextJsonKey);
|
||||
tp.cursor = readColorField(obj, kTerminalCursorJsonKey);
|
||||
return tp;
|
||||
}
|
||||
|
||||
std::optional<TerminalPalette> readModeTerminalJson(const nlohmann::json& obj) {
|
||||
auto it = obj.find(kTerminalJsonKey);
|
||||
if (it == obj.end() || !it->is_object())
|
||||
return std::nullopt;
|
||||
return readTerminalJson(*it);
|
||||
}
|
||||
|
||||
struct ParsedCommunityPalette {
|
||||
Palette dark;
|
||||
Palette light;
|
||||
TerminalPalette darkTerminal;
|
||||
TerminalPalette lightTerminal;
|
||||
FixedPaletteMode dark;
|
||||
FixedPaletteMode light;
|
||||
};
|
||||
|
||||
std::optional<ParsedCommunityPalette> parseCommunityPaletteJson(const std::filesystem::path& path) {
|
||||
@@ -179,21 +184,25 @@ namespace noctalia::theme {
|
||||
return std::nullopt;
|
||||
ParsedCommunityPalette out{};
|
||||
if (auto it = root.find("dark"); it != root.end() && it->is_object()) {
|
||||
out.dark = readPaletteJson(*it);
|
||||
out.dark.palette = readPaletteJson(*it);
|
||||
if (auto terminal = readModeTerminalJson(*it)) {
|
||||
out.dark.terminal = *terminal;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
if (auto it = root.find("light"); it != root.end() && it->is_object()) {
|
||||
out.light = readPaletteJson(*it);
|
||||
out.light.palette = readPaletteJson(*it);
|
||||
if (auto terminal = readModeTerminalJson(*it)) {
|
||||
out.light.terminal = *terminal;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
} else {
|
||||
out.light = out.dark;
|
||||
}
|
||||
if (auto it = root.find("darkTerminal"); it != root.end() && it->is_object()) {
|
||||
out.darkTerminal = readTerminalJson(*it);
|
||||
}
|
||||
if (auto it = root.find("lightTerminal"); it != root.end() && it->is_object()) {
|
||||
out.lightTerminal = readTerminalJson(*it);
|
||||
}
|
||||
return out;
|
||||
} catch (const std::exception& e) {
|
||||
kLog.warn("failed to parse community palette '{}': {}", path.string(), e.what());
|
||||
@@ -206,8 +215,6 @@ namespace noctalia::theme {
|
||||
.name = "community",
|
||||
.dark = parsed.dark,
|
||||
.light = parsed.light,
|
||||
.darkTerminal = parsed.darkTerminal,
|
||||
.lightTerminal = parsed.lightTerminal,
|
||||
};
|
||||
const std::string mode = resolvedModeName(cfg);
|
||||
const GeneratedPalette generated = expandBuiltinPalette(bp);
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
Palette palette = noctalia::theme::findBuiltinPalette("Noctalia")->dark;
|
||||
Palette palette = noctalia::theme::findBuiltinPalette("Noctalia")->dark.palette;
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user