@bniladridas/cursor 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.clang-tidy +28 -0
- package/.dockerignore +56 -0
- package/.env.example +29 -0
- package/.github/CODEOWNERS +2 -0
- package/.github/ISSUE_TEMPLATE/blank.md +27 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
- package/.github/SECURITY.md +24 -0
- package/.github/codeql/codeql-config.yml +8 -0
- package/.github/dependabot.yml +14 -0
- package/.github/labeler.yml +50 -0
- package/.github/packaging/brand-cursor.png +0 -0
- package/.github/packaging/database/init.sql +48 -0
- package/.github/packaging/docker/Dockerfile +111 -0
- package/.github/packaging/docker/docker-compose.yml +56 -0
- package/.github/packaging/scripts/preflight.sh +413 -0
- package/.github/packaging/scripts/prepare-release.sh +141 -0
- package/.github/packaging/scripts/release.sh +22 -0
- package/.github/packaging/scripts/setup-git-hooks.sh +73 -0
- package/.github/pull_request_template.md +31 -0
- package/.github/signed.json +9 -0
- package/.github/workflows/README.md +23 -0
- package/.github/workflows/ci.yml +181 -0
- package/.github/workflows/cla.yml +33 -0
- package/.github/workflows/formula-sha.yml +63 -0
- package/.github/workflows/issue-response.yml +44 -0
- package/.github/workflows/labeler.yml +42 -0
- package/.github/workflows/pr-body.yml +49 -0
- package/.github/workflows/release.yml +176 -0
- package/.github/workflows/security.yml +94 -0
- package/.github/workflows/stale.yml +38 -0
- package/AGENTS.md +49 -0
- package/CHANGELOG.md +3 -0
- package/CMakeLists.txt +646 -0
- package/Formula/cursor.rb +46 -0
- package/LICENSE +201 -0
- package/Makefile +28 -0
- package/README.md +46 -0
- package/cli.js +16 -0
- package/include/agent.h +86 -0
- package/include/agent_mode.h +17 -0
- package/include/memory_manager.h +102 -0
- package/include/services/ai_service.h +31 -0
- package/include/services/auth_service.h +87 -0
- package/include/services/checkpoint_service.h +69 -0
- package/include/services/codebase_service.h +38 -0
- package/include/services/command_service.h +23 -0
- package/include/services/context_service.h +74 -0
- package/include/services/database_service.h +56 -0
- package/include/services/error_service.h +106 -0
- package/include/services/file_service.h +51 -0
- package/include/services/git_service.h +29 -0
- package/include/services/github_service.h +85 -0
- package/include/services/mcp_service.h +85 -0
- package/include/services/multi_file_service.h +93 -0
- package/include/services/sandbox_service.h +96 -0
- package/include/services/theme_service.h +67 -0
- package/include/services/web_service.h +52 -0
- package/include/utils/config.h +68 -0
- package/include/utils/memory_utils.h +79 -0
- package/include/utils/platform.h +56 -0
- package/include/utils/ui.h +43 -0
- package/include/utils/validation.h +63 -0
- package/include/utils/version.h.in +17 -0
- package/install.js +49 -0
- package/package.json +16 -0
- package/release/checksums.txt +3 -0
- package/release/cursor-linux/cursor_v0.1.7_linux_amd64.tar.gz +0 -0
- package/release/cursor-macos/cursor_v0.1.7_darwin_arm64.tar.gz +0 -0
- package/release/cursor-windows/cursor__windows_amd64.zip +0 -0
- package/src/agent.cpp +2026 -0
- package/src/main.cpp +97 -0
- package/src/memory_manager.cpp +814 -0
- package/src/services/ai_service.cpp +366 -0
- package/src/services/auth_service.cpp +779 -0
- package/src/services/checkpoint_service.cpp +465 -0
- package/src/services/codebase_service.cpp +233 -0
- package/src/services/command_service.cpp +82 -0
- package/src/services/context_service.cpp +348 -0
- package/src/services/database_service.cpp +148 -0
- package/src/services/error_service.cpp +438 -0
- package/src/services/file_service.cpp +349 -0
- package/src/services/git_service.cpp +148 -0
- package/src/services/github_service.cpp +435 -0
- package/src/services/mcp_service.cpp +481 -0
- package/src/services/multi_file_service.cpp +591 -0
- package/src/services/sandbox_service.cpp +678 -0
- package/src/services/theme_service.cpp +429 -0
- package/src/services/web_service.cpp +532 -0
- package/src/utils/config.cpp +77 -0
- package/src/utils/memory_utils.cpp +93 -0
- package/src/utils/ui.cpp +307 -0
- package/src/utils/validation.cpp +306 -0
- package/src/utils/version.cpp +175 -0
- package/tests/e2e/docker-compose.yml +195 -0
- package/tests/e2e/run_e2e_tests.sh +70 -0
- package/tests/e2e/run_tests_in_docker.sh +115 -0
- package/tests/main_test.cpp +16 -0
- package/tests/mocks/mock_ollama.py +98 -0
- package/tests/mocks/start_nginx.sh +64 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
#include "services/theme_service.h"
|
|
2
|
+
#include <filesystem>
|
|
3
|
+
#include <fstream>
|
|
4
|
+
#include <iostream>
|
|
5
|
+
#include <nlohmann/json.hpp>
|
|
6
|
+
#include <sstream>
|
|
7
|
+
|
|
8
|
+
namespace Services {
|
|
9
|
+
|
|
10
|
+
std::string ThemeService::current_theme_name_ = "default";
|
|
11
|
+
std::map<std::string, Theme> ThemeService::available_themes_;
|
|
12
|
+
|
|
13
|
+
std::string ThemeService::get_theme_config_path() {
|
|
14
|
+
return "data/theme_config.json";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
void ThemeService::ensure_theme_directory() {
|
|
18
|
+
std::filesystem::create_directories("data");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
void ThemeService::initialize_default_themes() {
|
|
22
|
+
// Default theme (light)
|
|
23
|
+
Theme default_theme;
|
|
24
|
+
default_theme.name = "default";
|
|
25
|
+
default_theme.description = "Default light theme";
|
|
26
|
+
default_theme.is_dark_theme = false;
|
|
27
|
+
default_theme.colors[ThemeColor::PRIMARY] = "#0066CC";
|
|
28
|
+
default_theme.colors[ThemeColor::SECONDARY] = "#6C757D";
|
|
29
|
+
default_theme.colors[ThemeColor::SUCCESS] = "#28A745";
|
|
30
|
+
default_theme.colors[ThemeColor::WARNING] = "#FFC107";
|
|
31
|
+
default_theme.colors[ThemeColor::ERROR] = "#DC3545";
|
|
32
|
+
default_theme.colors[ThemeColor::INFO] = "#17A2B8";
|
|
33
|
+
default_theme.colors[ThemeColor::TEXT] = "#212529";
|
|
34
|
+
default_theme.colors[ThemeColor::BACKGROUND] = "#FFFFFF";
|
|
35
|
+
default_theme.colors[ThemeColor::ACCENT] = "#007BFF";
|
|
36
|
+
default_theme.colors[ThemeColor::MUTED] = "#6C757D";
|
|
37
|
+
available_themes_["default"] = default_theme;
|
|
38
|
+
|
|
39
|
+
// Dark theme
|
|
40
|
+
Theme dark_theme;
|
|
41
|
+
dark_theme.name = "dark";
|
|
42
|
+
dark_theme.description = "Dark theme for low-light environments";
|
|
43
|
+
dark_theme.is_dark_theme = true;
|
|
44
|
+
dark_theme.colors[ThemeColor::PRIMARY] = "#4A9EFF";
|
|
45
|
+
dark_theme.colors[ThemeColor::SECONDARY] = "#ADB5BD";
|
|
46
|
+
dark_theme.colors[ThemeColor::SUCCESS] = "#40E0D0";
|
|
47
|
+
dark_theme.colors[ThemeColor::WARNING] = "#FFD700";
|
|
48
|
+
dark_theme.colors[ThemeColor::ERROR] = "#FF6B6B";
|
|
49
|
+
dark_theme.colors[ThemeColor::INFO] = "#64B5F6";
|
|
50
|
+
dark_theme.colors[ThemeColor::TEXT] = "#E9ECEF";
|
|
51
|
+
dark_theme.colors[ThemeColor::BACKGROUND] = "#1A1A1A";
|
|
52
|
+
dark_theme.colors[ThemeColor::ACCENT] = "#BB86FC";
|
|
53
|
+
dark_theme.colors[ThemeColor::MUTED] = "#6C757D";
|
|
54
|
+
available_themes_["dark"] = dark_theme;
|
|
55
|
+
|
|
56
|
+
// Cyberpunk theme
|
|
57
|
+
Theme cyberpunk_theme;
|
|
58
|
+
cyberpunk_theme.name = "cyberpunk";
|
|
59
|
+
cyberpunk_theme.description = "Neon cyberpunk theme";
|
|
60
|
+
cyberpunk_theme.is_dark_theme = true;
|
|
61
|
+
cyberpunk_theme.colors[ThemeColor::PRIMARY] = "#00FFFF";
|
|
62
|
+
cyberpunk_theme.colors[ThemeColor::SECONDARY] = "#FF00FF";
|
|
63
|
+
cyberpunk_theme.colors[ThemeColor::SUCCESS] = "#00FF00";
|
|
64
|
+
cyberpunk_theme.colors[ThemeColor::WARNING] = "#FFFF00";
|
|
65
|
+
cyberpunk_theme.colors[ThemeColor::ERROR] = "#FF0080";
|
|
66
|
+
cyberpunk_theme.colors[ThemeColor::INFO] = "#80FF80";
|
|
67
|
+
cyberpunk_theme.colors[ThemeColor::TEXT] = "#00FFFF";
|
|
68
|
+
cyberpunk_theme.colors[ThemeColor::BACKGROUND] = "#000020";
|
|
69
|
+
cyberpunk_theme.colors[ThemeColor::ACCENT] = "#FF00FF";
|
|
70
|
+
cyberpunk_theme.colors[ThemeColor::MUTED] = "#808080";
|
|
71
|
+
available_themes_["cyberpunk"] = cyberpunk_theme;
|
|
72
|
+
|
|
73
|
+
// Ocean theme
|
|
74
|
+
Theme ocean_theme;
|
|
75
|
+
ocean_theme.name = "ocean";
|
|
76
|
+
ocean_theme.description = "Calm ocean-inspired theme";
|
|
77
|
+
ocean_theme.is_dark_theme = false;
|
|
78
|
+
ocean_theme.colors[ThemeColor::PRIMARY] = "#006994";
|
|
79
|
+
ocean_theme.colors[ThemeColor::SECONDARY] = "#4A90A4";
|
|
80
|
+
ocean_theme.colors[ThemeColor::SUCCESS] = "#2E8B57";
|
|
81
|
+
ocean_theme.colors[ThemeColor::WARNING] = "#DAA520";
|
|
82
|
+
ocean_theme.colors[ThemeColor::ERROR] = "#CD5C5C";
|
|
83
|
+
ocean_theme.colors[ThemeColor::INFO] = "#4682B4";
|
|
84
|
+
ocean_theme.colors[ThemeColor::TEXT] = "#2F4F4F";
|
|
85
|
+
ocean_theme.colors[ThemeColor::BACKGROUND] = "#F0F8FF";
|
|
86
|
+
ocean_theme.colors[ThemeColor::ACCENT] = "#20B2AA";
|
|
87
|
+
ocean_theme.colors[ThemeColor::MUTED] = "#708090";
|
|
88
|
+
available_themes_["ocean"] = ocean_theme;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
std::string ThemeService::get_ansi_color_code(const std::string &color) {
|
|
92
|
+
// Convert hex colors to ANSI escape codes
|
|
93
|
+
if (color == "#00FFFF") {
|
|
94
|
+
return "\033[96m"; // Bright cyan
|
|
95
|
+
}
|
|
96
|
+
if (color == "#FF00FF") {
|
|
97
|
+
return "\033[95m"; // Bright magenta
|
|
98
|
+
}
|
|
99
|
+
if (color == "#00FF00") {
|
|
100
|
+
return "\033[92m"; // Bright green
|
|
101
|
+
}
|
|
102
|
+
if (color == "#FFFF00") {
|
|
103
|
+
return "\033[93m"; // Bright yellow
|
|
104
|
+
}
|
|
105
|
+
if (color == "#FF0080")
|
|
106
|
+
return "\033[91m"; // Bright red
|
|
107
|
+
if (color == "#4A9EFF")
|
|
108
|
+
return "\033[94m"; // Bright blue
|
|
109
|
+
if (color == "#40E0D0")
|
|
110
|
+
return "\033[96m"; // Turquoise
|
|
111
|
+
if (color == "#FFD700")
|
|
112
|
+
return "\033[93m"; // Gold
|
|
113
|
+
if (color == "#FF6B6B")
|
|
114
|
+
return "\033[91m"; // Light red
|
|
115
|
+
if (color == "#64B5F6")
|
|
116
|
+
return "\033[94m"; // Light blue
|
|
117
|
+
if (color == "#BB86FC")
|
|
118
|
+
return "\033[95m"; // Light purple
|
|
119
|
+
if (color == "#28A745")
|
|
120
|
+
return "\033[32m"; // Green
|
|
121
|
+
if (color == "#DC3545")
|
|
122
|
+
return "\033[31m"; // Red
|
|
123
|
+
if (color == "#FFC107")
|
|
124
|
+
return "\033[33m"; // Yellow
|
|
125
|
+
if (color == "#17A2B8")
|
|
126
|
+
return "\033[36m"; // Cyan
|
|
127
|
+
if (color == "#007BFF")
|
|
128
|
+
return "\033[34m"; // Blue
|
|
129
|
+
if (color == "#0066CC")
|
|
130
|
+
return "\033[34m"; // Blue
|
|
131
|
+
if (color == "#006994")
|
|
132
|
+
return "\033[34m"; // Dark blue
|
|
133
|
+
if (color == "#2E8B57")
|
|
134
|
+
return "\033[32m"; // Sea green
|
|
135
|
+
if (color == "#20B2AA")
|
|
136
|
+
return "\033[36m"; // Light sea green
|
|
137
|
+
|
|
138
|
+
// Default colors
|
|
139
|
+
return "\033[37m"; // White
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
void ThemeService::initialize() {
|
|
143
|
+
initialize_default_themes();
|
|
144
|
+
load_theme_config();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
bool ThemeService::set_theme(const std::string &theme_name) {
|
|
148
|
+
auto it = available_themes_.find(theme_name);
|
|
149
|
+
if (it == available_themes_.end()) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
current_theme_name_ = theme_name;
|
|
154
|
+
save_theme_config();
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
std::string ThemeService::get_current_theme() { return current_theme_name_; }
|
|
159
|
+
|
|
160
|
+
std::vector<std::string> ThemeService::list_available_themes() {
|
|
161
|
+
std::vector<std::string> theme_names;
|
|
162
|
+
for (const auto &pair : available_themes_) {
|
|
163
|
+
theme_names.push_back(pair.first);
|
|
164
|
+
}
|
|
165
|
+
return theme_names;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
Theme ThemeService::get_theme_info(const std::string &theme_name) {
|
|
169
|
+
auto it = available_themes_.find(theme_name);
|
|
170
|
+
if (it != available_themes_.end()) {
|
|
171
|
+
return it->second;
|
|
172
|
+
}
|
|
173
|
+
return Theme{}; // Return empty theme if not found
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
std::string ThemeService::colorize(const std::string &text, ThemeColor color) {
|
|
177
|
+
if (!is_color_supported()) {
|
|
178
|
+
return text;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
auto it = available_themes_.find(current_theme_name_);
|
|
182
|
+
if (it == available_themes_.end()) {
|
|
183
|
+
return text;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
auto color_it = it->second.colors.find(color);
|
|
187
|
+
if (color_it == it->second.colors.end()) {
|
|
188
|
+
return text;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
std::string ansi_code = get_ansi_color_code(color_it->second);
|
|
192
|
+
return ansi_code + text + "\033[0m"; // Reset color after text
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
std::string ThemeService::colorize_command(const std::string &text) {
|
|
196
|
+
return colorize(text, ThemeColor::PRIMARY);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
std::string ThemeService::colorize_success(const std::string &text) {
|
|
200
|
+
return colorize(text, ThemeColor::SUCCESS);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
std::string ThemeService::colorize_error(const std::string &text) {
|
|
204
|
+
return colorize(text, ThemeColor::ERROR);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
std::string ThemeService::colorize_warning(const std::string &text) {
|
|
208
|
+
return colorize(text, ThemeColor::WARNING);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
std::string ThemeService::colorize_info(const std::string &text) {
|
|
212
|
+
return colorize(text, ThemeColor::INFO);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
std::string ThemeService::colorize_accent(const std::string &text) {
|
|
216
|
+
return colorize(text, ThemeColor::ACCENT);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
bool ThemeService::save_theme_config() {
|
|
220
|
+
try {
|
|
221
|
+
ensure_theme_directory();
|
|
222
|
+
|
|
223
|
+
nlohmann::json config;
|
|
224
|
+
config["current_theme"] = current_theme_name_;
|
|
225
|
+
config["themes"] = nlohmann::json::object();
|
|
226
|
+
|
|
227
|
+
for (const auto &[name, theme] : available_themes_) {
|
|
228
|
+
nlohmann::json theme_json;
|
|
229
|
+
theme_json["name"] = theme.name;
|
|
230
|
+
theme_json["description"] = theme.description;
|
|
231
|
+
theme_json["is_dark_theme"] = theme.is_dark_theme;
|
|
232
|
+
theme_json["colors"] = nlohmann::json::object();
|
|
233
|
+
|
|
234
|
+
for (const auto &[color_type, color_value] : theme.colors) {
|
|
235
|
+
std::string color_key;
|
|
236
|
+
switch (color_type) {
|
|
237
|
+
case ThemeColor::PRIMARY:
|
|
238
|
+
color_key = "primary";
|
|
239
|
+
break;
|
|
240
|
+
case ThemeColor::SECONDARY:
|
|
241
|
+
color_key = "secondary";
|
|
242
|
+
break;
|
|
243
|
+
case ThemeColor::SUCCESS:
|
|
244
|
+
color_key = "success";
|
|
245
|
+
break;
|
|
246
|
+
case ThemeColor::WARNING:
|
|
247
|
+
color_key = "warning";
|
|
248
|
+
break;
|
|
249
|
+
case ThemeColor::ERROR:
|
|
250
|
+
color_key = "error";
|
|
251
|
+
break;
|
|
252
|
+
case ThemeColor::INFO:
|
|
253
|
+
color_key = "info";
|
|
254
|
+
break;
|
|
255
|
+
case ThemeColor::TEXT:
|
|
256
|
+
color_key = "text";
|
|
257
|
+
break;
|
|
258
|
+
case ThemeColor::BACKGROUND:
|
|
259
|
+
color_key = "background";
|
|
260
|
+
break;
|
|
261
|
+
case ThemeColor::ACCENT:
|
|
262
|
+
color_key = "accent";
|
|
263
|
+
break;
|
|
264
|
+
case ThemeColor::MUTED:
|
|
265
|
+
color_key = "muted";
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
theme_json["colors"][color_key] = color_value;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
config["themes"][name] = theme_json;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
std::ofstream file(get_theme_config_path());
|
|
275
|
+
file << config.dump(2);
|
|
276
|
+
|
|
277
|
+
return true;
|
|
278
|
+
|
|
279
|
+
} catch (const std::exception &e) {
|
|
280
|
+
std::cerr << "Failed to save theme config: " << e.what() << std::endl;
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
bool ThemeService::load_theme_config() {
|
|
286
|
+
try {
|
|
287
|
+
std::string config_path = get_theme_config_path();
|
|
288
|
+
if (!std::filesystem::exists(config_path)) {
|
|
289
|
+
return true; // Use defaults
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
std::ifstream file(config_path);
|
|
293
|
+
nlohmann::json config;
|
|
294
|
+
file >> config;
|
|
295
|
+
|
|
296
|
+
if (config.contains("current_theme")) {
|
|
297
|
+
current_theme_name_ = config["current_theme"];
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Load custom themes (built-in themes are already initialized)
|
|
301
|
+
if (config.contains("themes")) {
|
|
302
|
+
for (const auto &[name, theme_json] : config["themes"].items()) {
|
|
303
|
+
// Skip built-in themes
|
|
304
|
+
if (name == "default" || name == "dark" || name == "cyberpunk" ||
|
|
305
|
+
name == "ocean") {
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
Theme theme;
|
|
310
|
+
theme.name = theme_json.value("name", name);
|
|
311
|
+
theme.description = theme_json.value("description", "");
|
|
312
|
+
theme.is_dark_theme = theme_json.value("is_dark_theme", false);
|
|
313
|
+
|
|
314
|
+
if (theme_json.contains("colors")) {
|
|
315
|
+
for (const auto &[color_key, color_value] :
|
|
316
|
+
theme_json["colors"].items()) {
|
|
317
|
+
ThemeColor color_type;
|
|
318
|
+
if (color_key == "primary")
|
|
319
|
+
color_type = ThemeColor::PRIMARY;
|
|
320
|
+
else if (color_key == "secondary")
|
|
321
|
+
color_type = ThemeColor::SECONDARY;
|
|
322
|
+
else if (color_key == "success")
|
|
323
|
+
color_type = ThemeColor::SUCCESS;
|
|
324
|
+
else if (color_key == "warning")
|
|
325
|
+
color_type = ThemeColor::WARNING;
|
|
326
|
+
else if (color_key == "error")
|
|
327
|
+
color_type = ThemeColor::ERROR;
|
|
328
|
+
else if (color_key == "info")
|
|
329
|
+
color_type = ThemeColor::INFO;
|
|
330
|
+
else if (color_key == "text")
|
|
331
|
+
color_type = ThemeColor::TEXT;
|
|
332
|
+
else if (color_key == "background")
|
|
333
|
+
color_type = ThemeColor::BACKGROUND;
|
|
334
|
+
else if (color_key == "accent")
|
|
335
|
+
color_type = ThemeColor::ACCENT;
|
|
336
|
+
else if (color_key == "muted")
|
|
337
|
+
color_type = ThemeColor::MUTED;
|
|
338
|
+
else
|
|
339
|
+
continue;
|
|
340
|
+
|
|
341
|
+
theme.colors[color_type] = color_value;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
available_themes_[name] = theme;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return true;
|
|
350
|
+
|
|
351
|
+
} catch (const std::exception &e) {
|
|
352
|
+
std::cerr << "Failed to load theme config: " << e.what() << std::endl;
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
bool ThemeService::create_custom_theme(const std::string &name,
|
|
358
|
+
const Theme &theme) {
|
|
359
|
+
available_themes_[name] = theme;
|
|
360
|
+
return save_theme_config();
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
bool ThemeService::delete_custom_theme(const std::string &name) {
|
|
364
|
+
// Don't allow deletion of built-in themes
|
|
365
|
+
if (name == "default" || name == "dark" || name == "cyberpunk" ||
|
|
366
|
+
name == "ocean") {
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
auto it = available_themes_.find(name);
|
|
371
|
+
if (it == available_themes_.end()) {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
available_themes_.erase(it);
|
|
376
|
+
|
|
377
|
+
// If we're deleting the current theme, switch to default
|
|
378
|
+
if (current_theme_name_ == name) {
|
|
379
|
+
current_theme_name_ = "default";
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return save_theme_config();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
void ThemeService::print_theme_preview(const std::string &theme_name) {
|
|
386
|
+
auto it = available_themes_.find(theme_name);
|
|
387
|
+
if (it == available_themes_.end()) {
|
|
388
|
+
std::cout << "Theme '" << theme_name << "' not found." << std::endl;
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const Theme &theme = it->second;
|
|
393
|
+
std::cout << "Theme: " << colorize_accent(theme.name) << std::endl;
|
|
394
|
+
std::cout << "Description: " << theme.description << std::endl;
|
|
395
|
+
std::cout << "Type: " << (theme.is_dark_theme ? "Dark" : "Light")
|
|
396
|
+
<< std::endl;
|
|
397
|
+
std::cout << std::endl;
|
|
398
|
+
|
|
399
|
+
std::cout << "Color Preview:" << std::endl;
|
|
400
|
+
std::cout << " " << colorize("Primary", ThemeColor::PRIMARY)
|
|
401
|
+
<< " - Commands and headers" << std::endl;
|
|
402
|
+
std::cout << " " << colorize("Success", ThemeColor::SUCCESS)
|
|
403
|
+
<< " - Success messages" << std::endl;
|
|
404
|
+
std::cout << " " << colorize("Warning", ThemeColor::WARNING)
|
|
405
|
+
<< " - Warning messages" << std::endl;
|
|
406
|
+
std::cout << " " << colorize("Error", ThemeColor::ERROR)
|
|
407
|
+
<< " - Error messages" << std::endl;
|
|
408
|
+
std::cout << " " << colorize("Info", ThemeColor::INFO)
|
|
409
|
+
<< " - Information messages" << std::endl;
|
|
410
|
+
std::cout << " " << colorize("Accent", ThemeColor::ACCENT)
|
|
411
|
+
<< " - Highlights and accents" << std::endl;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
void ThemeService::reset_colors() { std::cout << "\033[0m" << std::flush; }
|
|
415
|
+
|
|
416
|
+
bool ThemeService::is_color_supported() {
|
|
417
|
+
// Check if terminal supports colors
|
|
418
|
+
const char *term = std::getenv("TERM");
|
|
419
|
+
if (term == nullptr) {
|
|
420
|
+
return false;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
std::string term_str(term);
|
|
424
|
+
return term_str.find("color") != std::string::npos ||
|
|
425
|
+
term_str.find("xterm") != std::string::npos ||
|
|
426
|
+
term_str.find("screen") != std::string::npos || term_str == "vt100" ||
|
|
427
|
+
term_str == "vt220";
|
|
428
|
+
}
|
|
429
|
+
} // namespace Services
|