1 #include "config.hpp"
2 #include "filesystem.hpp"
3 #include "process.hpp"
4 #include "terminal.hpp"
5 #include "utility.hpp"
6 #include <algorithm>
7 #include <exception>
8 #include <iostream>
9 #include <thread>
10 
Config()11 Config::Config() {
12   home_path = filesystem::get_home_path();
13   if(home_path.empty())
14     throw std::runtime_error("Could not find home path");
15   home_juci_path = home_path / ".juci";
16 }
17 
load()18 void Config::load() {
19   auto config_dir = home_juci_path / "config";
20   auto config_json = config_dir / "config.json";
21   try {
22     boost::filesystem::create_directories(config_dir);
23 
24     if(!boost::filesystem::exists(config_json))
25       filesystem::write(config_json, default_config());
26 
27     auto juci_style_path = home_juci_path / "styles";
28     boost::filesystem::create_directories(juci_style_path);
29 
30     juci_style_path /= "juci-light.xml";
31     if(!boost::filesystem::exists(juci_style_path))
32       filesystem::write(juci_style_path, juci_light_style());
33     juci_style_path = juci_style_path.parent_path();
34     juci_style_path /= "juci-dark.xml";
35     if(!boost::filesystem::exists(juci_style_path))
36       filesystem::write(juci_style_path, juci_dark_style());
37     juci_style_path = juci_style_path.parent_path();
38     juci_style_path /= "juci-dark-blue.xml";
39     if(!boost::filesystem::exists(juci_style_path))
40       filesystem::write(juci_style_path, juci_dark_blue_style());
41 
42     JSON cfg(config_json);
43     update(cfg);
44     read(cfg);
45   }
46   catch(const std::exception &e) {
47     dispatcher.post([config_json = std::move(config_json), e_what = std::string(e.what())] {
48       ::Terminal::get().print("\e[31mError\e[m: could not parse " + filesystem::get_short_path(config_json).string() + ": " + e_what + "\n", true);
49     });
50     JSON default_cfg(default_config());
51     read(default_cfg);
52   }
53 }
54 
update(JSON & cfg)55 void Config::update(JSON &cfg) {
56   auto version = cfg.string("version");
57   if(version == JUCI_VERSION)
58     return;
59   JSON default_cfg(default_config());
60   make_version_dependent_corrections(cfg, default_cfg, version);
61   cfg.set("version", JUCI_VERSION);
62 
63   add_missing_nodes(cfg, default_cfg);
64   remove_deprecated_nodes(cfg, default_cfg);
65 
66   cfg.to_file(home_juci_path / "config" / "config.json", 2);
67 
68   auto style_path = home_juci_path / "styles";
69   filesystem::write(style_path / "juci-light.xml", juci_light_style());
70   filesystem::write(style_path / "juci-dark.xml", juci_dark_style());
71   filesystem::write(style_path / "juci-dark-blue.xml", juci_dark_blue_style());
72 }
73 
make_version_dependent_corrections(JSON & cfg,const JSON & default_cfg,const std::string & version)74 void Config::make_version_dependent_corrections(JSON &cfg, const JSON &default_cfg, const std::string &version) {
75   try {
76     if(version_compare(version, "1.2.4") <= 0) {
77       auto keybindings = cfg.object("keybindings");
78       auto print = keybindings.string_optional("print");
79       if(print && *print == "<primary>p") {
80         keybindings.set("print", "");
81         dispatcher.post([] {
82           ::Terminal::get().print("Preference change: keybindings.print set to \"\"\n");
83         });
84       }
85     }
86   }
87   catch(const std::exception &e) {
88     std::cerr << "Error correcting preferences: " << e.what() << std::endl;
89   }
90 }
91 
add_missing_nodes(JSON & cfg,const JSON & default_cfg)92 void Config::add_missing_nodes(JSON &cfg, const JSON &default_cfg) {
93   for(auto &default_cfg_child : default_cfg.children_or_empty()) {
94     try {
95       auto cfg_child = cfg.child(default_cfg_child.first);
96       add_missing_nodes(cfg_child, default_cfg_child.second);
97     }
98     catch(...) {
99       cfg.set(default_cfg_child.first, default_cfg_child.second);
100     }
101   }
102 }
103 
remove_deprecated_nodes(JSON & cfg,const JSON & default_cfg)104 void Config::remove_deprecated_nodes(JSON &cfg, const JSON &default_cfg) {
105   auto children = cfg.children_or_empty();
106   for(size_t i = 0; i < children.size();) {
107     try {
108       auto default_cfg_child = default_cfg.child(children[i].first);
109       remove_deprecated_nodes(children[i].second, default_cfg_child);
110       ++i;
111     }
112     catch(...) {
113       cfg.remove(children[i].first);
114       children = cfg.children_or_empty();
115     }
116   }
117 }
118 
read(const JSON & cfg)119 void Config::read(const JSON &cfg) {
120   for(auto &keybinding : cfg.children("keybindings"))
121     menu.keys[keybinding.first] = keybinding.second.string();
122 
123   auto source_json = cfg.object("source");
124   source.style = source_json.string("style");
125   source.font = source_json.string("font");
126   source.cleanup_whitespace_characters = source_json.boolean("cleanup_whitespace_characters", JSON::ParseOptions::accept_string);
127   source.show_whitespace_characters = source_json.string("show_whitespace_characters");
128   source.format_style_on_save = source_json.boolean("format_style_on_save", JSON::ParseOptions::accept_string);
129   source.format_style_on_save_if_style_file_found = source_json.boolean("format_style_on_save_if_style_file_found", JSON::ParseOptions::accept_string);
130   source.smart_brackets = source_json.boolean("smart_brackets", JSON::ParseOptions::accept_string);
131   source.smart_inserts = source_json.boolean("smart_inserts", JSON::ParseOptions::accept_string);
132   if(source.smart_inserts)
133     source.smart_brackets = true;
134   source.show_map = source_json.boolean("show_map", JSON::ParseOptions::accept_string);
135   source.map_font_size = source_json.integer("map_font_size", JSON::ParseOptions::accept_string);
136   source.show_git_diff = source_json.boolean("show_git_diff", JSON::ParseOptions::accept_string);
137   source.show_background_pattern = source_json.boolean("show_background_pattern", JSON::ParseOptions::accept_string);
138   source.show_right_margin = source_json.boolean("show_right_margin", JSON::ParseOptions::accept_string);
139   source.right_margin_position = source_json.integer("right_margin_position", JSON::ParseOptions::accept_string);
140   source.spellcheck_language = source_json.string("spellcheck_language");
141   auto default_tab_char_str = source_json.string("default_tab_char");
142   if(default_tab_char_str.size() == 1)
143     source.default_tab_char = default_tab_char_str[0];
144   else
145     source.default_tab_char = ' ';
146   source.default_tab_size = source_json.integer("default_tab_size", JSON::ParseOptions::accept_string);
147   source.auto_tab_char_and_size = source_json.boolean("auto_tab_char_and_size", JSON::ParseOptions::accept_string);
148   source.tab_indents_line = source_json.boolean("tab_indents_line", JSON::ParseOptions::accept_string);
149   source.word_wrap = source_json.string("word_wrap");
150   source.highlight_current_line = source_json.boolean("highlight_current_line", JSON::ParseOptions::accept_string);
151   source.show_line_numbers = source_json.boolean("show_line_numbers", JSON::ParseOptions::accept_string);
152   source.enable_multiple_cursors = source_json.boolean("enable_multiple_cursors", JSON::ParseOptions::accept_string);
153   source.auto_reload_changed_files = source_json.boolean("auto_reload_changed_files", JSON::ParseOptions::accept_string);
154   source.search_for_selection = source_json.boolean("search_for_selection", JSON::ParseOptions::accept_string);
155   source.clang_format_style = source_json.string("clang_format_style");
156   source.clang_usages_threads = static_cast<unsigned>(source_json.integer("clang_usages_threads", JSON::ParseOptions::accept_string));
157   source.clang_tidy_enable = source_json.boolean("clang_tidy_enable", JSON::ParseOptions::accept_string);
158   source.clang_tidy_checks = source_json.string("clang_tidy_checks");
159   source.clang_detailed_preprocessing_record = source_json.boolean("clang_detailed_preprocessing_record", JSON::ParseOptions::accept_string);
160   source.debug_place_cursor_at_stop = source_json.boolean("debug_place_cursor_at_stop", JSON::ParseOptions::accept_string);
161 
162   for(auto &documentation_searches : cfg.children("documentation_searches")) {
163     auto &documentation_search = source.documentation_searches[documentation_searches.first];
164     documentation_search.separator = documentation_searches.second.string("separator");
165     for(auto &i : documentation_searches.second.children("queries"))
166       documentation_search.queries[i.first] = i.second.string();
167   }
168 
169   auto theme_json = cfg.object("gtk_theme");
170   theme.name = theme_json.string("name");
171   theme.variant = theme_json.string("variant");
172   theme.font = theme_json.string("font");
173 
174   auto project_json = cfg.object("project");
175   project.default_build_path = project_json.string("default_build_path");
176   project.debug_build_path = project_json.string("debug_build_path");
177   auto cmake_json = project_json.object("cmake");
178   project.cmake.command = cmake_json.string("command");
179   project.cmake.compile_command = cmake_json.string("compile_command");
180   auto meson_json = project_json.object("meson");
181   project.meson.command = meson_json.string("command");
182   project.meson.compile_command = meson_json.string("compile_command");
183   project.default_build_management_system = project_json.string("default_build_management_system");
184   project.save_on_compile_or_run = project_json.boolean("save_on_compile_or_run", JSON::ParseOptions::accept_string);
185   project.ctags_command = project_json.string("ctags_command");
186   project.grep_command = project_json.string("grep_command");
187   project.cargo_command = project_json.string("cargo_command");
188   project.python_command = project_json.string("python_command");
189   project.markdown_command = project_json.string("markdown_command");
190 
191   auto terminal_json = cfg.object("terminal");
192   terminal.history_size = terminal_json.integer("history_size", JSON::ParseOptions::accept_string);
193   terminal.font = terminal_json.string("font");
194   terminal.clear_on_compile = terminal_json.boolean("clear_on_compile", JSON::ParseOptions::accept_string);
195   terminal.clear_on_run_command = terminal_json.boolean("clear_on_run_command", JSON::ParseOptions::accept_string);
196   terminal.hide_entry_on_run_command = terminal_json.boolean("hide_entry_on_run_command", JSON::ParseOptions::accept_string);
197 
198   auto log_json = cfg.object("log");
199   log.libclang = log_json.boolean("libclang", JSON::ParseOptions::accept_string);
200   log.language_server = log_json.boolean("language_server", JSON::ParseOptions::accept_string);
201 }
202 
default_config()203 std::string Config::default_config() {
204   static auto get_config = [] {
205     std::string cmake_version;
206     unsigned thread_count = 0;
207     std::stringstream ss;
208     TinyProcessLib::Process process(
209         "cmake --version", "",
210         [&ss](const char *buffer, size_t n) {
211           ss.write(buffer, n);
212         },
213         [](const char *buffer, size_t n) {});
214     if(process.get_exit_status() == 0) {
215       std::string line;
216       if(std::getline(ss, line)) {
217         auto pos = line.rfind(" ");
218         if(pos != std::string::npos) {
219           cmake_version = line.substr(pos + 1);
220           thread_count = std::thread::hardware_concurrency();
221         }
222       }
223     }
224 
225     return std::string(R"RAW({
226   "version": ")RAW" +
227                        std::string(JUCI_VERSION) +
228                        R"RAW(",
229   "gtk_theme": {
230     "name_comment": "Use \"\" for default theme, At least these two exist on all systems: Adwaita, Raleigh",
231     "name": "",
232     "variant_comment": "Use \"\" for default variant, and \"dark\" for dark theme variant. Note that not all themes support dark variant, but for instance Adwaita does",
233     "variant": "",
234     "font_comment": "Set to override theme font, for instance: \"Arial 12\"",
235     "font": ""
236   },
237   "source": {
238     "style_comment": "Use \"\" for default style, and for instance juci-dark or juci-dark-blue together with dark gtk_theme variant. Styles from normal gtksourceview install: classic, cobalt, kate, oblivion, solarized-dark, solarized-light, tango",
239     "style": "juci-light",
240     "font_comment": "Use \"\" for default font, and for instance \"Monospace 12\" to also set size",)RAW"
241 #ifdef __APPLE__
242                        R"RAW(
243     "font": "Menlo",)RAW"
244 #else
245 #ifdef _WIN32
246                        R"RAW(
247     "font": "Consolas",)RAW"
248 #else
249                        R"RAW(
250     "font": "Monospace",)RAW"
251 #endif
252 #endif
253                        R"RAW(
254     "cleanup_whitespace_characters_comment": "Remove trailing whitespace characters on save, and add trailing newline if missing",
255     "cleanup_whitespace_characters": false,
256     "show_whitespace_characters_comment": "Determines what kind of whitespaces should be drawn. Use comma-separated list of: space, tab, newline, nbsp, leading, text, trailing or all",
257     "show_whitespace_characters": "",
258     "format_style_on_save_comment": "Performs style format on save if supported on language in buffer",
259     "format_style_on_save": false,
260     "format_style_on_save_if_style_file_found_comment": "Format style if format file is found, even if format_style_on_save is false",
261     "format_style_on_save_if_style_file_found": true,
262     "smart_brackets_comment": "If smart_inserts is enabled, this option is automatically enabled. When inserting an already closed bracket, the cursor might instead be moved, avoiding the need of arrow keys after autocomplete",
263     "smart_brackets": true,
264     "smart_inserts_comment": "When for instance inserting (, () gets inserted. Applies to: (), [], \", '. Also enables pressing ; inside an expression before a final ) to insert ; at the end of line, and deletions of empty insertions",
265     "smart_inserts": true,
266     "show_map": true,
267     "map_font_size": 1,
268     "show_git_diff": true,
269     "show_background_pattern": true,
270     "show_right_margin": false,
271     "right_margin_position": 80,
272     "spellcheck_language_comment": "Use \"\" to set language from your locale settings",
273     "spellcheck_language": "en_US",
274     "auto_tab_char_and_size_comment": "Use false to always use default tab char and size",
275     "auto_tab_char_and_size": true,
276     "default_tab_char_comment": "Use \"\t\" for regular tab",
277     "default_tab_char": " ",
278     "default_tab_size": 2,
279     "tab_indents_line": true,
280     "word_wrap_comment": "Specify language ids that should enable word wrap, for instance: chdr, c, cpphdr, cpp, js, python, or all to enable word wrap for all languages",
281     "word_wrap": "markdown, latex",
282     "highlight_current_line": true,
283     "show_line_numbers": true,
284     "enable_multiple_cursors": false,
285     "auto_reload_changed_files": true,
286     "search_for_selection": true,
287     "clang_format_style_comment": "IndentWidth, AccessModifierOffset and UseTab are set automatically. See http://clang.llvm.org/docs/ClangFormatStyleOptions.html",
288     "clang_format_style": "ColumnLimit: 0, NamespaceIndentation: All",
289     "clang_tidy_enable_comment": "Enable clang-tidy in new C/C++ buffers",
290     "clang_tidy_enable": false,
291     "clang_tidy_checks_comment": "In new C/C++ buffers, these checks are appended to the value of 'Checks' in the .clang-tidy file, if any",
292     "clang_tidy_checks": "",
293     "clang_usages_threads_comment": "The number of threads used in finding usages in unparsed files. -1 corresponds to the number of cores available, and 0 disables the search",
294     "clang_usages_threads": -1,
295     "clang_detailed_preprocessing_record_comment": "Set to true to, at the cost of increased resource use, include all macro definitions and instantiations when parsing new C/C++ buffers. You should reopen buffers and delete build/.usages_clang after changing this option.",
296     "clang_detailed_preprocessing_record": false,
297     "debug_place_cursor_at_stop": false
298   },
299   "terminal": {
300     "history_size": 10000,
301     "font_comment": "Use \"\" to use source.font with slightly smaller size",
302     "font": "",
303     "clear_on_compile": true,
304     "clear_on_run_command": false,
305     "hide_entry_on_run_command": true
306   },
307   "project": {
308     "default_build_path_comment": "Use <project_directory_name> to insert the project top level directory name",
309     "default_build_path": "./build",
310     "debug_build_path_comment": "Use <project_directory_name> to insert the project top level directory name, and <default_build_path> to insert your default_build_path setting.",
311     "debug_build_path": "<default_build_path>/debug",
312     "cmake": {)RAW"
313 #ifdef _WIN32
314                        R"RAW(
315       "command": "cmake -G\"MSYS Makefiles\"",)RAW"
316 #else
317                        R"RAW(
318       "command": "cmake",)RAW"
319 #endif
320                        R"RAW(
321       "compile_command": "cmake --build .)RAW" +
322                        (thread_count > 1 && !cmake_version.empty() && version_compare(cmake_version, "3.12") >= 0 ? " --parallel " + std::to_string(thread_count) : "") +
323                        R"RAW("
324     },
325     "meson": {
326       "command": "meson",
327       "compile_command": "ninja"
328     },
329     "default_build_management_system_comment": "Select which build management system to use when creating a new C or C++ project, for instance \"cmake\" or \"meson\"",
330     "default_build_management_system": "cmake",
331     "save_on_compile_or_run": true,)RAW"
332 #ifdef JUCI_USE_UCTAGS
333                        R"RAW(
334     "ctags_command": "uctags",)RAW"
335 #else
336                        R"RAW(
337     "ctags_command": "ctags",)RAW"
338 #endif
339                        R"RAW(
340     "grep_command": "grep",
341     "cargo_command": "cargo",
342     "python_command": "python -u",
343     "markdown_command": "grip -b"
344   },
345   "keybindings": {
346     "preferences": "<primary>comma",
347     "snippets": "",
348     "commands": "",
349     "quit": "<primary>q",
350     "file_new_file": "<primary>n",
351     "file_new_folder": "<primary><shift>n",
352     "file_open_file": "<primary>o",
353     "file_open_folder": "<primary><shift>o",
354     "file_find_file": "<primary>p",
355     "file_switch_file_type": "<alt>o",
356     "file_reload_file": "",
357     "file_save": "<primary>s",
358     "file_save_as": "<primary><shift>s",
359     "file_close_file": "<primary>w",
360     "file_close_folder": "",
361     "file_close_project": "",
362     "file_close_other_files": "",
363     "file_print": "",
364     "edit_undo": "<primary>z",
365     "edit_redo": "<primary><shift>z",
366     "edit_cut": "<primary>x",
367     "edit_cut_lines": "<primary><shift>x",
368     "edit_copy": "<primary>c",
369     "edit_copy_lines": "<primary><shift>c",
370     "edit_paste": "<primary>v",
371     "edit_extend_selection": "<primary><shift>a",
372     "edit_shrink_selection": "<primary><shift><alt>a",
373     "edit_show_or_hide": "",
374     "edit_find": "<primary>f",
375     "source_spellcheck": "",
376     "source_spellcheck_clear": "",
377     "source_spellcheck_next_error": "<primary><shift>e",
378     "source_git_next_diff": "<primary>k",
379     "source_git_show_diff": "<alt>k",
380     "source_indentation_set_buffer_tab": "",
381     "source_indentation_auto_indent_buffer": "<primary><shift>i",
382     "source_goto_line": "<primary>g",
383     "source_center_cursor": "<primary>l",
384     "source_cursor_history_back": "<alt>Left",
385     "source_cursor_history_forward": "<alt>Right",
386     "source_show_completion_comment": "Add completion keybinding to disable interactive autocompletion",
387     "source_show_completion": "",
388     "source_find_symbol": "<primary><shift>f",
389     "source_find_pattern": "<alt><shift>f",
390     "source_comments_toggle": "<primary>slash",
391     "source_comments_add_documentation": "<primary><alt>slash",
392     "source_find_documentation": "<primary><shift>d",
393     "source_goto_declaration": "<primary>d",
394     "source_goto_type_declaration": "<alt><shift>d",
395     "source_goto_implementation": "<primary>i",
396     "source_goto_usage": "<primary>u",
397     "source_goto_method": "<primary>m",
398     "source_rename": "<primary>r",
399     "source_implement_method": "<primary><shift>m",
400     "source_goto_next_diagnostic": "<primary>e",
401     "source_apply_fix_its": "<control>space",
402     "project_set_run_arguments": "",
403     "project_compile_and_run": "<primary>Return",
404     "project_compile": "<primary><shift>Return",
405     "project_run_command": "<alt>Return",
406     "project_kill_last_running": "<primary>Escape",
407     "project_force_kill_last_running": "<primary><shift>Escape",
408     "debug_set_run_arguments": "",
409     "debug_start_continue": "<primary>y",
410     "debug_stop": "<primary><shift>y",
411     "debug_kill": "<primary><shift>k",
412     "debug_step_over": "<primary>j",
413     "debug_step_into": "<primary>t",
414     "debug_step_out": "<primary><shift>t",
415     "debug_backtrace": "<primary><shift>j",
416     "debug_show_variables": "<primary><shift>b",
417     "debug_run_command": "<alt><shift>Return",
418     "debug_toggle_breakpoint": "<primary>b",
419     "debug_show_breakpoints": "<primary><shift><alt>b",
420     "debug_goto_stop": "<primary><shift>l",)RAW"
421 #ifdef __linux
422                        R"RAW(
423     "window_next_tab": "<primary>Tab",
424     "window_previous_tab": "<primary><shift>Tab",)RAW"
425 #else
426                        R"RAW(
427     "window_next_tab": "<primary><alt>Right",
428     "window_previous_tab": "<primary><alt>Left",)RAW"
429 #endif
430                        R"RAW(
431     "window_goto_tab": "",
432     "window_toggle_split": "",
433     "window_split_source_buffer": "",)RAW"
434 #ifdef __APPLE__
435                        R"RAW(
436     "window_toggle_full_screen": "<primary><control>f",)RAW"
437 #else
438                        R"RAW(
439     "window_toggle_full_screen": "F11",)RAW"
440 #endif
441                        R"RAW(
442     "window_toggle_directories": "",
443     "window_toggle_terminal": "",
444     "window_toggle_status": "",
445     "window_toggle_menu": "",
446     "window_toggle_tabs": "",
447     "window_toggle_zen_mode": "",
448     "window_clear_terminal": ""
449   },
450   "documentation_searches": {
451     "clang": {
452       "separator": "::",
453       "queries": {
454         "@empty": "https://www.google.com/search?q=c%2B%2B+",
455         "std": "https://www.google.com/search?q=site:http://www.cplusplus.com/reference/+",
456         "boost": "https://www.google.com/search?q=site:http://www.boost.org/doc/libs/1_59_0/+",
457         "Gtk": "https://www.google.com/search?q=site:https://developer.gnome.org/gtkmm/stable/+",
458         "@any": "https://www.google.com/search?q="
459       }
460     }
461   },
462   "log": {
463     "libclang_comment": "Outputs diagnostics for new C/C++ buffers",
464     "libclang": false,
465     "language_server": false
466   }
467 }
468 )RAW");
469   };
470   static auto config = get_config();
471   return config;
472 }
473 
juci_light_style()474 const char *Config::juci_light_style() {
475   return R"RAW(<?xml version="1.0" encoding="UTF-8"?>
476 
477 <style-scheme id="juci-light" _name="juci" version="1.0">
478   <author>juCi++ team</author>
479   <_description>Default juCi++ style</_description>
480 
481   <!-- Palette -->
482   <color name="white"                       value="#FFFFFF"/>
483   <color name="black"                       value="#000000"/>
484   <color name="gray"                        value="#888888"/>
485   <color name="red"                         value="#CC0000"/>
486   <color name="green"                       value="#008800"/>
487   <color name="blue"                        value="#0000FF"/>
488   <color name="dark-blue"                   value="#002299"/>
489   <color name="yellow"                      value="#FFFF00"/>
490   <color name="light-yellow"                value="#FFFF88"/>
491   <color name="orange"                      value="#FF8800"/>
492   <color name="purple"                      value="#990099"/>
493 
494   <style name="text"                        foreground="#000000" background="#FFFFFF"/>
495   <style name="background-pattern"          background="#rgba(0,0,0,.03)"/>
496   <style name="selection"                   background="#4A90D9"/>
497 
498   <!-- Current Line Highlighting -->
499   <style name="current-line"                background="#rgba(0,0,0,.07)"/>
500 
501   <!-- Bracket Matching -->
502   <style name="bracket-match"               foreground="white" background="gray" bold="true"/>
503   <style name="bracket-mismatch"            foreground="white" background="#FF0000" bold="true"/>
504 
505   <!-- Search Matching -->
506   <style name="search-match"                foreground="#000000" background="#FFFF00"/>
507 
508   <!-- Language specifics -->
509   <style name="def:builtin"                 foreground="blue"/>
510   <style name="def:constant"                foreground="blue"/>
511   <style name="def:boolean"                 foreground="red"/>
512   <style name="def:decimal"                 foreground="red"/>
513   <style name="def:base-n-integer"          foreground="red"/>
514   <style name="def:floating-point"          foreground="red"/>
515   <style name="def:complex"                 foreground="red"/>
516   <style name="def:character"               foreground="red"/>
517   <style name="def:special-char"            foreground="red"/>
518 
519   <!-- Language specifics used by clang-parser in default config -->
520   <style name="def:string"                  foreground="red"/>
521   <style name="def:comment"                 foreground="gray"/>
522   <style name="def:statement"               foreground="blue"/>
523   <style name="def:type"                    foreground="blue"/>
524   <style name="def:function"                foreground="dark-blue"/>
525   <style name="def:identifier"              foreground="purple"/>
526   <style name="def:preprocessor"            foreground="green"/>
527   <style name="def:error"                   foreground="red"/>
528   <style name="def:warning"                 foreground="orange"/>
529   <style name="def:note"                    foreground="black" background="light-yellow"/>
530 
531   <style name="diff:added-line"             foreground="green"/>
532   <style name="diff:removed-line"           foreground="red"/>
533   <style name="diff:changed-line"           foreground="orange"/>
534   <style name="diff:diff-file"              use-style="def:type"/>
535   <style name="diff:location"               use-style="def:statement"/>
536   <style name="diff:special-case"           use-style="def:constant"/>
537 
538 </style-scheme>
539 )RAW";
540 }
541 
542 const char *Config::juci_dark_style() {
543   return R"RAW(<?xml version="1.0" encoding="UTF-8"?>
544 
545 <style-scheme id="juci-dark" _name="juci" version="1.0">
546   <author>juCi++ team</author>
547   <_description>Dark juCi++ style</_description>
548 
549   <!-- Palette -->
550   <color name="white"                       value="#D6D6D6"/>
551   <color name="black"                       value="#202428"/>
552   <color name="gray"                        value="#919191"/>
553   <color name="red"                         value="#FF9999"/>
554   <color name="yellow"                      value="#EEEE66"/>
555   <color name="green"                       value="#AACC99"/>
556   <color name="blue"                        value="#88AAFF"/>
557   <color name="light-blue"                  value="#AABBEE"/>
558   <color name="purple"                      value="#DD99DD"/>
559 
560   <style name="text"                        foreground="white" background="black"/>
561   <style name="background-pattern"          background="#rgba(255,255,255,.04)"/>
562   <style name="selection"                   background="#215D9C"/>
563 
564   <!-- Current Line Highlighting -->
565   <style name="current-line"                background="#rgba(255,255,255,.05)"/>
566 
567   <!-- Bracket Matching -->
568   <style name="bracket-match"               foreground="black" background="gray" bold="true"/>
569   <style name="bracket-mismatch"            foreground="black" background="#FF0000" bold="true"/>
570 
571   <!-- Search Matching -->
572   <style name="search-match"                foreground="#000000" background="#FFFF00"/>
573 
574   <!-- Language specifics -->
575   <style name="def:builtin"                 foreground="blue"/>
576   <style name="def:constant"                foreground="blue"/>
577   <style name="def:boolean"                 foreground="red"/>
578   <style name="def:decimal"                 foreground="red"/>
579   <style name="def:base-n-integer"          foreground="red"/>
580   <style name="def:floating-point"          foreground="red"/>
581   <style name="def:complex"                 foreground="red"/>
582   <style name="def:character"               foreground="red"/>
583   <style name="def:special-char"            foreground="red"/>
584 
585   <!-- Language specifics used by clang-parser in default config -->
586   <style name="def:string"                  foreground="red"/>
587   <style name="def:comment"                 foreground="gray"/>
588   <style name="def:statement"               foreground="blue"/>
589   <style name="def:type"                    foreground="blue"/>
590   <style name="def:function"                foreground="light-blue"/>
591   <style name="def:identifier"              foreground="purple"/>
592   <style name="def:preprocessor"            foreground="green"/>
593   <style name="def:error"                   foreground="red"/>
594   <style name="def:warning"                 foreground="yellow"/>
595   <style name="def:note"                    foreground="#E6E6E6" background="#383F46"/>
596 
597   <style name="diff:added-line"             foreground="green"/>
598   <style name="diff:removed-line"           foreground="red"/>
599   <style name="diff:changed-line"           foreground="yellow"/>
600   <style name="diff:diff-file"              use-style="def:type"/>
601   <style name="diff:location"               use-style="def:statement"/>
602   <style name="diff:special-case"           use-style="def:constant"/>
603 
604 </style-scheme>
605 )RAW";
606 }
607 
608 const char *Config::juci_dark_blue_style() {
609   return R"RAW(<?xml version="1.0" encoding="UTF-8"?>
610 
611 <style-scheme id="juci-dark-blue" _name="juci" version="1.0">
612   <author>juCi++ team</author>
613   <_description>Dark blue juCi++ style based on the Emacs deeper blue theme</_description>
614 
615   <!-- Palette -->
616   <color name="white"                       value="#D6D6D6"/>
617   <color name="dark-blue"                   value="#202233"/>
618   <color name="gray"                        value="#919191"/>
619   <color name="red"                         value="#FF7777"/>
620   <color name="yellow"                      value="#FFE100"/>
621   <color name="light-yellow"                value="#EAC595"/>
622   <color name="blue"                        value="#00CCFF"/>
623   <color name="green"                       value="#14ECA8"/>
624   <color name="light-blue"                  value="#8BFAFF"/>
625   <color name="light-green"                 value="#A0DB6B"/>
626 
627   <style name="text"                        foreground="white" background="dark-blue"/>
628   <style name="background-pattern"          background="#rgba(255,255,255,.04)"/>
629   <style name="selection"                   background="#215D9C"/>
630 
631   <!-- Current Line Highlighting -->
632   <style name="current-line"                background="#rgba(255,255,255,.05)"/>
633 
634   <!-- Bracket Matching -->
635   <style name="bracket-match"               foreground="dark-blue" background="gray" bold="true"/>
636   <style name="bracket-mismatch"            foreground="dark-blue" background="#FF0000" bold="true"/>
637 
638   <!-- Search Matching -->
639   <style name="search-match"                foreground="#000000" background="#FFFF00"/>
640 
641   <!-- Language specifics -->
642   <style name="def:builtin"                 foreground="blue"/>
643   <style name="def:constant"                foreground="blue"/>
644   <style name="def:boolean"                 foreground="light-yellow"/>
645   <style name="def:decimal"                 foreground="light-yellow"/>
646   <style name="def:base-n-integer"          foreground="light-yellow"/>
647   <style name="def:floating-point"          foreground="light-yellow"/>
648   <style name="def:complex"                 foreground="light-yellow"/>
649   <style name="def:character"               foreground="light-yellow"/>
650   <style name="def:special-char"            foreground="light-yellow"/>
651 
652   <!-- Language specifics used by clang-parser in default config -->
653   <style name="def:string"                  foreground="light-yellow"/>
654   <style name="def:comment"                 foreground="gray"/>
655   <style name="def:statement"               foreground="blue"/>
656   <style name="def:type"                    foreground="blue"/>
657   <style name="def:function"                foreground="light-blue"/>
658   <style name="def:identifier"              foreground="light-green"/>
659   <style name="def:preprocessor"            foreground="yellow"/>
660   <style name="def:error"                   foreground="red"/>
661   <style name="def:warning"                 foreground="yellow"/>
662   <style name="def:note"                    foreground="#E6E6E6" background="#383C59"/>
663 
664   <style name="diff:added-line"             foreground="green"/>
665   <style name="diff:removed-line"           foreground="red"/>
666   <style name="diff:changed-line"           foreground="yellow"/>
667   <style name="diff:diff-file"              use-style="def:type"/>
668   <style name="diff:location"               use-style="def:statement"/>
669   <style name="diff:special-case"           use-style="def:constant"/>
670 
671 </style-scheme>
672 )RAW";
673 }
674