;; The default is 800 kilobytes. Measured in bytes. (setq gc-cons-threshold (* 50 1000 1000)) ;; use UTF-8 everywhere (set-language-environment "UTF-8") ;; set default font size (defvar swarsel/default-font-size 130) (setq swarsel-standard-font "FiraCode Nerd Font Mono" swarsel-alt-font "FiraCode Nerd Font Mono") ;; set Nextcloud directory for journals etc. (setq swarsel-sync-directory "~/Nextcloud" swarsel-emacs-directory "~/.emacs.d" swarsel-dotfiles-directory "~/.dotfiles" swarsel-projects-directory "~/Documents/GitHub") (setq swarsel-emacs-org-filepath (expand-file-name "Emacs.org" swarsel-dotfiles-directory) swarsel-nix-org-filepath (expand-file-name "Nix.org" swarsel-dotfiles-directory)) ;; set Emacs main configuration .org names (setq swarsel-emacs-org-file "Emacs.org" swarsel-anki-org-file "Anki.org" swarsel-tasks-org-file "Tasks.org" swarsel-archive-org-file "Archive.org" swarsel-org-folder-name "org" swarsel-obsidian-daily-folder-name "⭐ Personal/Journal" swarsel-obsidian-folder-name "Obsidian" swarsel-obsidian-vault-name "Main") ;; set directory paths (setq swarsel-org-directory (expand-file-name swarsel-org-folder-name swarsel-sync-directory)) ; path to org folder (setq swarsel-obsidian-directory (expand-file-name swarsel-obsidian-folder-name swarsel-sync-directory)) ; path to obsidian (setq swarsel-obsidian-vault-directory (expand-file-name swarsel-obsidian-vault-name swarsel-obsidian-directory)) ; path to obsidian vault (setq swarsel-obsidian-daily-directory (expand-file-name swarsel-obsidian-daily-folder-name swarsel-obsidian-vault-directory)) ; path to obsidian daily folder ;; filepaths to certain documents (setq swarsel-org-anki-filepath (expand-file-name swarsel-anki-org-file swarsel-org-directory) ; path to anki export file swarsel-org-tasks-filepath (expand-file-name swarsel-tasks-org-file swarsel-org-directory) swarsel-org-archive-filepath (expand-file-name swarsel-archive-org-file swarsel-org-directory)) ;; set paths to authentication files (forge) ;; (setq auth-source-pass-filename "~/.local/share/password-store" (setq auth-sources '( "~/.emacs.d/.caldav" "~/.emacs.d/.authinfo.gpg") auth-source-cache-expiry nil) ; default is 2h ;; set pandoc for markdown compilation (setq markdown-command "pandoc") ;; set org-caldav-sync-initalization (setq swarsel-caldav-synced 0) ;; Change the user-emacs-directory to keep unwanted things out of ~/.emacs.d (setq user-emacs-directory (expand-file-name "~/.cache/emacs/") url-history-file (expand-file-name "url/history" user-emacs-directory)) ;; Use no-littering to automatically set common paths to the new user-emacs-directory (use-package no-littering) (setq custom-file (expand-file-name "programs/emacs/custom.el" swarsel-dotfiles-directory)) (load custom-file t) (defalias 'yes-or-no-p 'y-or-n-p) ;;(setq-default show-trailing-whitespace t) (add-hook 'before-save-hook 'delete-trailing-whitespace) (global-hl-line-mode 1) ;; (setq redisplay-dont-pause t) ;; obsolete (delete-selection-mode 1) (pixel-scroll-precision-mode 1) (setq vc-follow-symlinks t) (setq require-final-newline t) (winner-mode 1) ;; less noise when compiling elisp (setq byte-compile-warnings '(not free-vars unresolved noruntime lexical make-local)) (setq native-comp-async-report-warnings-errors nil) (setq load-prefer-newer t) ;; disable a keybind that does more harm than good (global-set-key [remap suspend-frame] (lambda () (interactive) (message "This keybinding is disabled (was 'suspend-frame')"))) ;; (scroll-bar-mode -1) ;; (tool-bar-mode -1) ;; (tooltip-mode -1) ;; (menu-bar-mode -1) (setq visible-bell nil) (setq initial-major-mode 'fundamental-mode initial-scratch-message nil) (setq-default indent-tabs-mode nil tab-width 2) (setq tab-always-indent 'complete) (use-package highlight-indent-guides :hook (prog-mode . highlight-indent-guides-mode) :init (setq highlight-indent-guides-method 'character) (setq highlight-indent-guides-character "‖") (setq highlight-indent-guides-responsive 'top) ) (setq scroll-step 1 scroll-margin 4 scroll-conservatively 5) (defun swarsel/with-buffer-name-prompt-and-make-subdirs () (let ((parent-directory (file-name-directory buffer-file-name))) (when (and (not (file-exists-p parent-directory)) (y-or-n-p (format "Directory `%s' does not exist! Create it? " parent-directory))) (make-directory parent-directory t)))) (add-to-list 'find-file-not-found-functions #'swarsel/with-buffer-name-prompt-and-make-subdirs) ;; Emulate vim in emacs (use-package evil :init (setq evil-want-integration t) ; loads evil (setq evil-want-keybinding nil) ; loads "helpful bindings" for other modes (setq evil-want-C-u-scroll t) ; scrolling using C-u (setq evil-want-C-i-jump nil) ; jumping with C-i (setq evil-want-Y-yank-to-eol t) ; give Y some utility (setq evil-shift-width 2) ; uniform indent (setq evil-respect-visual-line-mode t) ; i am torn on this one ; sane splitting (setq evil-split-window-below t) (setq evil-vsplit-window-right t) :config (evil-mode 1) (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state) ; alternative for exiting insert mode (define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join) ; dont show help but instead do normal vim delete backwards ;; evil undo system (evil-set-undo-system 'undo-tree) ;; Use visual line motions even outside of visual-line-mode buffers ;; (evil-global-set-key 'motion "j" 'evil-next-visual-line) ;; (evil-global-set-key 'motion "k" 'evil-previous-visual-line) ;; Don't use evil-mode in these contexts, or use it in a specific mode (evil-set-initial-state 'messages-buffer-mode 'emacs) (evil-set-initial-state 'dashboard-mode 'emacs) (evil-set-initial-state 'dired-mode 'emacs) (evil-set-initial-state 'cfw:details-mode 'emacs) (evil-set-initial-state 'Custom-mode 'emacs) ; god knows why this mode is in uppercase ; require a specific evil state (evil-set-initial-state 'mu4e-headers-mode 'normal) (evil-set-initial-state 'python-inferior-mode 'normal) (add-hook 'org-capture-mode-hook 'evil-insert-state) (add-to-list 'evil-buffer-regexps '("COMMIT_EDITMSG" . insert))) ;; Evil configuration for different modes (use-package evil-collection :after evil :config (evil-collection-init) (setq forge-add-default-bindings nil)) (use-package evil-snipe :after evil :demand :config (evil-snipe-mode +1) (evil-snipe-override-mode +1)) (use-package evil-cleverparens) (use-package evil-surround) (use-package evil-goggles :after evil :demand :init (setq evil-goggles-duration 0.05) :config (push '(evil-operator-eval :face evil-goggles-yank-face :switch evil-goggles-enable-yank :advice evil-goggles--generic-async-advice) evil-goggles--commands) (evil-goggles-mode) (evil-goggles-use-diff-faces) ) (use-package undo-tree ;; :init (global-undo-tree-mode) :bind (:map undo-tree-visualizer-mode-map ("h" . undo-tree-visualize-switch-branch-left) ("l" . undo-tree-visualize-switch-branch-left) ("j" . undo-tree-visualize-redo) ("k" . undo-tree-visualize-undo)) :config (setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo"))) ) (add-hook 'prog-mode-hook 'undo-tree-mode) (add-hook 'text-mode-hook 'undo-tree-mode) (add-hook 'org-mode-hook 'undo-tree-mode) (add-hook 'latex-mode-hook 'undo-tree-mode) (let ((backup-dir "~/tmp/emacs/backups") (auto-saves-dir "~/tmp/emacs/auto-saves/")) (dolist (dir (list backup-dir auto-saves-dir)) (when (not (file-directory-p dir)) (make-directory dir t))) (setq backup-directory-alist `(("." . ,backup-dir)) auto-save-file-name-transforms `((".*" ,auto-saves-dir t)) auto-save-list-file-prefix (concat auto-saves-dir ".saves-") tramp-backup-directory-alist `((".*" . ,backup-dir)) tramp-auto-save-directory auto-saves-dir)) (setq backup-by-copying t ; Don't delink hardlinks delete-old-versions t ; Clean up the backups version-control t ; Use version numbers on backups, kept-new-versions 5 ; keep some new versions kept-old-versions 2) ; and some old ones, too ;; Make ESC quit prompts (global-set-key (kbd "") 'keyboard-escape-quit) ;; Set up general keybindings (use-package general :config (general-create-definer swarsel/leader-keys :keymaps '(normal insert visual emacs) :prefix "SPC" :global-prefix "C-SPC") (swarsel/leader-keys "t" '(:ignore t :which-key "toggles") "ts" '(hydra-text-scale/body :which-key "scale text") "tl" '(display-line-numbers-mode :which-key "line numbers") "to" '(olivetti-mode :wk "olivetti") "td" '(darkroom-tentative-mode :wk "darkroom") "tw" '((lambda () (interactive) (toggle-truncate-lines)) :which-key "line wrapping") "m" '(:ignore m :which-key "modes/programs") "mm" '((lambda () (interactive) (mu4e)) :which-key "mu4e") "mg" '((lambda () (interactive) (magit-list-repositories)) :which-key "magit-list-repos") "mc" '((lambda () (interactive) (swarsel/open-calendar)) :which-key "calendar") "mp" '(popper-toggle :which-key "popper") "md" '(dirvish :which-key "dirvish") "c" '(:ignore c :which-key "capture") "cj" '((lambda () (interactive) (org-capture nil "jj")) :which-key "journal") "cs" '(markdown-download-screenshot :which-key "screenshot") "l" '(:ignore l :which-key "links") "le" '((lambda () (interactive) (find-file swarsel-emacs-org-filepath)) :which-key "Emacs.org") "ls" '((lambda () (interactive) (find-file "/smb:Swarsel@192.168.1.3:")) :which-key "Server") "lo" '(dired swarsel-obsidian-vault-directory :which-key "obsidian") "la" '((lambda () (interactive) (find-file swarsel-org-anki-filepath)) :which-key "anki") "ln" '((lambda () (interactive) (find-file swarsel-nix-org-filepath)) :which-key "Nix.org") "lp" '((lambda () (interactive) (projectile-switch-project)) :which-key "switch project") "lg" '((lambda () (interactive) (magit-list-repositories)) :which-key "list git repos") "a" '(:ignore a :which-key "anki") "ap" '(anki-editor-push-tree :which-key "push new cards") "an" '((lambda () (interactive) (org-capture nil "a")) :which-key "new card") "as" '(swarsel-anki-set-deck-and-notetype :which-key "change deck and notetype") "h" '(:ignore h :which-key "help") "hy" '(yas-describe-tables :which-key "yas tables") "hb" '(embark-bindings :which-key "current key bindings") "h" '(:ignore t :which-key "describe") "he" 'view-echo-area-messages "hf" 'describe-function "hF" 'describe-face "hl" '(view-lossage :which-key "show command keypresses") "hL" 'find-library "hm" 'describe-mode "hk" 'describe-key "hK" 'describe-keymap "hp" 'describe-package "hv" 'describe-variable "hd" 'devdocs-lookup "w" '(:ignore t :which-key "window") "wl" 'windmove-right "wh" 'windmove-left "wk" 'windmove-up "wj" 'windmove-down "wr" 'winner-redo "wd" 'delete-window "w=" 'balance-windows-area "wD" 'kill-buffer-and-window "wu" 'winner-undo "wr" 'winner-redo "w/" 'evil-window-vsplit "w-" 'evil-window-split "wm" '(delete-other-windows :wk "maximize") )) ;; General often used hotkeys (general-define-key "C-M-a" (lambda () (interactive) (org-capture nil "a")) ; make new anki card "C-M-d" 'swarsel-obsidian-daily ; open daily obsidian file and create if not exist "C-M-S" 'swarsel-anki-set-deck-and-notetype ; switch deck and notetye for new anki cards "C-M-s" 'markdown-download-screenshot ; wrapper for org-download-screenshot "C-c d" 'duplicate-line ; duplicate line on CURSOR "C-M-j" 'consult-buffer "C-s" 'consult-line ) (setq inhibit-startup-message t) ;; (set-fringe-mode nil) ; Give some breathing room ;; Increase undo limit and allow for more fine grained undo, base emacs deletes way too much on undo (setq undo-limit 80000000 evil-want-fine-undo t auto-save-default t password-cache-expiry nil ) ;; (display-time-mode 1) (global-subword-mode 1) ; Iterate through CamelCase words (use-package rainbow-mode :config (rainbow-mode)) (setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) ;; one line at a time (setq mouse-wheel-progressive-speed nil) ;; don't accelerate scrolling (setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse (add-hook 'prog-mode-hook 'display-line-numbers-mode) (add-hook 'text-mode-hook 'display-line-numbers-mode) ;; (defun swarsel/font-setup (frame) ;; (set-face-attribute 'default nil :font swarsel-standard-font :height swarsel/default-font-size) ;; ;; Set the fixed pitch face - basically normal text ;; (set-face-attribute 'fixed-pitch nil :font swarsel-standard-font :height 140) ;; ;; Set the variable pitch face - basically headers etc ;; (set-face-attribute 'variable-pitch nil :font swarsel-alt-font :height 100 :weight 'regular) ;; (set-face-attribute 'region nil :foreground "cyan" :background "gray40" :weight 'bold) ;; ;; (remove-hook 'after-make-frame-functions #'swarsel/font-setup) ;; ) ;; (add-hook 'after-make-frame-functions #'swarsel/font-setup) ;; (defun swarsel/font-setup (frame) (dolist (face '(default fixed-pitch)) (set-face-attribute face nil :font "FiraCode Nerd Font Mono")) (add-to-list 'default-frame-alist '(font . "FiraCode Nerd Font Mono")) (set-face-attribute 'default nil :height 100) (set-face-attribute 'fixed-pitch nil :height 1.0) (set-face-attribute 'variable-pitch nil :family "IBM Plex Sans" :weight 'regular :height 1.06) ;; (enable-theme 'doom-city-lights) ;; ) ;; (add-hook 'after-make-frame-functions #'swarsel/font-setup) (use-package doom-themes :init (load-theme 'doom-city-lights t)) (use-package solaire-mode :init (solaire-global-mode +1)) ;; (set-frame-parameter (selected-frame) 'alpha '(95 . 95)) ;; (add-to-list 'default-frame-alist '(alpha . (95 . 95))) ;; (set-frame-parameter (selected-frame) 'fullscreen 'maximized) ;; (add-to-list 'default-frame-alist '(fullscreen . maximized)) (use-package mixed-pitch :custom (mixed-pitch-set-height nil) (mixed-pitch-variable-pitch-cursor nil) :hook (text-mode . mixed-pitch-mode)) (use-package nerd-icons) ;; Adds a more beautiful modeline with less clutter (use-package doom-modeline :init (doom-modeline-mode) :custom ((doom-modeline-height 22) (doom-modeline-indent-info t))) ;; Generally show line numbers (column-number-mode) ;; (unless (string-match-p "^Power N/A" (battery)) ; On laptops... ;; (display-battery-mode 1)) (use-package vertico :custom (vertico-scroll-margin 0) (vertico-count 10) (vertico-resize t) (vertico-cycle t) :init (vertico-mode) (vertico-mouse-mode)) (use-package vertico-directory :ensure nil :after vertico :bind (:map vertico-map ("RET" . vertico-directory-enter) ("DEL" . vertico-directory-delete-char) ("M-DEL" . vertico-directory-delete-word)) ;; Tidy shadowed file names :hook (rfn-eshadow-update-overlay . vertico-directory-tidy)) (use-package orderless :custom (completion-styles '(orderless flex basic)) (completion-category-overrides '((file (styles . (partial-completion))) (eglot (styles orderless))))) (use-package consult :config (setq consult-fontify-max-size 1024) :bind ("C-x b" . consult-buffer) ("C-c " . consult-global-mark) ("C-c C-a" . consult-org-agenda) ("C-x O" . consult-outline) ("M-g M-g" . consult-goto-line) ("M-g i" . consult-imenu) ("M-s s" . consult-line) ("M-s M-s" . consult-line-multi)) (use-package embark :bind (("C-." . embark-act) ("M-." . embark-dwim) ("C-h B" . embark-bindings)) :custom (prefix-help-command #'embark-prefix-help-command) (embark-quit-after-action '((t . nil))) :config (add-to-list 'display-buffer-alist '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" nil (window-parameters (mode-line-format . none))))) (use-package embark-consult :after (embark consult) :demand t ; only necessary if you have the hook below ;; if you want to have consult previews as you move around an ;; auto-updating embark collect buffer :hook (embark-collect-mode . consult-preview-at-point-mode)) (use-package marginalia :after vertico :init (marginalia-mode) (setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))) (use-package nerd-icons-completion :after (marginalia nerd-icons) :hook (marginalia-mode . nerd-icons-completion-marginalia-setup) :init (nerd-icons-completion-mode)) ;; (use-package ivy ;; :init (ivy-mode 1) ;; :diminish ;; :bind (("C-s" . swiper) ; call swiper (find tool) ;; :map ivy-minibuffer-map ;; ;("TAB" . ivy-alt-done) ; autocomplete ;; ("C-l" . ivy-alt-done) ;; ("C-" . ivy-alt-done) ; for kyria ;; ("C-h" . counsel-up-directory) ; for kyria ;; ("C-" . counsel-up-directory) ; for kyria ;; ("C-j" . ivy-next-line) ; go up and down in ivy using vim keys ;; ("C-" . ivy-next-line) ; for kyria ;; ("C-k" . ivy-previous-line) ;; ("C-" . ivy-previous-line) ; for kyria ;; :map ivy-switch-buffer-map ;; ("C-k" . ivy-previous-line) ;; ("C-" . ivy-previous-line) ; for kyria ;; ("C-l" . ivy-done) ;; ("C-" . ivy-done) ; for kyria ;; ("C-d" . ivy-switch-buffer-kill) ;; :map ivy-reverse-i-search-map ;; ("C-k" . ivy-previous-line) ;; ("C-" . ivy-previous-line) ; for kyria ;; ("C-d" . ivy-reverse-i-search-kill)) ;; :config ;; (setq ivy-use-virtual-buffers t) ;; (setq ivy-count-format "(%d/%d) ") ;; (setq ivy-wrap t)) ;; ;; More information about functions in ivy-mode ;; (use-package ivy-rich ;; :init ;; (ivy-rich-mode 1)) ;; (use-package counsel ;; :init (counsel-mode 1) ;; :bind (("C-M-j" . counsel-switch-buffer) ;; ("M-x" . counsel-M-x) ;; ("C-x b" . counsel-ibuffer) ;; ("C-x C-f" . counsel-find-file) ;; :map minibuffer-local-map ;; ("C-r" . 'counsel-minibuffer-history)) ;; :config ;; (setq ivy-initial-inputs-alist nil)) (use-package which-key :init (which-key-mode) :diminish which-key-mode :config (setq which-key-idle-delay 0.3)) ;; (use-package helpful ;; :custom ;; (counsel-describe-function-function #'helpful-callable) ;; (counsel-describe-variable-function #'helpful-variable) ;; :bind ;; ([remap describe-function] . counsel-describe-function) ;; ([remap describe-command] . helpful-command) ;; ([remap describe-variable] . counsel-describe-variable) ;; ([remap describe-key] . helpful-key)) (use-package helpful :custom (help-select-window t) :bind (("C-h f" . helpful-callable) ("C-h v" . helpful-variable) ("C-h k" . helpful-key) ("C-h C-." . helpful-at-point))) (use-package hydra) ;; change the text size of the current buffer (defhydra hydra-text-scale (:timeout 4) "scale text" ("j" text-scale-increase "in") ("k" text-scale-decrease "out") ("f" nil "finished" :exit t)) (use-package ligature :config (ligature-set-ligatures 'prog-mode '("|||>" "<|||" "<==>" "" "---" "-<<" "<~~" "<~>" "<*>" "<||" "<|>" "<$>" "<==" "<=>" "<=<" "<->" "<--" "<-<" "<<=" "<<-" "<<<" "<+>" "" "###" "#_(" "..<" "..." "+++" "/==" "///" "_|_" "www" "&&" "^=" "~~" "~@" "~=" "~>" "~-" "**" "*>" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|" "[|" "]#" "::" ":=" ":>" ":<" "$>" "==" "=>" "!=" "!!" ">:" ">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~" "<*" "<|" "<:" "<$" "<=" "<>" "<-" "<<" "<+" "" "++" "?:" "?=" "?." "??" "/*" "/=" "/>" "//" "__" "~~" "(*" "*)" "\\\\" "://" ";;")) (global-ligature-mode t)) (use-package popper :bind (("M-[" . popper-toggle)) :init (setq popper-reference-buffers '("\\*Messages\\*" ("\\*Warnings\\*" . hide) "Output\\*$" "\\*Async Shell Command\\*" "\\*Async-native-compile-log\\*" help-mode helpful-mode "*Occur*" "*scratch*" "*julia*" "*Python*" ;; ("*tex-shell*" . hide) (compilation-mode . hide))) (popper-mode +1) (popper-echo-mode +1)) (use-package shackle :config (setq shackle-rules '(("*Messages*" :select t :popup t :align right :size 0.3) ("*Warnings*" :ignore t :popup t :align right :size 0.3) ("*Occur*" :select t :popup t :align below :size 0.2) ("*scratch*" :select t :popup t :align below :size 0.2) ("*Python*" :select t :popup t :align below :size 0.2) ("*tex-shell*" :ignore t :popup t :align below :size 0.2) (helpful-mode :select t :popup t :align right :size 0.35) (help-mode :select t :popup t :align right :size 0.4))) (shackle-mode 1)) (setq-default indicate-buffer-boundaries t) (defun swarsel/org-mode-setup () (org-indent-mode) (variable-pitch-mode 1) ;;(auto-fill-mode 0) (setq display-line-numbers-type 'relative display-line-numbers-current-absolute 1 display-line-numbers-width-start nil display-line-numbers-width 6 display-line-numbers-grow-only 1) (add-hook 'org-tab-first-hook 'org-end-of-line) (visual-line-mode 1)) ;; (setq evil-auto-indent nil) ;;(diminish org-indent-mode) (defun swarsel/org-font-setup () ;; Replace list hyphen with dot (font-lock-add-keywords 'org-mode '(("^ *\\([-]\\) " (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))) (use-package org ;;:diminish (org-indent-mode) :hook (org-mode . swarsel/org-mode-setup) :bind ("C-" . org-fold-outer) :config (setq org-ellipsis " ⤵" org-hide-emphasis-markers t) (setq org-startup-folded t) (setq org-support-shift-select t) (setq org-agenda-start-with-log-mode t) (setq org-log-done 'time) (setq org-log-into-drawer t) (setq org-startup-with-inline-images t) (setq org-image-actual-width nil) (setq org-format-latex-options '(:foreground "White" :background default :scale 2.0 :html-foreground "Black" :html-background "Transparent" :html-scale 1.0 :matchers ("begin" "$1" "$" "$$" "\\(" "\\["))) ;; (setq org-agenda-files ;; '(swarsel-org-tasks-filepath ;; swarsel-org-archive-filepath ;; swarsel-org-anki-filepath)) (setq org-agenda-files '("~/Calendars/leon_cal.org")) (require 'org-habit) (add-to-list 'org-modules 'org-habit) (setq org-habit-graph-column 60) (setq org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)") (sequence "BACKLOG(b)" "PLAN(p)" "READY(r)" "ACTIVE(a)" "REVIEW(v)" "WAIT(w@/!)" "HOLD(h)" "|" "COMPLETED(c)" "CANC(k@)"))) (setq org-refile-targets '((swarsel-archive-org-file :maxlevel . 1) (swarsel-anki-org-file :maxlevel . 1) (swarsel-tasks-org-file :maxlevel . 1))) ;; Configure custom agenda views (setq org-agenda-custom-commands '(("d" "Dashboard" ((agenda "" ((org-deadline-warning-days 7))) (todo "NEXT" ((org-agenda-overriding-header "Next Tasks"))) (tags-todo "agenda/ACTIVE" ((org-agenda-overriding-header "Active Projects"))))) ("n" "Next Tasks" ((todo "NEXT" ((org-agenda-overriding-header "Next Tasks"))))) ("W" "Work Tasks" tags-todo "+work-email") ;; Low-effort next actions ("e" tags-todo "+TODO=\"NEXT\"+Effort<15&+Effort>0" ((org-agenda-overriding-header "Low Effort Tasks") (org-agenda-max-todos 20) (org-agenda-files org-agenda-files))) ("w" "Workflow Status" ((todo "WAIT" ((org-agenda-overriding-header "Waiting on External") (org-agenda-files org-agenda-files))) (todo "REVIEW" ((org-agenda-overriding-header "In Review") (org-agenda-files org-agenda-files))) (todo "PLAN" ((org-agenda-overriding-header "In Planning") (org-agenda-todo-list-sublevels nil) (org-agenda-files org-agenda-files))) (todo "BACKLOG" ((org-agenda-overriding-header "Project Backlog") (org-agenda-todo-list-sublevels nil) (org-agenda-files org-agenda-files))) (todo "READY" ((org-agenda-overriding-header "Ready for Work") (org-agenda-files org-agenda-files))) (todo "ACTIVE" ((org-agenda-overriding-header "Active Projects") (org-agenda-files org-agenda-files))) (todo "COMPLETED" ((org-agenda-overriding-header "Completed Projects") (org-agenda-files org-agenda-files))) (todo "CANC" ((org-agenda-overriding-header "Cancelled Projects") (org-agenda-files org-agenda-files))))))) (setq org-capture-templates `( ("a" "Anki basic" entry (file+headline swarsel-org-anki-filepath "Dispatch") (function swarsel-anki-make-template-string)) ("A" "Anki cloze" entry (file+headline org-swarsel-anki-file "Dispatch") "* %<%H:%M>\n:PROPERTIES:\n:ANKI_NOTE_TYPE: Cloze\n:ANKI_DECK: 🦁 All::01 ❤️ Various::00 ✨ Allgemein\n:END:\n** Text\n%?\n** Extra\n") ("t" "Tasks / Projects") ("tt" "Task" entry (file+olp swarsel-org-tasks-filepath "Inbox") "* TODO %?\n %U\n %a\n %i" :empty-lines 1) ("j" "Journal Entries") ("jj" "Journal" entry (file+olp+datetree swarsel-org-journal-filepath) "\n* %<%I:%M %p> - Journal :journal:\n\n%?\n\n" ;; ,(dw/read-file-as-string "~/Notes/Templates/Daily.org") :clock-in :clock-resume :empty-lines 1))) (swarsel/org-font-setup)) ;; ;; Set faces for heading levels ;; (with-eval-after-load 'org-faces (dolist (face '((org-level-1 . 1.3) ;; (org-level-2 . 1.2) ;; (org-level-3 . 1.15) ;; (org-level-4 . 1.1) ;; (org-level-5 . 1.1) ;; (org-level-6 . 1.1) ;; (org-level-7 . 1.1) ;; (org-level-8 . 1.1))) ;; (set-face-attribute (car face) nil :font swarsel-alt-font :weight 'regular :height (cdr face))) ;; ;; Ensure that anything that should be fixed-pitch in Org files appears that way ;; (set-face-attribute 'org-block nil :inherit '(fixed-pitch)) ;; (set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch)) ;; (set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch)) ;; (set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch)) ;; (set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch)) ;; (set-face-attribute 'org-checkbox nil :inherit '(fixed-pitch))) ;; Show hidden emphasis markers (use-package org-appear :hook (org-mode . org-appear-mode) :init (setq org-appear-autolinks t) (setq org-appear-autosubmarkers t) ) (use-package org-bullets :after org :hook (org-mode . org-bullets-mode) :custom (org-bullets-bullet-list '("◉" "○" "●" "○" "●" "○" "●"))) (defun swarsel/org-mode-visual-fill () (setq visual-fill-column-width 150 visual-fill-column-center-text t) (visual-fill-column-mode 1)) (use-package visual-fill-column :hook (org-mode . swarsel/org-mode-visual-fill)) (setq org-fold-core-style 'overlays) (org-babel-do-load-languages 'org-babel-load-languages '((emacs-lisp . t) (python . t))) (push '("conf-unix" . conf-unix) org-src-lang-modes) (require 'org-tempo) (add-to-list 'org-structure-template-alist '("sh" . "src shell")) (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) (add-to-list 'org-structure-template-alist '("py" . "src python")) (add-to-list 'org-structure-template-alist '("nix" . "src nix :tangle")) (defun swarsel/org-babel-tangle-config () (when (string-equal (buffer-file-name) swarsel-emacs-org-filepath) ;; Dynamic scoping to the rescue (let ((org-confirm-babel-evaluate nil)) (org-babel-tangle))) (when (string-equal (buffer-file-name) swarsel-nix-org-filepath) ;; Dynamic scoping to the rescue (let ((org-confirm-babel-evaluate nil)) (org-babel-tangle)))) (add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'swarsel/org-babel-tangle-config))) (add-hook 'markdown-mode-hook (lambda () (local-set-key (kbd "C-c C-x C-l") 'org-latex-preview) (local-set-key (kbd "C-c C-x C-u") 'markdown-toggle-url-hiding) )) (use-package org-download :after org :defer nil :custom (org-download-method 'directory) (org-download-image-dir "./images") (org-download-heading-lvl 0) (org-download-timestamp "org_%Y%m%d-%H%M%S_") ;;(org-image-actual-width 500) (org-download-screenshot-method "grim -g \"$(slurp)\" %s") :bind ("C-M-y" . org-download-screenshot) :config (require 'org-download)) (use-package org-fragtog) (add-hook 'org-mode-hook 'org-fragtog-mode) (add-hook 'markdown-mode-hook 'org-fragtog-mode) (defun org-fold-outer () (interactive) (org-beginning-of-line) (if (string-match "^*+" (thing-at-point 'line t)) (outline-up-heading 1)) (outline-hide-subtree) ) (use-package org-modern :config (setq org-modern-block-name '((t . t) ("src" "»" "∥"))) :hook (org-mode . org-modern-mode)) (use-package nix-mode :mode "\\.nix\\'") ;; https://github.com/mooreryan/markdown-dnd-images ;; (add-to-list 'load-path "~/.emacs.d/packages") ;; (require 'markdown-dnd-images) ;; (setq dnd-save-directory "images") ;; (setq dnd-save-buffer-name nil) ;; (setq dnd-view-inline t) ;; (setq dnd-capture-source nil) ;; these next lines provide an interface for org-download in markdown mode for use with obsidian (defvar org-download-markdown-link-format "![[./%s]]\n" "Format of the file link to insert.") (defcustom org-download-markdown-link-format-function #'org-download-markdown-link-format-function-default "Function that takes FILENAME and returns a org link." :type 'function) (defun org-download-markdown-link-format-function-default (filename) "The default function of `org-download-link-format-function'." (if (and (>= (string-to-number org-version) 9.3) (eq org-download-method 'attach)) (format "[[attachment:%s]]\n" (org-link-escape (file-relative-name filename (org-attach-dir)))) (format org-download-markdown-link-format (org-link-escape (funcall org-download-abbreviate-filename-function filename))))) (defun org-download-markdown-image (link) "Save image at address LINK to `org-download--dir'." (interactive "sUrl: ") (let* ((link-and-ext (org-download--parse-link link)) (filename (cond ((and (derived-mode-p 'org-mode) (eq org-download-method 'attach)) (let ((org-download-image-dir (org-attach-dir t)) org-download-heading-lvl) (apply #'org-download--fullname link-and-ext))) ((fboundp org-download-method) (funcall org-download-method link)) (t (apply #'org-download--fullname link-and-ext))))) (setq org-download-path-last-file filename) (org-download--image link filename) (when (org-download-org-mode-p) (when (eq org-download-method 'attach) (org-attach-attach filename nil 'none)) (org-download-markdown-insert-link link filename)) (when (and (eq org-download-delete-image-after-download t) (not (url-handler-file-remote-p (current-kill 0)))) (delete-file link delete-by-moving-to-trash)))) (defun org-download-markdown-screenshot (&optional basename) "Capture screenshot and insert the resulting file. The screenshot tool is determined by `org-download-screenshot-method'." (interactive) (let* ((screenshot-dir (file-name-directory org-download-screenshot-file)) (org-download-screenshot-file (if basename (concat screenshot-dir basename) org-download-screenshot-file))) (make-directory screenshot-dir t) (if (functionp org-download-screenshot-method) (funcall org-download-screenshot-method org-download-screenshot-file) (shell-command-to-string (format org-download-screenshot-method org-download-screenshot-file))) (when (file-exists-p org-download-screenshot-file) (org-download-markdown-image org-download-screenshot-file) (delete-file org-download-screenshot-file)))) (defun org-download-markdown-insert-link (link filename) (let* ((beg (point)) (line-beg (line-beginning-position)) (indent (- beg line-beg)) (in-item-p (org-in-item-p)) str) (if (looking-back "^[ \t]+" line-beg) (delete-region (match-beginning 0) (match-end 0)) (newline)) (insert (funcall org-download-annotate-function link)) (dolist (attr org-download-image-attr-list) (insert attr "\n")) (insert (if (= org-download-image-html-width 0) "" (format "#+attr_html: :width %dpx\n" org-download-image-html-width))) (insert (if (= org-download-image-latex-width 0) "" (format "#+attr_latex: :width %dcm\n" org-download-image-latex-width))) (insert (if (= org-download-image-org-width 0) "" (format "#+attr_org: :width %dpx\n" org-download-image-org-width))) (insert (funcall org-download-markdown-link-format-function filename)) (org-download--display-inline-images) (setq str (buffer-substring-no-properties line-beg (point))) (when in-item-p (indent-region line-beg (point) indent)) str)) (defun markdown-download-screenshot () (interactive) (org-mode) (org-download-markdown-screenshot) (markdown-mode)) (add-hook 'markdown-mode-hook (lambda () (org-display-inline-images))) (use-package olivetti :init (setq olivetti-body-width 100) (setq olivetti-recall-visual-line-mode-entry-state t)) (use-package darkroom :init (setq darkroom-text-scale-increase 3)) (use-package rg) ;; (setq treesit-language-source-alist ;; '((bash "https://github.com/tree-sitter/tree-sitter-bash") ;; (cmake "https://github.com/uyha/tree-sitter-cmake") ;; (c "https://github.com/tree-sitter/tree-sitter-c") ;; (cpp "https://github.com/tree-sitter/tree-sitter-cpp") ;; (css "https://github.com/tree-sitter/tree-sitter-css") ;; (elisp "https://github.com/Wilfred/tree-sitter-elisp") ;; (go "https://github.com/tree-sitter/tree-sitter-go") ;; (html "https://github.com/tree-sitter/tree-sitter-html") ;; (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src") ;; (json "https://github.com/tree-sitter/tree-sitter-json") ;; (make "https://github.com/alemuller/tree-sitter-make") ;; (markdown "https://github.com/ikatyang/tree-sitter-markdown") ;; (python "https://github.com/tree-sitter/tree-sitter-python") ;; (toml "https://github.com/tree-sitter/tree-sitter-toml") ;; (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src") ;; (typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src") ;; (rust "https://github.com/tree-sitter/tree-sitter-rust") ;; (sql "https://github.com/m-novikov/tree-sitter-sql") ;; (yaml "https://github.com/ikatyang/tree-sitter-yaml"))) ;; (add-hook 'rustic-mode-hook 'tree-sitter-mode) ;; (add-hook 'rustic-mode-hook 'tree-sitter-hl-mode) (use-package emacs :ensure nil :init (setq treesit-language-source-alist '((bash . ("https://github.com/tree-sitter/tree-sitter-bash")) (c . ("https://github.com/tree-sitter/tree-sitter-c")) (cmake . ("https://github.com/uyha/tree-sitter-cmake")) (cpp . ("https://github.com/tree-sitter/tree-sitter-cpp")) (css . ("https://github.com/tree-sitter/tree-sitter-css")) (elisp . ("https://github.com/Wilfred/tree-sitter-elisp")) (go . ("https://github.com/tree-sitter/tree-sitter-go")) (html . ("https://github.com/tree-sitter/tree-sitter-html")) (javascript . ("https://github.com/tree-sitter/tree-sitter-javascript")) (json . ("https://github.com/tree-sitter/tree-sitter-json")) (julia . ("https://github.com/tree-sitter/tree-sitter-julia")) (latex . ("https://github.com/latex-lsp/tree-sitter-latex")) (make . ("https://github.com/alemuller/tree-sitter-make")) (markdown . ("https://github.com/ikatyang/tree-sitter-markdown")) (R . ("https://github.com/r-lib/tree-sitter-r")) (python . ("https://github.com/tree-sitter/tree-sitter-python")) (typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "typescript/src" "typescript")) (rust . ("https://github.com/tree-sitter/tree-sitter-rust")) (sql . ("https://github.com/m-novikov/tree-sitter-sql")) (toml . ("https://github.com/tree-sitter/tree-sitter-toml")) (yaml . ("https://github.com/ikatyang/tree-sitter-yaml")))) ;; :hook (((rustic-mode) . tree-sitter-mode) ;; ((rustic-mode) . tree-sitter-hl-mode)) ) (use-package treesit-auto :config (global-treesit-auto-mode) (setq treesit-auto-install 'prompt)) (use-package direnv ;; :init (add-hook 'prog-mode-hook #'direnv-update-environment) :custom (direnv-always-show-summary nil) :config (direnv-mode)) (use-package devdocs) (use-package projectile :diminish projectile-mode :config (projectile-mode) :custom ((projectile-completion-system 'ivy)) ;; integrate ivy into completion system :bind-keymap ("C-c p" . projectile-command-map) ; all projectile commands under this :init ;; NOTE: Set this to the folder where you keep your Git repos! (when (file-directory-p swarsel-projects-directory) (setq projectile-project-search-path (list swarsel-projects-directory))) ;(setq projectile-switch-project-action #'projectile-dired) ;list files (setq projectile-switch-project-action #'magit-status)) ;; (use-package counsel-projectile ;; :config (counsel-projectile-mode)) ;; (use-package project ;; :ensure nil ;; :bind ;; (:map project-prefix-map ;; ("v" . magit-project-status)) ;; :config ;; (add-to-list 'project-switch-commands '(magit-project-status "Magit" "m"))) (use-package magit :config (setq magit-repository-directories `((,swarsel-projects-directory . 1) (,swarsel-emacs-directory . 0) (,swarsel-obsidian-directory . 0))) :custom (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)) ; stay in the same window (use-package forge :after magit) (with-eval-after-load 'forge (add-to-list 'forge-alist '("sgit.iue.tuwien.ac.at" "sgit.iue.tuwien.ac.at/api/v1" "sgit.iue.tuwien.ac.at" forge-gitea-repository))) (use-package git-timemachine :hook (git-time-machine-mode . evil-normalize-keymaps) :init (setq git-timemachine-show-minibuffer-details t) :general (general-nmap "SPC g t" 'git-timemachine-toggle) (git-timemachine-mode-map "C-k" 'git-timemachine-show-previous-revision "C-j" 'git-timemachine-show-next-revision "q" 'git-timemachine-quit)) (use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode)) (use-package highlight-parentheses :config (setq highlight-parentheses-colors nil) (setq highlight-parentheses-background-colors '("magenta" "blue" "cyan" "green" "yellow" "orange" "red")) (global-highlight-parentheses-mode t)) (electric-pair-mode 1) (setq electric-pair-preserve-balance nil) ;; don't skip newline when auto-pairing parenthesis (setq electric-pair-skip-whitespace-chars '(9 32)) ;; (use-package company ;; :after lsp-mode ;; :hook (lsp-mode . company-mode) ;; :bind (:map company-active-map ;; ("" . company-complete-selection)) ;; (:map lsp-mode-map ;; ("" . company-indent-or-complete-common)) ;; :custom ;; (company-minimum-prefix-length 1) ;; (company-idle-delay 0.7)) ;; (use-package company-box ;; :hook (company-mode . company-box-mode)) ;; (use-package corfu ;; :custom ;; (corfu-cycle t) ;; :init ;; (global-corfu-mode)) (use-package corfu :init (global-corfu-mode) (corfu-history-mode) (corfu-popupinfo-mode) ; Popup completion info :custom (corfu-auto t) (corfu-auto-prefix 3) (corfu-auto-delay 0.3) (corfu-cycle t) (corfu-quit-no-match 'separator) (corfu-separator ?\s) (corfu-quit-no-match t) (corfu-popupinfo-max-height 70) (corfu-popupinfo-delay '(0.5 . 0.2)) ;; (corfu-preview-current 'insert) ; insert previewed candidate (corfu-preselect 'prompt) (corfu-on-exact-match nil) ; Don't auto expand tempel snippets ;; Optionally use TAB for cycling, default is `corfu-complete'. :bind (:map corfu-map ("M-SPC" . corfu-insert-separator) ("" . swarsel/corfu-normal-return) ("S-" . corfu-popupinfo-scroll-down) ("S-" . corfu-popupinfo-scroll-up) ("C-" . corfu-previous) ("C-" . corfu-next) ("" . swarsel/corfu-quit-and-up) ("" . swarsel/corfu-quit-and-down)) ) ;; dont disrupt file navigation with completions (defun swarsel/corfu-normal-return (&optional arg) (interactive) (corfu-complete) (corfu-quit)) (defun swarsel/corfu-quit-and-up (&optional arg) (interactive) (corfu-quit) (evil-previous-visual-line)) (defun swarsel/corfu-quit-and-down (&optional arg) (interactive) (corfu-quit) (evil-next-visual-line)) (use-package nerd-icons-corfu) (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter) (setq nerd-icons-corfu-mapping '((array :style "cod" :icon "symbol_array" :face font-lock-type-face) (boolean :style "cod" :icon "symbol_boolean" :face font-lock-builtin-face) ;; ... (t :style "cod" :icon "code" :face font-lock-warning-face))) (use-package cape ;; Bind dedicated completion commands ;; Alternative prefix keys: C-c p, M-p, M-+, ... ;; :bind (("C-c p p" . completion-at-point) ;; capf ;; ("C-c p t" . complete-tag) ;; etags ;; ("C-c p d" . cape-dabbrev) ;; or dabbrev-completion ;; ("C-c p h" . cape-history) ;; ("C-c p f" . cape-file) ;; ("C-c p k" . cape-keyword) ;; ("C-c p s" . cape-elisp-symbol) ;; ("C-c p e" . cape-elisp-block) ;; ("C-c p a" . cape-abbrev) ;; ("C-c p l" . cape-line) ;; ("C-c p w" . cape-dict) ;; ("C-c p :" . cape-emoji) ;; ("C-c p \\" . cape-tex) ;; ("C-c p _" . cape-tex) ;; ("C-c p ^" . cape-tex) ;; ("C-c p &" . cape-sgml) ;; ("C-c p r" . cape-rfc1345)) :init ;; Add to the global default value of `completion-at-point-functions' which is ;; used by `completion-at-point'. The order of the functions matters, the ;; first function returning a result wins. Note that the list of buffer-local ;; completion functions takes precedence over the global list. (add-to-list 'completion-at-point-functions #'cape-dabbrev) (add-to-list 'completion-at-point-functions #'cape-file) (add-to-list 'completion-at-point-functions #'cape-elisp-block) ;;(add-to-list 'completion-at-point-functions #'cape-history) ;;(add-to-list 'completion-at-point-functions #'cape-keyword) ;;(add-to-list 'completion-at-point-functions #'cape-tex) ;;(add-to-list 'completion-at-point-functions #'cape-sgml) ;;(add-to-list 'completion-at-point-functions #'cape-rfc1345) ;;(add-to-list 'completion-at-point-functions #'cape-abbrev) ;;(add-to-list 'completion-at-point-functions #'cape-dict) ;;(add-to-list 'completion-at-point-functions #'cape-elisp-symbol) ;;(add-to-list 'completion-at-point-functions #'cape-line) ) ;; (use-package rustic ;; :ensure ;; :bind (:map rustic-mode-map ;; ("M-j" . lsp-ui-imenu) ;; ("M-?" . lsp-find-references) ;; ("C-c C-c l" . flycheck-list-errors) ;; ("C-c C-c a" . lsp-execute-code-action) ;; ("C-c C-c r" . lsp-rename) ;; ("C-c C-c q" . lsp-workspace-restart) ;; ("C-c C-c Q" . lsp-workspace-shutdown) ;; ("C-c C-c s" . lsp-rust-analyzer-status)) ;; :config ;; (setq rustic-format-on-save t) ;; (add-hook 'rustic-mode-hook 'rk/rustic-mode-hook)) ;; (defun rk/rustic-mode-hook () ;; ;; so that run C-c C-c C-r works without having to confirm, but don't try to ;; ;; save rust buffers that are not file visiting. Once ;; ;; https://github.com/brotzeit/rustic/issues/253 has been resolved this should ;; ;; no longer be necessary. ;; (when buffer-file-name ;; (setq-local buffer-save-without-query t)) ;; (add-hook 'before-save-hook 'lsp-format-buffer nil t)) ;; (use-package rustic ;; :config ;; (setq rustic-format-on-save t) ;; (setq rustic-lsp-client 'eglot) ;; :custom ;; (lsp-rust-analyzer-cargo-watch-command "clippy") ;; (lsp-rust-analyzer-server-display-inlay-hints t) ;; :mode ("\\.rs" . rustic-mode)) (use-package rustic :config (setq rustic-format-on-save t) (setq rustic-lsp-client 'eglot) :mode ("\\.rs" . rustic-mode)) ;; run the python inferior shell immediately upon entering a python buffer (add-hook 'python-mode-hook 'swarsel/run-python) (defun swarsel/run-python () (save-selected-window (switch-to-buffer-other-window (process-buffer (python-shell-get-or-create-process (python-shell-parse-command)))))) ;; (use-package cuda-mode) ;; ;; add path manually; ;; (add-hook 'cuda-mode-hook ;; (lambda () ;; ( setq c-basic-offset 4 ;; flycheck-cuda-include-path (list ".")) ;; )) (use-package tramp :init (setq vc-ignore-dir-regexp (format "\\(%s\\)\\|\\(%s\\)" vc-ignore-dir-regexp tramp-file-name-regexp)) (setq tramp-default-method "ssh") (setq tramp-auto-save-directory (expand-file-name "tramp-auto-save" user-emacs-directory)) (setq tramp-persistency-file-name (expand-file-name "tramp-connection-history" user-emacs-directory)) (setq password-cache-expiry nil) (setq tramp-use-ssh-controlmaster-options nil) (setq remote-file-name-inhibit-cache nil) :config (customize-set-variable 'tramp-ssh-controlmaster-options (concat "-o ControlPath=/tmp/ssh-tramp-%%r@%%h:%%p " "-o ControlMaster=auto -o ControlPersist=yes")) ) (use-package evil-nerd-commenter :bind ("M-/" . evilnc-comment-or-uncomment-lines)) (use-package yasnippet :init (yas-global-mode 1) :config (yas-reload-all) ) ;; (use-package yasnippet-snippets) (setq wtf/latex-greek-prefix "'") (setq wtf/latex-math-prefix "`") (setq wtf/latex-mathbb-prefix "''") (setq swarsel/latex-mathcal-prefix "``") (use-package yasnippet :config (setq swtf/greek-alphabet '(("a" . "\\alpha") ("b" . "\\beta" ) ("g" . "\\gamma") ("d" . "\\delta") ("e" . "\\epsilon") ("z" . "\\zeta") ("h" . "\\eta") ("t" . "\\theta") ("i" . "\\iota") ("k" . "\\kappa") ("l" . "\\lambda") ("m" . "\\mu") ("n" . "\\nu") ("x" . "\\xi") ("p" . "\\pi") ("r" . "\\rho") ("s" . "\\sigma") ("t" . "\\tau") ("u" . "\\upsilon") ("f" . "\\phi") ("c" . "\\chi") ("v" . "\\psi") ("o" . "\\omega"))) ;; The same for capitalized letters (dolist (elem swtf/greek-alphabet) (let ((key (car elem)) (value (cdr elem))) (when (string-equal key (downcase key)) (add-to-list 'swtf/greek-alphabet (cons (capitalize (car elem)) (concat (substring value 0 1) (capitalize (substring value 1 2)) (substring value 2))))))) (yas-define-snippets 'latex-mode (mapcar (lambda (elem) (list (concat wtf/latex-greek-prefix (car elem)) (cdr elem) (concat "Greek letter " (car elem)))) swtf/greek-alphabet)) (setq wtf/english-alphabet '("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z")) (dolist (elem wtf/english-alphabet) (when (string-equal elem (downcase elem)) (add-to-list 'wtf/english-alphabet (upcase elem)))) (yas-define-snippets 'latex-mode (mapcar (lambda (elem) (list (concat wtf/latex-mathbb-prefix elem) (concat "\\mathbb{" elem "}") (concat "Mathbb letter " elem))) wtf/english-alphabet)) (yas-define-snippets 'latex-mode (mapcar (lambda (elem) (list (concat swarsel/latex-mathcal-prefix elem) (concat "\\mathcal{" elem "}") (concat "Mathcal letter " elem))) wtf/english-alphabet)) (setq swtf/latex-math-symbols '(("x" . "\\times") ("*" . "\\cdot") ("." . "\\ldots") ("op" . "\\operatorname{$1}$0") ("o" . "\\circ") ("V" . "\\forall") ("v" . "\\vee") ("w" . "\\wedge") ("q" . "\\quad") ("f" . "\\frac{$1}{$2}$0") ("s" . "\\sum_{$1}^{$2}$0") ("p" . "\\prod_{$1}^{$2}$0") ("e" . "\\exists") ("i" . "\\int_{$1}^{$2}$0") ("c" . "\\cap") ("u" . "\\cup") ("0" . "\\emptyset"))) (yas-define-snippets 'latex-mode (mapcar (lambda (elem) (let ((key (car elem)) (value (cdr elem))) (list (concat wtf/latex-math-prefix key) value (concat "Math symbol " value)))) swtf/latex-math-symbols)) ) (defun duplicate-line (arg) "Duplicate current line, leaving point in lower line." (interactive "*p") ;; save the point for undo (setq buffer-undo-list (cons (point) buffer-undo-list)) ;; local variables for start and end of line (let ((bol (save-excursion (beginning-of-line) (point))) eol) (save-excursion ;; don't use forward-line for this, because you would have ;; to check whether you are at the end of the buffer (end-of-line) (setq eol (point)) ;; store the line and disable the recording of undo information (let ((line (buffer-substring bol eol)) (buffer-undo-list t) (count arg)) ;; insert the line arg times (while (> count 0) (newline) ;; because there is no newline in 'line' (insert line) (setq count (1- count))) ) ;; create the undo information (setq buffer-undo-list (cons (cons eol (point)) buffer-undo-list))) ) ; end-of-let ;; put the point in the lowest line and return (next-line arg)) ;; (use-package lsp-mode ;; :ensure t ;; :init ;; ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l") ;; (setq lsp-keymap-prefix "C-c l") ;; :hook (;; replace XXX-mode with concrete major-mode(e. g. python-mode) ;; (python-mode . lsp) ;; (c++-mode . lsp) ;; (c-mode . lsp) ;; (cuda-mode . lsp) ;; (rustic-mode . lsp) ;; ;; if you want which-key integration ;; (lsp-mode . lsp-enable-which-key-integration)) ;; :commands lsp) ;; (use-package lsp-ui ;; :config ;; (setq lsp-ui-doc-enable t ;; lsp-ui-doc-show-with-cursor t ;; lsp-ui-doc-delay 0.5 ;; lsp-ui-doc-max-height 70) ;; ) ;; optionally if you want to use debugger ;; (use-package dap-mode) ;; (use-package lsp-treemacs ;; :after lsp) ;; ;; currently there is a bug with the double click behavior that was recently added. Fixed by this ;; (autoload 'treemacs-define-doubleclick-action "treemacs-mouse-interface" nil nil) ;; ;; (use-package flycheck ;; :hook ;; ((lsp-mode text-mode) . flycheck-mode) ;; :config ;; (define-key flycheck-mode-map flycheck-keymap-prefix nil) ;; ;;(setq flycheck-keymap-prefix (kbd my-flycheck-prefix)) ;; (define-key flycheck-mode-map flycheck-keymap-prefix ;; flycheck-command-map)) ;; ;; (use-package flycheck-posframe ;; :ensure t ;; :after flycheck ;; :config (add-hook 'flycheck-mode-hook #'flycheck-posframe-mode) ;; :init ;; (setq ;; flycheck-posframe-position 'point-top-left-corner ;; flycheck-posframe-error-prefix "❌ " ;; flycheck-posframe-info-prefix "ℹ️️️ " ;; flycheck-posframe-warning-prefix "⚠️ " ;; flycheck-posframe-prefix "💬 ")) (use-package eglot :ensure nil :hook ((python-mode c-mode c++-mode ) . (lambda () (progn (eglot-ensure) (add-hook 'before-save-hook 'eglot-format nil 'local)))) :custom (eldoc-echo-area-use-multiline-p nil) (completion-category-defaults nil) :config ;; (push '(rustic-ts-mode . eglot-rust-analyzer) eglot-server-programs) (push '(rustic-mode . eglot-rust-analyzer) eglot-server-programs) (add-to-list 'eglot-server-programs '((rust-mode) . (eglot-rust-analyzer "rust-analyzer"))) ;; (add-to-list 'eglot-server-programs '((python-mode) . ("pylsp"))) ;; (add-to-list 'eglot-server-programs '((c-mode) . ("clangd"))) :bind (:map eglot-mode-map ("M-(" . flymake-goto-next-error) ("C-c ," . eglot-code-actions))) (use-package breadcrumb :config (breadcrumb-mode)) ;; (use-package lsp-bridge ;; :ensure nil ;; :init ;; (global-lsp-bridge-mode) ;; :config ;; (setq lsp-bridge-enable-debug nil ;; lsp-bridge-enable-auto-format-code 0 ;; lsp-bridge-python-lsp-server 'pylsp ;; lsp-bridge-disable-backup nil ;; lsp-bridge-enable-org-babel 1 ;; acm-enable-search-file-words 0 ;; lsp-bridge-enable-hover-diagnostic 1) ;; ) (setq backup-by-copying-when-linked t) ;; (use-package dired ;; :ensure nil ;; :commands (dired dired-jump) ;; :bind (("C-x C-j" . dired-jump)) ;; :custom ((dired-listing-switches "-agho --group-directories-first")) ;; :config ;; (evil-collection-define-key 'normal 'dired-mode-map ;; "h" 'dired-single-up-directory ;; "l" 'dired-single-buffer)) ;; (use-package dired-single) ;; (use-package nerd-icons-dired ;; :hook ;; (dired-mode . nerd-icons-dired-mode)) ;; (use-package nerd-icons-completion ;; :after nerd-icons) ;; (use-package nerd-icons-ivy-rich) ;; (use-package nerd-icons-ibuffer) ;; ;; more colorful dired ;; (use-package diredfl ;; :hook ;; (dired-mode . diredfl-mode)) (use-package dirvish :init (dirvish-override-dired-mode) :config (dirvish-peek-mode) (dirvish-side-follow-mode) :custom (delete-by-moving-to-trash t) (dired-listing-switches "-l --almost-all --human-readable --group-directories-first --no-group") (dirvish-attributes '(vc-state subtree-state nerd-icons collapse file-time file-size)) (dirvish-quick-access-entries '(("h" "~/" "Home") ("c" "~/.dotfiles/" "Config") ("d" "~/Downloads/" "Downloads") ("D" "~/Documents/" "Documents") ("p" "~/Documents/GitHub/" "Projects") ("/" "/" "Root"))) :bind ((" d" . 'dirvish) ("C-=" . 'dirvish-side) :map dirvish-mode-map ("h" . dired-up-directory) ("" . dired-up-directory) ("l" . dired-find-file) ("" . dired-find-file) ("j" . evil-next-visual-line) ("k" . evil-previous-visual-line) ("a" . dirvish-quick-access) ("f" . dirvish-file-info-menu) ("z" . dirvish-history-last) ("J" . dirvish-history-jump) ("y" . dirvish-yank-menu) ("TAB" . dirvish-subtree-toggle) ("M-f" . dirvish-history-go-forward) ("M-b" . dirvish-history-go-backward) ("M-l" . dirvish-ls-switches-menu) ("M-m" . dirvish-mark-menu) ("M-t" . dirvish-layout-toggle) ("M-s" . dirvish-setup-menu) ("M-e" . dirvish-emerge-menu) ("M-j" . dirvish-fd-jump))) (use-package pdf-tools :init (if (not (boundp 'pdf-tools-directory)) (pdf-tools-install)) :mode ("\\.pdf" . pdf-view-mode)) (use-package openwith) (openwith-mode t) ;; (setq openwith-associations '(("\\.pdf\\'" "evince" (file)) ("\\.xopp\\'" "xournalpp" (file)))) (setq openwith-associations '(("\\.xopp\\'" "xournalpp" (file)))) ;(setq openwith-associations '(("\\.xopp\\'" "xournalpp" (file)))) (use-package ein) (use-package obsidian :ensure t :demand t :config (obsidian-specify-path swarsel-obsidian-vault-directory) (global-obsidian-mode t) :custom ;; This directory will be used for `obsidian-capture' if set. (obsidian-inbox-directory "Inbox") (bind-key (kbd "C-c M-o") 'obsidian-hydra/body 'obsidian-mode-map) :bind (:map obsidian-mode-map ;; Replace C-c C-o with Obsidian.el's implementation. It's ok to use another key binding. ("C-c C-o" . obsidian-follow-link-at-point) ;; Jump to backlinks ("C-c C-b" . obsidian-backlink-jump) ;; If you prefer you can use `obsidian-insert-link' ("C-c C-l" . obsidian-insert-wikilink))) (use-package anki-editor :after org :bind (:map org-mode-map ("" . anki-editor-cloze-region-auto-incr) ("" . anki-editor-cloze-region-dont-incr) ("" . anki-editor-reset-cloze-number) ("" . anki-editor-push-tree)) :hook (org-capture-after-finalize . anki-editor-reset-cloze-number) ; Reset cloze-number after each capture. :config (setq anki-editor-create-decks t ;; Allow anki-editor to create a new deck if it doesn't exist anki-editor-org-tags-as-anki-tags t) (defun anki-editor-cloze-region-auto-incr (&optional arg) "Cloze region without hint and increase card number." (interactive) (anki-editor-cloze-region swarsel-anki-editor-cloze-number "") (setq swarsel-anki-editor-cloze-number (1+ swarsel-anki-editor-cloze-number)) (forward-sexp)) (defun anki-editor-cloze-region-dont-incr (&optional arg) "Cloze region without hint using the previous card number." (interactive) (anki-editor-cloze-region (1- swarsel-anki-editor-cloze-number) "") (forward-sexp)) (defun anki-editor-reset-cloze-number (&optional arg) "Reset cloze number to ARG or 1" (interactive) (setq swarsel-anki-editor-cloze-number (or arg 1))) (defun anki-editor-push-tree () "Push all notes under a tree." (interactive) (anki-editor-push-notes '(4)) (anki-editor-reset-cloze-number)) ;; Initialize (anki-editor-reset-cloze-number) ) (require 'anki-editor) (defvar swarsel-anki-deck nil) (defvar swarsel-anki-notetype nil) (defvar swarsel-anki-fields nil) (defun swarsel-anki-set-deck-and-notetype () (interactive) (setq swarsel-anki-deck (completing-read "Choose a deck: " (sort (anki-editor-deck-names) #'string-lessp))) (setq swarsel-anki-notetype (completing-read "Choose a note type: " (sort (anki-editor-note-types) #'string-lessp))) (setq swarsel-anki-fields (progn (anki-editor--anki-connect-invoke-result "modelFieldNames" `((modelName . ,swarsel-anki-notetype))))) ) (defun swarsel-anki-make-template-string () (if (not swarsel-anki-deck) (call-interactively 'swarsel-anki-set-deck-and-notetype)) (setq swarsel-temp swarsel-anki-fields) (concat (concat "* %<%H:%M>\n:PROPERTIES:\n:ANKI_NOTE_TYPE: " swarsel-anki-notetype "\n:ANKI_DECK: " swarsel-anki-deck "\n:END:\n** ")(pop swarsel-temp) "\n%?\n** " (mapconcat 'identity swarsel-temp "\n\n** ") "\n\n")) (defun swarsel-today() (format-time-string "%Y-%m-%d")) (defun swarsel-obsidian-daily () (interactive) (if (not (file-exists-p (expand-file-name (concat (swarsel-today) ".md") swarsel-obsidian-daily-directory))) (write-region "" nil (expand-file-name (concat (swarsel-today) ".md") swarsel-obsidian-daily-directory)) ) (find-file (expand-file-name (concat (swarsel-today) ".md") swarsel-obsidian-daily-directory))) (use-package mu4e :ensure nil ;; :load-path "/usr/share/emacs/site-lisp/mu4e/" ;;:defer 20 ; Wait until 20 seconds after startup :config ;; This is set to 't' to avoid mail syncing issues when using mbsync (setq mu4e-change-filenames-when-moving t) (setq mu4e-mu-binary (executable-find "mu")) ;; Refresh mail using isync every 10 minutes (setq mu4e-update-interval (* 10 60)) (setq mu4e-get-mail-command "mbsync -a") (setq mu4e-maildir "~/Mail") ;;(setq mu4e t) (setq mu4e-drafts-folder "/Drafts") (setq mu4e-sent-folder "/Sent Mail") (setq mu4e-refile-folder "/All Mail") (setq mu4e-trash-folder "/Trash") (setq mu4e-maildir-shortcuts '((:maildir "/leon/Inbox" :key ?1) (:maildir "/nautilus/Inbox" :key ?2) (:maildir "/mrswarsel/Inbox" :key ?3) (:maildir "/Sent Mail" :key ?s) (:maildir "/Trash" :key ?t) (:maildir "/Drafts" :key ?d) (:maildir "/All Mail" :key ?a)))) (setq user-mail-address "leon.schwarzaeugl@gmail.com" user-full-name "Leon Schwarzäugl") (let ((mu4epath (concat (f-dirname (file-truename (executable-find "mu"))) "/../share/emacs/site-lisp/mu4e"))) (when (and (string-prefix-p "/nix/store/" mu4epath) (file-directory-p mu4epath)) (add-to-list 'load-path mu4epath))) (use-package org-caldav :init (setq org-caldav-url "https://stash.swarsel.win/remote.php/dav/calendars/Swarsele") (setq org-caldav-calendars '((:calendar-id "personal" :inbox "~/Calendars/leon_cal.org"))) ;; (setq org-caldav-backup-file "~/org-caldav/org-caldav-backup.org") ;; (setq org-caldav-save-directory "~/org-caldav/") :config (setq org-icalendar-alarm-time 1) ;; This makes sure to-do items as a category can show up on the calendar (setq org-icalendar-include-todo t) ;; This ensures all org "deadlines" show up, and show up as due dates (setq org-icalendar-use-deadline '(event-if-todo event-if-not-todo todo-due)) ;; This ensures "scheduled" org items show up, and show up as start times (setq org-icalendar-use-scheduled '(todo-start event-if-todo event-if-not-todo)) ) (use-package calfw :ensure nil :bind ("C-c A" . swarsel/open-calendar) :init (use-package calfw-cal :ensure nil) (use-package calfw-org :ensure nil) (use-package calfw-ical :ensure nil) :config (bind-key "g" 'cfw:refresh-calendar-buffer cfw:calendar-mode-map) (bind-key "q" 'evil-quit cfw:details-mode-map) ;; (custom-set-faces ;; '(cfw:face-title ((t (:foreground "#f0dfaf" :weight bold :height 65)))) ;; ) ) (defun swarsel/open-calendar () (interactive) (unless (eq swarsel-caldav-synced 1) (org-caldav-sync) (setq swarsel-caldav-synced 1)) ;; (select-frame (make-frame '((name . "calendar")))) ; makes a new frame and selects it ;; (set-face-attribute 'default (selected-frame) :height 65) ; reduces the font size of the new frame (cfw:open-calendar-buffer :contents-sources (list (cfw:org-create-source "Purple") ; orgmode source (cfw:ical-create-source "TISS" "https://tiss.tuwien.ac.at/events/rest/calendar/personal?locale=de&token=4463bf7a-87a3-490a-b54c-99b4a65192f3" "Cyan")))) (use-package mu4e-alert) (mu4e-alert-set-default-style 'libnotify) (add-hook 'after-init-hook #'mu4e-alert-enable-notifications) ;;show mail ;;(mu4e) (use-package dashboard :ensure t :config (dashboard-setup-startup-hook) ;; (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))) (setq dashboard-display-icons-p t ;; display icons on both GUI and terminal dashboard-icon-type 'nerd-icons ;; use `nerd-icons' package dashboard-set-file-icons t dashboard-items '((recents . 5) (projects . 5) (agenda . 5)) dashboard-set-footer nil dashboard-banner-logo-title "Welcome to SwarsEmacs!" dashboard-image-banner-max-height 300 dashboard-startup-banner "~/.dotfiles/wallpaper/swarsel.png" dashboard-projects-backend 'projectile dashboard-set-navigator t dashboard-navigator-buttons `(;; line1 ((,"" "SwarselSocial" "Browse Swarsele" (lambda (&rest _) (browse-url "instagram.com/Swarsele"))) (,"" "SwarselSound" "Browse SwarselSound" (lambda (&rest _) (browse-url "sound.swarsel.win")) ) (,"" "SwarselSwarsel" "Browse Swarsel" (lambda (&rest _) (browse-url "github.com/Swarsel")) ) (,"" "SwarselStash" "Browse SwarselStash" (lambda (&rest _) (browse-url "stash.swarsel.win")) ) (,"󰫑" "SwarselSport" "Browse SwarselSports" (lambda (&rest _) (browse-url "social.parkour.wien/@Lenno"))) ) ( (,"󱄅" "swarsel.win" "Browse swarsel.win" (lambda (&rest _) (browse-url "swarsel.win"))) ) ))) (setq dashboard-projects-switch-function 'counsel-projectile-switch-project-by-name) (fset 'epg-wait-for-status 'ignore)