dotfiles/flakes/emacs/config/init.el
2026-05-12 17:59:49 +02:00

892 lines
27 KiB
EmacsLisp

;; -*- lexical-binding: t; -*-
(add-hook 'emacs-startup-hook
(lambda ()
(message "tobmacs loaded in %s."
(emacs-init-time))))
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(load custom-file 'noerror)
(require 'bind-key)
(use-package agent-shell
:config
(setq agent-shell-openai-authentication
(agent-shell-openai-make-authentication :login t)
agent-shell-prefer-viewport-interaction t))
(use-package apheleia
:config
(setf (alist-get 'nixpkgs-fmt apheleia-formatters)
'("nixpkgs-fmt"))
(setf (alist-get 'python-mode apheleia-mode-alist)
'(ruff-isort ruff))
(setf (alist-get 'python-ts-mode apheleia-mode-alist)
'(ruff-isort ruff))
(setf (alist-get 'nix-mode apheleia-mode-alist)
'nixpkgs-fmt))
(use-package autorevert
:config
(setq auto-revert-check-vc-info t
auto-revert-avoid-polling t
auto-revert-interval 5)
(global-auto-revert-mode))
(use-package avy
:bind
("C-." . avy-goto-char-timer)
("C-," . avy-goto-char)
("M-g l" . avy-goto-line))
(use-package cape
:init
(add-to-list 'completion-at-point-functions #'cape-dabbrev)
(add-to-list 'completion-at-point-functions #'cape-keyword)
(add-to-list 'completion-at-point-functions #'cape-file)
(add-to-list 'completion-at-point-functions #'cape-history))
(use-package cider
:hook
(cider-repl-mode . rainbow-delemiters-mode)
:config
(setq nrepl-log-messages t)
(setq cider-download-java-sources t))
(use-package clojure-mode
:defer t
:config
(use-package flycheck-clj-kondo)
(require 'flycheck-clj-kondo))
(use-package consult
:bind
(("C-x b" . consult-buffer)
("C-x 4 b" . consult-buffer-other-window)
("C-x r b" . consult-bookmark)
("C-x p b" . consult-project-buffer)
("M-y" . consult-yank-pop)
("C-c k" . consult-kmacro)
("M-g g" . consult-goto-line)
("M-g M-g" . consult-outline)
("M-i" . consult-imenu)
("M-s l" . consult-line)
("M-s L" . consult-line-multi)
("M-g m" . consult-mark)
("M-g k" . consult-global-mark)
("M-s r" . consult-ripgrep))
:hook
(completion-list-mode . consult-preview-at-point-mode))
(use-package copilot
:bind (:map copilot-completion-map
("C-<tab>" . copilot-accept-completion)
("M-C-<tab>" . copilot-accept-completion-by-word)))
(use-package corfu
:custom
(corfu-cycle t)
(corfu-auto-prefix 2)
(corfu-preselect-first nil)
(corfu-quit-no-match 'separator)
:init
(global-corfu-mode)
(corfu-history-mode)
(corfu-popupinfo-mode)
:config
(add-hook 'eshell-mode-hook
(lambda ()
(setq-local corfu-auto nil)
(corfu-mode))))
(use-package denote
:hook (dired-mode . denote-dired-mode)
:bind
(("C-c n n" . denote)
("C-c n r" . denote-rename-file)
("C-c n l" . denote-link)
("C-c n b" . denote-backlinks)
("C-c n d" . denote-dired)
("C-c n g" . denote-grep))
:config
(setq denote-directory (expand-file-name "~/TobCloud/Denote/"))
(denote-rename-buffer-mode 1))
(use-package diff-hl
:init
(global-diff-hl-mode 1)
(diff-hl-flydiff-mode 1)
:hook
(dired-mode . diff-hl-dired-mode)
(vc-checkin . diff-hl-update)
:config
(unless (display-graphic-p)
(diff-hl-margin-mode 1)))
(use-package dired
:init
(setq dired-dwim-target t
dired-hide-details-hide-symlink-targets nil
dired-auto-revert-buffer #'dired-directory-changed-p
dired-mouse-drag-files t
dired-recursive-copies 'always
dired-recursive-deletes 'top
dired-kill-when-opening-new-dired-buffer t)
(add-hook 'dired-mode-hook #'dired-hide-details-mode)
(add-hook 'dired-mode-hook #'hl-line-mode))
(use-package dockerfile-mode
:defer t)
(use-package ediff
:config
(setq
ediff-keep-variants nil
ediff-make-buffers-readonly-at-startup nil
ediff-show-clashes-only t
ediff-split-window-function 'split-window-horizontally
ediff-window-setup-function 'ediff-setup-windows-plain))
(use-package ef-themes
:config
(setq ef-themes-headings
'((0 . (variable-pitch light 2.0))
(1 . (variable-pitch light 1.7))
(2 . (variable-pitch semibold 1.5))
(t . (variable-pitch 1.0))))
(setq ef-themes-mixed-fonts t
ef-themes-variable-pitch-ui t)
(mapc #'disable-theme custom-enabled-themes))
(use-package eglot
:hook ((tsx-ts-mode . eglot-ensure)
(js-mode . eglot-ensure)
(js-ts-mode . eglot-ensure)
(json-mode . eglot-ensure)
(json-ts-mode . eglot-ensure)
(python-base-mode . eglot-ensure)
(typescript-ts-mode . eglot-ensure)
(typescript-mode . eglot-ensure)
(nix-mode . eglot-ensure)
(swift-mode . eglot-ensure)
(swift-ts-mode . eglot-ensure))
:custom
(eglot-autoshutdown t)
(eglot-events-buffer-size 0)
(eglot-sync-connect nil)
(eglot-ignored-server-capabilities
'(:documentFormattingProvider
:documentRangeFormattingProvider
:documentOnTypeFormattingProvider))
:config
(add-to-list 'eglot-server-programs
'(python-base-mode . ("ty" "server"))
0)
(dolist (mode '(json-mode json-ts-mode))
(add-to-list 'eglot-server-programs
`(,mode . ("vscode-json-language-server" "--stdio"))
0))
(dolist (mode '(swift-mode swift-ts-mode))
(add-to-list 'eglot-server-programs
`(,mode . ("xcrun" "sourcekit-lsp")))))
(use-package emacs
:demand t
:bind (("C-x 1" . to/toggle-delete-other-windows)
("<C-wheel-up>" . ignore)
("<C-wheel-down>" . ignore)
("<pinch>" . ignore))
:config
(minibuffer-electric-default-mode)
(minibuffer-regexp-mode 1)
(repeat-mode)
(winner-mode)
;; (fset 'yes-or-no-p 'y-or-n-p)
(delete-selection-mode)
(pixel-scroll-precision-mode)
(setopt
auto-save-file-name-transforms `((".*" ,temporary-file-directory t))
backup-directory-alist `((".*" . ,temporary-file-directory))
confirm-kill-processes nil
create-lockfiles nil
delete-by-moving-to-trash t
display-time-default-load-average nil
echo-keystrokes 0.1
enable-recursive-minibuffers t
fast-but-imprecise-scrolling t
help-window-select t
highlight-nonselected-windows nil
history-delete-duplicates t
initial-major-mode 'emacs-lisp-mode
initial-scratch-message nil
isearch-allow-motion t
isearch-lazy-count t
kill-do-not-save-duplicates t
large-file-warning-threshold 100000000
lazy-count-prefix-format "(%s/%s) "
lazy-count-suffix-format nil
minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt)
next-line-add-newlines nil
read-extended-command-predicate #'command-completion-default-include-p
require-final-newline t
save-interprogram-paste-before-kill t
search-whitespace-regexp ".*?"
sentence-end-double-space nil
set-mark-command-repeat-pop t
scroll-conservatively 101
scroll-margin 0
scroll-preserve-screen-position t
tab-always-indent 'complete
undo-limit 67108864 ;; 64mb
undo-outer-limit 1006632960 ;; x 10 (960mb)
undo-strong-limit 100663296 ;; x 1.5 (96mb)
use-dialog-box nil
use-short-answers t
user-full-name "Tobias Ostner"
user-mail-address "tobias.ostner@gmail.com"
visible-bell t
window-combination-resize t)
(setq
auto-window-vscroll nil
bookmark-fringe-mark nil
coding-system-for-read 'utf-8
default-process-coding-system '(utf-8-unix . utf-8-unix)
frame-title-format nil
global-auto-revert-non-file-buffers t
locale-coding-system 'utf-8
ns-use-proxy-icon nil
read-process-output-max (* 4 1024 1024)
redisplay-skip-fontification-on-input t
truncate-string-ellipsis "..."
bidi-inhibit-bpa t)
(setq-default
cursor-type 'bar
cursor-in-non-selected-windows nil
fill-column 100
indent-tabs-mode nil
tab-width 4
bidi-display-reordering 'left-to-right
bidi-paragraph-direction 'left-to-right)
(set-charset-priority 'unicode)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
(require 'epg)
(setq epg-pinentry-mode 'loopback)
(when (fboundp 'mac-auto-operator-composition-mode)
(mac-auto-operator-composition-mode))
(when (memq window-system '(mac ns))
(setq mac-option-modifier 'none
mac-command-modifier 'meta
visible-bell nil
ring-bell-function 'flash-mode-line)
(defun flash-mode-line ()
(invert-face 'mode-line)
(run-with-timer 0.1 nil #'invert-face 'mode-line))
(setq frame-resize-pixelwise t)
(add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))
(add-to-list 'default-frame-alist '(ns-appearance . dark)))
(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)
(add-hook 'package-menu-mode-hook #'hl-line-mode)
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode))
(use-package envrc
:config
(envrc-global-mode))
(use-package exec-path-from-shell
:if (memq window-system '(mac ns))
:config
(dolist (v '("PATH" "MANPATH" "NIX_PATH" "LOGSEQ_DIR"))
(exec-path-from-shell-copy-env v))
(exec-path-from-shell-initialize))
(use-package flycheck
:hook (clojure-mode . flycheck-mode))
(use-package flycheck-swiftlint
:after flycheck
:config
(flycheck-swiftlint-setup))
(use-package frame
:init
(keymap-global-unset "C-z" nil))
(use-package fontaine
:init
(setq fontaine-presets
'((regular)
(presentation
:default-weight semilight
:default-height 250)
(t
:default-family "Cascadia Code"
:default-weight regular
:default-height 140
:fixed-pitch-height 1.0
:fixed-pitch-serif-height 1.0
:variable-pitch-family "Noto Sans"
:variable-pitch-height 1.1
:bold-weight bold
:italic-slant italic
:line-spacing 0.3)))
:config
(setq-default text-scale-remap-header-line t)
(fontaine-set-preset (or (fontaine-restore-latest-preset) 'regular))
(add-hook 'kill-emacs-hook #'fontaine-store-latest-preset)
(dolist (hook '(text-mode-hook help-mode-hook))
(add-hook
hook
(lambda ()
(unless (or (derived-mode-p
'mhtml-mode
'nxml-mode
'yaml-mode
'ledger-mode)
(member (buffer-name) '("*Colors*" "*Faces*" "*Quick Help*")))
(variable-pitch-mode))))))
(use-package graphql-mode
:defer t)
(use-package helpful
:bind (("C-h f" . helpful-callable)
("C-h v" . helpful-variable)))
(use-package hl-line
:hook (prog-mode . hl-line-mode))
(use-package jinx
:hook ((conf-mode prog-mode text-mode) . jinx-mode)
:custom
(jinx-languages "en_US de_DE"))
(use-package js2-mode
:defer t
:custom
(js2-basic-offset 2)
(js-chain-indent t)
(js-indent-level 2))
(use-package ledger-mode
:defer t
:config
(add-to-list 'ledger-reports
'("Subscriptions last month"
"%(binary) -f %(ledger-file) bal Expenses:Subscriptions --period \"last month\"")))
(use-package ligature
:after fontaine
:config
(defun to/set-ligatures-for-font (font-family)
(let ((ligatures
(cond ((string= font-family "Iosevka Comfy")
'("<---" "<--" "<<-" "<-" "->" "-->" "--->" "<->" "<-->" "<--->"
"<---->" "<!--" "<==" "<===" "<=" "=>" "=>>" "==>" "===>" ">="
"<=>" "<==>" "<===>" "<====>" "<!---" "<~~" "<~" "~>" "~~>" "::"
":::" "==" "!=" "===" "!==" ":=" ":-" ":+" "<*" "<*>" "*>" "<|"
"<|>" "|>" "+:" "-:" "=:" "<******>" "++" "+++"))
((string= font-family "Cascadia Code")
'("www" "--" "---" "-~" "(*" "{|" "}#" "[|" "]#" ".-" ".." "..." "..="
"..<" ".?" ".=" "::" ":::" "::=" ":=" "://" ";;" "!." "!:" "!!" "!!."
"!=" "!==" "?." "?:" "??" "??=" "?=" "*)" "**" "***" "*>" "*/" "#("
"#{" "#[" "#:" "#!" "#?" "#=" "#_" "#_(" "/*" "/>" "//" "///" "/\\"
"\\\\" "&&" "|}" "|]" "||" "|||" "|||>" "|>" "$>" "++" "+++" "+>" "=="
"===" "=>>" "=<<" ">=" ">>" ">>=" ">>>" "<!--" "<*" "<*>" "<|" "<||"
"<|||" "<|>" "<$" "<$>" "<+" "<+>" "<=" "<>" "<<" "<<=" "<<<" "<~"
"<~>" "<~~" "</" "</>" "~-" "~@" "~=" "~>" "~~" "~~>" "^=" "%%"
"->" "->>" "-->" "--->" "<-" "<--" "<---" "__" "___"))
((string= font-family "Fira Code")
'("www" "**" "***" "**/" "*>" "*/" "\\\\" "\\\\\\" "{-" "[]" "::"
":::" ":=" "!!" "!=" "!==" "-}" "--" "---" "-->" "->" "->>" "-<"
"-<<" "-~" "#{" "#[" "##" "###" "####" "#(" "#?" "#_" "#_(" ".-"
".=" ".." "..<" "..." "?=" "??" ";;" "/*" "/**" "/=" "/==" "/>"
"//" "///" "&&" "||" "||=" "|=" "|>" "^=" "$>" "++" "+++" "+>"
"=:=" "==" "===" "==>" "=>" "=>>" "<=" "=<<" "=/=" ">-" ">=" ">=>"
">>" ">>-" ">>=" ">>>" "<*" "<*>" "<|" "<|>" "<$" "<$>" "<!--"
"<-" "<--" "<->" "<+" "<+>" "<=" "<==" "<=>" "<=<" "<>" "<<" "<<-"
"<<=" "<<<" "<~" "<~~" "</" "</>" "~@" "~-" "~=" "~>" "~~" "~~>"
"%%"))
((string= font-family "JetBrains Mono")
'("--" "---" "==" "===" "!=" "!==" "=!=" "=:=" "=/=" "<=" ">="
"&&" "&&&" "&=" "++" "+++" "***" ";;" "!!" "??" "???" "?:" "?."
"?=" "<:" ":<" ":>" ">:" "<:<" "<>" "<<<" ">>>" "<<" ">>" "||"
"-|" "_|_" "|-" "||-" "|=" "||=" "##" "###" "####" "#{" "#[" "]#"
"#(" "#?" "#_" "#_(" "#:" "#!" "#=" "^=" "<$>" "<$" "$>" "<+>" "<+"
"+>" "<*>" "<*" "*>" "</" "</>" "/>" "<!--" "<#--" "-->" "->" "->>"
"<<-" "<-" "<=<" "=<<" "<<=" "<==" "<=>" "<==>" "==>" "=>" "=>>"
">=>" ">>=" ">>-" ">-" "-<" "-<<" ">->" "<-<" "<-|" "<=|" "|=>"
"|->" "<->" "<~~" "<~" "<~>" "~~" "~~>" "~>" "~-" "-~" "~@"
"[||]" "|]" "[|" "|}" "{|" "[<" ">]" "|>" "<|" "||>" "<||" "|||>"
"<|||" "<|>" "..." ".." ".=" "..<" ".?" "::" ":::" ":=" "::=" ":?"
":?>" "//" "///" "/*" "*/" "/=" "//=" "/==" "@_" "__" "???" "<:<"
";;;"))
(t '()))))
(ligature-set-ligatures 'prog-mode ligatures)))
(to/set-ligatures-for-font (face-attribute 'default :family))
(global-ligature-mode t))
(use-package magit
:after (nerd-icons diff-hl)
:hook
(magit-post-refresh . diff-hl-magit-post-refresh)
:custom
(magit-format-file-function #'magit-format-file-nerd-icons)
(magit-process-connection-type nil))
(use-package magit-todos
:after magit
:config
(magit-todos-mode 1))
(use-package git-timemachine
:defer t)
(use-package marginalia
:config
(marginalia-mode))
(use-package markdown-mode
:preface
(defun to/apply-markdown-faces (&rest _)
(when (facep 'markdown-header-face-1)
(set-face-attribute
'markdown-header-face-1 nil
:inherit 'variable-pitch
:weight 'light
:height 1.7))
(dolist (face '(markdown-code-face
markdown-inline-code-face
markdown-language-keyword-face
markdown-pre-face))
(when (facep face)
(set-face-attribute face nil :inherit 'fixed-pitch))))
:hook (markdown-mode . variable-pitch-mode)
:custom
(markdown-fontify-code-blocks-natively t)
(markdown-spaces-after-code-fence 0)
:config
(to/apply-markdown-faces))
(use-package modus-themes
:config
(defun to/modus-themes-custom-faces (&rest _)
(setq x-underline-at-descent-line t)
(let ((bg-main (modus-themes-get-color-value 'bg-main))
(bg-mode-line-active (modus-themes-get-color-value 'bg-mode-line-active))
(bg-mode-line-inactive (modus-themes-get-color-value 'bg-mode-line-inactive))
(border-mode-line-active (modus-themes-get-color-value 'border-mode-line-active))
(border-mode-line-inactive (modus-themes-get-color-value 'border-mode-line-inactive)))
(set-face-attribute
'tab-bar nil
:box (list :line-width 4 :color bg-main)
:background bg-main)
(set-face-attribute
'mode-line-active nil
:underline border-mode-line-active
:overline border-mode-line-active
:box (list :line-width 4 :color bg-mode-line-active))
(set-face-attribute
'mode-line-inactive nil
:underline border-mode-line-inactive
:overline border-mode-line-inactive
:box (list :line-width 4 :color bg-mode-line-inactive))))
(setq modus-themes-org-blocks 'tinted-background
modus-themes-bold-constructs t
modus-themes-italic-constructs t
modus-themes-completions '((t . (extrabold)))
modus-themes-to-toggle '(modus-operandi-tinted modus-vivendi-tinted)
modus-themes-mixed-fonts t
modus-themes-variable-pitch-ui nil
modus-themes-headings
'((0 . (variable-pitch light 2.0))
(1 . (variable-pitch light 1.7))
(2 . (variable-pitch semibold 1.5))
(t . (variable-pitch 1.0)))
modus-themes-common-palette-overrides '((fringe unspecified)
(border-mode-line-active unspecified)
(border-mode-line-inactive unspecified)))
(add-hook 'modus-themes-after-load-theme-hook #'to/modus-themes-custom-faces)
(add-hook 'modus-themes-after-load-theme-hook #'to/apply-markdown-faces))
(use-package catppuccin-theme
:preface
(defun to/apply-org-heading-faces (&rest _)
(when (facep 'org-level-1)
(set-face-attribute
'org-document-title nil
:inherit 'variable-pitch
:weight 'light
:height 2.0)
(set-face-attribute
'org-level-1 nil
:inherit 'variable-pitch
:weight 'light
:height 1.7)
(set-face-attribute
'org-level-2 nil
:inherit 'variable-pitch
:weight 'semibold
:height 1.5)
(dolist (face '(org-level-3
org-level-4
org-level-5
org-level-6
org-level-7
org-level-8))
(set-face-attribute
face nil
:inherit 'variable-pitch
:weight 'regular
:height 1.0))))
:init
(setq catppuccin-flavor 'macchiato)
:config
(mapc #'disable-theme custom-enabled-themes)
(load-theme 'catppuccin t)
(with-eval-after-load 'org
(to/apply-org-heading-faces))
(with-eval-after-load 'org-modern
(to/apply-org-heading-faces))
(with-eval-after-load 'markdown-mode
(to/apply-markdown-faces))
(advice-add 'catppuccin-reload :after #'to/apply-org-heading-faces)
(advice-add 'catppuccin-reload :after #'to/apply-markdown-faces))
(use-package minions
:config
(minions-mode))
(use-package multiple-cursors
:bind
(("C-c m n" . mc/mark-next-like-this)
("C-c m l" . mc/edit-lines)
("C-c m p" . mc/mark-previous-like-this)
("C-c m a" . mc/mark-all-like-this)
(:repeat-map mc/multi-cursors-repeat-map
("n" . mc/mark-next-like-this)
("p" . mc/mark-previous-like-this))))
(use-package nerd-icons
:defer 2
:if window-system
:config
(use-package nerd-icons-completion
:config
(nerd-icons-completion-mode))
(use-package nerd-icons-corfu
:config
(add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
(use-package nerd-icons-dired
:defer t
:hook dired-mode)
(use-package nerd-icons-ibuffer
:defer t
:hook ibuffer-mode))
(use-package nix-mode
:defer t)
(use-package ob
:after org
:config
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp .t)
(shell . t)
(python . t))))
(use-package ob-restclient
:after org
:defer t
:config
(org-babel-do-load-languages
'org-babel-load-languages
(append org-babel-load-languages
'((restclient . t)))))
(use-package ob-swift
:after org
:defer 3
:config
(org-babel-do-load-languages
'org-babel-load-languages
(append org-babel-load-languages
'((swift . t)))))
(use-package ob-typescript
:after org
:config
(org-babel-do-load-languages
'org-babel-load-languages
(append org-babel-load-languages
'((typescript . t)))))
(use-package olivetti
:hook (org-mode markdown-mode)
:custom
(olivetti-body-width 90))
(use-package orderless
:custom
(completion-styles '(orderless basic))
(completion-category-defaults nil)
(completion-category-overrides '((file (styles partial-completion)))))
(use-package org
:bind
(("C-c c" . 'org-capture)
("C-c a" . 'org-agenda))
:hook
(org-mode . visual-line-mode)
:config
(require 'org-tempo)
(setq org-auto-align-tags nil
org-tags-column 0
org-special-ctrl-a/e t
org-pretty-entities t
org-hide-emphasis-markers t
org-src-preserve-indentation t
org-startup-with-inline-images t
org-image-actual-width '(460)
org-agenda-files '("~/Logseq/Me/journals/" "~/Logseq/Me/pages")
org-agenda-custom-commands
'(("p" "Personal Todos" tags-todo "-@work")
("w" "Work Todos" tags-todo "+@work"))
org-capture-templates
'(("i" "Inbox" entry (file "~/Logseq/Me/pages/Inbox.org")
"* %?\n"))
org-tag-alist
'(("@work") ("@home")
("someday") ("project")
("bitcoin") ("ai-ml") ("emacs") ("tobcloud"))
org-todo-keywords
'((sequence "TODO" "DOING" "WAITING" "|" "DONE"))
org-confirm-babel-evaluate nil
org-startup-indented t
calendar-week-start-day 1
org-M-RET-may-split-line '((default . nil))
org-insert-heading-respect-content t))
(use-package org-modern
:after org
:config
(global-org-modern-mode)
(setq org-modern-table nil))
(use-package ox-gfm
:defer t
:after org)
(use-package ox-reveal
:after org)
(use-package pulsar
:config
(pulsar-global-mode 1)
(add-hook 'next-error-hook #'pulsar-pulse-line))
(use-package rainbow-delimiters
:hook (emacs-lisp-mode clojure-mode))
(use-package rainbow-mode
:hook ((text-mode prog-mode) . rainbow-mode))
(use-package recentf
:ensure nil
:init
(recentf-mode 1))
(use-package restclient
:defer t
:mode (("\\.http\\'" . restclient-mode)))
(use-package savehist
:custom
(savehist-additional-variables
'(search-ring regexp-search-ring kill-ring))
:init
(savehist-mode))
(use-package saveplace
:preface
(defun to/recenter-after-save-place ()
"Recenter the window after save-place restores point."
(when buffer-file-name
(ignore-errors (recenter))))
:hook (save-place-after-find-file . to/recenter-after-save-place)
:init
(save-place-mode 1))
(use-package server
:hook (after-init . (lambda ()
(unless (server-running-p)
(server-start)))))
(use-package smartparens
:hook ((prog-mode . smartparens-mode))
:bind
(:map smartparens-mode-map
("C-M-f" . sp-forward-sexp)
("C-M-b" . sp-backward-sexp)
("C-M-e" . sp-up-sexp)
("C-M-u" . sp-backward-up-sexp)
("C-M-d" . sp-down-sexp)
("C-M-a" . sp-backward-down-sexp)
("C-M-t" . sp-transpose-sexp)
("C-M-k" . sp-kill-sexp)
("C-M-w" . sp-copy-sexp)
("C-M-]" . sp-forward-slurp-sexp)
("C-M-[" . sp-backward-slurp-sexp)
("C-M-}" . sp-forward-barf-sexp)
("C-M-{" . sp-backward-barf-sexp)
("M-<backspace>" . sp-unwrap-sexp))
:config
(require 'smartparens-config)
(defun to/indent-between-pair (&rest _ignored)
(message "to/indent-between-pair")
(newline)
(indent-according-to-mode)
(forward-line -1)
(indent-according-to-mode))
(sp-local-pair 'prog-mode "{" nil :post-handlers '((to/indent-between-pair "RET")))
(sp-local-pair 'prog-mode "[" nil :post-handlers '((to/indent-between-pair "RET")))
(sp-local-pair 'prog-mode "(" nil :post-handlers '((to/indent-between-pair "RET")))
(sp-local-pair 'swift-mode "\\(" ")" :when '(sp-in-string-p)))
(use-package super-save
:config
(super-save-mode)
(setq super-save-delete-trailing-whitespace 'except-current-line))
(use-package swift-mode
:hook (swift-mode . subword-mode)
:config
(setq
swift-mode:multiline-statement-offset 2
swift-mode:parenthesized-expression-offset 2
swift-mode:basic-offset 2
swift-mode:repl-executable "xcrun swift repl"))
(use-package swift-ts-mode
:custom
(swift-ts-mode-indent-offset 2))
(use-package tab-bar
:config
(tab-bar-mode)
(setq tab-bar-show t
tab-bar-close-button-show nil
tab-bar-new-tab-choice "*scratch*"
tab-bar-format (remove 'tab-bar-format-add-tab tab-bar-format))
(set-face-attribute
'tab-bar nil
:height 1.0))
(use-package terraform-mode)
(use-package tramp
:init
(setq
tramp-auto-save-directory
(expand-file-name "tramp-autosaves" temporary-file-directory)
tramp-allow-unsafe-temporary-files t))
(use-package treesit-auto
:custom
(treesit-auto-install nil)
:config
(setq treesit-auto-langs
'(swift
python
typescript
tsx
javascript
json))
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode))
(use-package yaml-mode)
(use-package vertico
:config
(vertico-mode)
(setq vertico-cycle t)
(vertico-multiform-mode)
(setq vertico-multiform-commands
'((consult-imenu buffer indexed))))
(use-package vertico-directory
:after vertico
:hook (rfn-eshadow-update-overlay . vertico-directory-tidy)
:bind (:map vertico-map
("DEL" . vertico-directory-delete-char)
("M-DEL" . vertico-directory-delete-word)))
(use-package visual-wrap
:preface
(defun to/enable-code-wrap ()
"Wrap long code lines with context-aware continuation indentation."
(setq-local truncate-lines nil)
(setq-local truncate-partial-width-windows nil)
(setq-local word-wrap t)
(setq-local visual-wrap-extra-indent 0)
(visual-wrap-prefix-mode 1))
:hook
((prog-mode . to/enable-code-wrap)
(conf-mode . to/enable-code-wrap)))
(use-package vterm
:defer 2
:if module-file-suffix)
(use-package web-mode
:mode
("\\.html?\\'" . web-mode)
:custom
(web-mode-markup-indent-offset 2)
(web-mode-css-indent-offset 2)
(web-mode-code-indent-offset 2)
(web-mode-enable-current-element-highlight t))
(use-package whitespace
:config
(setq whitespace-line-column nil
whitespace-style '(face empty tabs lines-tail trailing)))
(use-package winpulse
:config
(winpulse-mode 1))
(use-package yasnippet
:defer 2
:config
(yas-global-mode))
(provide 'init)
;;; init.el ends here