;; -*- 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 ace-window :bind ("M-o" . ace-window) :config (setq aw-keys '(?a ?b ?c ?d ?e ?f ?g ?h ?i ?j) aw-dispatch-always nil)) (use-package apheleia :config (add-to-list 'apheleia-formatters '(nixpkgs-fmt . ("nixpkgs-fmt"))) (add-to-list 'apheleia-mode-alist '(nix-mode . nixpkgs-fmt))) (use-package autorevert :config (setq auto-revert-check-vc-info t auto-revert-interval 1) (global-auto-revert-mode)) (use-package avy :bind ("C-." . avy-goto-char-timer)) (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 :defer 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)) :hook (completion-list-mode . consult-preview-at-point-mode)) (use-package copilot :hook (prog-mode . copilot-mode) :bind (("C-" . copilot-accept-completion) ("M-C-" . copilot-accept-completion-by-word) ("C-n" . copilot-next-completion) ("C-p" . copilot-previous-completion)) :commands (copilot-login) :custom (copilot-indent-offset-warning-disable t) :config (add-to-list 'copilot-indentation-alist '(prog-mode 2)) (defun to/copilot-disable-predicate () (member major-mode '(shell-mode eshell-mode term-mode vterm-mode compilation-mode debugger-mode dired-mode compilation-mode minibuffer-mode vertico-mode))) (add-to-list 'copilot-disable-predicates #'to/copilot-disable-predicate)) (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 dired :init (setq dired-dwim-target t dired-hide-details-hide-symlink-targets nil dired-auto-revert-buffer #'dired-directory-changed-p 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 ((typescript-mode . eglot-ensure) (tsx-ts-mode . eglot-ensure) (js-mode . eglot-ensure) (js-ts-mode . eglot-ensure) (json-mode . eglot-ensure) (typescript-ts-mode . eglot-ensure) (nix-mode . eglot-ensure)) :custom (eglot-autoshutdown t) (eglot-events-buffer-size 0) (eglot-sync-connect nil) (eglot-ignored-server-capabilities '(:documentHighlightProvider :documentFormattingProvider :documentRangeFormattingProvider :documentOnTypeFormattingProvider :colorProvider :foldingRangeProvider)) (add-to-list 'eglot-server-programs '((json-mode js-mode js-ts-mode) . ("vscode-json-languageserver" "--stdio")))) (use-package emacs :ensure nil :demand t :bind (("" . ignore) ("" . ignore) ("" . ignore)) :custom (cursor-type 'bar) (visible-bell t) (global-auto-revert-non-file-buffers t) (kill-do-not-save-duplicates t) (fast-but-imprecise-scrolling t) (scroll-conservatively 101) (scroll-margin 0) (scroll-preserve-screen-position t) :config (minibuffer-electric-default-mode) (repeat-mode) (winner-mode) ;; (fset 'yes-or-no-p 'y-or-n-p) (delete-selection-mode) (pixel-scroll-precision-mode) (setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t)) auto-window-vscroll nil backup-directory-alist `((".*" . ,temporary-file-directory)) bookmark-fringe-mark nil coding-system-for-read 'utf-8 create-lockfiles nil default-process-coding-system '(utf-8-unix . utf-8-unix) delete-by-moving-to-trash t echo-keystrokes 0.1 enable-recursive-minibuffers t fast-but-imprecise-scrolling t frame-title-format nil history-delete-duplicates t isearch-allow-motion t isearch-lazy-count t lazy-count-prefix-format "(%s/%s) " lazy-count-suffix-format nil locale-coding-system 'utf-8 minibuffer-prompt-properties '(read-only t cursor-intangible t face minibuffer-prompt) next-line-add-newlines nil ns-use-proxy-icon nil read-extended-command-predicate #'command-completion-default-include-p read-process-output-max (* 1024 1024) search-whitespace-regexp ".*?" sentence-end-double-space nil tab-always-indent 'complete tab-width 4 truncate-string-ellipsis "..." undo-limit 6710886400 ;; 64mb undo-outer-limit 1006632960 ;; x 10 (960mb) undo-strong-limit 100663296 ;; x 1.5 (96mb) use-dialog-box nil user-full-name "Tobias Ostner" user-mail-address "tobias.ostner@gmail.com") (setq-default indent-tabs-mode nil bidi-paragraph-direction 'left-to-right bidi-inhibit-bpa t) (set-charset-priority 'unicode) (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 "Jetbrains Mono" :default-weight regular :default-height 130 :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 gptel :bind ("C-c RET" . gptel-send) :config (setq gptel-backend (gptel-make-openai "OpenRouter" :host "openrouter.ai" :endpoint "/api/v1/chat/completions" :stream t :key (lambda () (nth 0 (process-lines "pass" "show" "emacs-openrouter-api-key"))) :models '(openai/gpt-5 openai/gpt-5-mini openai/gpt-5-nano deepseek/deepseek-chat-v3-0324:free))) (setq gptel-default-mode 'org-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)) (use-package js2-mode :defer t :custom (js2-basic-offset 2) (js-chain-indent t) (js-indent-level 2)) (use-package json-mode :defer t) (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 "Fira Code") '("www" "**" "***" "**/" "*>" "*/" "\\\\" "\\\\\\" "{-" "[]" "::" ":::" ":=" "!!" "!=" "!==" "-}" "--" "---" "-->" "->" "->>" "-<" "-<<" "-~" "#{" "#[" "##" "###" "####" "#(" "#?" "#_" "#_(" ".-" ".=" ".." "..<" "..." "?=" "??" ";;" "/*" "/**" "/=" "/==" "/>" "//" "///" "&&" "||" "||=" "|=" "|>" "^=" "$>" "++" "+++" "+>" "=:=" "==" "===" "==>" "=>" "=>>" "<=" "=<<" "=/=" ">-" ">=" ">=>" ">>" ">>-" ">>=" ">>>" "<*" "<*>" "<|" "<|>" "<$" "<$>" "" "->" "->>" "<<-" "<-" "<=<" "=<<" "<<=" "<==" "<=>" "<==>" "==>" "=>" "=>>" ">=>" ">>=" ">>-" ">-" "-<" "-<<" ">->" "<-<" "<-|" "<=|" "|=>" "|->" "<->" "<~~" "<~" "<~>" "~~" "~~>" "~>" "~-" "-~" "~@" "[||]" "|]" "[|" "|}" "{|" "[<" ">]" "|>" "<|" "||>" "<||" "|||>" "<|||" "<|>" "..." ".." ".=" "..<" ".?" "::" ":::" ":=" "::=" ":?" ":?>" "//" "///" "/*" "*/" "/=" "//=" "/==" "@_" "__" "???" "<:<" ";;;")) (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 :custom (magit-format-file-function #'magit-format-file-nerd-icons) :defer t) (use-package magit-todos :after magit :config (magit-todos-mode 1)) (use-package marginalia :config (marginalia-mode)) (use-package markdown-mode :defer t) (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 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) (modus-themes-load-theme 'modus-vivendi-tinted)) (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-mode :hook (after-init . recentf-mode)) (use-package restclient :defer t :mode (("\\.http\\'" . restclient-mode))) (use-package savehist :init (savehist-mode)) (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-" . 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 (set-fill-column 100) (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 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-new-button-show nil) (set-face-attribute 'tab-bar nil :height 1.0)) (use-package terraform-mode) (use-package treesit-auto :custom (treesit-auto-install 'prompt) :config (add-to-list 'treesit-auto-recipe-list (make-treesit-auto-recipe :lang 'swift :ts-mode 'swift-ts-mode :remap '(swift-mode) :ext "\\.swift\\'")) (setq treesit-auto-langs '(swift python typescript tsx javascript jsx)) (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 :ensure nil :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 vterm :defer 2 :if module-file-suffix) (use-package whitespace :config (setq whitespace-line-column nil whitespace-style '(face empty tabs lines-tail trailing))) (use-package yasnippet :defer 2 :config (yas-global-mode)) (provide 'init) ;;; init.el ends here