;;; init.el --- Description -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2023 Daniel Ziltener ;; ;; Author: Daniel Ziltener ;; Maintainer: Daniel Ziltener ;; Created: November 13, 2023 ;; Modified: November 13, 2023 ;; Version: 0.0.1 ;; Keywords: abbrev bib c calendar comm convenience data docs ;; emulations extensions faces files frames games hardware help ;; hypermedia i18n internal languages lisp local maint mail matching ;; mouse multimedia news outlines processes terminals tex tools unix ;; vc wp ;; Homepage: https://gitea.lyrion.ch/zilti/guixconfig ;; Package-Requires: ((emacs "29.1")) ;; ;; This file is not part of GNU Emacs. ;; ;;; Commentary: ;; ;; Description ;; ;;; Code: ;;; Requirements ;; Since I am using `cl-defun` in this init file, I need to require ;; `cl-macs`. (require 'cl-macs) ;;; Early Variables (setq custom-file "~/.config/emacs/custom.el") (when (file-exists-p custom-file) (load custom-file)) (defvar init-dir (file-name-directory (or load-file-name (buffer-file-name)))) ;;; Package Management ;;;; Repositories (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (package-initialize) ;;;; VC ;; This will be unnecessary starting at Emacs 30 (unless (package-installed-p 'vc-use-package) (package-vc-install "https://github.com/slotThe/vc-use-package")) (setopt use-package-always-ensure t) (require 'vc-use-package) ;;; Personal Information Setup (setq user-full-name "Daniel Ziltener" user-mail-address "dziltener@lyrion.ch") ;; I use `pass` as password storage. (auth-source-pass-enable) ;;; Package Management Configuration ;; See: https://github.com/radian-software/el-patch (use-package el-patch) ;;;; Guix Management (use-package guix :after magit-popup) ;;; Helper Functions (cl-defun conditional-keybind (filter-fn target-fn &optional (fail-fn #'self-insert-command)) "Creates a keybinding that checks `filter-fn`. If it succeeds, `target-fn` is run, otherwise `fail-fn`. If no fail-fn is given, `self-insert-command` is run instead. `target-fn` and `fail-fn` must both be interactive." (lambda (_prefix) (interactive "P") (if (funcall filter-fn) (call-interactively target-fn) (call-interactively fail-fn)))) ;;; Emacs (use-package emacs :after org :custom (completion-cycle-threshold 10) (display-time-mode t) (enable-recursive-minibuffers t) (enable-remote-dir-locals t) (fill-column 100) (global-hl-line-mode t) (global-prettify-symbols-mode t) (indent-tabs-mode nil) (menu-bar-mode nil) (minibuffer-prompt-properties (read-only t cursor-intangible t face minibuffer-prompt)) (native-comp-async-report-warnings-errors nil) (display-warning-minimum-level :error) (warning-suppress-types '(emacs)) (read-extended-command-predicate #'command-completion-default-include-p) (recentf-mode t) (pixel-scroll-precision-large-scroll-height 30) (scroll-bar-mode nil) (tab-always-indent 'complete) (tool-bar-mode nil) (newsticker-url-list-defaults nil) (newsticker-url-list '(("Tagesschau" "https://www.tagesschau.de/index~atom.xml" nil nil nil) ("NZZ Neuste" "https://www.nzz.ch/recent.rss" nil nil nil) ("SRF News" "https://www.srf.ch/news/bnf/rss/1646" nil nil nil) ("SRF Wissen" "https://www.srf.ch/bnf/rss/630" nil nil nil) ("Deutschlandfunk Nachrichten" "https://www.deutschlandfunk.de/nachrichten-100.rss" nil nil nil) ("Deutschlandfunk Wissen" "https://www.deutschlandfunk.de/wissen-106.rss" nil nil nil) ("RBB" "https://www.rbb24.de/aktuell/index.xml/feed=rss.xml" nil nil nil) ("Guix" "https://guix.gnu.org/feeds/blog.atom" nil nil nil) ("Mastering Emacs" "https://www.masteringemacs.org/feed" nil nil nil) ("Schiene.de" "https://www.schiene.de/feed/" nil nil nil) ("Anil Dash Blog" "https://www.anildash.com/feed.xml" nil nil nil) ("Karl Voit's Blog" "https://karl-voit.at/feeds/lazyblorg-all.atom_1.0.links-and-content.xml" nil nil nil) ("Vaxry's Blog" "https://blog.vaxry.net/feed" nil nil nil))) :custom-face (default ((t (:weight normal :height 110 :family "MonaspiceXe Nerd Font Mono")))) (fixed-pitch ((t (:weight normal :height 110 :family "MonaspiceXe Nerd Font Mono")))) (variable-pitch ((t (:weight normal :height 135 :family "MonaspiceXe Nerd Font Propo")))) :hook (minibuffer-setup . cursor-intangible-mode) :config (setq xref-backend-functions (list)) (advice-add 'risky-local-variable-p :override #'ignore) (global-display-fill-column-indicator-mode t) (pixel-scroll-precision-mode 1)) (defun set-buffer-variable-pitch () (interactive) (variable-pitch-mode t) (setq line-spacing 3) (set-face-attribute 'org-table nil :inherit 'fixed-pitch) (set-face-attribute 'org-code nil :inherit 'fixed-pitch) (set-face-attribute 'org-block nil :inherit 'fixed-pitch) ;; investigate: this face does not exist ;;(set-face-attribute 'org-block-background nil :inherit 'fixed-pitch) ) (use-package outline-minor :ensure nil :bind (:map evil-normal-state-map ("zoc" . #'outline-cycle-buffer)) :hook clojure-mode scheme-mode emacs-lisp-mode) ;;; Org Mode (use-package org :vc (:fetcher "https://git.savannah.gnu.org/git/emacs/org-mode.git" :rev "emacs-sync") :preface (defun cc/org-local-stuff () (setq-local visual-fill-column-center-text t)) :after visual-fill-column :custom (org-babel-load-languages '((emacs-lisp . t) (scheme . t) (shell . t))) :hook (org-mode . org-indent-mode) (org-src-mode . hack-local-variables) (org-mode . visual-line-mode) (org-mode . set-buffer-variable-pitch) :config (setq org-directory "~/org") ;;(add-to-list 'org-modules 'collector) ) (use-package org-roam :custom (org-roam-directory "~/org/roam") :config (org-roam-db-autosync-mode)) (use-package consult-notes :config (consult-notes-org-roam-mode t)) (use-package websocket :after org-roam) (use-package org-roam-ui :after org-roam :custom (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)) (use-package org-modern :hook (org-mode . org-modern-mode) (org-agenda-finalize . org-modern-agenda)) (use-package org-rainbow-tags :hook (org-mode . org-rainbow-tags-mode)) ;;; Design (use-package color-theme-modern) (use-package moe-theme) (use-package catppuccin-theme :custom (catppuccin-flavor 'mocha) (catppuccin-highlight-matches t) (catppuccin-italic-comments t) :custom-face (font-lock-doc-face ((t (:inherit font-lock-comment-face :foreground "#fab387")))) :config ;;(load-theme 'catppuccin) ) (use-package unicode-fonts :config (unicode-fonts-setup)) (set-frame-parameter nil 'alpha-background 90) (add-to-list 'default-frame-alist '(alpha-background . 90)) (use-package lambda-line :vc (:fetcher github :repo "lambda-emacs/lambda-line") :custom (lambda-line-icon-time t) ;; requires ClockFace font (see below) (lambda-line-clockface-update-fontset "ClockFaceRect") ;; set clock icon (lambda-line-position 'bottom) ;; Set position of status-line (lambda-line-abbrev t) ;; abbreviate major modes (lambda-line-hspace " ") ;; add some cushion (lambda-line-prefix t) ;; use a prefix symbol (lambda-line-prefix-padding nil) ;; no extra space for prefix (lambda-line-status-invert nil) ;; no invert colors (lambda-line-gui-ro-symbol " ⨂") ;; symbols (lambda-line-gui-mod-symbol " ⬤") (lambda-line-gui-rw-symbol "  ") (lambda-line-vc-symbol "  ") (lambda-line-space-top +.50) ;; padding on top and bottom of line (lambda-line-space-bottom -.50) (lambda-line-symbol-position 0.1) ;; adjust the vertical placement of symbol :config ;; add evil indicator (advice-add 'lambda-line-compose :around (lambda (orig-fun status name primary tertiary secondary) (funcall orig-fun status (concat name evil-mode-line-tag) primary tertiary secondary))) ;; activate lambda-line (lambda-line-mode) (lambda-line-clockface-update-fontset "ClockFaceRect") (customize-set-variable 'flymake-mode-line-counter-format '("" flymake-mode-line-error-counter flymake-mode-line-warning-counter flymake-mode-line-note-counter "")) (customize-set-variable 'flymake-mode-line-format '(" " flymake-mode-line-exception flymake-mode-line-counters)) ;; set divider line in footer (when (eq lambda-line-position 'top) (setq-default mode-line-format (list "%_")) (setq mode-line-format (list "%_")))) (use-package lambda-themes :vc (:fetcher github :repo "lambda-emacs/lambda-themes") :custom (lambda-themes-set-italic-comments t) (lambda-themes-set-italic-keywords t) (lambda-themes-set-variable-pitch t) :config ;; load preferred theme (load-theme 'lambda-dark)) ;;;; Long line handling (use-package visual-fill-column :custom (visual-fill-column-enable-sensible-window-split t) :hook (prog-mode . visual-line-mode) visual-line-mode ;; :config ;; (add-hook 'prog-mode-hook #'visual-line-mode) ;; (add-hook 'visual-line-mode-hook #'visual-fill-column-mode) ) (use-package adaptive-wrap :config (setq-default adaptive-wrap-extra-indent 4) ;;(add-hook 'visual-line-mode-hook #'adaptive-wrap-prefix-mode) :hook (visual-line-mode . adaptive-wrap-prefix-mode)) (use-package password-store) (use-package password-store-otp) (use-package pass) ;;; Evil Mode (use-package evil :init (setq evil-want-keybinding nil evil-emacs-state-tag " 󰯸 " evil-normal-state-tag " 󰰓 " evil-visual-state-tag " 󰰬 " evil-insert-state-tag " 󰰅 " evil-motion-state-tag " 󰬔 " evil-operator-state-tag " 󰰕 ") :config (evil-set-leader 'normal (kbd "")) (evil-set-leader 'normal (kbd "z") t) (evil-ex-define-cmd "q" 'delete-frame) (evil-mode 1) :bind (:map evil-normal-state-map ("f" . 'find-file) ("k" . 'kill-buffer))) (use-package evil-collection :after evil :ensure t :delight evil-collection-unimpaired-mode :custom (evil-collection-outline-bind-tab-p 1) :commands evil-collection-init :init (evil-collection-init)) ;;; Search, Completion, Execution ;;;; Preliminary Packages (use-package savehist :ensure nil :init (savehist-mode)) (use-package orderless :after consult :config (with-eval-after-load 'eglot (setq completion-category-defaults nil)) (setq completion-styles '(orderless basic) completion-category-defaults nil completion-category-overrides '((file (styles basic partial-completion))))) (use-package embark-consult :hook (embark-collect-mode . consult-preview-at-point-mode) :config (require 'consult-flymake) (require 'consult-xref) :custom (xref-show-xrefs-function #'consult-xref) :bind (:map evil-normal-state-map ("" . 'consult-find) ("gs" . 'consult-eglot-symbols) ("b" . 'consult-buffer) ("gb" . 'consult-project-buffer) ("g/" . 'consult-git-grep) ("/" . 'consult-grep) ("/" . 'consult-line)) ("C-" . 'embark-act) ("C-M-" . 'embark-bindings)) (use-package wgrep :config (setq wgrep-auto-save-buffer t)) (use-package vertico :commands vertico-mode :init (vertico-mode)) (use-package marginalia :commands marginalia-mode :init (marginalia-mode)) (use-package nerd-icons-completion :after marginalia :commands nerd-icons-completion-mode :hook (marginalia-mode-hook . nerd-icons-completion-marginalia-setup) :init (nerd-icons-completion-mode)) (use-package which-key :commands which-key-setup-minibuffer :init (which-key-setup-minibuffer) :config (which-key-mode t)) ;;;; Code Completion (use-package cape :config (require 'cape-char) (require 'cape-keyword) (defun my/capf () (setq completion-at-point-functions (list (cape-capf-super #'tempel-complete #'cape-dabbrev #'cape-file #'cape-dict #'cape-line #'cape-emoji #'cape-keyword)))) (defun my/eglot-capf () (setq completion-at-point-functions (list (cape-capf-super #'eglot-completion-at-point #'tempel-complete #'cape-dabbrev #'cape-file #'cape-dict #'cape-line #'cape-emoji #'cape-keyword)))) (defun my/geiser-capf () (setq completion-at-point-functions (list (apply #'cape-capf-super (append geiser-capf--capfs (list #'tempel-complete #'cape-dabbrev #'cape-file #'cape-dict #'cape-line #'cape-emoji #'cape-keyword)))))) (advice-add 'eglot-completion-at-point :around #'cape-wrap-buster) :hook (org-mode . my/capf) (prog-mode . my/capf) (eglot-managed-mode . my/eglot-capf) (geiser-mode . my/geiser-capf)) (defun my/corfu-combined-sort (candidates) "Sort CANDIDATES using both display-sort-function and corfu-sort-function." (let ((candidates (let ((display-sort-func (corfu--metadata-get 'display-sort-function))) (if display-sort-func (funcall display-sort-func candidates) candidates)))) (if corfu-sort-function (funcall corfu-sort-function candidates) candidates))) (use-package corfu :custom (corfu-cycle t) (corfu-preselect 'prompt) (corfu-auto t) (corfu-scroll-margin 5) (corfu-quit-no-match 'separator) (evil-collection-corfu-key-themes '(tab-n-go)) (corfu-popupinfo-delay '(0.1 . 0.5)) :config (setq corfu-sort-override-function #'my/corfu-combined-sort) (add-to-list 'savehist-additional-variables 'corfu-history) :commands global-corfu-mode :init (require 'corfu-popupinfo) (require 'corfu-history) (global-corfu-mode) (corfu-popupinfo-mode 1) (corfu-history-mode 1)) (use-package nerd-icons-corfu :after corfu :init (add-to-list 'corfu-margin-formatters 'nerd-icons-corfu-formatter)) (use-package corfu-terminal :if (not (display-graphic-p)) :after corfu :hook global-corfu-mode) (use-package tempel) (use-package xref-union :custom (xref-union-excluded-backends (lambda (b) (eq b #'etags--xref-backend))) :hook cider-mode) ;;; Basic Navigation (use-package goto-chg :bind (:map evil-normal-state-map ("g," . 'goto-last-change) ("g;" . 'goto-last-change-reverse))) (use-package evil-snipe :after evil-easymotion :custom (evil-snipe-scope 'whole-visible) (evil-snipe-repeat-scope 'whole-buffer) (evil-snipe-spillover-scope 'whole-buffer) (evil-snipe-tab-increment t) :commands evil-snipe-override-mode :init (evil-snipe-override-mode 1) :hook (magit-mode . turn-off-evil-snipe-override-mode) ;; See https://github.com/hlissner/evil-snipe/issues/95 ;; :config ;; (evilem-define "gs" 'evil-snipe-repeat ;; :bind ((evil-snipe-scope 'buffer) ;; (evil-snipe-enable-highlight) ;; (evil-snipe-enable-incremental-highlight))) ) (use-package evil-easymotion :after evil :config (evilem-default-keybindings "")) ;;; Lisp Navigation and Editing ;;;; Helper Functions (defun cc/move-sexp-backward () "Move balanced expression (sexp) to the right of point backward one sexp. Point must be at the beginning of balanced expression (sexp)." (interactive) (transpose-sexps 1) (forward-sexp -2)) (defun cc/move-sexp-forward () "Move balanced expression (sexp) to the right of point forward one sexp. Point must be at the beginning of balanced expression (sexp)." (interactive) (forward-sexp 1) (transpose-sexps 1) (forward-sexp -1)) (defvar last-sexp nil) (defun cc/clone-sexp () "Clone the sexp right after the cursor." (interactive) (call-interactively #'mark-sexp) (call-interactively #'kill-ring-save) (call-interactively #'evil-paste-before) (call-interactively #'forward-char) (call-interactively #'paredit-newline)) (defun cc/slurp-forward () "Slurps forward when the key is after the closing paren." (interactive) (call-interactively #'backward-char) (call-interactively #'paredit-forward-slurp-sexp)) (defun cc/barf-forward () "Barfs forward even when the key is after the closing paren." (interactive) (call-interactively #'backward-char) (call-interactively #'paredit-forward-barf-sexp)) (defun looking-at-opening-paren () (looking-at (rx (or "(" "{" "[")))) (defun being-past-closing-paren () (looking-back (rx (or ")" "}" "]")))) ;;;; Basic (use-package paredit :config ;; (add-hook 'clojure-ts-mode-hook #'paredit-mode) ;; (add-hook 'emacs-lisp-mode-hook #'paredit-mode) ;; (add-hook 'scheme-mode-hook #'paredit-mode) (evil-define-key 'insert paredit-mode-map (kbd "r") (conditional-keybind #'looking-at-opening-paren #'paredit-raise-sexp) (kbd "w") (conditional-keybind #'looking-at-opening-paren #'cc/move-sexp-backward) (kbd "s") (conditional-keybind #'looking-at-opening-paren #'cc/move-sexp-forward) (kbd "c") (conditional-keybind #'looking-at-opening-paren #'cc/clone-sexp) (kbd ">") (conditional-keybind #'being-past-closing-paren #'cc/slurp-forward) (kbd "<") (conditional-keybind #'being-past-closing-paren #'cc/barf-forward)) :hook clojure-ts-mode clojure-mode emacs-lisp-mode scheme-mode) ;;;; Visual Aid ;; (use-package rainbow-delimiters ;; :hook ;; emacs-lisp-mode ;; scheme-mode) ;;; Programming (use-package editorconfig :delight editorconfig-mode :commands editorconfig-mode :init (editorconfig-mode 1)) (use-package flymake :ensure nil :delight '(:eval (cons "  " (flymake--mode-line-counters)))) (use-package eglot :ensure nil :custom (eglot-connect-timeout 90) (eglot-autoshutdown t) (eglot-report-progress t) :config ;;(add-to-list 'eglot-server-programs '(scheme-mode . ("chicken-lsp-server"))) (setq-default eglot-workspace-configuration '((clojure-lsp (maxCompletions . 300)))) :hook (clojure-mode . eglot-ensure) ;; (eglot-managed-mode . (lambda () ;; (add-hook 'before-save-hook ;; (lambda () ;; (call-interactively #'eglot-format-buffer)) ;; nil 'local))) (eglot-managed-mode . eglot-inlay-hints-mode)) (use-package consult-eglot :after (consult eglot)) (use-package dape :custom (dape-buffer-window-arrangement 'gud) :hook (kill-emacs . dape-breakpoint-save) (after-init . dape-breakpoint-load) (dape-compile . kill-buffer) (dape-display-source . pulse-momentary-highlight-one-line)) ;;;; Clojure (use-package clojure-mode :preface (defun embark-eglot-rename (from to) "Renames the symbol at point." (interactive "sRename: \nsRename %s to: ") (funcall-interactively #'eglot-rename to)) :delight "" :after (embark cider) :config (defvar-keymap embark-clj-identifier-map :parent embark-identifier-map "c" #'embark-eglot-rename) (add-to-list 'embark-keymap-alist '(identifier . embark-clj-identifier-map)) :hook (clojure-mode . (lambda () (setq-local prettify-symbols-alist '(("fn" . "λ") ("comp" . "∘") ("and" . "∧") ("or" . "∨") ("not" . "¬")))))) (use-package cider ;;:elpaca (:host github :repo "clojure-emacs/cider" :tag "v1.12.0") :delight (cider-mode '(:eval (concat "  [" (cider--modeline-info) "]"))) :config (evil-define-key 'normal 'cider-mode-map (kbd "ce") #'cider-eval-sexp-at-point)) ;;;; Scheme (use-package geiser :custom (geiser-chicken-match-limit 200) :config (defalias 'run-geiser 'geiser)) ;; (use-package paren-face ;; :hook ;; scheme-mode ;; emacs-lisp-mode ;; clojure-ts-mode ;; ;; :config ;; ;; (add-hook 'scheme-mode-hook #'paren-face-mode) ;; ;; (add-hook 'emacs-lisp-mode-hook #'paren-face-mode) ;; ;; (add-hook 'clojure-ts-mode-hook #'paren-face-mode) ;; ) (use-package highlight-parentheses :custom (highlight-parentheses-highlight-adjacent t) (highlight-parentheses-colors '("yellow" "light gray" "dark gray" "dim gray")) :hook prog-mode ;; :config ;; (add-hook 'prog-mode-hook #'highlight-parentheses-mode) ) ;;;;; Chicken Scheme (use-package scheme :ensure nil :hook (scheme-mode . eglot-ensure) (scheme-mode . (lambda () (setq-local prettify-symbols-alist '(("lambda" . "λ") ("compose" . "∘") ("and" . "∧") ("or" . "∨") ("not" . "¬")))))) (defun flymake-chicken-init () (add-hook flymake-diagnostic-functions flymake-chicken-backend nil t) (flymake-mode)) (use-package geiser-chicken) ;;;;; Guile (use-package geiser-guile :config (when (executable-find "guix") (add-to-list 'geiser-guile-load-path (expand-file-name "~/.config/guix/current/share/guile/site/3.0")))) ;; (use-package flymake-chicken ;; :hook ;; ((scheme-mode . flymake-chicken-init) ;; (scheme-mode . flymake-mode)) ;; :custom ;; (flycheck-global-modes '(not scheme-mode)) ;; :config ;; (add-hook 'flymake-diagnostic-functions #'flymake-chicken-backend nil t)) ;;; Other Languages (use-package zig-mode :hook (zig-mode . eglot-ensure) :mode ("\\.zig\\'" . zig-mode)) (use-package nix-mode :mode ("\\.nix\\'" . nix-mode) :hook (nix-mode . eglot-ensure)) ;; (use-package lsp-tailwindcss ;; :init ;; (setq lsp-tailwindcss-add-on-mode t ;; lsp-tailwindcss-experimental-class-regex ["\"([^\"]*)\""]) ;; :config ;; (add-to-list 'lsp-tailwindcss-major-modes 'clojurescript-ts-mode) ;; (add-to-list 'lsp-tailwindcss-major-modes 'clojurec-ts-mode)) (use-package dhall-mode :mode "\\.dhall\'" :hook ((dhall-mode . lsp))) ;;; Version Control ;;;; Git ;; The following snippet is a convenience function for git-commit to add the ticket number, if found ;; in the branch name, to the commit message. (defun add-git-commit-ticket-id-from-branch () "A git-commit-mode-hook which inserts the first consecutive sequence of at least 3 digits in the current branch name at the beginning of the commit message buffer (in square brackets)." (when-let ((branch (magit-get-current-branch))) (when (string-match "\\([[:digit:]]\\{3,\\}\\)" branch) (let ((prefix (format "[T-%s] \n" (match-string 1 branch)))) (goto-char (point-min)) (insert prefix) (forward-char -1))))) (add-hook 'git-commit-mode-hook 'add-git-commit-ticket-id-from-branch) ;; Magit requires 'transient' >= 0.5.0, but due to bad defaults, Emacs' package manager refuses to ;; upgrade this and other built-in packages to higher releases from GNU Elpa. (use-package transient :init (progn (unload-feature 'transient t) (require 'transient))) ;; To fix this, you have to add this to your init file: ;; (setq package-install-upgrade-built-in t) ;; You must also make sure the updated version is loaded, by evaluating the `progn` form below. (use-package magit :after magit-popup :init (progn (unload-feature 'transient t) (require 'transient))) (use-package hl-todo) (use-package magit-todos :after (magit hl-todo) :hook (magit-mode . magit-todos-mode)) (use-package magit-popup) (use-package forge :after magit :custom (forge-alist '(("github.com" "api.github.com" "github.com" forge-github-repository) ("gitlab.com" "gitlab.com/api/v4" "gitlab.com" forge-gitlab-repository) ("dev.bevuta.com" "dev.bevuta.com/api/v4" "dev.bevuta.com" forge-gitlab-repository) ("codeberg.org" "codeberg.org/api/v1" "codeberg.org" forge-gitea-repository) ("forgejo.lyrion.ch:7920" "forgejo.lyrion.ch/api/v1" "forgejo.lyrion.ch" forge-gitea-repository) ("git.sr.ht" nil "git.sr.ht" forge-srht-repository))) :config (advice-add 'magit :after (lambda (&rest _args) (call-interactively #'forge-pull)))) (use-package git-gutter :hook prog-mode ;; :config ;; (add-hook 'prog-mode-hook #'git-gutter-mode) ) ;;; File Formats ;;;; Beancount (use-package beancount :vc (:fetcher github :repo "beancount/beancount-mode")) ;;;; Asciidoc (use-package adoc-mode :hook (adoc-mode . visual-line-mode) (adoc-mode . (lambda () (setq-local visual-fill-column-center-text t)))) ;;; LaTeX ;; https://github.com/politza/pdf-tools/#known-problems (add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer) ;;; Communication ;;;; E-Mail (use-package gnus :custom (message-send-mail-function 'message-send-mail-with-sendmail) (sendmail-program "msmtp") (message-sendmail-f-is-evil t) (message-sendmail-extra-arguments '("--read-envelope-from"))) (use-package piem :vc (piem :url "https://git.kyleam.com/piem")) (use-package git-email :vc (:fetcher codeberg :repo "martianh/git-email") :after (magit piem) :init (require 'git-email-magit) (require 'git-email-gnus) (require 'git-email-piem)) ;;;; IRC (use-package rcirc :ensure nil :after password-store :custom (rcirc-server-alist `(("liberachat.irc.lyrion.ch" :server-alias "irc.libera.chat" :port 6697 :nick "zilti" :full-name "Daniel Ziltener" :user-name "zilti/irc.libera.chat" :password ,(password-store-get "Privat/Soju") :encryption tls :channels ("#chicken"))) `(("oftc.irc.lyrion.ch" :server-alias "irc.oftc.net" :port 6697 :nick "zilti" :full-name "Daniel Ziltener" :user-name "zilti/irc.oftc.net" :password ,(password-store-get "Privat/Soju") :encryption tls :channels ())))) ;;; Wrapping Up ;; (use-package envrc ;; :config ;; (envrc-global-mode)) (use-package direnv :config (direnv-mode)) (provide 'init) ;;; init.el ends here