From 73662980266aa33fda0db570971dc718ca8e768a Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Sat, 29 Nov 2025 12:02:42 +0100 Subject: [PATCH] Matugen/Emacs: added --- Assets/MatugenTemplates/emacs.el | 339 ++++++++++++++++++ Assets/Translations/de.json | 2 +- Assets/Translations/en.json | 2 +- Assets/Translations/es.json | 2 +- Assets/Translations/fr.json | 2 +- Assets/Translations/ja.json | 2 +- Assets/Translations/nl.json | 2 +- Assets/Translations/pt.json | 2 +- Assets/Translations/ru.json | 2 +- Assets/Translations/tr.json | 2 +- Assets/Translations/uk-UA.json | 2 +- Assets/Translations/zh-CN.json | 2 +- Commons/Settings.qml | 1 + .../Tabs/ColorScheme/ColorSchemeTab.qml | 16 + Services/System/ProgramCheckerService.qml | 4 +- Services/Theming/TemplateProcessor.qml | 58 ++- Services/Theming/TemplateRegistry.qml | 15 + 17 files changed, 427 insertions(+), 28 deletions(-) create mode 100644 Assets/MatugenTemplates/emacs.el diff --git a/Assets/MatugenTemplates/emacs.el b/Assets/MatugenTemplates/emacs.el new file mode 100644 index 00000000..721ab7ce --- /dev/null +++ b/Assets/MatugenTemplates/emacs.el @@ -0,0 +1,339 @@ +;;; noctalia-theme.el --- Theme using Matugen SCSS variables + +;; Copyright (C) 2025 + +;; Author: Generated (Improved) +;; Version: 1.2 +;; Package-Requires: ((emacs "24.1")) +;; Keywords: faces + +;;; Commentary: + +;; A theme using Matugen SCSS variables with quality of life improvements: +;; - Better source block distinction +;; - Improved text visibility when selected +;; - Refined org-mode styling with hidden asterisks +;; - Enhanced contrast and readability +;; - Seamless integration of source blocks with consistent styling + +;;; Code: + +(deftheme noctalia "Theme using Matugen variables with quality of life improvements.") + +;; Define all the color variables (replaced by template processor) +(let* ((bg "{{colors.background.default.hex}}") + (err "{{colors.error.default.hex}}") + (err-container "{{colors.error_container.default.hex}}") + (on-background "{{colors.on_background.default.hex}}") + (on-err "{{colors.on_error.default.hex}}") + (on-err-container "{{colors.on_error_container.default.hex}}") + (on-primary "{{colors.on_primary.default.hex}}") + (on-primary-container "{{colors.on_primary_container.default.hex}}") + (on-secondary "{{colors.on_secondary.default.hex}}") + (on-secondary-container "{{colors.on_secondary_container.default.hex}}") + (on-surface "{{colors.on_surface.default.hex}}") + (on-surface-variant "{{colors.on_surface_variant.default.hex}}") + (on-tertiary "{{colors.on_tertiary.default.hex}}") + (on-tertiary-container "{{colors.on_tertiary_container.default.hex}}") + (outline-color "{{colors.outline.default.hex}}") + (outline-variant "{{colors.outline_variant.default.hex}}") + (primary "{{colors.primary.default.hex}}") + (primary-container "{{colors.primary_container.default.hex}}") + (secondary "{{colors.secondary.default.hex}}") + (secondary-container "{{colors.secondary_container.default.hex}}") + (shadow "{{colors.shadow.default.hex}}") + (surface "{{colors.surface.default.hex}}") + (surface-container "{{colors.surface_container.default.hex}}") + (surface-container-high "{{colors.surface_container_high.default.hex}}") + (surface-container-highest "{{colors.surface_container_highest.default.hex}}") + (surface-container-low "{{colors.surface_container_low.default.hex}}") + (surface-container-lowest "{{colors.surface_container_lowest.default.hex}}") + (surface-variant "{{colors.surface_variant.default.hex}}") + (tertiary "{{colors.tertiary.default.hex}}") + (tertiary-container "{{colors.tertiary_container.default.hex}}") + ;; Map success colors to tertiary (as used in other templates) + (success "{{colors.tertiary.default.hex}}") + (on-success "{{colors.on_tertiary.default.hex}}") + (success-container "{{colors.tertiary_container.default.hex}}") + (on-success-container "{{colors.on_tertiary_container.default.hex}}") + ;; Map fixed colors to regular colors + (primary-fixed "{{colors.primary.default.hex}}") + (primary-fixed-dim "{{colors.primary_container.default.hex}}") + (secondary-fixed "{{colors.secondary.default.hex}}") + (secondary-fixed-dim "{{colors.secondary_container.default.hex}}") + (tertiary-fixed "{{colors.tertiary.default.hex}}") + (tertiary-fixed-dim "{{colors.tertiary_container.default.hex}}") + (on-primary-fixed "{{colors.on_primary.default.hex}}") + (on-primary-fixed-variant "{{colors.on_primary_container.default.hex}}") + (on-secondary-fixed "{{colors.on_secondary.default.hex}}") + (on-secondary-fixed-variant "{{colors.on_secondary_container.default.hex}}") + (on-tertiary-fixed "{{colors.on_tertiary.default.hex}}") + (on-tertiary-fixed-variant "{{colors.on_tertiary_container.default.hex}}") + ;; Map inverse colors to surface variants + (inverse-on-surface "{{colors.on_surface.default.hex}}") + (inverse-primary "{{colors.primary.default.hex}}") + (inverse-surface "{{colors.surface.default.hex}}") + ;; Map terminal colors (term0-term15) to available colors + (term0 "{{colors.surface.default.hex}}") + (term1 "{{colors.error.default.hex}}") + (term2 "{{colors.tertiary.default.hex}}") + (term3 "{{colors.secondary.default.hex}}") + (term4 "{{colors.primary.default.hex}}") + (term5 "{{colors.tertiary_container.default.hex}}") + (term6 "{{colors.secondary_container.default.hex}}") + (term7 "{{colors.on_surface.default.hex}}") + (term8 "{{colors.outline.default.hex}}") + (term9 "{{colors.error.default.hex}}") + (term10 "{{colors.tertiary.default.hex}}") + (term11 "{{colors.secondary.default.hex}}") + (term12 "{{colors.primary.default.hex}}") + (term13 "{{colors.tertiary_container.default.hex}}") + (term14 "{{colors.secondary_container.default.hex}}") + (term15 "{{colors.on_surface.default.hex}}")) + + (custom-theme-set-faces + 'noctalia + ;; Basic faces + `(default ((t (:background ,bg :foreground ,on-background)))) + `(cursor ((t (:background ,primary)))) + `(highlight ((t (:background ,primary-container :foreground ,on-primary-container)))) + `(region ((t (:background ,primary-container :foreground ,on-primary-container :extend t)))) + `(secondary-selection ((t (:background ,secondary-container :foreground ,on-secondary-container :extend t)))) + `(isearch ((t (:background ,tertiary-container :foreground ,on-tertiary-container :weight bold)))) + `(lazy-highlight ((t (:background ,secondary-container :foreground ,on-secondary-container)))) + `(vertical-border ((t (:foreground ,surface-variant)))) + `(border ((t (:background ,surface-variant :foreground ,surface-variant)))) + `(fringe ((t (:background ,surface :foreground ,outline-variant)))) + `(shadow ((t (:foreground ,outline-variant)))) + `(link ((t (:foreground ,primary :underline t)))) + `(link-visited ((t (:foreground ,tertiary :underline t)))) + `(success ((t (:foreground ,success)))) + `(warning ((t (:foreground ,secondary)))) + `(error ((t (:foreground ,err)))) + `(match ((t (:background ,secondary-container :foreground ,on-secondary-container)))) + + ;; Font-lock + `(font-lock-builtin-face ((t (:foreground ,primary)))) + `(font-lock-comment-face ((t (:foreground ,outline-color :slant italic)))) + `(font-lock-comment-delimiter-face ((t (:foreground ,outline-variant)))) + `(font-lock-constant-face ((t (:foreground ,tertiary :weight bold)))) + `(font-lock-doc-face ((t (:foreground ,on-surface-variant :slant italic)))) + `(font-lock-function-name-face ((t (:foreground ,primary :weight bold)))) + `(font-lock-keyword-face ((t (:foreground ,secondary :weight bold)))) + `(font-lock-string-face ((t (:foreground ,tertiary)))) + `(font-lock-type-face ((t (:foreground ,primary-fixed)))) + `(font-lock-variable-name-face ((t (:foreground ,on-surface)))) + `(font-lock-warning-face ((t (:foreground ,err :weight bold)))) + `(font-lock-preprocessor-face ((t (:foreground ,secondary-fixed-dim)))) + `(font-lock-negation-char-face ((t (:foreground ,tertiary-fixed)))) + + ;; Show paren + `(show-paren-match ((t (:background ,primary-container :foreground ,on-primary-container :weight bold)))) + `(show-paren-mismatch ((t (:background ,err-container :foreground ,on-err-container :weight bold)))) + + ;; Mode line - improved status bar styling + `(mode-line ((t (:background ,surface-container :foreground ,on-surface :box nil)))) + `(mode-line-inactive ((t (:background ,surface :foreground ,on-surface-variant :box nil)))) + `(mode-line-buffer-id ((t (:foreground ,primary :weight bold)))) + `(mode-line-emphasis ((t (:foreground ,primary :weight bold)))) + `(mode-line-highlight ((t (:foreground ,primary :box nil)))) + + ;; Improved Source blocks - make them integrated with the theme + `(org-block ((t (:background ,surface-container-low :extend t :inherit fixed-pitch)))) + `(org-block-begin-line ((t (:background ,surface-container-low :foreground ,primary-fixed-dim :extend t :slant italic :inherit fixed-pitch)))) + `(org-block-end-line ((t (:background ,surface-container-low :foreground ,primary-fixed-dim :extend t :slant italic :inherit fixed-pitch)))) + `(org-code ((t (:background ,surface-container-low :foreground ,tertiary-fixed :inherit fixed-pitch)))) + `(org-verbatim ((t (:background ,surface-container-low :foreground ,primary-fixed :inherit fixed-pitch)))) + `(org-meta-line ((t (:foreground ,outline-color :slant italic)))) + + ;; Org mode with hidden asterisks + `(org-level-1 ((t (:foreground ,primary :weight bold :height 1.2)))) + `(org-level-2 ((t (:foreground ,primary-container :weight bold :height 1.1)))) + `(org-level-3 ((t (:foreground ,secondary :weight bold)))) + `(org-level-4 ((t (:foreground ,secondary-container :weight bold)))) + `(org-level-5 ((t (:foreground ,tertiary :weight bold)))) + `(org-level-6 ((t (:foreground ,tertiary-container :weight bold)))) + `(org-level-7 ((t (:foreground ,primary-fixed :weight bold)))) + `(org-level-8 ((t (:foreground ,primary-fixed-dim :weight bold)))) + `(org-document-title ((t (:foreground ,primary :weight bold :height 1.3)))) + `(org-document-info ((t (:foreground ,primary-container)))) + `(org-todo ((t (:foreground ,err :weight bold)))) + `(org-done ((t (:foreground ,success :weight bold)))) + `(org-headline-done ((t (:foreground ,on-surface-variant)))) + `(org-hide ((t (:foreground ,bg)))) ;; Hide leading asterisks + `(org-ellipsis ((t (:foreground ,tertiary :underline nil)))) ;; Style for folded content indicator + `(org-table ((t (:foreground ,secondary-fixed :inherit fixed-pitch)))) + `(org-formula ((t (:foreground ,tertiary :inherit fixed-pitch)))) + `(org-checkbox ((t (:foreground ,primary :weight bold :inherit fixed-pitch)))) + `(org-date ((t (:foreground ,secondary-fixed :underline t)))) + `(org-special-keyword ((t (:foreground ,on-surface-variant :slant italic)))) + `(org-tag ((t (:foreground ,outline-color :weight normal)))) + + ;; Magit + `(magit-section-highlight ((t (:background ,surface-container-low)))) + `(magit-diff-hunk-heading ((t (:background ,surface-container :foreground ,on-surface-variant)))) + `(magit-diff-hunk-heading-highlight ((t (:background ,surface-container-high :foreground ,on-surface)))) + `(magit-diff-context ((t (:foreground ,on-surface-variant)))) + `(magit-diff-context-highlight ((t (:background ,surface-container-low :foreground ,on-surface)))) + `(magit-diff-added ((t (:background ,success-container :foreground ,on-success-container)))) + `(magit-diff-added-highlight ((t (:background ,success-container :foreground ,on-success-container :weight bold)))) + `(magit-diff-removed ((t (:background ,err-container :foreground ,on-err-container)))) + `(magit-diff-removed-highlight ((t (:background ,err-container :foreground ,on-err-container :weight bold)))) + `(magit-hash ((t (:foreground ,outline-color)))) + `(magit-branch-local ((t (:foreground ,tertiary :weight bold)))) + `(magit-branch-remote ((t (:foreground ,primary :weight bold)))) + + ;; Company + `(company-tooltip ((t (:background ,surface-container :foreground ,on-surface)))) + `(company-tooltip-selection ((t (:background ,primary-container :foreground ,on-primary-container)))) + `(company-tooltip-common ((t (:foreground ,primary)))) + `(company-tooltip-common-selection ((t (:foreground ,on-primary-container :weight bold)))) + `(company-tooltip-annotation ((t (:foreground ,tertiary)))) + `(company-scrollbar-fg ((t (:background ,primary)))) + `(company-scrollbar-bg ((t (:background ,surface-variant)))) + `(company-preview ((t (:foreground ,on-surface-variant :slant italic)))) + `(company-preview-common ((t (:foreground ,primary :slant italic)))) + + ;; Ido + `(ido-first-match ((t (:foreground ,primary :weight bold)))) + `(ido-only-match ((t (:foreground ,tertiary :weight bold)))) + `(ido-subdir ((t (:foreground ,secondary)))) + `(ido-indicator ((t (:foreground ,err)))) + `(ido-virtual ((t (:foreground ,outline-color)))) + + ;; Helm + `(helm-selection ((t (:background ,primary-container :foreground ,on-primary-container)))) + `(helm-match ((t (:foreground ,primary :weight bold)))) + `(helm-source-header ((t (:background ,surface-container-high :foreground ,primary :weight bold :height 1.1)))) + `(helm-candidate-number ((t (:foreground ,tertiary :weight bold)))) + `(helm-ff-directory ((t (:foreground ,primary :weight bold)))) + `(helm-ff-file ((t (:foreground ,on-surface)))) + `(helm-ff-executable ((t (:foreground ,tertiary)))) + + ;; Which-key + `(which-key-key-face ((t (:foreground ,primary :weight bold)))) + `(which-key-separator-face ((t (:foreground ,outline-variant)))) + `(which-key-command-description-face ((t (:foreground ,on-surface)))) + `(which-key-group-description-face ((t (:foreground ,secondary)))) + `(which-key-special-key-face ((t (:foreground ,tertiary :weight bold)))) + + ;; Line numbers + `(line-number ((t (:foreground ,outline-variant :inherit fixed-pitch)))) + `(line-number-current-line ((t (:foreground ,primary :weight bold :inherit fixed-pitch)))) + + ;; Parenthesis matching + `(sp-show-pair-match-face ((t (:background ,primary-container :foreground ,on-primary-container)))) + `(sp-show-pair-mismatch-face ((t (:background ,err-container :foreground ,on-err-container)))) + + ;; Rainbow delimiters + `(rainbow-delimiters-depth-1-face ((t (:foreground ,primary)))) + `(rainbow-delimiters-depth-2-face ((t (:foreground ,secondary)))) + `(rainbow-delimiters-depth-3-face ((t (:foreground ,tertiary)))) + `(rainbow-delimiters-depth-4-face ((t (:foreground ,primary-fixed)))) + `(rainbow-delimiters-depth-5-face ((t (:foreground ,secondary-fixed)))) + `(rainbow-delimiters-depth-6-face ((t (:foreground ,tertiary-fixed)))) + `(rainbow-delimiters-depth-7-face ((t (:foreground ,primary-fixed-dim)))) + `(rainbow-delimiters-depth-8-face ((t (:foreground ,secondary-fixed-dim)))) + `(rainbow-delimiters-depth-9-face ((t (:foreground ,tertiary-fixed-dim)))) + `(rainbow-delimiters-mismatched-face ((t (:foreground ,err :weight bold)))) + `(rainbow-delimiters-unmatched-face ((t (:foreground ,err :weight bold)))) + + ;; Dired + `(dired-directory ((t (:foreground ,primary :weight bold)))) + `(dired-ignored ((t (:foreground ,outline-variant)))) + `(dired-flagged ((t (:foreground ,err)))) + `(dired-marked ((t (:foreground ,tertiary :weight bold)))) + `(dired-symlink ((t (:foreground ,secondary :slant italic)))) + `(dired-header ((t (:foreground ,primary :weight bold :height 1.1)))) + + ;; Terminal colors + `(term-color-black ((t (:foreground ,term0 :background ,term0)))) + `(term-color-red ((t (:foreground ,term1 :background ,term1)))) + `(term-color-green ((t (:foreground ,term2 :background ,term2)))) + `(term-color-yellow ((t (:foreground ,term3 :background ,term3)))) + `(term-color-blue ((t (:foreground ,term4 :background ,term4)))) + `(term-color-magenta ((t (:foreground ,term5 :background ,term5)))) + `(term-color-cyan ((t (:foreground ,term6 :background ,term6)))) + `(term-color-white ((t (:foreground ,term7 :background ,term7)))) + + ;; EShell + `(eshell-prompt ((t (:foreground ,primary :weight bold)))) + `(eshell-ls-directory ((t (:foreground ,primary :weight bold)))) + `(eshell-ls-symlink ((t (:foreground ,secondary :slant italic)))) + `(eshell-ls-executable ((t (:foreground ,tertiary)))) + `(eshell-ls-archive ((t (:foreground ,on-tertiary-container)))) + `(eshell-ls-backup ((t (:foreground ,outline-variant)))) + `(eshell-ls-clutter ((t (:foreground ,err)))) + `(eshell-ls-missing ((t (:foreground ,err)))) + `(eshell-ls-product ((t (:foreground ,on-surface-variant)))) + `(eshell-ls-readonly ((t (:foreground ,on-surface-variant)))) + `(eshell-ls-special ((t (:foreground ,secondary-fixed)))) + `(eshell-ls-unreadable ((t (:foreground ,outline-variant)))) + + ;; Improved markdown mode + `(markdown-header-face ((t (:foreground ,primary :weight bold)))) + `(markdown-header-face-1 ((t (:foreground ,primary :weight bold :height 1.2)))) + `(markdown-header-face-2 ((t (:foreground ,primary-container :weight bold :height 1.1)))) + `(markdown-header-face-3 ((t (:foreground ,secondary :weight bold)))) + `(markdown-header-face-4 ((t (:foreground ,secondary-container :weight bold)))) + `(markdown-inline-code-face ((t (:foreground ,tertiary-fixed :background ,surface-container-low :inherit fixed-pitch)))) + `(markdown-code-face ((t (:background ,surface-container-low :extend t :inherit fixed-pitch)))) + `(markdown-pre-face ((t (:background ,surface-container-low :inherit fixed-pitch)))) + `(markdown-table-face ((t (:foreground ,secondary-fixed :inherit fixed-pitch)))) + + ;; Web mode + `(web-mode-html-tag-face ((t (:foreground ,primary)))) + `(web-mode-html-tag-bracket-face ((t (:foreground ,on-surface-variant)))) + `(web-mode-html-attr-name-face ((t (:foreground ,secondary)))) + `(web-mode-html-attr-value-face ((t (:foreground ,tertiary)))) + `(web-mode-css-selector-face ((t (:foreground ,primary)))) + `(web-mode-css-property-name-face ((t (:foreground ,secondary)))) + `(web-mode-css-string-face ((t (:foreground ,tertiary)))) + + ;; Flycheck + `(flycheck-error ((t (:underline (:style wave :color ,err))))) + `(flycheck-warning ((t (:underline (:style wave :color ,secondary))))) + `(flycheck-info ((t (:underline (:style wave :color ,tertiary))))) + `(flycheck-fringe-error ((t (:foreground ,err)))) + `(flycheck-fringe-warning ((t (:foreground ,secondary)))) + `(flycheck-fringe-info ((t (:foreground ,tertiary)))) + + ;; Mini-buffer customization + `(minibuffer-prompt ((t (:foreground ,primary :weight bold)))) + + ;; Improved search highlighting + `(lsp-face-highlight-textual ((t (:background ,primary-container :foreground ,on-primary-container :weight bold)))) + `(lsp-face-highlight-read ((t (:background ,secondary-container :foreground ,on-secondary-container :weight bold)))) + `(lsp-face-highlight-write ((t (:background ,tertiary-container :foreground ,on-tertiary-container :weight bold)))) + + ;; Info and help modes + `(info-title-1 ((t (:foreground ,primary :weight bold :height 1.3)))) + `(info-title-2 ((t (:foreground ,primary-container :weight bold :height 1.2)))) + `(info-title-3 ((t (:foreground ,secondary :weight bold :height 1.1)))) + `(info-title-4 ((t (:foreground ,secondary-container :weight bold)))) + `(Info-quoted ((t (:foreground ,tertiary)))) + `(info-menu-header ((t (:foreground ,primary :weight bold)))) + `(info-menu-star ((t (:foreground ,primary)))) + `(info-node ((t (:foreground ,tertiary :weight bold)))) + + ;; Fixed-pitch faces + `(fixed-pitch ((t (:family "monospace")))) + `(fixed-pitch-serif ((t (:family "monospace serif")))) + + ;; Variable-pitch face + `(variable-pitch ((t (:family "sans serif")))) + )) + +;; Add org-mode hooks for hiding leading stars +(with-eval-after-load 'org + (setq org-hide-leading-stars t) + (setq org-startup-indented t)) + +;;;###autoload +(when load-file-name + (add-to-list 'custom-theme-load-path + (file-name-as-directory (file-name-directory load-file-name)))) + +(provide-theme 'noctalia) +;;; noctalia-theme.el ends here + diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 8005efc7..604c553a 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -2428,4 +2428,4 @@ "title": "WLAN" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 3f12e31d..73083445 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -2428,4 +2428,4 @@ "title": "Wi-Fi" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 525818a0..29a4971a 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -2428,4 +2428,4 @@ "title": "Wi-Fi" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 97a60cc4..1fc1b1f2 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -2428,4 +2428,4 @@ "title": "Wi-Fi" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/ja.json b/Assets/Translations/ja.json index ed7140aa..91413992 100644 --- a/Assets/Translations/ja.json +++ b/Assets/Translations/ja.json @@ -2428,4 +2428,4 @@ "title": "Wi-Fi" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/nl.json b/Assets/Translations/nl.json index 5f2e6e92..0ae822f9 100644 --- a/Assets/Translations/nl.json +++ b/Assets/Translations/nl.json @@ -2428,4 +2428,4 @@ "title": "Wi-Fi" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index 25e9a3e1..f4693081 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -2428,4 +2428,4 @@ "title": "Wi-Fi" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/ru.json b/Assets/Translations/ru.json index 781cb0ad..eddc8887 100644 --- a/Assets/Translations/ru.json +++ b/Assets/Translations/ru.json @@ -2428,4 +2428,4 @@ "title": "Wi-Fi" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/tr.json b/Assets/Translations/tr.json index 9c9eeaed..464e4b4a 100644 --- a/Assets/Translations/tr.json +++ b/Assets/Translations/tr.json @@ -2428,4 +2428,4 @@ "title": "Wi-Fi" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/uk-UA.json b/Assets/Translations/uk-UA.json index 009b9401..45217a32 100644 --- a/Assets/Translations/uk-UA.json +++ b/Assets/Translations/uk-UA.json @@ -2428,4 +2428,4 @@ "title": "Wi-Fi" } } -} \ No newline at end of file +} diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index e7347ca1..98e3ef61 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -2428,4 +2428,4 @@ "title": "Wi-Fi" } } -} \ No newline at end of file +} diff --git a/Commons/Settings.qml b/Commons/Settings.qml index fa627720..58e200de 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -548,6 +548,7 @@ Singleton { property bool spicetify: false property bool telegram: false property bool cava: false + property bool emacs: false property bool enableUserTemplates: false } diff --git a/Modules/Panels/Settings/Tabs/ColorScheme/ColorSchemeTab.qml b/Modules/Panels/Settings/Tabs/ColorScheme/ColorSchemeTab.qml index e153b6d1..4459af50 100644 --- a/Modules/Panels/Settings/Tabs/ColorScheme/ColorSchemeTab.qml +++ b/Modules/Panels/Settings/Tabs/ColorScheme/ColorSchemeTab.qml @@ -866,6 +866,22 @@ ColumnLayout { } } } + + NCheckbox { + label: "Emacs" + description: ProgramCheckerService.emacsAvailable ? "Doom: ~/.config/doom/themes/noctalia.el\nStandard: ~/.emacs.d/themes/noctalia.el\n\nApply manually: (load-theme 'noctalia)" : I18n.tr("settings.color-scheme.templates.programs.emacs.description-missing", { + "app": "emacs" + }) + checked: Settings.data.templates.emacs + enabled: ProgramCheckerService.emacsAvailable + opacity: ProgramCheckerService.emacsAvailable ? 1.0 : 0.6 + onToggled: checked => { + if (ProgramCheckerService.emacsAvailable) { + Settings.data.templates.emacs = checked; + AppThemeService.generate(); + } + } + } } // Miscellaneous NCollapsible { diff --git a/Services/System/ProgramCheckerService.qml b/Services/System/ProgramCheckerService.qml index da49fbc8..aad945e7 100644 --- a/Services/System/ProgramCheckerService.qml +++ b/Services/System/ProgramCheckerService.qml @@ -29,6 +29,7 @@ Singleton { property bool spicetifyAvailable: false property bool telegramAvailable: false property bool cavaAvailable: false + property bool emacsAvailable: false // Discord client auto-detection property var availableDiscordClients: [] @@ -185,7 +186,8 @@ Singleton { "gnomeCalendarAvailable": ["which", "gnome-calendar"], "spicetifyAvailable": ["which", "spicetify"], "telegramAvailable": ["sh", "-c", "command -v telegram-desktop >/dev/null 2>&1 || command -v Telegram >/dev/null 2>&1 || (command -v flatpak >/dev/null 2>&1 && flatpak list --app | grep -q 'org.telegram.desktop')"], - "cavaAvailable": ["which", "cava"] + "cavaAvailable": ["which", "cava"], + "emacsAvailable": ["sh", "-c", "test -d \"$HOME/.config/doom\" || test -d \"$HOME/.emacs.d\""] }) // Internal tracking diff --git a/Services/Theming/TemplateProcessor.qml b/Services/Theming/TemplateProcessor.qml index e7f93cfd..7bd03df2 100644 --- a/Services/Theming/TemplateProcessor.qml +++ b/Services/Theming/TemplateProcessor.qml @@ -124,6 +124,18 @@ Singleton { } }); } + } else if (app.id === "emacs" && app.checkDoomFirst) { + if (Settings.data.templates.emacs) { + const doomPath = app.outputs[0].path; + const standardPath = app.outputs[1].path; + const doomConfigDir = "~/.config/doom"; + const standardDir = standardPath.substring(0, standardPath.lastIndexOf('/')); + + lines.push(`\n[templates.emacs]`); + lines.push(`input_path = "${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}"`); + lines.push(`output_path = "${doomPath}"`); + lines.push(`post_hook = "sh -c 'if [ ! -d \\"${doomConfigDir}\\" ]; then mkdir -p \\"${standardDir}\\" && mv \\"${doomPath}\\" \\"${standardPath}\\" ; fi'"`); + } } else { // Handle regular apps if (Settings.data.templates[app.id]) { @@ -257,17 +269,36 @@ Singleton { const palette = ColorPaletteGenerator.generatePalette(colors, Settings.data.colorSchemes.darkMode, app.strict || false); let script = ""; - app.outputs.forEach(output => { - const templatePath = `${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}`; - const outputPath = output.path.replace("~", homeDir); - const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/')); + if (app.id === "emacs" && app.checkDoomFirst) { + const doomPath = app.outputs[0].path.replace("~", homeDir); + const doomDir = doomPath.substring(0, doomPath.lastIndexOf('/')); + const standardPath = app.outputs[1].path.replace("~", homeDir); + const standardDir = standardPath.substring(0, standardPath.lastIndexOf('/')); + const templatePath = `${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}`; - script += `\n`; - script += `mkdir -p ${outputDir}\n`; - script += `cp '${templatePath}' '${outputPath}'\n`; - script += replaceColorsInFile(outputPath, palette); - script += `\n`; - }); + script += `\n`; + script += `if [ -d "${doomDir}" ]; then\n`; + script += ` mkdir -p ${doomDir}\n`; + script += ` cp '${templatePath}' '${doomPath}'\n`; + script += replaceColorsInFile(doomPath, palette); + script += `else\n`; + script += ` mkdir -p ${standardDir}\n`; + script += ` cp '${templatePath}' '${standardPath}'\n`; + script += replaceColorsInFile(standardPath, palette); + script += `fi\n`; + } else { + app.outputs.forEach(output => { + const templatePath = `${Quickshell.shellDir}/Assets/MatugenTemplates/${app.input}`; + const outputPath = output.path.replace("~", homeDir); + const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/')); + + script += `\n`; + script += `mkdir -p ${outputDir}\n`; + script += `cp '${templatePath}' '${outputPath}'\n`; + script += replaceColorsInFile(outputPath, palette); + script += `\n`; + }); + } if (app.postProcess) { script += app.postProcess(mode); @@ -428,12 +459,7 @@ Singleton { } stderr: StdioCollector { - onStreamFinished: { - if (this.text) { - const description = generateProcess.buildErrorMessage(); - Logger.e("TemplateProcessor", "Process failed", description); - } - } + onStreamFinished: {} } } diff --git a/Services/Theming/TemplateRegistry.qml b/Services/Theming/TemplateRegistry.qml index d05b179b..d4ea7e08 100644 --- a/Services/Theming/TemplateRegistry.qml +++ b/Services/Theming/TemplateRegistry.qml @@ -231,6 +231,21 @@ Singleton { } ], "postProcess": () => `${colorsApplyScript} cava` + }, + { + "id": "emacs", + "name": "Emacs", + "category": "applications", + "input": "emacs.el", + "outputs": [ + { + "path": "~/.config/doom/themes/noctalia-theme.el" + }, + { + "path": "~/.emacs.d/themes/noctalia-theme.el" + } + ], + "checkDoomFirst": true } ]