My doom emacs configuration

doom header

;;; $DOOMDIR/config.el -*- lexical-binding: t; -*-
;; Place your private configuration here! Remember, you do not need to run 'doom
;; sync' after modifying this file!

EXWM Configuration

Package Requirements

Helper Functions

System Integration

Window Management

Polybar Integration

Perspective EXWM Integration

Core EXWM Configuration

Keybindings

Multi-Monitor Configuration

Visual Customization

System Integration

multi monitor code suggestion fix

doom configuration

(setq doom-font (font-spec :family "Maple Mono NF" :size 20 :weight 'normal)
      doom-variable-pitch-font (font-spec :family "Maple Mono NF" :size 22)
      doom-big-font (font-spec :family "Maple Mono NF" :size 24))
;; Enable EXWM

;; (setq fancy-splash-image "~/.config/doom/Emacs.png")


(setq display-line-numbers-type 'relative)

doom theme fix

;; (setq doom-theme 'elegant) ; my own custom theme
(after! doom-themes
  (load-theme 'doom-nano-light t))
(use-package! doom-nano-modeline
  :config
  (doom-nano-modeline-mode 1)
  (global-hide-mode-line-mode 1))
;; (setq catppuccin-flavor 'frappe)
;; (setq doom-theme 'doom-nano-light)


;; (custom-set-faces!
;;   '(default :background "#303446")
;;   '(org-list-dt :foreground "#EF9F76")
;;   '(org-bullet :foreground "#F4B8E4"))

doom custom theme

;;; doom-bluecurve-theme.el --- inspired by Red Hat Bluecurve -*- lexical-binding: t; no-byte-compile: t; -*-
;;
;; Copyright (C) 2025 by Custom User
;;
;; Author: Custom User
;; Version: 1.0.0
;; Keywords: custom themes, faces
;; Homepage: https://github.com/doomemacs/themes
;; Package-Requires: ((emacs "25.1") (cl-lib "0.5") (doom-themes "2.2.1"))
;;
;;; Commentary:
;;
;; A theme inspired by the classic Red Hat Bluecurve theme.
;;
;;; Code:

;; (require 'doom-themes)

;; ;;
;; ;;; Variables

;; (defgroup doom-bluecurve-theme nil
;;   "Options for the `doom-bluecurve' theme."
;;   :group 'doom-themes)

;; (defcustom doom-bluecurve-brighter-modeline nil
;;   "If non-nil, more vivid colors will be used to style the mode-line."
;;   :group 'doom-bluecurve-theme
;;   :type 'boolean)

;; (defcustom doom-bluecurve-brighter-comments nil
;;   "If non-nil, comments will be highlighted in more vivid colors."
;;   :group 'doom-bluecurve-theme
;;   :type 'boolean)

;; (defcustom doom-bluecurve-padded-modeline doom-themes-padded-modeline
;;   "If non-nil, adds a 4px padding to the mode-line.
;; Can be an integer to determine the exact padding."
;;   :group 'doom-bluecurve-theme
;;   :type '(choice integer boolean))

;; ;;
;; ;;; Theme definition

;; (def-doom-theme doom-bluecurve
;;   "A theme inspired by Red Hat Bluecurve"

;;   ;; name        default   256       16
;;   ((bg         '("#e6e6e6" "#e6e6e6" "white"))
;;    (fg         '("#000000" "#000000" "black"))

;;    ;; These are off-color variants of bg/fg, used primarily for `solaire-mode',
;;    ;; but can also be useful as a basis for subtle highlights (e.g. for hl-line
;;    ;; or region), especially when paired with the `doom-darken', `doom-lighten',
;;    ;; and `doom-blend' helper functions.
;;    (bg-alt     '("#eeeeee" "#eeeeee" "white"))
;;    (fg-alt     '("#777777" "#777777" "black"))

;;    ;; These should represent a spectrum from bg to fg, where base0 is a starker
;;    ;; bg and base8 is a starker fg. They are used for (1) custom themed faces,
;;    ;; (2) to define the face of unspecified `custom-set-faces'.
;;    (base0      '("#f0f0f0" "#f0f0f0" "white"))
;;    (base1      '("#eeeeee" "#eeeeee" "brightwhite"))
;;    (base2      '("#e6e6e6" "#e6e6e6" "brightwhite"))
;;    (base3      '("#cccccc" "#cccccc" "brightwhite"))
;;    (base4      '("#b3b3b3" "#b3b3b3" "brightblack"))
;;    (base5      '("#999999" "#999999" "brightblack"))
;;    (base6      '("#777777" "#777777" "brightblack"))
;;    (base7      '("#555555" "#555555" "black"))
;;    (base8      '("#000000" "#000000" "black"))

;;    (grey       base4)
;;    (red        '("#cc0000" "#cc0000" "red"))
;;    (orange     '("#f57900" "#f57900" "brightred"))
;;    (green      '("#73d216" "#73d216" "green"))
;;    (teal       '("#5e7ab7" "#5e7ab7" "brightgreen"))
;;    (yellow     '("#f5c211" "#f5c211" "yellow"))
;;    (blue       '("#4464ac" "#4464ac" "brightblue"))
;;    (dark-blue  '("#3450a0" "#3450a0" "blue"))
;;    (magenta    '("#551a8b" "#551a8b" "brightmagenta"))
;;    (violet     '("#6c3483" "#6c3483" "magenta"))
;;    (cyan       '("#0088cc" "#0088cc" "brightcyan"))
;;    (dark-cyan  '("#0077aa" "#0077aa" "cyan"))

;;    ;; These are the "universal syntax classes" that doom-themes establishes.
;;    ;; These *must* be included in every doom themes, or your theme will throw an
;;    ;; error, as they are used in the base theme defined in doom-themes-base.
;;    (highlight      blue)
;;    (vertical-bar   (doom-darken base2 0.1))
;;    (selection      dark-blue)
;;    (builtin        blue)
;;    (comments       (if doom-bluecurve-brighter-comments dark-cyan base6))
;;    (doc-comments   (if doom-bluecurve-brighter-comments (doom-lighten dark-cyan 0.15) base6))
;;    (constants      magenta)
;;    (functions      blue)
;;    (keywords       blue)
;;    (methods        blue)
;;    (operators      fg)
;;    (type           blue)
;;    (strings        green)
;;    (variables      fg)
;;    (numbers        magenta)
;;    (region         base3)
;;    (error          red)
;;    (warning        orange)
;;    (success        green)
;;    (vc-modified    yellow)
;;    (vc-added       green)
;;    (vc-deleted     red)

;;    ;; custom categories
;;    (modeline-bg     (if doom-bluecurve-brighter-modeline base3 base2))
;;    (modeline-bg-alt (doom-darken bg 0.15))
;;    (modeline-fg     base8)
;;    (modeline-fg-alt base6)

;;    (-modeline-pad
;;     (when doom-bluecurve-padded-modeline
;;       (if (integerp doom-bluecurve-padded-modeline) doom-bluecurve-padded-modeline 4))))

;;   ;;;; Base theme face overrides
;;   (((font-lock-comment-face &override)
;;     :slant 'italic
;;     :background (if doom-bluecurve-brighter-comments (doom-lighten bg 0.05)))
;;    ((font-lock-keyword-face &override) :weight 'bold)
;;    ((font-lock-constant-face &override) :weight 'bold)
;;    ((line-number &override) :foreground base6)
;;    ((line-number-current-line &override) :foreground fg :background base2)
;;    (mode-line
;;     :background modeline-bg :foreground modeline-fg
;;     :box (if -modeline-pad `(:line-width ,-modeline-pad :color ,modeline-bg)))
;;    (mode-line-inactive
;;     :background modeline-bg-alt :foreground modeline-fg-alt
;;     :box (if -modeline-pad `(:line-width ,-modeline-pad :color ,modeline-bg-alt)))
;;    (mode-line-emphasis :foreground (if doom-bluecurve-brighter-modeline base8 highlight))

;;    ;;;; css-mode <built-in> / scss-mode
;;    (css-proprietary-property :foreground orange)
;;    (css-property             :foreground green)
;;    (css-selector             :foreground blue)
;;    ;;;; doom-modeline
;;    (doom-modeline-bar :background (if doom-bluecurve-brighter-modeline modeline-bg highlight))
;;    (doom-modeline-evil-emacs-state  :foreground magenta)
;;    (doom-modeline-evil-insert-state :foreground blue)
;;    ;;;; markdown-mode
;;    (markdown-markup-face :foreground base5)
;;    (markdown-header-face :inherit 'bold :foreground blue)
;;    (markdown-code-face :background base1)
;;    ;;;; org <built-in>
;;    (org-block :background base1)
;;    (org-block-begin-line :foreground fg :slant 'italic)
;;    ;;;; solaire-mode
;;    (solaire-mode-line-face
;;     :inherit 'mode-line
;;     :background modeline-bg-alt
;;     :box (if -modeline-pad `(:line-width ,-modeline-pad :color ,modeline-bg-alt)))
;;    (solaire-mode-line-inactive-face
;;     :inherit 'mode-line-inactive
;;     :background modeline-bg-alt
;;     :box (if -modeline-pad `(:line-width ,-modeline-pad :color ,modeline-bg-alt))))

;;   ;;;; Base theme variable overrides-
;;   ())

;;; doom-bluecurve-theme.el ends here

custom dashboard

;; Bild-Banner
(setq +doom-dashboard-menu-sections (cl-subseq +doom-dashboard-menu-sections 0 0 ))

(setq fancy-splash-image (expand-file-name "data/logo.svg" doom-user-dir))

;; Titel
(setq dashboard-banner-logo-title "GNU Emacs version 26.3")

;; Link und Hilfe
(add-hook! '+doom-dashboard-functions :
  (insert "\n"
          (+doom-dashboard--center +doom-dashboard--width " www.gnu.org ")
          "\n"
          (+doom-dashboard--center +doom-dashboard--width "Type Ctrl-h for help")
          "\n\n"))

;; Footer
(add-hook! '+doom-dashboard-functions :append
  (insert "\n"
          (+doom-dashboard--center +doom-dashboard--width
           "GNU Emacs comes with ABSOLUTELY NO WARRANTY")
          "\n"
          (+doom-dashboard--center +doom-dashboard--width
           (format "Copyright (C) %s Free Software Foundation, Inc." (format-time-string "%Y")))
          "\n"
          (+doom-dashboard--center +doom-dashboard--width
           (format "Current date: %s" (format-time-string "%A, %B %d, %Y, %H:%M %Z")))
          "\n"))

eat configuration

(use-package! eat
  :defer t
  :config
  (when (fboundp 'eat-global-mode)
    (eat-global-mode)
    (setq eat-kill-buffer-on-exit t)))

tailwindcss configuration

(use-package! eglot
  :config
  (add-to-list 'eglot-server-programs
               '(((web-mode :language-id "html")
                  (heex-ts-mode :language-id "html")) . ("tailwindcss-language-server" "--stdio"))))

(after! lsp-mode
  (use-package! lsp-tailwindcss
    :config
    (setq lsp-tailwindcss-add-on-mode t
          lsp-tailwindcss-server-version "0.14.8"
          lsp-tailwindcss-skip-config-check t)))

citar configuration

(setq! citar-bibliography '("~/org-roam/library/master.bib"))
(setq! citar-library-paths '("~/org-roam/library/files/")
       citar-notes-paths '("~/org-roam/library/notes/"))

org-roam

(setq org-roam-directory (file-truename "~/org-roam"))
(after! org-roam
  (defun org-roam-node-insert-immediate (arg &rest args)
    (interactive "P")
    (let ((args (cons arg args))
          (org-roam-capture-templates (list (append (car org-roam-capture-templates)
                                                    '(:immediate-finish t)))))
      (apply #'org-roam-node-insert args))))
(use-package consult-org-roam
  :after org-roam
  :init
  (require 'consult-org-roam)

  (consult-org-roam-mode 1)
  :custom

  (consult-org-roam-grep-func #'consult-ripgrep)

  (consult-org-roam-buffer-narrow-key ?r)

  (consult-org-roam-buffer-after-buffers t)
  :config

  (consult-customize consult-org-roam-forward-links :preview-key "M-.")
  :bind

  ("C-c n e" . consult-org-roam-file-find)
  ("C-c n b" . consult-org-roam-backlinks)
  ("C-c n B" . consult-org-roam-backlinks-recursive)
  ("C-c n l" . consult-org-roam-forward-links)
  ("C-c n r" . consult-org-roam-search))

vulpea

(add-hook 'after-init-hook #'vulpea-agenda-files-update)
(use-package! vulpea
  :after org-roam
  :config
  (defun vulpea-project-p ()
    "Return non-nil if current buffer has any todo entry.

TODO entries marked as done are ignored, meaning the this
function returns nil if current buffer contains only completed
tasks."
    (seq-find                                 ; (3)
     (lambda (type)
       (eq type 'todo))
     (org-element-map                         ; (2)
         (org-element-parse-buffer 'headline) ; (1)
         'headline
       (lambda (h)
         (org-element-property :todo-type h)))))

  (defun vulpea-project-update-tag ()
    "Update PROJECT tag in the current buffer."
    (when (and (not (active-minibuffer-window))
               (vulpea-buffer-p))
      (save-excursion
        (goto-char (point-min))
        (let* ((tags (vulpea-buffer-tags-get))
               (original-tags tags))
          (if (vulpea-project-p)
              (setq tags (cons "Tasks" tags))
            (setq tags (remove "Tasks" tags)))


          ;; cleanup duplicates
          (setq tags (seq-uniq tags))

          ;; update tags if changed
          (when (or (seq-difference tags original-tags)
                    (seq-difference original-tags tags))
            (apply #'vulpea-buffer-tags-set tags))))))

  (defun vulpea-buffer-p ()
    "Return non-nil if the currently visited buffer is a note."
    (and buffer-file-name
         (string-prefix-p
          (expand-file-name (file-name-as-directory org-roam-directory))
          (file-name-directory buffer-file-name))))

  (defun vulpea-project-files ()
    "Return a list of note files containing 'project' tag." ;
    (seq-uniq
     (seq-map
      #'car
      (org-roam-db-query
       [:select [nodes:file]
        :from tags
        :left-join nodes
        :on (= tags:node-id nodes:id)
        :where (like tag (quote "%\"Tasks\"%"))]))))

  (defun vulpea-agenda-files-update (&rest _)
    "Update the value of `org-agenda-files'."
    (setq org-agenda-files (vulpea-project-files)))

  (add-hook 'find-file-hook #'vulpea-project-update-tag)
  (add-hook 'before-save-hook #'vulpea-project-update-tag)

  (advice-add 'org-agenda :before #'vulpea-agenda-files-update)
  (advice-add 'org-todo-list :before #'vulpea-agenda-files-update)
  )

org-ql

(use-package! org-ql
  :config
  (setq org-ql-views
        '(("bachelor" lambda nil
            (interactive)
            (org-ql-search
              (org-agenda-files)
              '(and (todo) (tags "Bachelor"))
              :title "Bachelor TODOs")))))
(map! :leader
      (:prefix ("o" . "org")
               (:prefix ("a" . "agenda")
                        (:prefix ("q" . "ql-view")
                         :desc "Org QL View Sidebar" "s" #'org-ql-view-sidebar))))
;; (use-package! org-ql
;;   :config
;;   (setq
;;    org-ql-views
;;    '(("stuck" lambda nil
;;       (interactive)
;;       (org-ql-search
;;         (org-agenda-files)
;;         '(and (tags "story")
;;               (not (tags "ignore"))
;;               (not (done)) ;; Finished stories should be excluded
;;               (not (descendants (todo "NEXT"))) ;; If there are already
;;               ;; something in progress
;;               ;; it will shown
;;               (and (not (descendants (done))) ;; There are not scheduled not finished items
;;                    (not (descendants (scheduled)))))
;;         :narrow nil :super-groups
;;         '((:name "Waiting"   :order 8 :todo "WAIT")
;;           (:name "Important" :order 1 :deadline t :priority>= "B")
;;           (:name "Work"      :order 2 :tag "work")
;;           (:name "Study"     :order 2 :tag "study")
;;           (:name "Stucked"   :order 3 :tag "story"))
;;         :title "stuck-projects"))
;;      ("reports" lambda nil
;;       (interactive)
;;       (org-ql-search
;;         (org-agenda-files)
;;         '(and (or (tags-local "weekly")
;;                   (tags-local "monthly"))
;;               (not (tags "ignore")))
;;         :narrow nil :super-groups
;;         '((:name "Weekly reports" :tag "weekly")
;;           (:name "Monthly reports" :tag "monthly"))
;;         :title "Introspection reports"))
;;      ("next" lambda nil
;;       (interactive)
;;       (org-ql-search
;;         (org-agenda-files)
;;         '(and (or (tags-local "refile")
;;                   (todo "PROG")
;;                   (todo "WAIT")
;;                   (todo "NEXT"))
;;               (not (tags "ignore"))
;;               (not (property "linked"))
;;               (not (done)))
;;         :sort '(date)
;;         :narrow nil
;;         :super-groups
;;         `((:name "In progress" :order 1 :todo "PROG")
;;           (:name "Daily"       :order 2 :regexp ,org-repeat-re)
;;           (:name "Waiting"     :order 3 :todo "WAIT")
;;           (:name "Refile"      :order 3 :tag "refile")
;;           (:name "Important"   :order 3 :priority>= "B")
;;           (:auto-tags t        :order 5))
;;         :title "Next actions"))
;;      ("calendar" lambda nil
;;       (interactive)
;;       (org-ql-search
;;         (org-agenda-files)
;;         `(and (ts-active)
;;               (regexp ,org-scheduled-time-hour-regexp)
;;               (not (done)))
;;         :sort '(date)
;;         :narrow nil
;;         :super-groups
;;         '((:auto-planning t))
;;         :title "Calendar"))
;;      ("dashboard" lambda nil
;;       (interactive)
;;       (org-ql-search
;;         (org-agenda-files)
;;         '(and (or (ts-active :to today)
;;                   (deadline auto)
;;                   (todo "PROG")
;;                   (and (tags "journal")
;;                        (not (tags "weekly"))
;;                        (not (tags "monthly"))
;;                        (not (tags "yearly"))
;;                        (todo)))
;;               (not (todo "WAIT"))
;;               (not (tags "ignore"))
;;               (not (property "linked"))
;;               (not (done)))
;;         :sort '(date)
;;         :narrow nil
;;         :super-groups
;;         `((:name "In progress" :order 1
;;            :tag "monthly" :tag "weekly" :todo "PROG")
;;           (:name "Agenda"      :order 2
;;            :deadline t :regexp ,org-scheduled-time-hour-regexp)
;;           (:name "Daily"       :order 2
;;            :and (:todo nil :regexp ,org-repeat-re))
;;           (:name "Today"       :order 3 :tag "Tasks")
;;           (:name "Important"   :order 3 :priority>= "B")
;;           (:auto-tags t        :order 5))
;;         :title "Dashboard"))))
;;   )

org-roam ui

(use-package! websocket
  :after org-roam)

(use-package! org-roam-ui
  :after org-roam ;; or :after org
  ;;         normally we'd recommend hooking orui after org-roam, but since org-roam does not have
  ;;         a hookable mode anymore, you're advised to pick something yourself
  ;;         if you don't care about startup time, use
  ;;  :hook (after-init . org-roam-ui-mode)
  :config
  (setq org-roam-ui-sync-theme t
        org-roam-ui-follow t
        org-roam-ui-update-on-save t
        org-roam-ui-open-on-start t))

toc-org

;; toc-org Konfiguration
(use-package! toc-org
  :after org
  :hook (org-mode . toc-org-mode)
  :config
  (setq toc-org-hrefify-default "gh"))

;; Integration mit org-roam
(after! org-roam
  (add-hook 'org-roam-mode-hook 'toc-org-mode))

md-to-org

(defun jab/md-to-org-region (start end)
  "Convert region from markdown to org, replacing selection"
  (interactive "r")
  (shell-command-on-region start end "pandoc -f markdown -t org" t t))

org-projects

(use-package! project-tasks
  :defer t
  :commands (project-tasks)
  :init
  ;; Zeige project-tasks beim Wechseln von Projekten
  (add-to-list 'project-switch-commands '(project-tasks "tasks") t)
  ;; Füge Aktion zur embark-file-map hinzu (falls du embark verwendest)
  (with-eval-after-load 'embark
    (define-key embark-file-map (kbd "P") #'project-tasks-in-dir))
  :custom
  ;; Setze die Liste der Task-Dateien
  (project-tasks-files '("tasks.org"))
  :config
  (add-to-list 'marginalia-prompt-categories '("select task" . project-task))
  (defvar-keymap embark-project-task-actions
    :doc "Keymap for actions for project-task (when mentioned by name)."
    :parent embark-general-map
    "j" #'project-tasks-goto-task)
  (add-to-list 'embark-keymap-alist '(project-task . embark-project-task-actions))
  ;; Binde project-tasks an die Projekt-Keymap
  :bind (:map project-prefix-map
         ("P" . project-tasks)))

org-tidy

(require 'org-tidy)
(add-hook 'org-mode-hook #'org-tidy-mode)

org-babel-async

(use-package! ob-async
  :after org)

make org prettier

(defun org-agenda-open-hook ()
  (olivetti-mode))

(add-hook 'org-agenda-mode-hook #'org-agenda-open-hook)
(with-eval-after-load 'org (global-org-modern-mode))

(setq org-modern-star 'fold)
(setq org-modern-fold-stars '(("" . "")))
(setq org-modern-star 'replace)
(setq org-modern-replace-stars "◉○◉○◉")

org agenda

(setq org-directory "~/org/")
(setq org-noter-notes-search-path '("~/org/notes/"))
(after! org
  (setq! org-agenda-span 7
         org-agenda-start-day "+0d"
         org-agenda-hide-tags-regexp ".*")
  ;; Define custom TODO keywords
  (setq org-todo-keywords
        '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)")
          (sequence "BACKLOG(b)" "PLAN(p)" "READY(r)" "ACTIVE(a)" "REVIEW(v)"
                    "WAIT(w@/!)" "HOLD(h)" "IDEA(i)" "|" "COMPLETED(c)" "CANC(k@)")))

  ;; Configure custom agenda views
  (setq org-agenda-custom-commands
        '(("d" "Dashboard"
           ((agenda "" ((org-deadline-warning-days 7)))
            (tags "+class"
                  ((org-agenda-overriding-header "Classes")
                   (org-agenda-files '("~/org/university.org"))))
            (todo "NEXT"
                  ((org-agenda-overriding-header "Next Tasks")))
            (tags-todo "agenda/ACTIVE"
                       ((org-agenda-overriding-header "Active Projects")))

            ))

        ("P" "Stayem Dashboard"
        ((tags-todo "+category=\"stayem\"+TODO=\"TODO\""
                ((org-agenda-overriding-header "Todo items")
                (org-agenda-files org-agenda-files)))
        (tags-todo "+category=\"stayem\"+TODO=\"BACKLOG\""
                ((org-agenda-overriding-header "Backlog")
                (org-agenda-files org-agenda-files)))))


          ("n" "Next Tasks"
           ((todo "NEXT"
                  ((org-agenda-overriding-header "Next Tasks")))))

          ("C" "Class Tasks"
           ((tags-todo "+class")))

          ;; Low-effort next actions
          ("e" tags-todo "+TODO=\"NEXT\"+Effort<15&+Effort>0"
           ((org-agenda-overriding-header "Low Effort Tasks")
            (org-agenda-max-todos 20)
            (org-agenda-files org-agenda-files)))

          ("w" "Workflow Status"
           ((todo "WAIT"
                  ((org-agenda-overriding-header "Waiting on External")
                   (org-agenda-files org-agenda-files)))
            (todo "REVIEW"
                  ((org-agenda-overriding-header "In Review")
                   (org-agenda-files org-agenda-files)))
            (todo "PLAN"
                  ((org-agenda-overriding-header "In Planning")
                   (org-agenda-todo-list-sublevels nil)
                   (org-agenda-files org-agenda-files)))
            (todo "BACKLOG"
                  ((org-agenda-overriding-header "Project Backlog")
                   (org-agenda-todo-list-sublevels nil)
                   (org-agenda-files org-agenda-files)))
            (todo "READY"
                  ((org-agenda-overriding-header "Ready for Work")
                   (org-agenda-files org-agenda-files)))
            (todo "ACTIVE"
                  ((org-agenda-overriding-header "Active Projects")
                   (org-agenda-files org-agenda-files)))
            (todo "COMPLETED"
                  ((org-agenda-overriding-header "Completed Projects")
                   (org-agenda-files org-agenda-files)))
            (todo "CANC"
                  ((org-agenda-overriding-header "Cancelled Projects")
                   (org-agenda-files org-agenda-files))))))))

calendar


(defun my-open-calendar ()
  (interactive)
  (cfw:open-calendar-buffer
   :contents-sources
   (list
    (cfw:org-create-source "Green")
    )))

deft

(setq deft-directory "~/org-roam/notes")

olivetti global mode

(setq-default olivetti-body-width 120)
(define-globalized-minor-mode my-global-olivetti-mode olivetti-mode
  (lambda () (olivetti-mode 1)))
(my-global-olivetti-mode)

gleam configuration

(use-package! gleam-ts-mode
  :mode (rx ".gleam" eos))

(after! treesit
  (add-to-list 'auto-mode-alist '("\\.gleam$" . gleam-ts-mode)))

(after! gleam-ts-mode
  (unless (treesit-language-available-p 'gleam)
    (gleam-ts-install-grammar)))

;; Gleam-Modus konfigurieren
(use-package! gleam-ts-mode
  :mode (rx ".gleam" eos))

;; Tree-Sitter-Grammatik für Gleam installieren
(after! gleam-ts-mode
  (unless (treesit-language-available-p 'gleam)
    (gleam-ts-install-grammar)))

;; Entscheide dich für EINEN der folgenden Blöcke:

;; Option 1: Wenn du Eglot verwenden möchtest
(after! eglot
  (add-to-list 'eglot-server-programs '(gleam-ts-mode . ("gleam" "lsp"))))
(add-hook 'gleam-ts-mode-local-vars-hook #'eglot-ensure)

python configuration

(use-package! pyvenv
  :config
  (pyvenv-mode t)

  ;; Automatisch das Virtual Environment aktivieren
  (defun my/auto-activate-venv ()
    (let ((venv-path (locate-dominating-file default-directory ".venv")))
      (when venv-path
        (pyvenv-activate (expand-file-name ".venv" venv-path)))))

  (add-hook 'python-mode-hook #'my/auto-activate-venv))

typst configuration

(use-package! treesit
  :config
  (add-to-list 'treesit-language-source-alist
               '(typst "https://github.com/uben0/tree-sitter-typst"))
  (treesit-install-language-grammar 'typst))

(with-eval-after-load 'eglot
  (with-eval-after-load 'typst-ts-mode
    (add-to-list 'eglot-server-programs
                 `((typst-ts-mode) .
                   ,(eglot-alternatives `(,typst-ts-lsp-download-path
                                          "tinymist"
                                          "typst-lsp"))))))

typst exporter

(use-package! ox-typst
  :after org)

lsp bridge

;; (use-package! lsp-bridge
;;   :after yasnippet
;;   :init
;;   (require 'yasnippet)
;;   (yas-global-mode 1)
;;   :config
;;   (require 'lsp-bridge)
;;   (global-lsp-bridge-mode)

;;   ;; TailwindCSS-Unterstützung
;;   ;; Installation des TailwindCSS-Servers
;;   ;; npm install -g @tailwindcss/language-server

;;   ;; Multiserver-Konfiguration für HTML mit TailwindCSS
;;   (setq lsp-bridge-multi-lang-server-mode-list
;;         '(((web-mode html-mode) . "html_tailwindcss")))

;;   ;; Aktiviere Vervollständigung in Strings (wichtig für TailwindCSS in HTML-Klassen)
;;   (setq lsp-bridge-enable-completion-in-string t)
;;   (add-to-list 'lsp-bridge-completion-in-string-file-types '("html"))

;;   ;; Benutzerdefinierte Spracherkennung für TailwindCSS
;;   (setq lsp-bridge-get-language-id
;;         (lambda (file-path)
;;           (cond ((string-match-p "\\.html$" file-path) "html")
;;                 (t (lsp-bridge-get-lang-id-by-extension file-path))))))

GPT.el

(use-package! gptel
  :config
  (setq gptel-model 'gemma3:4b
        gptel-backend (gptel-make-ollama "ollama"
                        :host "localhost:11434"
                        :stream t
                        :models '(gemma3:12b gemma3:4b)))
  (setq gptel-default-mode 'org-mode))

ox-zola

(use-package! ox-zola
  :ensure t
  :after ox
  :config
  (require 'ox-hugo))