Compare commits

...

12 Commits

Author SHA1 Message Date
c4b861996f refactor: delete org.el 2024-11-15 14:11:41 +01:00
ad762f9e92 roam: changes 2024-05-31 17:21:57 +02:00
70e56bfbaf roam: update capture templates 2024-05-31 17:21:01 +02:00
05dd325fda mu4e: fix doom view mime part function 2024-05-05 10:42:31 +02:00
e168ba24b3 email: =mu4e call jumps into headers mode 2024-04-12 10:54:37 +02:00
1de6abe136 email: start mu4e in background
Instead of autoloading one function...
2024-04-12 10:44:53 +02:00
655b40956b Add copilot and gptel 2024-04-12 10:26:02 +02:00
5c37f99702 WIP: khalel sync 2024-02-11 19:58:30 +01:00
07c8e15411 fixup! WIP: org-caldav 2024-02-10 18:39:31 +01:00
24f8d78e58 WIP: org-remark 2024-02-10 18:38:57 +01:00
ec3c516deb Fix clock function 2024-02-10 18:38:13 +01:00
154a5faebe WIP: org-caldav 2024-02-10 18:37:50 +01:00
6 changed files with 394 additions and 295 deletions

View File

@ -227,67 +227,6 @@
(map! :map Info-mode-map (map! :map Info-mode-map
:n "g n" #'Info-goto-node)) :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)
;; )
(after! biblio (after! biblio
(map! :map biblio-selection-mode-map (map! :map biblio-selection-mode-map
@ -397,6 +336,10 @@
(setq +latex-viewers '(pdf-tools)) (setq +latex-viewers '(pdf-tools))
(after! eww
(setq eww-auto-rename-buffer 'title))
;; (setq! +biblio-pdf-library-dir "~/Nextcloud/Papers/" ;; (setq! +biblio-pdf-library-dir "~/Nextcloud/Papers/"
;; +biblio-default-bibliography-files '("~/Nextcloud/Papers/library.bib") ;; +biblio-default-bibliography-files '("~/Nextcloud/Papers/library.bib")
;; +biblio-notes-path org-roam-directory) ;; +biblio-notes-path org-roam-directory)
@ -468,7 +411,35 @@
:before #'server-edit :before #'server-edit
(save-buffer)) (save-buffer))
(use-package! gptel
:config
(setq! gptel-api-key (lambda () (with-temp-buffer
(insert-file-contents "/run/secrets/chatgpt_api_key")
(buffer-string)))))
(use-package! copilot
:hook (prog-mode . copilot-mode)
:bind (:map copilot-completion-map
("<tab>" . 'copilot-accept-completion)
("TAB" . 'copilot-accept-completion)
("C-TAB" . 'copilot-accept-completion-by-word)
("C-<tab>" . 'copilot-accept-completion-by-word)))
;; 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 "~/Sync/Logseq/")
;; C-k is mapped to ~org-element-up~ by default
(map! :after org
:map evil-org-mode-map
:i "C-k" #'org-kill-line)
(map! :after org
:map org-mode-map
:localleader
"Y" #'ox-clip-image-to-clipboard)
;; load personal modules ;; load personal modules
(load! "org") ;; (load! "org")
(load! "gtd") (load! "gtd")
(load! "roam")
(load! "email") (load! "email")

244
email.el
View File

@ -1,127 +1,135 @@
;;; email.el -*- lexical-binding: t; -*- ;;; email.el -*- lexical-binding: t; -*-
(after! mu4e ;; Start mu4e in the background
;; Recommended msmtp config from doom module documentation ;; https://github.com/djcb/mu/issues/2282
(setq sendmail-program (executable-find "msmtp") (require 'mu4e)
send-mail-function #'smtpmail-send-it (mu4e 'background)
message-sendmail-f-is-evil t
message-sendmail-extra-arguments '("--read-envelope-from")
message-send-mail-function #'message-send-mail-with-sendmail)
;; `set-email-account!' doesn't accept a custom match-func ;; Recommended msmtp config from doom module documentation
(setq mu4e-contexts (setq sendmail-program (executable-find "msmtp")
(list send-mail-function #'smtpmail-send-it
;; (make-mu4e-context message-sendmail-f-is-evil t
;; :name "upcycling" message-sendmail-extra-arguments '("--read-envelope-from")
;; :enter-func message-send-mail-function #'message-send-mail-with-sendmail)
;; (lambda () (mu4e-message "Switched to upcycling"))
;; :leave-func
;; (lambda () (progn (setq +mu4e-personal-addresses nil)
;; (mu4e-clear-caches)))
;; :match-func
;; (lambda (msg)
;; (when msg
;; (mu4e-message-contact-field-matches msg
;; :to "upcycling@fsfe.org")))
;; :vars '((user-mail-address . "upcycling@fsfe.org")
;; (user-full-name . "FSFE Team Upcycling Android")))
(make-mu4e-context
:name "mailbox"
:enter-func
(lambda () (mu4e-message "Switched to mailbox"))
:leave-func
(lambda () (progn (setq +mu4e-personal-addresses nil)
(mu4e-clear-caches)))
:match-func
(lambda (msg)
(when msg
(string-prefix-p "/mailbox"
(mu4e-message-field msg :maildir) t)))
:vars '((user-mail-address . "me@maxschlueter.com")
(user-full-name . "Max Schlueter")
(+mu4e-personal-addresses ("me@maxschlueter.com")
("maxsc@fsfe.org"))
))))
(setq mu4e-attachment-dir "~/Downloads" ;; `set-email-account!' doesn't accept a custom match-func
mu4e-sent-folder "/mailbox/Sent" (setq mu4e-contexts
mu4e-drafts-folder "/mailbox/Drafts" (list
mu4e-trash-folder "/mailbox/Trash" ;; (make-mu4e-context
mu4e-refile-folder "/mailbox/Archive" ;; :name "upcycling"
;; TODO create context-aware variable ;; :enter-func
mu4e-spam-folder "/mailbox/Junk" ;; (lambda () (mu4e-message "Switched to upcycling"))
mu4e-compose-signature nil ;; :leave-func
mu4e-maildir-shortcuts (list (list :maildir "/mailbox/Inbox" ;; (lambda () (progn (setq +mu4e-personal-addresses nil)
:key ?i) ;; (mu4e-clear-caches)))
(list :maildir "/mailbox/Sent" ;; :match-func
:key ?s) ;; (lambda (msg)
(list :maildir "/mailbox/Drafts" ;; (when msg
:key ?d) ;; (mu4e-message-contact-field-matches msg
(list :maildir "/mailbox/Trash" ;; :to "upcycling@fsfe.org")))
:key ?t) ;; :vars '((user-mail-address . "upcycling@fsfe.org")
(list :maildir "/mailbox/Archive" ;; (user-full-name . "FSFE Team Upcycling Android")))
:key ?a)) (make-mu4e-context
mu4e-bookmarks (list (list :name "All Inboxes" :name "mailbox"
:query "maildir:/mailbox/Inbox" :enter-func
:key ?i) (lambda () (mu4e-message "Switched to mailbox"))
(list :name "Unread messages" :leave-func
:query "flag:unread AND NOT flag:trashed" (lambda () (progn (setq +mu4e-personal-addresses nil)
:key ?u) (mu4e-clear-caches)))
(list :name "Today's messages" :match-func
:query "date:today..now" (lambda (msg)
:key ?t) (when msg
(list :name "Last 7 days" (string-prefix-p "/mailbox"
:query "date:7d..now" (mu4e-message-field msg :maildir) t)))
:hide-unread t :vars '((user-mail-address . "me@maxschlueter.com")
:key ?t))) (user-full-name . "Max Schlueter")
(+mu4e-personal-addresses ("me@maxschlueter.com")
("maxsc@fsfe.org"))
))))
;; Render buttons to verify&decrypt messages (setq mu4e-attachment-dir "~/Downloads"
(setq mm-decrypt-option 'always mu4e-sent-folder "/mailbox/Sent"
mm-verify-option 'always mu4e-drafts-folder "/mailbox/Drafts"
gnus-buttonized-mime-types '("multipart/encrypted" "multipart/signed") mu4e-trash-folder "/mailbox/Trash"
mml-secure-openpgp-encrypt-to-self t) mu4e-refile-folder "/mailbox/Archive"
;; TODO create context-aware variable
mu4e-spam-folder "/mailbox/Junk"
mu4e-compose-signature nil
mu4e-maildir-shortcuts (list (list :maildir "/mailbox/Inbox"
:key ?i)
(list :maildir "/mailbox/Sent"
:key ?s)
(list :maildir "/mailbox/Drafts"
:key ?d)
(list :maildir "/mailbox/Trash"
:key ?t)
(list :maildir "/mailbox/Archive"
:key ?a))
mu4e-bookmarks (list (list :name "All Inboxes"
:query "maildir:/mailbox/Inbox"
:key ?i)
(list :name "Unread messages"
:query "flag:unread AND NOT flag:trashed"
:key ?u)
(list :name "Today's messages"
:query "date:today..now"
:key ?t)
(list :name "Last 7 days"
:query "date:7d..now"
:hide-unread t
:key ?t)))
;; Move message to the trash folder but do not set the trash flag ;; TODO helper function used by `+mu4e-view-select-mime-part-action' is deprecated
;; https://github.com/djcb/mu/issues/1136#issuecomment-1066303788 ;; https://github.com/doomemacs/doomemacs/issues/7847
(setf (alist-get 'trash mu4e-marks) (map! :map mu4e-view-mode-map
(list :char '("d" . "") :ne "A" #'mu4e-view-mime-part-action)
:prompt "dtrash"
:dyn-target (lambda (target msg)
(mu4e-get-trash-folder msg))
:action (lambda (docid msg target)
;; Here's the main difference to the regular trash mark,
;; no +T before -N so the message is not marked as
;; IMAP-deleted:
(mu4e--server-move docid (mu4e--mark-check-target target) "+S-u-N"))))
(add-to-list 'mu4e-marks ;; Render buttons to verify&decrypt messages
'(spam (setq mm-decrypt-option 'always
:char "S" mm-verify-option 'always
:prompt "Spam" gnus-buttonized-mime-types '("multipart/encrypted" "multipart/signed")
:shot-target (lambda (target) mu4e-spam-folder) mml-secure-openpgp-encrypt-to-self t)
:action (lambda (docid msg target)
(mu4e--server-move docid mu4e-spam-folder "+S-u-N"))))
(defun my:mu4e-mark-for-spam() ;; Move message to the trash folder but do not set the trash flag
"Mark as read and move to spam." ;; https://github.com/djcb/mu/issues/1136#issuecomment-1066303788
(interactive) (setf (alist-get 'trash mu4e-marks)
(mu4e-headers-mark-and-next 'spam)) (list :char '("d" . "")
:prompt "dtrash"
:dyn-target (lambda (target msg)
(mu4e-get-trash-folder msg))
:action (lambda (docid msg target)
;; Here's the main difference to the regular trash mark,
;; no +T before -N so the message is not marked as
;; IMAP-deleted:
(mu4e--server-move docid (mu4e--mark-check-target target) "+S-u-N"))))
(map! :map mu4e-headers-mode-map :n "S" #'my:mu4e-mark-for-spam) (add-to-list 'mu4e-marks
'(spam
:char "S"
:prompt "Spam"
:shot-target (lambda (target) mu4e-spam-folder)
:action (lambda (docid msg target)
(mu4e--server-move docid mu4e-spam-folder "+S-u-N"))))
(add-to-list 'mu4e-view-mime-part-actions (defun my:mu4e-mark-for-spam()
'(:name "calendar" "Mark as read and move to spam."
:handler (lambda (file) (interactive)
(shell-command (mu4e-headers-mark-and-next 'spam))
(format "khal import --batch %s" file))
(khalel-import-events))
:receives temp))
;; Sign sent email automatically (map! :map mu4e-headers-mode-map :n "S" #'my:mu4e-mark-for-spam)
;; (add-hook 'message-send-hook 'mml-secure-message-sign-smime)
(require 'khalel-icalendar) (add-to-list 'mu4e-view-mime-part-actions
) '(:name "calendar"
:handler (lambda (file)
(shell-command
(format "khal import --batch %s" file))
(khalel-import-events))
:receives temp))
;; Sign sent email automatically
;; (add-hook 'message-send-hook 'mml-secure-message-sign-smime)
(require 'khalel-icalendar)
;; (defun max/mu4e-view-import-attachment-calendar (msg attnum) ;; (defun max/mu4e-view-import-attachment-calendar (msg attnum)
;; (let* ((att (mu4e~view-get-attach msg attnum)) ;; (let* ((att (mu4e~view-get-attach msg attnum))
@ -139,17 +147,7 @@
;; (add-to-list 'mu4e-view-attachment-actions ;; (add-to-list 'mu4e-view-attachment-actions
;; '("cImport in calendar" . max/mu4e-view-import-attachment-calendar) t) ;; '("cImport in calendar" . max/mu4e-view-import-attachment-calendar) t)
;; Autoload this command so that the mbsync service can update the index (map! "<f2>" #'=mu4e)
(autoload #'mu4e-update-index "mu4e" nil t)
(defun max/=mu4e ()
"Start email client and view all inboxes."
(interactive)
(require 'mu4e)
(+workspace-switch +mu4e-workspace-name t)
(mu4e--start (lambda () (mu4e-headers-search (mu4e-get-bookmark-query ?i)))))
(map! "<f2>" #'max/=mu4e)
(after! epa (after! epa
(setq epa-keyserver "keys.openpgp.org") (setq epa-keyserver "keys.openpgp.org")

89
gtd.el
View File

@ -6,8 +6,8 @@
org-agenda-files (mapcar (lambda (filename) (expand-file-name filename org-directory)) org-agenda-files (mapcar (lambda (filename) (expand-file-name filename org-directory))
'("gtd/inbox.org" '("gtd/inbox.org"
"gtd/tasks.org" "gtd/tasks.org"
"gtd/journal.org" "caldav/personal.org" ;; synced by khalel
"gtd/calendar.org"))) "gtd/journal.org")))
;; (file-expand-wildcards (concat org-directory "gtd/*.org")))) ;; (file-expand-wildcards (concat org-directory "gtd/*.org"))))
;; org-agenda-files (append (mapcar 'file-truename ;; org-agenda-files (append (mapcar 'file-truename
;; (file-expand-wildcards (concat org-directory "gtd/*.org"))) ;; (file-expand-wildcards (concat org-directory "gtd/*.org")))
@ -184,11 +184,16 @@ the current import date range."
:config :config
(advice-add #'khalel--insert-import-file-header :override #'max/khalel--insert-import-file-header) (advice-add #'khalel--insert-import-file-header :override #'max/khalel--insert-import-file-header)
(advice-add #'khalel-import-events :around #'doom-shut-up-a) (advice-add #'khalel-import-events :around #'doom-shut-up-a)
;; HACK: Getting an error message otherwise:
;; org-element--list-struct: Tab width in Org files must be 8, not 4. Please adjust your tab-width settings for Org mode.
;; TODO: Set tab width for org mode only
(setq-default tab-width 8)
(setq khalel-default-calendar "personal" (setq khalel-default-calendar "personal"
khalel-import-org-file-confirm-overwrite nil khalel-import-org-file-confirm-overwrite nil
khalel-import-start-date "-15d" khalel-import-start-date "-15d"
khalel-import-end-date "+30d" khalel-import-end-date "+30d"
khalel-import-org-file (expand-file-name "gtd/calendar.org" org-directory) khalel-import-org-file (expand-file-name "caldav/personal.org" org-directory)
khalel-import-format "* {title} {cancelled} :{calendar}:\n\ khalel-import-format "* {title} {cancelled} :{calendar}:\n\
:PROPERTIES:\n:CALENDAR: {calendar}\n\ :PROPERTIES:\n:CALENDAR: {calendar}\n\
:LOCATION: {location}\n\ :LOCATION: {location}\n\
@ -221,6 +226,54 @@ show up there.\n\n"))
(map! "C-c e" #'gtd-capture-event) (map! "C-c e" #'gtd-capture-event)
;;; TODO: not working still
;;; https://www.reddit.com/r/orgmode/comments/8rl8ep/making_orgcaldav_useable/
(use-package! org-caldav
:autoload org-caldav-sync
:init
(defvar +gtd/org-caldav-directory nil
"Directory where org-caldav synchronizes the calendars to.")
(setq org-icalendar-alarm-time 10)
:config
(setq org-caldav-resume-aborted 'always
+gtd/org-caldav-directory (expand-file-name "caldav" org-directory)
org-caldav-save-directory +gtd/org-caldav-directory
org-caldav-backup-file (expand-file-name "org-caldav-backup.org" +gtd/org-caldav-directory)
org-caldav-url "https://nextcloud.maxschlueter.com/remote.php/dav/calendars/max"
org-caldav-calendar-id "test"
org-caldav-files `(,(expand-file-name "personal.org" +gtd/org-caldav-directory))
org-caldav-inbox (expand-file-name "personal.org" +gtd/org-caldav-directory))
;; (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 (,(expand-file-name "personal.org" +gtd/org-caldav-directory)))))
;; :inbox ,(concat max/org-calendar-directory "personal.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)))
;;
;;; Reference system
(load! "roam")
;;
;;; Misc
(after! org (after! org
(setq org-clock-persist t (setq org-clock-persist t
;; Useful when clocking in on a waiting task ;; Useful when clocking in on a waiting task
@ -244,7 +297,29 @@ show up there.\n\n"))
org-pomodoro-short-break-length 5 org-pomodoro-short-break-length 5
org-pomodoro-long-break-length 20)) org-pomodoro-long-break-length 20))
;; (defvar org-clock-heading-str-limit 40
;;; Reference system "Maximum length of `org-clock-heading' string. Will be truncated if too long.")
(defun max/org-clock-get-clock-string ()
(load! "roam") "Form a clock string that will be shown in a status bar.
Adapted from `org-clock-get-clock-string'."
(require 'org-clock)
(when (org-clocking-p)
(let* ((currently-clocked-time
(floor (org-time-convert-to-integer
(time-since org-clock-start-time))
60))
(org-clock-heading-str (if (> (length org-clock-heading) org-clock-heading-str-limit)
(concat (substring org-clock-heading 0 org-clock-heading-str-limit) "...")
org-clock-heading))
(clocked-time (org-clock-get-clocked-time))
(work-done-str (org-duration-from-minutes clocked-time))
(current-work-done-str (org-duration-from-minutes currently-clocked-time)))
(if org-clock-effort
(let* ((effort-in-minutes (org-duration-to-minutes org-clock-effort))
(effort-str (org-duration-from-minutes effort-in-minutes)))
(format "%s (%s/%s) %s"
org-clock-heading-str work-done-str effort-str current-work-done-str))
(format "%s (%s) %s"
org-clock-heading-str
work-done-str
current-work-done-str)))))

52
org.el
View File

@ -1,52 +0,0 @@
;;; org.el -*- lexical-binding: t; -*-
;; 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/")
(require 'org)
(defvar org-clock-heading-str-limit 20
"Maximum length of `org-clock-heading' string. Will be truncated if too long.")
(defun max/org-clock-get-clock-string ()
"Form a clock string that will be shown in a status bar.
Adapted from `org-clock-get-clock-string'."
(require 'org-clock)
(when (org-clocking-p)
(let* ((currently-clocked-time
(floor (org-time-convert-to-integer
(time-since org-clock-start-time))
60))
(org-clock-heading-str (if (> (length org-clock-heading) org-clock-heading-str-limit)
(concat (substring org-clock-heading 0 org-clock-string-limit) "...")
org-clock-heading))
(clocked-time (org-clock-get-clocked-time))
(work-done-str (org-duration-from-minutes clocked-time))
(current-work-done-str (org-duration-from-minutes currently-clocked-time)))
(if org-clock-effort
(let* ((effort-in-minutes (org-duration-to-minutes org-clock-effort))
(effort-str (org-duration-from-minutes effort-in-minutes)))
(format "%s (%s/%s) %s"
org-clock-heading-str work-done-str effort-str current-work-done-str))
(format "%s (%s) %s"
org-clock-heading
work-done-str
current-work-done-str)))))
;; Fix org-babel shell block not inheriting envrc
;; https://github.com/purcell/envrc/issues/28
(advice-add 'org-babel-eval :around #'envrc-propagate-environment)
(after! org
;; Store org links to info pages
(add-to-list 'org-modules 'ol-info))
;; C-k is mapped to ~org-element-up~ by defualt
(map! :after evil-org
:map evil-org-mode-map
:i "C-k" #'org-kill-line)
(map! :after org
:map org-mode-map
:localleader
"Y" #'ox-clip-image-to-clipboard)

View File

@ -58,7 +58,13 @@
(package! org-inline-pdf) (package! org-inline-pdf)
(package! org-clock-convenience) (package! org-clock-convenience)
(package! org-super-agenda) (package! org-super-agenda)
(package! org-caldav)
;;; Roam
;;
(package! org-transclusion) (package! org-transclusion)
(package! org-remark)
;; org-roam-ui keeps up with the latest features in org-roam ;; org-roam-ui keeps up with the latest features in org-roam
(unpin! org-roam) (unpin! org-roam)
@ -70,19 +76,13 @@
(package! jl-encrypt (package! jl-encrypt
:recipe (:host gitlab :repo "lechten/defaultencrypt")) :recipe (:host gitlab :repo "lechten/defaultencrypt"))
;; (package! mu4e-alert)
;; (package! clip2org) ;; (package! clip2org)
(package! centered-cursor-mode) (package! centered-cursor-mode)
;; (package! counsel-tramp) ;; (package! counsel-tramp)
;; (package! org-capture-pop-frame)
(package! org-caldav)
;; XXX https://github.com/alphapapa/org-protocol-capture-html/issues/40
;; (package! org-protocol-capture-html)
(package! ob-typescript) (package! ob-typescript)
(package! indium) (package! indium)
;; (package! mac-pseudo-daemon) ;; (package! mac-pseudo-daemon)
;; (package! nix-docbook-mode) ;; (package! nix-docbook-mode)
(package! base16-theme)
(package! pdf-tools :built-in 'prefer) (package! pdf-tools :built-in 'prefer)
(package! nov) (package! nov)
;; (package! org-gtd) ;; (package! org-gtd)
@ -94,6 +94,6 @@
:branch "main" :branch "main"
:files (:defaults "bin"))) :files (:defaults "bin")))
;; https://github.com/doomemacs/doomemacs/issues/7196 (package! gptel)
(unpin! evil-collection) (package! copilot
(package! evil-collection :recipe (:repo "emacs-evil/evil-collection" :branch "master")) :recipe (:host github :repo "copilot-emacs/copilot.el" :files ("*.el" "dist")))

191
roam.el
View File

@ -2,64 +2,77 @@
(after! org-roam (after! org-roam
(setq org-roam-capture-templates (setq org-roam-capture-templates
'(("m" "main" plain '(("d" "default" plain
"%?" "%?"
:target :target
(file+head (file+head
"main/${slug}.org" "pages/${slug}.org"
"#+title: ${title}\n") "#+title: ${title}\n")
:unnarrowed t) :unnarrowed t)
("c" "cheatsheet" plain ))
"%?"
:target
(file+head
"cheatsheet/${slug}.org"
"#+title: ${title}\n")
:unnarrowed t)
("w" "worksheet" plain
"%?"
:target
(file+head
"worksheet/${slug}.org"
"#+title: ${title}\n")
:unnarrowed t)
("p" "person" plain
"%?"
:target
(file+head
"person/${slug}.org"
"#+title: ${title}\n")
:unnarrowed t)
("n" "literature note" plain
"%?"
:target
(file+head
"%(concat
(when citar-org-roam-subdir (concat citar-org-roam-subdir \"/\")) \"${citekey}.org\")"
"#+title: ${title}\n")
:unnarrowed t)))
(setq org-roam-dailies-capture-templates (setq org-roam-dailies-capture-templates
'(("d" "default" entry '(("d" "default" entry
"* %?" "* %?"
:target (file+head "%<%Y-%m-%d>.org" :target (file "%<%Y_%m_%d>.org"))))
"#+title: %<%Y-%m-%d>\n")))) ;; "#+title: %<%Y-%m-%d>\n"))))
(map! :leader (map! :leader
:desc "Capture today" "n n" #'org-roam-dailies-capture-today) :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-download (setq org-roam-capture-ref-templates
(setq org-download-screenshot-method "flameshot gui --raw > %s")) '(("r" "reference" plain
"%?"
:target
(file+head
"references/${slug}.org"
"#+title: ${title}")
:unnarrowed t)))
(setq org-roam-directory org-directory
;; compares a file relative to `org-roam-directory'
org-roam-file-exclude-regexp '("logseq")
org-roam-completion-everywhere nil
org-roam-dailies-directory "journals/"))
(setq org-download-image-dir (expand-file-name "assets" org-directory))
(use-package! org-download
:commands
org-download-dnd
org-download-yank
org-download-screenshot
org-download-clipboard
org-download-dnd-base64
:init
;; HACK We add these manually so that org-download is truly lazy-loaded
(pushnew! dnd-protocol-alist
'("^\\(?:https?\\|ftp\\|file\\|nfs\\):" . org-download-dnd)
'("^data:" . org-download-dnd-base64))
(advice-add #'org-download-enable :override #'ignore)
:config
(setq org-download-method 'directory
;; org-download-heading-lvl nil
org-download-timestamp "_%Y%m%d_%H%M%S"
org-download-annotate-function (lambda (_link) "")
org-download-screenshot-method "flameshot gui --raw > %s"))
;; org-download-abbreviate-filename-function
;; (lambda (path)
;; (if (file-in-directory-p path org-download-image-dir)
;; (file-relative-name path org-download-image-dir)
;; path)))
;; (after! org-download
;; (setq org-download-method 'directory
;; ;; org-download-heading-lvl nil
;; ;; org-download-timestamp "_%Y%m%d_%H%M%S"
;; org-download-screenshot-method "flameshot gui --raw > %s"))
(after! citar (after! citar
;; (setq citar-file-parser-functions ;; (setq citar-file-parser-functions
;; '(citar-file--parser-default ;; '(citar-file--parser-default
;; citar-file--parser-triplet)) ;; citar-file--parser-triplet))
(setq citar-org-roam-capture-template-key "n") ;; (setq citar-org-roam-capture-template-key "n")
(setq! citar-library-paths '("~/Zotero" "~/Nextcloud/Calibre") (setq! citar-library-paths '("~/Zotero" "~/Nextcloud/Calibre")
citar-notes-paths `(,(expand-file-name "reference" org-roam-directory)) citar-notes-paths (list (expand-file-name "references" org-roam-directory))
citar-bibliography `(,(expand-file-name "library.bib" org-roam-directory) citar-bibliography (list (expand-file-name "library.bib" org-roam-directory)
,(expand-file-name "books.bib" org-roam-directory)))) (expand-file-name "books.bib" org-roam-directory))))
(after! citar-org-roam (after! citar-org-roam
;; (citar-register-notes-source ;; (citar-register-notes-source
@ -71,7 +84,7 @@
;; :create #'orb-citar-edit-note ;; :create #'orb-citar-edit-note
;; :annotate #'citar-org-roam--annotate)) ;; :annotate #'citar-org-roam--annotate))
;; (setq citar-notes-source 'orb-citar-source) ;; (setq citar-notes-source 'orb-citar-source)
(setq citar-org-roam-subdir "reference")) (setq citar-org-roam-subdir "references"))
;; insert drawings from my RM2 ;; insert drawings from my RM2
(use-package! org-inline-pdf (use-package! org-inline-pdf
@ -102,5 +115,99 @@
:prefix "n" :prefix "n"
:desc "Org Transclusion Mode" "t" #'org-transclusion-mode)) :desc "Org Transclusion Mode" "t" #'org-transclusion-mode))
(defun my/org-remark-notes-file-name-function ()
(cond ((buffer-file-name)
(let ((source-filename (org-remark-source-find-file-name)))
(when (and (stringp source-filename)
(file-exists-p source-filename))
(concat (file-name-sans-extension
(file-name-nondirectory source-filename))
"-notes.org"))))
((eq major-mode 'eww-mode)
(my/org-remark-eww--create-capture-note eww-data))))
(defun my/org-remark-eww--create-capture-note (info)
"Open or create org-roam node from `eww-data'."
;; (let* ((title (plist-get eww-data :title))
;; (ref (plist-get eww-data :url)))
(org-roam-capture-
;; :keys (plist-get info :template)
:node (org-roam-node-create :title (plist-get info :title))
:info (list :ref (plist-get info :url))
;; :body (plist-get info :body))
:templates '(("r" "reference" plain "%?"
:target (file+head "${slug}.org"
"#+title: ${title}")
:immediate-finish t
:unnarrowed t))))
;; :templates org-roam-capture-ref-templates))
;; (apply 'org-roam-capture-
;; :info (setq infoplist
;; ;; Add notetitle in case someone wants to use it in their
;; ;; capture template.
;; (plist-put infoplist :note-title notetitle))
;; :info (list )
;; :node (org-roam-node-create :title title)
;; :props '(:finalize find-file)
;; (if templatekey
;; (list :keys templatekey)
;; (list
;; :templates
;; '(("r" "reference" plain "%?" :if-new
;; (file+head
;; "%(concat
;; (when citar-org-roam-subdir (concat citar-org-roam-subdir \"/\")) \"${citar-citekey}.org\")"
;; "#+title: ${note-title}\n")
;; :immediate-finish t
;; :unnarrowed t)))))
;; (org-roam-ref-add url)))
;; (org-roam-capture-
;; :keys (plist-get info :template)
;; :node (org-roam-node-create :title (plist-get info :title))
;; :info (list :ref (plist-get info :ref)
;; :body (plist-get info :body))
;; :templates org-roam-capture-ref-templates))
;; (use-package! org-remark
;; :after org
;; :init
;; (require 'org-remark-global-tracking)
;; (org-remark-global-tracking-mode +1)
;; (map! "C-c n m" #'org-remark-mark)
;; :config
;; (map! :map org-remark-mode-map
;; "C-c n o" #'org-remark-open
;; "C-c n ]" #'org-remark-view-next
;; "C-c n [" #'org-remark-view-prev
;; "C-c n R" #'org-remark-remove))
(use-package! org-remark
:bind (;; :bind keyword also implicitly defers org-remark itself.
;; Keybindings before :map is set for global-map.
("C-c n m" . org-remark-mark)
("C-c n l" . org-remark-mark-line)
:map org-remark-mode-map
("C-c n o" . org-remark-open)
("C-c n ]" . org-remark-view-next)
("C-c n [" . org-remark-view-prev)
("C-c n r" . org-remark-remove)
("C-c n d" . org-remark-delete))
;; Alternative way to enable `org-remark-global-tracking-mode' in
;; `after-init-hook'.
;; :hook (after-init . org-remark-global-tracking-mode)
:init
;; It is recommended that `org-remark-global-tracking-mode' be
;; enabled when Emacs initializes. Alternatively, you can put it to
;; `after-init-hook' as in the comment above
(org-remark-global-tracking-mode +1)
:config
(setq org-remark-notes-file-name #'my/org-remark-notes-file-name-function)
(use-package org-remark-info :after info :config (org-remark-info-mode +1))
(use-package org-remark-eww :after eww :config (org-remark-eww-mode +1))
(use-package org-remark-nov :after nov :config (org-remark-nov-mode +1)))
(after! org-roam-bibtex (after! org-roam-bibtex
(setq orb-insert-link-description 'citekey)) (setq orb-insert-link-description 'citekey))