;;; .emacs --- Oleg's Emacs configuration
;; Copyright © 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2025 Oleg Pykhalov <go.wigust@gmail.com>
;; Released under the GNU GPLv3 or any later version.

;; Tip: "M-x e" on `(emacs-init-time)'.

;; Prettify without breaking indentation,
;; Origin <http://endlessparentheses.com/using-prettify-symbols-in-clojure-and-elisp-without-breaking-indentation.html>.

;; Prevent stale elisp bytecode from shadowing more up-to-date source
;; files.  Origin <https://github.com/technomancy/better-defaults>.

;; Added by Package.el.  This must come before configurations of
;; installed packages.  Don't delete this line.  If you don't want it,
;; just comment it out by adding a semicolon to the start of the line.
;; You may delete these explanatory comments.
;; (package-initialize)

(setq read-process-output-max (* 1024 1024)) ;; 1mb
(setq gc-cons-threshold 100000000)

;; [[https://github.com/skeeto/elfeed/issues/95][End of file during parsing · Issue #95 · skeeto/elfeed]]
(setq write-region-inhibit-fsync t)

;; [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Startup-Summary.html][gnu.org/s/emacs/manual/html_node/elisp/Startup-Summary.html]]
;;
;; Uncomment the following:
;;
;; (setq initial-buffer-choice 'text-mode)
;;
;; and add to the end of the ~/.emacs file:
;;
;; (benchmark-init/show-durations-tabulated)

(autoload 'f-directories "f" nil t)
(autoload 'string-trim-right "subr-x" nil t)
(autoload 'flet "cl" nil t)
(autoload 'beginend-global-mode "beginend" nil t)
(require 'dash) ; TODO: Use `autoload' instead of `require'.
(require 'cl-lib)

(defun load-config-file (file)
  (load (concat (getenv "HOME") "/.emacs.d/modules/" file)))

(setq load-prefer-newer t)

(setq epg-gpg-program "gpg")

;; (require 'benchmark-init)

;; To disable collection of benchmark data after init is done.
;; (add-hook 'after-init-hook 'benchmark-init/deactivate)

(setq package-archives nil) ; Makes unpure packages archives unavailable

(setq user-mail-address "go.wigust@gmail.com")
(setq user-full-name "Oleg Pykhalov")
(setq default-input-method "russian-computer") ; <C-\> keyboard layout

;; https://github.com/skeeto/elfeed/issues/437
;;
;; Multibyte characters broken in titles, fixed by running
;; `toggle-enable-multibyte-characters` twice · Issue #437 ·
;; skeeto/elfeed
;; (set-language-environment "utf-8")

(autoload 'debbugs-browse-url "debbugs-browse" nil t)

(load-config-file "utils.el")

(load-config-file "dired.el")
(load-config-file "ffap.el")
(load-config-file "nav.el")
(load-config-file "keys.el")
(load-config-file "org.el")
(load-config-file "lisp.el")
(load-config-file "files.el")
(load-config-file "nix.el")
(load-config-file "scheme.el")
(load-config-file "guix.el")
(load-config-file "yaml.el")
(load-config-file "kubernetes.el")
(load-config-file "term.el")
(load-config-file "audio.el")
(load-config-file "mail.el")
(load-config-file "c.el")
(load-config-file "version-control-lexical.el")
(load-config-file "version-control.el")
(load-config-file "erc.el")
(load-config-file "rfc.el")
(load-config-file "web.el")
(load-config-file "outline.el")
(load-config-file "snippets.el")
(load-config-file "copyright.el")
(load-config-file "lsp.el")
(add-hook 'emacs-startup-hook (lambda () (load-config-file "theme.el")))
(load-config-file "ci.el")
(load-config-file "compile.el")
(load-config-file "hooks.el")
(load-config-file "debug.el")
(load-config-file "elfeed.el")
(load-config-file "time.el")
(load-config-file "debbugs.el")
(load-config-file "text.el")
(load-config-file "groovy.el")
(load-config-file "haskell.el")
(load-config-file "completion.el")
(load-config-file "ftp.el")
(load-config-file "info.el")
(load-config-file "majordomo.el")
(load-config-file "blog.el")
(load-config-file "po.el")
(load-config-file "python.el")
(load-config-file "java.el")
(load-config-file "js.el")
(load-config-file "perl.el")
(load-config-file "rust.el")
(load-config-file "ml.el")
(load-config-file "tramp.el")
(load-config-file "llm.el")

;; (load-config-file "twitch.el")
;; (load-config-file "youtube.el")

(autoload 'get-synonyms "thesaurus" nil t)
(autoload 'mf/mirror-region-in-multifile "multifiles" nil t)

;; (autoload 'org-notifications-start "org-notifications" nil t)
;; (setq org-notifications-non-agenda-file
;;       (list (expand-file-name "~/src/gitlab.com/wigust/notes/agenda.org")))
;; ;; (setq org-notifications-notify-before-time 5)
;; (org-notifications-start)

(setq ewmctrl-wmctrl-path "/run/current-system/profile/bin/wmctrl")
(defalias 'rg 'deadgrep)

;; TODO: debpaste API broken
;; (setq debpaste-user-name "wigust")

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(build-farm-build-arguments '("jobset=guix-master" "system=x86_64-linux"))
 '(company-backends
   '(company-abbrev company-bbdb company-eclim company-semantic company-xcode company-cmake company-capf company-files
                    (company-dabbrev-code company-gtags company-etags company-keywords)
                    company-oddmuse company-dabbrev))
 '(custom-safe-themes
   '("e1ad4299390cb3fc0cbf5a705442eaf08510aa947c90c8bc83b1d7308befb475" "0568a5426239e65aab5e7c48fa1abde81130a87ddf7f942613bf5e13bf79686b" "076ee9f2c64746aac7994b697eb7dbde23ac22988d41ef31b714fc6478fee224" "d9864caf2fc6cd9bc5bed941c526a4690bf6c27f0d8c1ca28ff7e05806b57204" "aa85228e4b6d188c3c0b8553548142c2c75726429614376c26255a51378982f5" "a10ca93d065921865932b9d7afae98362ce3c347f43cb0266d025d70bec57af1" "4ce515d79ef94f3b7651c8e2a7c7d81814b9ca911eb2a16955f45f4555faf524" "ba881f92a04cf56df49740324caea02d25442a327f1c33d1a1946f0b9a846f53" "3c83b3676d796422704082049fc38b6966bcad960f896669dfc21a7a37a748fa" "a27c00821ccfd5a78b01e4f35dc056706dd9ede09a8b90c6955ae6a390eb1c1e" default))
 '(dap-auto-configure-mode nil)
 '(dap-tooltip-mode nil)
 '(dap-ui-controls-mode nil nil (dap-ui))
 '(dap-ui-many-windows-mode nil)
 '(dap-ui-mode nil nil (dap-ui))
 '(debug-on-error nil)
 '(display-time-mode nil)
 '(indent-tabs-mode nil)
 '(menu-bar-mode nil)
 '(org-agenda-files '("~/org/inbox.org" "~/org/todo.org" "~/org/web.org"))
 '(python-shell-interpreter "python3" t)
 '(safe-local-variable-values
   '((geiser-repl-per-project-p . t)
     (eval progn
           (setq-local create-lockfiles nil))
     (eval let
           ((root-dir-unexpanded
             (locate-dominating-file default-directory ".dir-locals.el")))
           (when root-dir-unexpanded
             (let*
                 ((root-dir
                   (file-local-name
                    (expand-file-name root-dir-unexpanded)))
                  (root-dir*
                   (directory-file-name root-dir)))
               (unless
                   (boundp 'geiser-guile-load-path)
                 (defvar geiser-guile-load-path 'nil))
               (make-local-variable 'geiser-guile-load-path)
               (require 'cl-lib)
               (cl-pushnew root-dir* geiser-guile-load-path :test #'string-equal))))
     (projectile-project-compilation-cmd . ".direnv/aliases/shell -- .direnv/aliases/build")
     (eval progn
           (when
               (boundp #'projectile-project-root)
             (setenv "GUIX_PACKAGE_PATH"
                     (concat
                      (projectile-project-root)
                      "dotfiles/guixsd/modules")))
           (setq-local geiser-guile-load-path
                       (append
                        (list
                         (concat
                          (getenv "HOME")
                          "/src/cgit.duckdns.org/guix/guix-wigust/guix"))
                        (list
                         (concat
                          (getenv "HOME")
                          "/src/gitlab.com/nonguix/nonguix"))
                        (if
                            (boundp #'projectile-project-root)
                            (list
                             (concat
                              (projectile-project-root)
                              "dotfiles/guixsd/modules"))
                          'nil))))
     (eval with-eval-after-load 'yasnippet
           (let
               ((guix-yasnippets
                 (expand-file-name "etc/snippets/yas"
                                   (locate-dominating-file default-directory ".dir-locals.el"))))
             (unless
                 (member guix-yasnippets yas-snippet-dirs)
               (add-to-list 'yas-snippet-dirs guix-yasnippets)
               (yas-reload-all))))
     (eval add-to-list 'completion-ignored-extensions ".go")
     (eval setq-local geiser-guile-load-path
           (append
            (list
             (concat
              (getenv "HOME")
              "/src/cgit.duckdns.org/guix/guix-wigust/guix"))
            (list
             (concat
              (getenv "HOME")
              "/src/gitlab.com/nonguix/nonguix"))
            (if
                (boundp #'projectile-project-root)
                (list
                 (concat
                  (projectile-project-root)
                  "dotfiles/guixsd/modules"))
              'nil)))
     (eval progn
           (require 'lisp-mode)
           (defun emacs27-lisp-fill-paragraph
               (&optional justify)
             (interactive "P")
             (or
              (fill-comment-paragraph justify)
              (let
                  ((paragraph-start
                    (concat paragraph-start "\\|\\s-*\\([(;\"]\\|\\s-:\\|`(\\|#'(\\)"))
                   (paragraph-separate
                    (concat paragraph-separate "\\|\\s-*\".*[,\\.]$"))
                   (fill-column
                    (if
                        (and
                         (integerp emacs-lisp-docstring-fill-column)
                         (derived-mode-p 'emacs-lisp-mode))
                        emacs-lisp-docstring-fill-column fill-column)))
                (fill-paragraph justify))
              t))
           (setq-local fill-paragraph-function #'emacs27-lisp-fill-paragraph))
     (eval setq-local geiser-guile-load-path
           (append
            (list
             (concat
              (getenv "HOME")
              "/src/cgit.duckdns.org/git/guix/guix-wigust/guix"))
            (list
             (concat
              (getenv "HOME")
              "/src/gitlab.com/nonguix/nonguix"))
            (if
                (boundp #'projectile-project-root)
                (list
                 (concat
                  (projectile-project-root)
                  "dotfiles/guixsd/modules"))
              'nil)))
     (eval setq-local geiser-guile-load-path
           (append
            (list
             (concat
              (getenv "HOME")
              "/src/cgit.duckdns.org/git/guix/guix-wigust"))
            (if
                (boundp #'projectile-project-root)
                (list
                 (concat
                  (projectile-project-root)
                  "dotfiles/guixsd/modules"))
              'nil)))
     (magit-todos-depth)
     (magit-todos-exclude-globs "*.go" "*.info" "*.po")
     (magit-todos-update)
     (magit-todos-depth . 1)
     (eval progn
           (let
               ((top
                 (locate-dominating-file default-directory ".dir-locals.el")))
             (add-to-list 'geiser-guile-load-path top)))
     (geiser-active-implementations guile)
     (eval c-set-offset 'arglist-cont-nonempty
           '(c-lineup-gcc-asm-reg c-lineup-arglist))
     (eval c-set-offset 'arglist-close 0)
     (eval c-set-offset 'arglist-intro '++)
     (eval c-set-offset 'case-label 0)
     (eval c-set-offset 'statement-case-open 0)
     (eval setq-local geiser-guile-load-path
           (list
            (concat
             (projectile-project-root)
             "dotfiles/guixsd/modules")
            (concat
             (getenv "HOME")
             "/src/cgit.duckdns.org/git/guix/guix-wigust/guix")))
     (projectile-project-compilation-cmd . "nix-shell --run 'nix build -L'")
     (eval add-hook 'before-save-hook 'time-stamp)
     (projectile-project-test-cmd . "/home/oleg/src/git.savannah.gnu.org/git/guix/pre-inst-env ./test.sh")
     (projectile-project-compilation-cmd . "/home/oleg/src/git.savannah.gnu.org/git/guix/pre-inst-env guix build --with-source=file://$PWD guile-bash")
     (projectile-project-install-cmd . "/home/oleg/src/git.savannah.gnu.org/git/guix/pre-inst-env guix package --with-source=file://$PWD -i guile-bash")
     (projectile-project-test-cmd . "./test.sh")
     (projectile-project-compilation-cmd . "guix build --with-source=file://$PWD guile-bash")
     (projectile-project-install-cmd . "guix package --with-source=file://$PWD -i guile-bash")
     (projectile-project-configure-cmd . "./configure")
     (projectile-project-install-cmd . "make install")
     (eval let
           ((root-dir-unexpanded
             (concat
              (locate-dominating-file default-directory ".dir-locals.el")
              "guix/")))
           (when root-dir-unexpanded
             (let*
                 ((root-dir
                   (expand-file-name root-dir-unexpanded))
                  (root-dir*
                   (directory-file-name root-dir)))
               (unless
                   (boundp 'geiser-guile-load-path)
                 (defvar geiser-guile-load-path 'nil))
               (make-local-variable 'geiser-guile-load-path)
               (require 'cl-lib)
               (cl-pushnew root-dir* geiser-guile-load-path :test #'string-equal))))
     (eval setq-local guix-directory
           (concat
            (locate-dominating-file default-directory ".dir-locals.el")
            "guix/"))
     (eval setq-local geiser-guile-load-path
           (list
            (concat
             (projectile-project-root)
             "dotfiles/guixsd/modules")))
     (eval c-set-offset 'inlambda 0)
     (c-block-comment-prefix . "  ")
     (eval let
           ((root-dir-unexpanded
             (locate-dominating-file default-directory ".dir-locals.el")))
           (when root-dir-unexpanded
             (let*
                 ((root-dir
                   (expand-file-name root-dir-unexpanded))
                  (root-dir*
                   (directory-file-name root-dir)))
               (unless
                   (boundp 'geiser-guile-load-path)
                 (defvar geiser-guile-load-path 'nil))
               (make-local-variable 'geiser-guile-load-path)
               (require 'cl-lib)
               (cl-pushnew root-dir* geiser-guile-load-path :test #'string-equal))))
     (eval setq-local guix-directory
           (locate-dominating-file default-directory ".dir-locals.el"))
     (eval let*
           ((root-dir
             (expand-file-name
              (locate-dominating-file default-directory ".dir-locals.el")))
            (root-dir*
             (directory-file-name root-dir)))
           (unless
               (boundp 'geiser-guile-load-path)
             (defvar geiser-guile-load-path 'nil))
           (make-local-variable 'geiser-guile-load-path)
           (require 'cl-lib)
           (cl-pushnew root-dir* geiser-guile-load-path :test #'string-equal))
     (eval let*
           ((root-dir
             (expand-file-name
              (locate-dominating-file default-directory ".dir-locals.el")))
            (root-dir*
             (directory-file-name root-dir)))
           (unless
               (boundp 'geiser-guile-load-path)
             (defvar geiser-guile-load-path 'nil))
           (make-local-variable 'geiser-guile-load-path)
           (cl-pushnew root-dir* geiser-guile-load-path :test #'string-equal))
     (eval setq guix-directory
           (locate-dominating-file default-directory ".dir-locals.el"))
     (eval setq-local indent-tabs-mode t)
     (projectile-project-test-cmd . "make check")
     (git-auto-commit-mode . t)
     (eval progn
           (put 'with-directory 'scheme-indent-function 1)
           (put 'with-repository 'scheme-indent-function 2))
     (TeX-master . "guile.texi")
     (eval c-set-offset 'access-label '-)
     (eval c-set-offset 'substatement-open 0)
     (eval c-set-offset 'arglist-cont-nonempty '+)
     (eval c-set-offset 'arglist-cont 0)
     (eval c-set-offset 'arglist-intro '+)
     (eval c-set-offset 'inline-open 0)
     (eval c-set-offset 'defun-open 0)
     (eval c-set-offset 'innamespace 0)
     (indicate-empty-lines . t)
     (eval modify-syntax-entry 43 "'")
     (eval modify-syntax-entry 36 "'")
     (eval modify-syntax-entry 126 "'")
     (bug-reference-bug-regexp . "<https?://\\(debbugs\\|bugs\\)\\.gnu\\.org/\\([0-9]+\\)>")))
 '(tool-bar-mode nil)
 '(tramp-default-method "ssh")
 '(warning-suppress-types
   '(((defvaralias losing-value geiser-debug-show-debug-p))
     (emacs)
     (comp))))

(put 'list-timers 'disabled nil)

(setq auto-mode-alist (delete (assoc "\\.drv" auto-mode-alist) auto-mode-alist))

;; TODO: Package emacs-rainbow-fart
;; (load (expand-file-name "~/src/emacs-rainbow-fart/rainbow-fart.el") t)
;; (setq rainbow-fart-keyword-interval nil)
;; (setq rainbow-fart-voice-model "built-in-voice-english")

;;; .emacs ends here
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(default ((t (:family "Adwaita Mono" :foundry "UKWN" :slant normal :weight regular :height 98 :width normal))))
 '(highlight-indent-guides-character-face ((t (:foreground "gray15"))))
 '(vterm-color-black ((t (:background "gray15" :foreground "gray15"))))
 '(vterm-color-blue ((t (:background "steel blue" :foreground "steel blue")))))

