;;; $DOOMDIR/config.el -*- lexical-binding: t; -*- ;; Load extra configuration of Nix-computed paths deifned in programs.emacs.extraConfig ;; (load "default") ;; Place your private configuration here! Remember, you do not need to run 'doom ;; sync' after modifying this file! ;; Some functionality uses this to identify you, e.g. GPG configuration, email ;; clients, file templates and snippets. (setq user-full-name "Max Schlueter" user-mail-address "me@maxschlueter.com") ;; Doom exposes five (optional) variables for controlling fonts in Doom. Here ;; are the three important ones: ;; ;; + `doom-font' ;; + `doom-variable-pitch-font' ;; + `doom-big-font' -- used for `doom-big-font-mode'; use this for ;; presentations or streaming. ;; ;; They all accept either a font-spec, font string ("Input Mono-12"), or xlfd ;; font string. You generally only need these two: (setq doom-font (font-spec :family "Fira Mono" :size 14.0)) ;; There are two ways to load a theme. Both assume the theme is installed and ;; available. You can either set `doom-theme' or manually load a theme with the ;; `load-theme' function. This is the default: (setq doom-theme 'doom-solarized-light) ;; TODO: Restore session at startup ;; (add-hook 'window-setup-hook #'doom-load-session 'append) ;; If you use `org' and don't want your org files in the default location below, ;; change `org-directory'. It must be set before org loads! ;; https://github.com/hlissner/doom-emacs/issues/4832 ;; (after! org ;; (defun +org--restart-mode-h () ;; "Restart `org-mode', but only once." ;; (quiet! (org-mode-restart)) ;; (delq! (current-buffer) org-agenda-new-buffers) ;; (remove-hook 'doom-switch-buffer-hook #'+org--restart-mode-h ;; 'local))) ;; If you use `org' and don't want your org files in the default location below, ;; change `org-directory'. It must be set before org loads! (setq org-directory "~/Nextcloud/org/") ;; (defun max/org-gtd--incubate () ;; "Process GTD inbox item by incubating it. ;; Allow the user apply user-defined tags from ;; `org-tag-persistent-alist', `org-tag-alist' or file-local tags in ;; the inbox. Refile to any org-gtd incubate target (see manual)." ;; (interactive) ;; (org-gtd--decorate-item) ;; (org-gtd--refile org-gtd-incubated) ;; (org-gtd-process-inbox)) ;; (defun max/org-gtd--quick-action () ;; "Process GTD inbox item by doing it now. ;; Allow the user apply user-defined tags from ;; `org-tag-persistent-alist', `org-tag-alist' or file-local tags in ;; the inbox. Mark it as done and archive." ;; (interactive) ;; (org-back-to-heading) ;; (org-gtd--decorate-item) ;; (org-clock-in) ;; (org-gtd--refile org-gtd-actions) ;; (org-gtd-process-inbox)) ;; (use-package! org-gtd ;; :after org ;; :config ;; (setq org-gtd-directory (concat org-directory "newgtd/") ;; org-edna-use-inheritance t ;; org-gtd-update-ack "2.1.0" ;; org-gtd-refile-to-any-target t) ;; (advice-add #'org-gtd--incubate :override #'max/org-gtd--incubate) ;; (advice-add #'org-gtd--quick-action :override #'max/org-gtd--quick-action) ;; (map! :leader ;; (:prefix ("d" . "org-gtd") ;; :desc "Capture" "c" #'org-gtd-capture ;; :desc "Engage" "e" #'org-gtd-engage ;; :desc "Process inbox" "p" #'org-gtd-process-inbox ;; :desc "Show all next" "n" #'org-gtd-show-all-next ;; :desc "Stuck projects" "s" #'org-gtd-show-stuck-projects)) ;; (set-popup-rule! "^\\*ivy-occur" :size 0.35 :ttl 0 :quit nil) ;; (map! :map org-gtd-process-map ;; :desc "Choose" "C-c c" #'org-gtd-choose)) ;; (set-popup-rule! "^\\*helpful" :ignore t) ;;; Autoload this function for the org-pomodoro polybar module ;; (autoload #'org-pomodoro-active-p "org-pomodoro" nil t) (map! :map evil-org-agenda-mode-map :m "c p" #'org-agenda-set-property) ;; (defun max/skip-habits () ;; "Skip trees that are habits." ;; (save-restriction ;; (widen) ;; (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) ;; (cond ;; ((org-is-habit-p) ;; next-headline) ;; (t ;; nil))))) ;; (setq org-columns-default-format "%40ITEM(Task) %Effort(EE){:} %CLOCKSUM(Time Spent) %SCHEDULED(Scheduled) %DEADLINE(Deadline)") ;; (setq org-agenda-custom-commands `((" " "Agenda" ;; ((alltodo "" ;; ((org-agenda-overriding-header "Inbox") ;; (org-agenda-files '(,(expand-file-name "gtd/inbox.org" org-directory))))) ;; (agenda "" ;; ((org-agenda-span 'week) ;; (org-deadline-warning-days 365))) ;; (todo "NEXT" ;; ((org-agenda-overriding-header "In Progress") ;; (org-agenda-files '(,(expand-file-name "gtd/projects.org" org-directory))))) ;; (todo "TODO" ;; ((org-agenda-overriding-header "Active Projects") ;; (org-agenda-files '(,(expand-file-name "gtd/projects.org" org-directory))) ;; (org-agenda-skip-function #'max/skip-habits))))) ;; ("W" "Weekly Review" ;; ((agenda "" ;; ((org-agenda-span 'week) ;; (org-agenda-start-day "-6d"))) ;; (todo "NEXT" ;; ((org-agenda-overriding-header "In Progress") ;; (org-agenda-files '(,(expand-file-name "gtd/projects.org" org-directory))))) ;; (todo "TODO" ;; ((org-agenda-overriding-header "Active Projects") ;; (org-agenda-files '(,(expand-file-name "gtd/projects.org" org-directory))) ;; (org-agenda-skip-function #'max/skip-habits)))))))) (defun max/org-agenda-bulk-mark-inbox-items () "Bulk mark all inbox items in the org-agenda." (let ((entries-marked 0)) (save-excursion (goto-char (point-min)) (while (not (eobp)) (if (and (org-get-at-bol 'org-hd-marker) (string= "inbox" (funcall 'org-agenda-get-category))) (progn (setq entries-marked (1+ entries-marked)) (call-interactively 'org-agenda-bulk-mark)) (beginning-of-line 2)))) (unless entries-marked (message "No inbox items found.")))) (defun max/org-agenda-process-inbox-item () "Process a single item in the org-agenda." (interactive) (org-with-wide-buffer (org-agenda-set-tags) (org-agenda-priority) (org-agenda-set-effort) (org-agenda-refile nil nil t))) (defun max/org-agenda-bulk-process-entries () "Bulk process all marked entries in the org-agenda using `max/org-agenda-process-inbox-item'." (if (not (null org-agenda-bulk-marked-entries)) (let ((entries (reverse org-agenda-bulk-marked-entries)) (processed 0) (skipped 0)) (dolist (e entries) (let ((pos (text-property-any (point-min) (point-max) 'org-hd-marker e))) (if (not pos) (progn (message "Skipping removed entry at %s" e) (cl-incf skipped)) (goto-char pos) (let (org-loop-over-headlines-in-active-region) (funcall 'max/org-agenda-process-inbox-item)) ;; `post-command-hook' is not run yet. We make sure any ;; pending log note is processed. (when org-log-setup (org-add-log-note)) ;; (when (or (memq 'org-add-log-note (default-value 'post-command-hook)) ;; (memq 'org-add-log-note post-command-hook)) ;; (org-add-log-note)) (cl-incf processed)))) (org-agenda-redo) (unless org-agenda-persistent-marks (org-agenda-bulk-unmark-all)) (message "Acted on %d entries%s%s" processed (if (= skipped 0) "" (format ", skipped %d (disappeared before their turn)" skipped)) (if (not org-agenda-persistent-marks) "" " (kept marked)"))))) (defun max/org-agenda-process-inbox () "Processes all inbox items in the org-agenda." (interactive) (max/org-agenda-bulk-mark-inbox-items) (max/org-agenda-bulk-process-entries)) (map! :after evil-org-agenda :map evil-org-agenda-mode-map :m "P" #'max/org-agenda-process-inbox) ;; org-agenda-custom-commands ;; '((" " "Agenda" ;; ((agenda "" ;; ( ;; (org-agenda-start-day nil) ;; (org-agenda-span 'day) ;; (org-deadline-warning-days 365))) ;; (alltodo "" ;; ((org-agenda-overriding-header "") ;; (org-super-agenda-groups ;; '((:name "To Refile" ;; :category "inbox") ;; (:name "Emails" ;; :category "emails") ;; (:name "In Progress" ;; :todo "NEXT") ;; (:name "Projects" ;; :file-path "projects.org$") ;; (:name "One-off Tasks" ;; :category "next")) ;; )))))))) (use-package! org-inline-pdf :hook (org-mode . org-inline-pdf-mode)) (use-package! indium :hook ((js-mode typescript-mode) . indium-interaction-mode) :init (setq indium-chrome-data-dir (concat doom-cache-dir "indium-chrome-profile")) :config (map! :localleader :map indium-interaction-mode-map "I" #'indium-launch) ) ;; (use-package! ox-mm ;; :after org) ;; khalel-import-time-delta "30d" (after! info (map! :map Info-mode-map :n "g n" #'Info-goto-node)) ;; (setq max/org-calendar-directory (concat org-directory "calendar/")) ;; (setq max/org-calendar-file (concat max/org-calendar-directory "calendar.org")) ;;; https://www.reddit.com/r/orgmode/comments/8rl8ep/making_orgcaldav_useable/ ;; (use-package! org-caldav ;; :after org ;; :init ;; ;; (defun org-caldav-sync-at-close () ;; ;; (org-caldav-sync) ;; ;; (save-some-buffers)) ;; ;; (defvar org-caldav-sync-timer nil ;; ;; "Timer that `org-caldav-push-timer' used to reschedule itself, or nil.") ;; ;; (defun org-caldav-sync-with-delay (secs) ;; ;; (when org-caldav-sync-timer ;; ;; (cancel-timer org-caldav-sync-timer)) ;; ;; (setq org-caldav-sync-timer ;; ;; (run-with-idle-timer ;; ;; (* 1 secs) nil 'org-caldav-sync))) ;; (setq org-icalendar-alarm-time 1) ;; :config ;; (setq org-caldav-resume-aborted 'always ;; org-caldav-save-directory max/org-calendar-directory ;; org-caldav-backup-file (concat max/org-calendar-directory "org-caldav-backup.org") ;; org-caldav-url "https://nextcloud.maxschlueter.com/remote.php/dav/calendars/max" ;; org-caldav-calendar-id "calendar" ;; org-caldav-files `(,max/org-calendar-file) ;; org-caldav-inbox max/org-calendar-file) ;; (after! org-agenda ;; (add-to-list 'org-agenda-files max/org-calendar-file t) ;; (setq org-agenda-include-diary t ;; org-agenda-insert-diary-strategy 'top-level ;; org-agenda-insert-diary-extract-time t ;; org-agenda-diary-file max/org-calendar-file)) ;; ;; (setq org-caldav-calendars ;; ;; `((:calendar-id "personal" ;; ;; :files (,(concat max/org-calendar-directory "personal.org")) ;; ;; :inbox ,(concat max/org-calendar-directory "personal.org")) ;; ;; (:calendar-id "work" ;; ;; :files (,(concat max/org-calendar-directory "work.org")) ;; ;; :inbox ,(concat max/org-calendar-directory "work.org")) ;; ;; )) ;; (defun max/org-caldav-get-inbox () ;; (let* ((calid (completing-read "Calendar: " ;; (cl-loop for cal in org-caldav-calendars ;; collect (plist-get cal :calendar-id)) ;; nil t)) ;; (calinbox (cl-loop for cal in org-caldav-calendars ;; when (string= (plist-get cal :calendar-id) calid) ;; return (plist-get cal :inbox)))) ;; calinbox)) ;; ;; (add-hook 'after-save-hook ;; ;; (lambda () ;; ;; (when (eq major-mode 'org-mode) ;; ;; (org-caldav-sync-with-delay 300)))) ;; ;; (add-hook 'kill-emacs-hook 'org-caldav-sync-at-close) ;; ) (setq +org-roam-open-buffer-on-find-file nil) (after! org-roam (setq org-roam-dailies-capture-templates '(("d" "default" entry "* %?" :target (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n")))) ;; ("j" "journal" entry ;; #'org-roam-capture--get-point ;; "* %?" ;; :file-name "daily/%<%Y-%m-%d>" ;; :head "#+title: %<%Y-%m-%d>\n" ;; :olp ("Journal")))) (map! :leader :desc "Capture today" "n n" #'org-roam-dailies-capture-today) (setq org-roam-directory (concat org-directory "roam/") org-roam-completion-everywhere nil)) (after! org-noter ;; (map! :map pdf-view-mode-map "i" nil) ;; (map! :map pdf-view-mode-map :gn "i" #'org-noter-insert-note) (setq org-noter-always-create-frame t)) (after! biblio (map! :map biblio-selection-mode-map "C-j" #'biblio--selection-next "C-k" #'biblio--selection-previous) (setq biblio-crossref-user-email-address user-mail-address)) (after! bibtex-completion ;; (require 'ivy-bibtex) ;; (setq! bibtex-completion-library-path '("~/Nextcloud/Papers/") ;; bibtex-completion-notes-path org-roam-directory ;; bibtex-completion-bibliography '("~/Nextcloud/Papers/library.bib")) ;; TODO: make it a citar action (defun max/bibtex-completion-org-capture (keys) (let ((titles (bibtex-completion-format-citation-org-title-link-to-PDF keys))) (with-current-buffer (find-file-noselect (expand-file-name "gtd/inbox.org" org-directory)) (save-excursion (goto-char (point-max)) (insert (concat "* TODO Read: " titles "\n")))))) (ivy-bibtex-ivify-action max/bibtex-completion-org-capture max/ivy-bibtex-org-capture) (ivy-add-actions 'ivy-bibtex '(("x" max/ivy-bibtex-org-capture "Capture PDF to read")))) (after! citar (setq! citar-library-paths '("~/Nextcloud/Papers/") citar-notes-paths `(,org-roam-directory) citar-bibliography '("~/Nextcloud/Papers/library.bib"))) (use-package citar-org-roam :after citar org-roam :no-require :config (citar-org-roam-mode)) ;; Taken from: https://github.com/hlissner/doom-emacs/pull/6077 ;; (use-package! org-roam-bibtex ;; ;; :when (featurep! :lang org +roam2) ;; :after org-roam ;; :preface ;; ;; if the user has not set a template mechanism set a reasonable one of them ;; ;; The package already tests for nil itself so we define a dummy tester ;; (defvar orb-preformat-keywords ;; '("title" "url" "file" "author-or-editor" "keywords" "citekey" "pdf")) ;; :hook (org-roam-mode . org-roam-bibtex-mode) ;; :custom ;; (orb-note-actions-interface (cond ((featurep! :completion ivy) 'ivy) ;; ((featurep! :completion helm) 'helm) ;; ((t 'default)))) ;; :config ;; (setq orb-insert-interface (cond ((featurep! :completion ivy) 'ivy-bibtex) ;; ((featurep! :completion helm) 'helm-bibtex) ;; ((t 'generic)))) ;; (setq orb-process-file-keyword t ;; orb-file-field-extensions '("pdf")) ;; (add-to-list 'org-roam-capture-templates ;; '("b" "Bibliography note" plain ;; "%? ;; - keywords :: %^{keywords} ;; - related :: ;; * %^{title} ;; :PROPERTIES: ;; :Custom_ID: %^{citekey} ;; :URL: %^{url} ;; :AUTHOR: %^{author-or-editor} ;; :NOTER_DOCUMENT: %^{file} ;; :NOTER_PAGE: ;; :END:\n\n" ;; :if-new (file+head "${citekey}.org" ":PROPERTIES: ;; :ROAM_REFS: cite:${citekey} ;; :END: ;; #+TITLE: ${title}\n") ;; :unnarrowed t))) (after! projectile (setq projectile-project-search-path '(("~/Projects" . 1)))) ;; (setq ns-auto-hide-menu-bar t) ;(defun switch-to-agenda () (defun max/org-clock-get-clock-string () "Form a clock string that will be shown in polybar." (require 'org-clock) (when (org-clocking-p) (let ((currently-clocked-time (floor (org-time-convert-to-integer (time-since org-clock-start-time)) 60)) (clocked-time (org-clock-get-clocked-time))) (if org-clock-effort (let* ((effort-in-minutes (org-duration-to-minutes org-clock-effort)) (current-work-done-str (org-duration-from-minutes currently-clocked-time)) (work-done-str (org-duration-from-minutes clocked-time)) (effort-str (org-duration-from-minutes effort-in-minutes))) (format "%s (%s/%s) %s" current-work-done-str work-done-str effort-str org-clock-heading)) (format "%s %s" (org-duration-from-minutes clocked-time) org-clock-heading))))) ;; (when (org-clocking-p) ;; (org-no-properties (org-clock-get-clock-string)))) ;; (when (org-clocking-p) ;; (let* ((clocked-time (org-clock-get-clocked-time)) ;; (work-done-str (org-duration-from-minutes clocked-time))) ;; (make-symbol work-done-str)))) ;; (defun my/toggle-org-agenda () ;; "Toggle my custom org agenda view" ;; (interactive) ;; (if (get-buffer-window org-agenda-buffer-name) ;; (org-agenda-quit) ;; (org-agenda nil " "))) (after! auth-source (when IS-MAC (setq auth-sources '(macos-keychain-internet macos-keychain-generic)))) ;; (setq mac-right-option-modifier nil) ;; (set-irc-server! "chat.freenode.net" ;; `(:tls t ;; :port 6697 ;; :nick "maxsc" ;; :sasl-username ,(+pass-get-user "irc/freenode.net") ;; :sasl-password (lambda (&rest _) (+pass-get-secret "irc/freenode.net")) ;; :channels ("#home-manager"))) ;; (map! "" #'=irc) ;;; https://github.com/alphapapa/org-ql/issues/67 ;(after! (org-super-agenda evil-org-agenda) ; (setq org-super-agenda-header-map (copy-keymap evil-org-agenda-mode-map))) ;;; (after! woman ;;; (set-popup-rule! "^\\*WoMan" :side 'left :size 30 :ttl 0) ;;; ) ;;; (after! org (set-popup-rule! "^CAPTURE-.*\\.org$" :side 'right :size .50 :select t :vslot 2 :ttl 3)) ;;; (after! org-roam ;;; (advice-add #'display-buffer-pop-up-frame :before #'org-roam-protocol-open-ref)) (setq +latex-viewers '(pdf-tools)) (setq org-roam-directory (concat org-directory "roam/")) ;; (setq! +biblio-pdf-library-dir "~/Nextcloud/Papers/" ;; +biblio-default-bibliography-files '("~/Nextcloud/Papers/library.bib") ;; +biblio-notes-path org-roam-directory) (after! org-roam-bibtex (setq orb-insert-link-description 'citekey)) ;; https://tecosaur.github.io/emacs-config/config.html#getting-notified ;; http://cachestocaches.com/2017/3/complete-guide-email-emacs-using-mu-and-/ ;; (use-package! mu4e-alert ;; :after mu4e ;; :init ;; (setq mu4e-alert-interesting-mail-query ;; (concat ;; "flag:unread maildir:/mailbox.org/Inbox" ;; " OR " ;; "flag:unread maildir:/uni-potsdam.de/Inbox" ;; )) ;; (setq doom-modeline-mu4e t) ;; :config ;; (mu4e-alert-enable-mode-line-display) ;; (mu4e-alert-set-default-style 'libnotify) ;; (mu4e-alert-enable-notifications)) ;; ;; (after! forge (setq forge-owned-accounts '(("MaxSchlueter")))) (setq +workspaces-on-switch-project-behavior t) (after! evil-snipe (setq evil-snipe-spillover-scope 'visible)) (map! "" #'redraw-display) (after! restart-emacs (defun max/restart-emacs--get-emacs-binary () (let ((invocation-directory (file-truename "~/.nix-profile/Applications/Emacs.app/Contents/MacOS"))) (expand-file-name invocation-name invocation-directory))) (advice-add #'restart-emacs--get-emacs-binary :override #'max/restart-emacs--get-emacs-binary)) ;; (server-start) ;; (use-package! mac-pseudo-daemon ;; :config ;; (mac-pseudo-daemon-mode) ;; ) ;; (load! nix-docbook-mode) ;;; (after! calfw-org ;;; (autoload (function cfw:org-create-file-source) "cfw:org-create-file-source" nil t)) ;;; (after! calfw-org ;;; (autoload #'cfw:org-create-file-source "cfw:org-create-file-source")) ;; load personal modules (load! "email") (load! "gtd")