;;; EMACS init file -*- lexical-binding:t -*- (eval-and-compile (defconst my-is-nixos (file-exists-p "/nix") "Whether or not Emacs is running on NixOS.")) (when my-is-nixos (setq auth-sources '("/run/agenix/authinfo"))) (require 'cl-lib) (with-eval-after-load 'package (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) (package-initialize)) (setq use-package-always-ensure (not my-is-nixos) use-package-always-defer t use-package-expand-minimally t) (require 'use-package) (let ((emacs-tmp-dir (expand-file-name (format "emacs%d" (user-uid)) temporary-file-directory))) (setq auto-save-file-name-transforms `((".*" ,emacs-tmp-dir t)) auto-save-list-file-prefix emacs-tmp-dir backup-directory-alist (setq undo-tree-history-directory-alist `((".*" . ,emacs-tmp-dir))) org-preview-latex-image-directory (expand-file-name "ltximg" emacs-tmp-dir))) (setq backup-by-copying t inhibit-splash-screen t custom-file (expand-file-name "custom.el" temporary-file-directory)) (defun my-inhibit-hl-line-mode () "Disable `gobal-hl-line-mode' for the current buffer." (setq-local global-hl-line-mode nil)) (use-package f :demand t) (use-package dash :demand t :hook (emacs-lisp-mode . dash-fontify-mode) :init (with-eval-after-load 'info-look (dash-register-info-lookup))) (use-package undo-fu :demand t :config (global-unset-key (kbd "C-/")) (global-unset-key (kbd "C-?")) (global-set-key (kbd "C-/") #'undo-fu-only-undo) (global-set-key (kbd "C-?") #'undo-fu-only-redo)) (use-package god-mode :demand t :bind ("" . god-mode-all) ("ESC ESC ESC" . god-mode-all) ("C-S-h" . help-command) ("C-h" . my--god-del) (:map god-local-mode-map ("i" . god-mode-all) ("" . my--god-c-g) ("ESC ESC ESC" . keyboard-escape-quit) ("z" . repeat) ("q" . my--god-c-q)) (:map minibuffer-local-map ("" . abort-minibuffers) ("ESC ESC ESC" . keyboard-escape-quit)) :custom (god-exempt-major-modes nil) (god-exempt-predicates (list #'god-exempt-mode-p)) (god-mode-enable-function-key-translations nil) (god-mode-alist '((nil . "C-") ("g" . "M-") ("m" . "C-M-"))) :config (defun my--god-c-q () (interactive) (let ((god-local-mode nil)) (if-let* ((buffer-read-only) (ret (key-binding (read-kbd-macro "q"))) ((not (or (eq ret #'self-insert-command) (and (boundp lispy-mode) lispy-mode))))) (call-interactively ret) (switch-to-prev-buffer)))) (cl-macrolet ((define-kmacro-wrapper (name key) `(defun ,name () (interactive) (call-interactively (key-binding (read-kbd-macro ,key)))))) (define-kmacro-wrapper my--god-del "DEL") (define-kmacro-wrapper my--god-c-g "C-g")) (with-eval-after-load 'catppuccin-theme (add-hook 'god-mode-enabled-hook (lambda () (face-spec-set 'cursor `((t (:background ,(catppuccin-get-color 'rosewater))))) (unless (display-graphic-p) (send-string-to-terminal "\e[2 q")))) (add-hook 'god-mode-disabled-hook (lambda () (face-spec-set 'cursor `((t (:background ,(catppuccin-get-color 'mauve))))) (unless (display-graphic-p) ;; Escape codes for hbar cursor in insert mode (send-string-to-terminal "\e[4 q"))))) (god-mode)) (use-package multiple-cursors :bind ("C-S-c" . mc/edit-lines) ("C->" . mc/mark-next-like-this) ("C-<" . mc/mark-previous-like-this) ("C-+" . mc/mark-all-like-this) ("C-|" . mc/mark-pop) ("C-c c" . mc/mark-all-in-region) ("C-c C" . mc/mark-all-in-region-regexp) ("C-c u" . mc/mark-all-like-this-dwim) ("C-c U" . mc/mark-all-dwim) ("C-S-" . mc/add-cursor-on-click) :custom (mc/always-run-for-all t) :init ;; NOTE: For SOME REASON lispy also defvars the mc cmds list to nil when ;; sourced so they need to be modified twice (let ((add-cmds (lambda () (dolist (f '(god-local-mode god-mode-all god-global-mode)) (add-to-list 'mc/cmds-to-run-once f))))) ;; Because multiple-cursors-core is what actually gets autoloaded (eval-after-load 'multiple-cursors-core add-cmds) (eval-after-load 'lispy add-cmds))) (use-package expand-region :bind ("C-=" . er/expand-region)) (use-package avy :bind ("C-'" . avy-goto-char) ("C-," . avy-goto-char-2) ("C-\"" . avy-goto-char-timer) ("M-g f" . avy-goto-line) ("M-g w" . avy-goto-word-1) ("M-g e" . avy-goto-word-0) :custom (avy-timeout-seconds 0.3)) (use-package lispy :hook emacs-lisp-mode ielm-mode lisp-mode scheme-mode clojure-mode :config (add-to-list 'lispy-compat 'god-mode) (add-to-list 'lispy-compat 'magit-blame-mode) (when (boundp 'god-local-mode-map) (push (assoc 'god-local-mode minor-mode-map-alist) minor-mode-map-alist))) (use-package ace-window :bind ("C-c w" . ace-window) :custom (aw-dispatch-always t) (aw-scope 'frame) (aw-keys '(?a ?w ?d ?f ?g ?h ?k ?l)) :config (with-eval-after-load 'catppuccin-theme (face-spec-set 'aw-leading-char-face `((t (:foreground ,(catppuccin-get-color 'crust) :background ,(catppuccin-get-color 'red) :weight bold)))) (face-spec-set 'aw-background-face `((t (:foreground ,(catppuccin-get-color 'overlay1))))))) (use-package goggles :hook prog-mode :config (setq-default goggles-pulse t) (with-eval-after-load 'catppuccin-theme (let ((new-spec `((t (:background ,(catppuccin-get-color 'surface1)))))) (dolist (f '(goggles-added goggles-removed goggles-changed)) (face-spec-set f new-spec)))) (setcar (cdr (assq 'goggles-mode minor-mode-alist)) " O-O")) (defun my--set-tab-width-2 () (setq tab-width 2)) (use-package treesit :ensure nil :mode ("\\.ts\\'" . typescript-ts-mode) ("\\.tsx\\'" . tsx-ts-mode) ("\\.rs\\'" . rust-ts-mode) ("\\.ya?ml\\'" . yaml-ts-mode) ("/Dockerfile\\'" . dockerfile-ts-mode) ("\\(/CMakeLists.txt\\|\\.cmake\\)\\'" . cmake-ts-mode) :hook (typescript-ts-mode . my--set-tab-width-2) (tsx-ts-mode . my--set-tab-width-2) :init (add-to-list 'major-mode-remap-alist '(sh-mode . bash-ts-mode)) (add-to-list 'major-mode-remap-alist '(css-mode . css-ts-mode)) (add-to-list 'major-mode-remap-alist '(c-mode . c-ts-mode)) (add-to-list 'major-mode-remap-alist '(c++-mode . c++-ts-mode)) (add-to-list 'major-mode-remap-alist '(csharp-mode . csharp-ts-mode)) (add-to-list 'major-mode-remap-alist '(java-mode . java-ts-mode)) (add-to-list 'major-mode-remap-alist '(python-mode . python-ts-mode)) (add-to-list 'major-mode-remap-alist '(ruby-mode . ruby-ts-mode)) (add-to-list 'major-mode-remap-alist '(html-mode . html-ts-mode)) (add-to-list 'major-mode-remap-alist '(js-mode . js-ts-mode)) (add-to-list 'major-mode-remap-alist '(js-json-mode . json-ts-mode)) (add-to-list 'major-mode-remap-alist '(conf-toml-mode . toml-ts-mode)) :config (unless my-is-nixos (add-to-list 'treesit-extra-load-path (expand-file-name "tree-sitter-module/dist/" user-emacs-directory)))) (use-package dtrt-indent :demand t :config (setcar (cdr (assq 'dtrt-indent-mode minor-mode-alist)) " dtrt") (dtrt-indent-global-mode)) (use-package aggressive-indent :custom (aggressive-indent-sit-for-time 0.1) :hook emacs-lisp-mode ielm-mode lisp-mode scheme-mode clojure-mode nix-mode) (use-package rainbow-delimiters :hook prog-mode sly-mrepl-mode racket-repl-mode) (use-package highlight-indent-guides :hook prog-mode :custom (highlight-indent-guides-auto-enabled nil) (highlight-indent-guides-method 'character) (highlight-indent-guides-responsive 'stack)) (use-package which-key :demand t :custom (which-key-idle-delay 0.2) :config (with-eval-after-load 'god-mode (which-key-enable-god-mode-support)) (which-key-mode)) (use-package flymake :ensure nil :bind (:map flymake-mode-map ("M-n" . flymake-goto-next-error) ("M-p" . flymake-goto-prev-error))) (use-package eglot :ensure nil :bind (:map eglot-mode-map ("C-c e c" . eglot-code-actions) ("C-c e r" . eglot-rename) ("C-c e f" . eglot-format) ("C-c e s" . eglot-shutdown) ("C-c e S" . eglot-shutdown-all) ("C-c e R" . eglot-reconnect)) :hook (c-mode . eglot-ensure) (c-ts-mode . eglot-ensure) (c++-mode . eglot-ensure) (c++-ts-mode . eglot-ensure) (haskell-mode . eglot-ensure) (java-mode . eglot-ensure) (java-ts-mode . eglot-ensure) (js-mode . eglot-ensure) (js-ts-mode . eglot-ensure) (lua-mode . eglot-ensure) (nix-mode . eglot-ensure) (python-mode . eglot-ensure) (python-ts-mode . eglot-ensure) (rust-ts-mode . eglot-ensure) (typescript-ts-mode . eglot-ensure) (tsx-ts-mode . eglot-ensure) :custom (eglot-events-buffer-size 0) (eglot-autoshutdown t) (eglot-confirm-server-initiated-edits nil) :config (setq-default eglot-workspace-configuration '((haskell (formattingProvider . "floskell"))))) (use-package eglot-booster :ensure nil :after eglot :demand t :custom (eglot-booster-no-remote-boost t) :config (eglot-booster-mode)) (use-package eglot-java :hook java-mode java-ts-mode) (use-package yasnippet :config (advice-add #'yas-expand-snippet :around (lambda (oldfun &rest r) (let ((org-src-tab-acts-natively nil)) (apply oldfun r))) '((name . my--yas-expand-disable-org-tab-native))) (yas-global-mode)) (use-package yasnippet-snippets) (use-package consult :bind ("M-s r" . consult-ripgrep) ("M-s d" . consult-find) ("C-x M-:" . consult-complex-command) ("C-x b" . consult-buffer) ("C-x r b" . consult-bookmark)) (use-package consult-yasnippet :bind ("C-c s" . consult-yasnippet) ("C-c S" . consult-yasnippet-visit-snippet-file)) (use-package embark :bind ("C-." . embark-act) ("C-;" . embark-dwim)) (use-package embark-consult) (use-package orderless :demand t :custom (completion-styles '(orderless basic)) (completion-category-defaults nil) (completion-category-overrides '((file (styles basic partial-completion))))) (use-package marginalia :after vertico :demand t :bind (:map minibuffer-local-map ("M-a" . marginalia-cycle)) :config (marginalia-mode)) (use-package vertico :demand t :config (vertico-mode) (vertico-mouse-mode)) (use-package corfu :demand t :custom (corfu-auto t) (corfu-cycle t) (corfu-preselect-first nil) (corfu-scroll-margin 3) (tab-always-indent 'complete) :config (add-hook 'minibuffer-setup-hook (lambda () (when (where-is-internal #'completion-at-point (list (current-local-map))) (setq-local corfu-echo-display nil corfu-popupinfo-delay nil) (corfu-mode)))) (global-corfu-mode)) (use-package cape) (use-package all-the-icons :demand t) (use-package all-the-icons-completion :after marginalia all-the-icons :hook (marginalia-mode . all-the-icons-completion-marginalia-setup) :init (all-the-icons-completion-mode)) (use-package treemacs) (use-package treemacs-all-the-icons :after treemacs :demand t :config (treemacs-load-theme 'all-the-icons)) (use-package doom-modeline :demand t :custom (doom-modeline-continuous-word-count-modes '(markdown-mode gfm-mode org-mode)) (doom-modeline-enable-word-count t) (doom-modeline-indent-info t) (doom-modeline-minor-modes t) (doom-modeline-battery nil) :config (doom-modeline-mode)) (use-package minions :demand t :config (minions-mode)) (use-package dirvish :after dired :demand t :custom (dired-auto-revert-buffer t) (dirvish-attributes '(all-the-icons)) :config (dirvish-override-dired-mode)) (use-package persp-mode :if nil :bind ("C-c p" . persp-key-map) :custom (persp-keymap-prefix nil) :init (when (daemonp) (require 'persp-mode)) :config (with-eval-after-load 'consult (consult-customize consult--source-buffer :hidden t :default nil) (add-to-list 'consult-buffer-sources (list :name "Perspective" :narrow ?s :category 'buffer :state #'consult--buffer-state :history 'buffer-name-history :default t :items (lambda () (consult--buffer-query :sort 'visibility :predicate (lambda (buf) (memq buf (persp-buffer-list))) :as #'buffer-name))))) (persp-mode)) (use-package alert :ensure nil :custom (alert-default-style 'libnotify) (alert-libnotify-command (expand-file-name "scripts/emacs-hyprland-notify" user-emacs-directory))) (use-package pdf-tools :mode ("\\.pdf\\'" . pdf-view-mode) :bind (:map pdf-view-mode-map ("/" . #'isearch-forward)) :config (pdf-tools-install)) (defun my-double-space-sentence () (setq-local sentence-end-double-space t)) (use-package engrave-faces) (use-package org :hook (org-mode . auto-fill-mode) (org-mode . my-inhibit-hl-line-mode) (org-mode . my-double-space-sentence) :custom (org-startup-with-inline-images t) (org-special-ctrl-a/e t) (org-insert-heading-respect-content t) (org-list-allow-alphabetical t) (org-hide-emphasis-markers t) (org-pretty-entities t) (org-babel-load-languages '((emacs-lisp . t) (ruby . t) (python . t) (shell . t) (C . t))) (org-agenda-files '("~/Agenda")) ;; NixOS minimal LaTeX setup (org-latex-compiler "lualatex") (org-preview-latex-default-process 'dvisvgm) (org-latex-src-block-backend 'engraved) :config (setq org-format-latex-options (plist-put org-format-latex-options :scale 1.1) org-modules (append '(org-tempo org-habit) org-modules)) (with-eval-after-load 'catppuccin-theme (face-spec-set 'org-block `((t (:foreground ,(catppuccin-get-color 'text))))))) (use-package org-alert :init (when (daemonp) (run-with-idle-timer 10 nil #'require 'org-alert)) :config (setq org-alert-notification-title "org-alert" org-alert-notify-cutoff 30) (org-alert-enable)) (use-package org-modern :hook org-mode (org-agenda-finalize . org-modern-agenda) :config (with-eval-after-load 'catppuccin-theme (face-spec-set 'org-modern-done `((t (:foreground ,(catppuccin-get-color 'text) :background ,(catppuccin-get-color 'surface0))))) (face-spec-set 'org-modern-date-inactive `((t (:foreground ,(catppuccin-get-color 'subtext0) :background ,(catppuccin-get-color 'surface0))))) (face-spec-set 'org-modern-horizontal-rule `((t (:strike-through ,(catppuccin-get-color 'overlay1))))) (face-spec-set 'org-modern-tag `((t (:foreground ,(catppuccin-get-color 'base) :background ,(catppuccin-get-color 'sapphire))))) (face-spec-set 'org-modern-time-active `((t (:foreground ,(catppuccin-get-color 'base) :background ,(catppuccin-get-color 'overlay2))))) (face-spec-set 'org-modern-time-inactive `((t (:foreground ,(catppuccin-get-color 'base) :background ,(catppuccin-get-color 'surface0))))))) (use-package org-modern-indent :ensure nil :hook org-modern-mode) (use-package djvu) (use-package nov :mode ("\\.epub\\'" . nov-mode)) (use-package org-pdftools :hook (org-mode . org-pdftools-setup-link)) (use-package editorconfig :demand t :config (editorconfig-mode) (setcar (cdr (assq 'editorconfig-mode minor-mode-alist)) " EdConf")) (use-package envrc :bind ("C-c v" . envrc-command-map) :hook (after-init . envrc-global-mode)) (use-package sly :custom (sly-symbol-completion-mode nil) :config (setq inferior-lisp-program "sbcl") (defun my--sly-add-project-root-to-asdf (old-init) (let ((dir (if-let* ((proj (project-current)) (root (project-root proj))) root default-directory))) (if (directory-files dir nil "\\.asd\\'" t 1) (let ((old-init-list (read old-init))) (setf (cddadr old-init-list) (cons `(push (pathname ,(sly-to-lisp-filename dir)) (symbol-value (read-from-string "asdf:*central-registry*"))) (cddadr old-init-list))) (format "%S\n\n" old-init-list)) old-init))) (advice-add #'sly-init-using-asdf :filter-return #'my--sly-add-project-root-to-asdf) (sly-setup)) (use-package sly-asdf) (use-package sly-named-readtables) (use-package racket-mode :hook (racket-mode . racket-xp-mode)) (use-package haskell-mode :hook (haskell-mode . interactive-haskell-mode) :custom (haskell-process-show-debug-tips nil)) (use-package lua-mode :custom (lua-indent-level 4) (lua-indent-nested-block-content-align nil) (lua-indent-close-paren-align nil)) (use-package nix-mode) (use-package markdown-mode :mode ("README\\.md\\'" . gfm-mode) :custom (markdown-command '("pandoc" "--from=markdown" "--to=html5"))) (use-package csv-mode) (use-package meson-mode) (use-package jinx :hook text-mode) (use-package minimap :custom-face (minimap-active-region-background ((t (:background unspecified :inherit hl-line)))) :hook (minimap-sb-mode . turn-on-solaire-mode)) (use-package magit :hook (git-commit-setup . git-commit-turn-on-auto-fill)) (use-package forge :after magit :demand t) (use-package tramp :custom (remote-file-name-inhibit-cache nil) (tramp-verbose 1) :config (setq vc-ignore-dir-regexp (format "%s\\|%s" vc-ignore-dir-regexp tramp-file-name-regexp))) (use-package eat :bind ("C-c t" . eat) (:map eat-mode-map ("" . eat-self-input)) :hook (eat-mode . my-inhibit-hl-line-mode) :config (with-eval-after-load 'god-mode (add-to-list 'god-exempt-major-modes 'eat-mode))) (use-package circe :hook (circe-channel-mode . enable-lui-autopaste) :custom (circe-default-nick "eriedaberrie") (circe-default-user "eriedaberrie") (circe-default-realname "eriedaberrie") (circe-format-self-say ">>> {body}") (lui-time-stamp-position 'right-margin) (lui-fill-type nil) (lui-time-stamp-format "%T") :config (--when-let (nth 0 (auth-source-search :max 1 :require '(:user :secret) :host "irc.libera.chat" :port 6697)) (let ((user (plist-get it :user)) (secret (plist-get it :secret))) (setq circe-network-options `(("Libera Chat" :tls t :nick ,user :sasl-username ,user :sasl-password ,(if (functionp secret) (funcall secret) secret) :channels ("#emacs" "#nixos" "#lisp" "#commonlisp")))))) (add-hook 'lui-mode-hook (lambda () (visual-line-mode) (setq-local fringes-outside-margins t right-margin-width 8 wrap-prefix " ") (setcdr (assoc 'continuation fringe-indicator-alist) nil)))) (use-package circe-notifications :hook (circe-server-connected . enable-circe-notifications)) (use-package mpv) (use-package lingva :custom (lingva-instance "lingva.garudalinux.org")) (use-package mastodon :custom (mastodon-instance-url "https://fosstodon.org") (mastodon-active-user "eriedaberrie") (mastodon-toot-timestamp-format "%F %-I:%M %p")) (use-package elfeed :custom (elfeed-feeds '(("https://archlinux.org/feeds/news/" arch-linux) ("https://nixos.org/blog/announcements-rss.xml" nixos)))) (use-package xkcd) (use-package page-break-lines :hook emacs-lisp-mode lisp-mode scheme-mode compilation-mode outline-mode help-mode) (use-package hl-todo :hook prog-mode) (use-package gruvbox-theme) (use-package catppuccin-theme :demand t :custom-face (line-number-current-line ((t (:inherit (hl-line default))))) :custom (catppuccin-flavor 'mocha) (catppuccin-highlight-matches t) (catppuccin-italic-comments t) (catppuccin-italic-blockquotes t) (catppuccin-italic-variables t)) (defun my-load-theme-with-solaire () (load-theme 'catppuccin t) (catppuccin-reload) (face-spec-set 'font-lock-variable-name-face `((t (:foreground ,(catppuccin-get-color 'flamingo))))) (solaire-global-mode) (when (daemonp) (remove-hook 'server-after-make-frame-hook #'my-load-theme-with-solaire))) (use-package solaire-mode :demand t :custom (solaire-mode-real-buffer-fn (lambda () (and (solaire-mode-real-buffer-p) (or (custom-theme-enabled-p 'gruvbox) (not (memq 'minimap-sb-mode local-minor-modes)))))) :config (if (daemonp) (add-hook 'server-after-make-frame-hook #'my-load-theme-with-solaire) (my-load-theme-with-solaire))) (use-package with-editor :bind ([remap async-shell-command] . with-editor-async-shell-command) ([remap shell-command] . with-editor-shell-command) :hook (shell-mode . with-editor-export-editor) (eshell-mode . with-editor-export-editor) (term-exec . with-editor-export-editor)) (use-package nyan-mode :custom (nyan-animate-nyancat t) (nyan-wavy-trail t)) (use-package smtpmail :ensure nil :custom (smtpmail-smtp-service 587) (smtpmail-stream-type 'starttls) (smtpmail-default-smtp-server "smtp.gmail.com") (message-send-mail-function #'smtpmail-send-it) (message-citation-line-function #'message-insert-formatted-citation-line) (message-kill-buffer-on-exit t)) (use-package mu4e :if my-is-nixos :ensure nil :bind ("C-c m m" . mu4e) ("C-c m c" . mu4e-compose-new) ("C-c m u" . mu4e-update-mail-and-index) :hook (mu4e-view-mode . my-inhibit-hl-line-mode) (message-mode . my-double-space-sentence) :custom (mail-user-agent 'mu4e-user-agent) (mu4e-get-mail-command "mbsync -a") (mu4e-sent-messages-behavior 'delete) (mu4e-change-filenames-when-moving t) (mu4e-view-show-images t) (mu4e-use-fancy-chars t) (mu4e-attachment-dir "~/Downloads") (mu4e-context-policy 'ask) (mu4e-compose-context-policy 'ask-if-none) (mu4e-confirm-quit nil) (mu4e-completing-read-function #'completing-read) :init (let ((age-file "/run/agenix/email.json")) (when (file-exists-p age-file) (defvar my--agenix-email-json-data (with-temp-buffer (insert-file-contents age-file) (json-parse-buffer :object-type 'alist))) (pcase-let ((`((address . ,address) (name . ,name) ,_) (alist-get 'personal my--agenix-email-json-data))) (setq user-mail-address address user-full-name name)))) :config (when (boundp 'my--agenix-email-json-data) (setq mu4e-contexts (--map (pcase-let ((`(,type (address . ,address) (name . ,name) ,_) it)) (make-mu4e-context :name (symbol-name type) :enter-func (lambda () (mu4e-message (format "Entering \"%s\" context" type))) :leave-func (lambda () (mu4e-message (format "Leaving \"%s\" context" type))) :match-func (lambda (msg) (when msg (mu4e-message-contact-field-matches msg :to address))) :vars (cl-labels ((folder-name (folder-type) (format "/%s/[Gmail]/%s" type folder-type))) `((user-mail-address . ,address) (user-full-name . ,name) (mu4e-drafts-folder . ,(folder-name "Drafts")) (mu4e-sent-folder . ,(folder-name "Sent Mail")) (mu4e-trash-folder . ,(folder-name "Trash")) (smtpmail-smtp-server . "smtp.gmail.com") (smtpmail-smtp-user . ,address))))) my--agenix-email-json-data))) (when (fboundp 'imagemagick-register-types) (imagemagick-register-types))) (use-package org-msg :after message :demand t :custom (org-msg-convert-citation t) (org-msg-greeting-fmt "\nHi%s,\n\n")) (use-package emacs-everywhere :custom (emacs-everywhere-app-info-function (lambda () (let* ((string-data (emacs-everywhere-call "hyprctl" "-j" "activewindow")) (window-data (json-parse-string string-data :object-type 'plist :array-type 'list :null-object nil :false-object nil)) (window-id (plist-get window-data :address)) (app-id (plist-get window-data :class)) (window-title (plist-get window-data :title)) (window-geometry (append (plist-get window-data :at) (plist-get window-data :size)))) (make-emacs-everywhere-app :id window-id :class app-id :title window-title :geometry window-geometry)))) (emacs-everywhere-window-focus-command '("hyprctl" "dispatch" "focuswindow" "address:%w")) :config (dolist (f '((alpha-background . 1.0) (width . 120) (height . 20))) (add-to-list 'emacs-everywhere-frame-parameters f))) (use-package prettify-symbols :ensure nil :hook prog-mode org-mode :custom (prettify-symbols-unprettify-at-point t)) (use-package electric-pair-mode :ensure nil :hook (prog-mode . electric-pair-local-mode) (eval-expression-minibuffer-setup . electric-pair-local-mode) (sly-mrepl-mode . electric-pair-local-mode) (racket-repl-mode . electric-pair-local-mode)) (use-package ffap :ensure nil :demand t :config (ffap-bindings)) (use-package eldoc :ensure nil :custom (eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly)) (use-package ibuffer :ensure nil :bind ("C-x C-b" . ibuffer)) (use-package info :ensure nil :hook (Info-mode . my-inhibit-hl-line-mode)) (use-package tool-bar :ensure nil :config (tool-bar-mode 0)) (use-package menu-bar :ensure nil :config (menu-bar-mode 0)) (use-package scroll-bar :ensure nil :config (scroll-bar-mode 0)) (setq pixel-scroll-precision-large-scroll-height 40 fast-but-imprecise-scrolling t) (pixel-scroll-precision-mode) (setcar mouse-wheel-scroll-amount 3) (setq server-client-instructions nil scroll-step 1 scroll-margin 8 scroll-conservatively 9999 python-indent-guess-indent-offset nil read-file-name-completion-ignore-case t read-buffer-completion-ignore-case t completion-ignore-case t sentence-end-double-space nil custom-safe-themes t x-stretch-cursor t) (setq-default c-basic-offset 4 c-ts-mode-indent-offset 4 json-ts-mode-indent-offset 4 sgml-basic-offset 4 tab-width 4 fill-column 78) ;; Because python-mode sets tab-width to 8 for some reason (add-hook 'python-mode-hook (lambda () (setq tab-width 4))) (column-number-mode) (size-indication-mode) (global-hl-line-mode) (defun my-relative-linenum (&optional toggle) "Simply enables relative line numbers." (interactive "p") (setq display-line-numbers (if (and toggle display-line-numbers) nil 'relative))) (dolist (hook '(prog-mode-hook conf-mode-hook)) (add-hook hook #'my-relative-linenum)) (defun my-use-spaces-for-indent () "Simply turn off `indent-tabs-mode'." (setq indent-tabs-mode nil)) (dolist (hook '(emacs-lisp-mode-hook lisp-mode-hook scheme-mode-hook clojure-mode-hook)) (add-hook hook #'my-use-spaces-for-indent)) (add-hook 'text-mode-hook #'word-wrap-whitespace-mode) (add-hook 'text-mode-hook #'visual-line-mode) (defun scroll-down-3 () "Scroll down by 3." (interactive) (scroll-down 3)) (defun scroll-up-3 () "Scroll up by 3." (interactive) (scroll-up 3)) (defun my-frame-make-detect-term (&optional frame) "Check when FRAME are made in order to make terminal-only configurations." (unless (display-graphic-p frame) (xterm-mouse-mode) (global-set-key (kbd "") #'scroll-down-3) (global-set-key (kbd "") #'scroll-up-3) (remove-hook 'after-make-frame-functions #'my-frame-make-detect-term))) (if (daemonp) (add-to-list 'after-make-frame-functions #'my-frame-make-detect-term) (my-frame-make-detect-term)) (defun my-sudo-edit () "Edit current file as root." (interactive) (unless (and buffer-file-name (file-writable-p buffer-file-name)) (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name)))) (setq auto-mode-alist (append '(("\\.yuck\\'" . lisp-mode) ("/flake\\.lock\\'" . js-json-mode)) auto-mode-alist '(("/qutebrowser-editor-" . text-mode)))) (when (daemonp) (with-current-buffer "*scratch*" (cd "~/"))) (defvar my-ac-previous-status t "Whether connected to AC during last check.") (require 'battery) (defun my-bat-check () "Check if battery status has changed. Used to toggle `goggles-pulse', `pixel-scroll-precision-mode', and `nyan-mode'." (let ((ac-status (not (string= (cdr (assq ?B (funcall battery-status-function))) "discharging")))) (unless (eq ac-status my-ac-previous-status) (setq my-ac-previous-status ac-status) (when (boundp 'goggles-pulse) (setq goggles-pulse ac-status)) (when nyan-mode (if ac-status (nyan-start-animation) (nyan-stop-animation))) (setq nyan-animate-nyancat ac-status nyan-wavy-trail ac-status) (pixel-scroll-precision-mode (if ac-status 1 0))))) (when battery-status-function (run-with-timer 0 30 #'my-bat-check))