;; -*- lexical-binding: t; -*- (load-file "~/.config/emacs/init-elpaca.el") (defun git-tracked-file-p (filename) "Check whether the file FILENAME is tracked by git." (let ((dirname (file-name-parent-directory filename))) (zerop (call-process "git" nil nil nil "-C" dirname "ls-files" "--error-unmatch" filename)))) (defun should-auto-save-current-buffer-p () "Check whether the current buffer should be autosaved." (when buffer-file-name (git-tracked-file-p buffer-file-name))) (defun find-init-file () "Find the user's init file" (interactive) (find-file user-init-file)) (use-package emacs :ensure nil :bind (("C-z" . nil) ("C-z i" . find-init-file) ("C-z f" . ffap)) :hook ((after-save . executable-make-buffer-file-executable-if-script-p) (xref-after-update . outline-minor-mode)) :init (setq load-path (append (list (expand-file-name "~/.config/emacs/site-lisp/") (expand-file-name "~/Projects/lilypond/elisp") ) load-path)) :config ;; keep-sorted start (defalias 'yes-or-no-p 'y-or-n-p) (display-battery-mode) (display-time-mode) (load "lilypond-init.el") (prefer-coding-system 'utf-8) (progn (which-key-mode) (with-eval-after-load 'diminish (diminish 'which-key-mode))) (put 'dired-find-alternate-file 'disabled nil) (set-default-file-modes #o750) (windmove-default-keybindings 'super) ;; keep-sorted end :custom ;; keep-sorted start (auto-save-interval 20) (auto-save-visited-mode t) (auto-save-visited-predicate #'should-auto-save-current-buffer) (column-number-mode t) (dired-dwim-target 'dired-dwim-target-next) (display-time-24hr-format t) (display-time-day-and-date t) (global-auto-revert-mode t) (global-auto-revert-non-file-buffers t) (inhibit-startup-screen t) (show-paren-context-when-offscreen 'overlay) (xref-search-program 'ripgrep) ;; keep-sorted end ) (use-package diminish) (use-package better-defaults :ensure (:repo "https://git.sr.ht/~technomancy/better-defaults")) (use-package treemacs-icons-dired :hook (dired-mode . treemacs-icons-dired-mode)) (use-package dired-subtree :after dired :bind (:map dired-mode-map ("" . dired-subtree-toggle) ("" . dired-subtree-cycle) ("" . dired-subtree-remove)) :config ;; keep-sorted start (defadvice dired-subtree-cycle (after add-icons activate) (revert-buffer)) (defadvice dired-subtree-toggle (after add-icons activate) (revert-buffer)) ;; keep-sorted end :custom (dired-subtree-use-backgrounds nil)) (use-package undo-tree :ensure (:repo "https://gitlab.com/tsc25/undo-tree") :init (global-undo-tree-mode) :custom (undo-tree-history-directory-alist '(("." . "~/.config/emacs/undo-tree"))) :diminish undo-tree-mode ) (use-package transient) (use-package cond-let :ensure (:repo "https://github.com/tarsius/cond-let")) (use-package magit :bind (("C-x g" . magit-status) ("C-x M-g" . magit-list-repositories)) :init (require 'magit-extras) :custom (magit-repository-directories '(("~/" . 0) ("~/Projects/" . 1)))) (use-package nyan-mode :init (nyan-mode 1) :custom (nyan-animate-nyancat t) (nyan-wavy-trail t)) (use-package mozc :bind (("C-c m" . mozc-mode))) (use-package material-theme :config (load-theme 'material t)) (use-package windmove :ensure nil :bind (("s-w" . windmove-up) ("s-a" . windmove-left) ("s-s" . windmove-down) ("s-d" . windmove-right))) (use-package counsel :bind (("C-s" . swiper-isearch) ("M-x" . counsel-M-x) ("M-y" . counsel-yank-pop) (" f" . counsel-describe-function) (" v" . counsel-describe-variable) ("C-x C-f" . counsel-find-file) ("C-x b" . ivy-switch-buffer) ("C-x d" . counsel-dired) ("C-c u" . counsel-unicode-char) ("C-c v" . ivy-push-view) ("C-c V" . ivy-pop-view) :map ivy-minibuffer-map ("C-" . ivy-immediate-done)) :init (ivy-add-actions 'project-find-file '(("x" counsel-locate-action-extern "open externally"))) (setq ivy-re-builders-alist '((t . ivy--regex-ignore-order))) :custom (ivy-mode 1) (ivy-count-format "(%d/%d) ")) (use-package org :ensure nil :bind (("C-c l" . org-store-link) ("C-c c" . org-capture) ("C-c a" . org-agenda) ("C-c b" . org-switchb) :map org-mode-map ("M-." . org-open-at-point) ("M-," . org-mark-ring-goto)) :custom ;; keep-sorted start block=yes (org-agenda-start-on-weekday 0) (org-agenda-weekend-days '(5 6)) (org-default-notes-file "~/Documents/notes.org") (org-agenda-files (list org-default-notes-file)) (org-capture-templates '( ("i" "Thoughts on Debugging and Research" entry (file+headline org-default-notes-file "Inquiries") "** %?\n %U\n*** Failures and possible solutions") ("t" "Task" entry (file+headline org-default-notes-file "Tasks") "** TODO %?\n %U") )) (org-clock-sound "~/Music/single-ding.wav") ;; keep-sorted end ) (use-package org-contrib) (use-package org-contacts :after org-contrib) (use-package age :custom (age-default-identity "~/.age/key") (age-default-recipient "~/.age/key.pub") :config (age-file-enable)) ;; EPUB reader (use-package nov :init (setq auto-mode-alist (map-merge 'list '(("\\.epub\\'" . nov-mode)) auto-mode-alist)) ) (use-package company :init (global-company-mode) :diminish company-mode) (use-package apt-mode :disabled t) (use-package docker :bind ("C-c d" . docker) :custom (docker-command "podman") (docker-network-columns '((:name "Network ID" :width 20 :template "{{ json .ID }}" :sort nil :format nil) (:name "Name" :width 50 :template "{{ json .Name }}" :sort nil :format nil) (:name "Driver" :width 10 :template "{{ json .Driver }}" :sort nil :format nil)))) (use-package iedit) (use-package wgrep) (use-package apheleia :config (apheleia-global-mode) (setf (alist-get 'emacs-lisp-mode apheleia-mode-alist nil 'remove) nil) (setf (alist-get 'ruff-isort apheleia-formatters) '("ruff" "check" "-n" "--select" "I" "--select" "F401" "--fix" "--fix-only" "--stdin-filename" filepath "-")) (setf (alist-get 'python-mode apheleia-mode-alist) '(ruff-isort ruff)) (setf (alist-get 'python-ts-mode apheleia-mode-alist) '(ruff-isort ruff)) :diminish apheleia-mode ) (use-package flymake :ensure nil :bind (:map flymake-mode-map ("C-c C-l" . flymake-show-buffer-diagnostics) ("C-x C-l" . flymake-show-project-diagnostics) ("C-c C-n" . flymake-goto-next-error) ("C-c C-p" . flymake-goto-prev-error)) :custom (flymake-show-diagnostics-at-end-of-line t) ) ;; Note: debugging Python in a virtualenv requires debugpy to be installed inside the venv (use-package dape) ;; Requires poetry to be installed (use-package poetry) (defun load-python-env () "Set up the Python IDE in the current project." (interactive) (when (derived-mode-p 'python-mode) (progn (poetry-venv-workon) (eglot-ensure)))) (use-package python :bind (:map python-mode-map ("C-c C-p" . nil) ("C-c C-l" . nil) ("C-c t" . elpy-test)) :hook (hack-local-variables . load-python-env) :config (load "python-tests.el") :custom (elpy-test-runner 'elpy-test-pytest-runner) ) ;; Jupyter notebook integration (use-package ein :bind (("C-z j" . ein:run) :map ein:notebook-mode-map ("C-c C-x k" . ein:notebook-switch-kernel)) :config (require 'ein-notebook) :custom ;; keep-sorted start (ein:jupyter-default-notebook-directory "~/Projects/notebooks") (ein:output-area-inlined-images t) ;; keep-sorted end ) (use-package direnv :config (direnv-mode)) (use-package rustic :custom (rustic-lsp-client 'eglot) ) (use-package go-config :ensure nil :hook (go-ts-mode . eglot-ensure) :init (setq auto-mode-alist (map-merge 'list '(("\\.go\\'" . go-ts-mode) ("/go\\.mod\\'" . go-mod-ts-mode) ("/go\\.work\\'" . go-work-ts-mode)) auto-mode-alist)) ) (defun list-ollama-models () "Query the local Ollama server for the list of installed models." (condition-case error-var (mapcar #'intern (mapcar #'car (mapcar #'split-string (cdr (process-lines "podllama" "list"))))) (error (message "Failed to list local models: %s" error-var) ()))) (use-package gptel :hook ;; keep-sorted start (gptel-mode . gptel-highlight-mode) (gptel-mode . visual-line-mode) (gptel-post-response . gptel-end-of-response) (gptel-post-stream . gptel-auto-scroll) ;; keep-sorted end :custom ;; keep-sorted start (gptel-backend (gptel-get-backend "Ollama")) (gptel-default-mode 'org-mode) (gptel-expert-commands t) (gptel-highlight-methods '(face margin)) (gptel-model 'llama3.2:latest) ;; keep-sorted end :preface (gptel-make-anthropic "Claude" :stream t :key 'gptel-api-key-from-auth-source ) (gptel-make-ollama "Ollama" :stream t :models (list-ollama-models) ) ) (use-package power-mode) (use-package emms :config (require 'emms-setup) (emms-all) :custom ;; keep-sorted start (emms-info-functions '(emms-info-native)) (emms-player-list '(emms-player-mpv)) ;; keep-sorted end ) (defun my-qr-selection () (interactive) (if (use-region-p) (qrencode-region (region-beginning) (region-end)) (let ((url (thing-at-point-url-at-point))) (if (null url) (call-interactively #'qrencode-string) (qrencode--encode-to-buffer url))))) (use-package qrencode :bind (("C-z q" . my-qr-selection)))