1 ;; Added by Package.el. This must come before configurations of
2 ;; installed packages. Don't delete this line. If you don't want it,
3 ;; just comment it out by adding a semicolon to the start of the line.
4 ;; You may delete these explanatory comments.
7 (add-to-list 'load-path "~/.emacs.d/lisp/")
11 ;; Configure printing using CUPS network printer
17 ;; Enable the melpa archive for packages
20 (setq package-enable-at-startup nil)
21 (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
22 (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t)
23 (add-to-list 'package-archives
24 '("elpy" . "http://jorgenschaefer.github.io/packages/")))
26 (use-package system-packages
29 (use-package modus-themes
31 :demand t ;; Without this, the theme load is deferred due to the
34 ;; Add all customisation prior to loading the themes
35 (setq modus-themes-mixed-fonts t)
37 (modus-themes-select 'modus-vivendi-tinted)
39 :bind ("<f5>" . modus-themes-toggle))
41 (use-package orderless
44 (setq completion-styles '(orderless basic)
45 completion-category-overrides '((file (styles basic partial-completion)))))
47 ;; follow links to version-controlled files without confirming
50 ;; ESS - for working in R
51 (autoload 'R-mode "ess-site.el" "Major mode for editing R source." t)
52 (setq load-path (cons "/usr/share/emacs/site-lisp/ess" load-path))
53 (load "/usr/share/emacs/site-lisp/ess/lisp/ess-site")
54 (setq inferior-julia-program-name "/usr/bin/julia")
56 (use-package ess-view-data
59 ;; enable autocomplete
62 ;; Optional customizations
64 (corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
65 (corfu-auto t) ;; Enable auto completion
66 ;; (corfu-separator ?\s) ;; Orderless field separator
67 ;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary
68 ;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match
69 ;; (corfu-preview-current nil) ;; Disable current candidate preview
70 ;; (corfu-preselect 'prompt) ;; Preselect the prompt
71 ;; (corfu-on-exact-match nil) ;; Configure handling of exact matches
72 ;; (corfu-scroll-margin 5) ;; Use scroll margin
74 ;; Enable Corfu only for certain modes. See also `global-corfu-modes'.
75 ;; :hook ((prog-mode . corfu-mode)
76 ;; (shell-mode . corfu-mode)
77 ;; (eshell-mode . corfu-mode))
79 ;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can
80 ;; be used globally (M-/). See also the customization variable
81 ;; `global-corfu-modes' to exclude certain modes.
88 ;; Bind prefix keymap providing all Cape commands under a mnemonic key.
89 ;; Press C-c p ? to for help.
90 :bind ("C-c p" . cape-prefix-map) ;; Alternative keys: M-p, M-+, ...
91 ;; Alternatively bind Cape commands individually.
92 ;; :bind (("C-c p d" . cape-dabbrev)
93 ;; ("C-c p h" . cape-history)
94 ;; ("C-c p f" . cape-file)
97 ;; Add to the global default value of `completion-at-point-functions' which is
98 ;; used by `completion-at-point'. The order of the functions matters, the
99 ;; first function returning a result wins. Note that the list of buffer-local
100 ;; completion functions takes precedence over the global list.
101 (add-hook 'completion-at-point-functions #'cape-dict) ;; requires words package to be installed on Arch to provide /usr/share/dict/words
102 (add-hook 'completion-at-point-functions #'cape-dabbrev)
103 (add-hook 'completion-at-point-functions #'cape-file)
104 (add-hook 'completion-at-point-functions #'cape-elisp-block)
105 ;; (add-hook 'completion-at-point-functions #'cape-history)
112 (("C-c c" . org-capture)
113 ("C-c l" . org-store-link)
114 ("C-c a" . org-agenda))
116 (org-default-notes-file "~/Nextcloud/notes/inbox.org")
117 (org-agenda-files `(,org-default-notes-file "~/Nextcloud/notes/calendar-nextcloud.org"))
118 (org-capture-bookmark nil)
120 (org-capture-templates
121 '(("f" "Fleeting note" entry
122 (file+headline org-default-notes-file "Notes")
123 "* %?\nEntered on %U\n %i\n %a")
124 ("b" "Tax receipt" item
125 (file "~/Documents/belastingen/FY24-25.org")
127 ("a" "Appointment" entry
128 (file+olp+datetree "~/Nextcloud/notes/calendar-nextcloud.org")
129 "* %?\n :PROPERTIES:\n :location: %^{Location}\n :END:\n%(fv/org-capture-appointment-timestamp)\n\n"
134 ("p" "Permanent note" plain
135 (file denote-last-path)
138 :immediate-finish nil
141 ("t" "New task" entry
142 (file+headline org-default-notes-file "Tasks")
144 ("e" "Email follow-up" entry (file+headline org-default-notes-file "Tasks")
145 "* TODO %:fromname: %a %?\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\") t)")))
147 (org-agenda-custom-commands
148 '(("P" "Expired calendar events" ((tags "TIMESTAMP<=\"<now>\"")))
149 ("n" "Agenda and all TODOs" ((agenda "") (alltodo "")))))
152 (defun my/opened-buffer-files ()
153 "Return the list of org files currently opened in emacs"
156 (if (and (buffer-file-name x)
157 (string-match "\\.org$"
158 (buffer-file-name x)))
159 (buffer-file-name x)))
161 (setq org-refile-targets `((my/opened-buffer-files :maxlevel . 9)
162 (,(file-expand-wildcards "~/Nextcloud/notes/*.org") :maxlevel . 1)))
163 (setq org-agenda-skip-scheduled-if-done t)
164 (setq org-agenda-skip-deadline-if-done t)
165 (setq org-agenda-start-on-weekday nil)
166 (setq org-log-done 'time)
167 ;; Automatically flow lines based on window width and use
168 ;; variable width fonts in org-mode.
169 (add-hook 'org-mode-hook 'visual-line-mode)
170 (add-hook 'org-mode-hook 'variable-pitch-mode)
171 ;; org-mode support for R and LaTeX
172 (org-babel-do-load-languages
173 'org-babel-load-languages
177 (defun fv/org-capture-appointment-timestamp (&optional duration)
178 "Get an Org timestamp for an appointment.
179 Prompt for a start time, calculate the end time by adding DURATION (default 30
180 minutes), and return a formatted Org timestamp with start and end times."
181 (let* ((duration (or duration 30))
182 (start-time (org-read-date t t nil "From:"))
183 (end-time (time-add start-time (seconds-to-time (* duration 60)))))
184 (concat (format-time-string (org-time-stamp-format t) start-time)
186 (format-time-string (org-time-stamp-format t) end-time))))
188 (use-package org-caldav
191 (setq org-caldav-url "https://owncloud.vanrenterghem.biz/remote.php/dav/calendars/frederik")
192 (setq org-caldav-calendar-id "default%20calendar")
193 ;; Org filename where new entries from calendar stored
194 (setq org-caldav-inbox '(file+olp+datetree "~/Nextcloud/notes/calendar-nextcloud.org"))
195 ;; Additional Org files to check for calendar events
196 (setq org-caldav-files nil)
197 ;; Usually a good idea to set the timezone manually
198 (setq org-icalendar-timezone "Australia/Perth")
199 (setq org-caldav-delete-calendar-entries 'ask))
201 (use-package org-protocol)
206 (setq TeX-auto-save t
208 TeX-view-program-selection
209 '(((output-dvi has-no-display-manager)
211 ((output-dvi style-pstricks)
214 (output-pdf "PDF Tools")
215 (output-html "xdg-open"))))
216 ;; (load "preview-latex.el" nil t t)
219 ;; Automatically switch to various modes
220 (setq auto-mode-alist
221 '(("\\.mdwn\\'" . markdown-mode)
222 ("\\.md\\'" . markdown-mode)
223 ("\\.yarn\\'" . markdown-mode)
224 ("\\.cpp\\'" . c++-mode)
225 ("\\.js\\'" . js-mode)
226 ("\\.json\\'" . js-mode)
227 ("Makefile" . makefile-mode)
228 ("README" . markdown-mode)
229 ("NEWS" . markdown-mode)
230 ("COMMIT_EDITMSG\\'" . text-mode)
231 ("\\.html\\'" . html-mode)
232 ("\\.css\\'" . css-mode)
233 ("\\.yaml\\'" . yaml-mode)
234 ("\\.yml\\'" . yaml-mode)
235 ("\\.ick\\'" . yaml-mode)
236 ("\\.py\\'" . python-mode)
238 ("\\.org\\'" . org-mode)
239 ("\\.tex\\'" . latex-mode)
240 ("\\.sh\\'" . shell-script-mode)
241 ("\\.hs\\'" . haskell-mode)
242 ("\\.el\\'" . emacs-lisp-mode)))
245 (custom-set-variables
246 ;; custom-set-variables was added by Custom.
247 ;; If you edit it by hand, you could mess it up, so be careful.
248 ;; Your init file should contain only one such instance.
249 ;; If there is more than one, they won't work right.
250 '(browse-url-browser-function 'browse-url-firefox)
252 '("8d146df8bd640320d5ca94d2913392bc6f763d5bc2bb47bed8e14975017eea91"
253 "9a977ddae55e0e91c09952e96d614ae0be69727ea78ca145beea1aae01ac78d2"
254 "0cf95236abcf59e05b1ea69b4edd53d293a5baec4fe4c3484543fee99bfd2204"
255 "80b00f3bf7cdbdca6c80aadfbbb03145f3d0aacf6bf2a559301e61109954e30a"
257 '(org-export-backends '(ascii html icalendar latex md odt))
258 '(package-selected-packages
259 '(## ack all-the-icons-dired auctex calfw calfw-org company consult
260 consult-denote denote devdocs dired-preview
261 dired-quick-sort eat elfeed-protocol ellama elpy embark
262 embark-consult emms engrave-faces ess ess-R-data-view
263 ess-smart-underscore ess-view-data flx fontaine ftable
264 haskell-mode htmlize jinx julia-mode leuven-theme libmpdel
265 lsp-mode lua-mode magit marginalia mpdel-embark mu4e
266 mustache nerd-icons nerd-icons-dired nov orderless org
267 org-caldav org-contrib org-ql org-static-blog osm ox-rss
268 pass password-store powerthesaurus request straight
270 '(use-package-compute-statistics t))
272 ;; custom-set-faces was added by Custom.
273 ;; If you edit it by hand, you could mess it up, so be careful.
274 ;; Your init file should contain only one such instance.
275 ;; If there is more than one, they won't work right.
279 ;; Send mail using SMTP via mail.vanrenterghem.io.
280 (setq send-mail-function 'smtpmail-send-it)
281 (setq smtpmail-smtp-server "mail.vanrenterghem.io"
282 smtpmail-smtp-service 587
283 smtpmail-stream-type 'starttls)
284 (setq user-full-name "Frederik Vanrenterghem"
285 smtpmail-local-domain "vanrenterghem.io"
286 user-mail-address (concat "frederik@" smtpmail-local-domain))
287 ;; Ignored in mu4e as it sets user-agent
288 (setq mail-default-headers
289 (concat "X-Mailer: GNU Emacs " (symbol-value 'emacs-version)))
290 (setq w3m-pop-up-frames t)
292 (global-set-key [remap list-buffers] 'ibuffer)
294 ;;; use pass (~/.password-store)
295 ;;; (see The Unix password store)
299 (auth-source-pass-enable)
300 (setq pass-username-field "Username"))
302 ;; Elfeed news reader from Nextcloud
306 (setq elfeed-use-curl nil)
307 (elfeed-set-timeout 36000)
308 (define-key elfeed-search-mode-map (kbd "*") (lambda () (interactive) (apply 'elfeed-search-toggle-all '(star))))
309 (define-key elfeed-show-mode-map (kbd "*") (lambda () (interactive) (apply 'elfeed-show-tag '(star))))
310 (add-hook 'elfeed-show-mode 'variable-pitch-mode))
312 (use-package elfeed-protocol
316 (setq elfeed-protocol-feeds '(
317 ("owncloud+https://frederik@owncloud.vanrenterghem.biz" :use-authinfo t)
319 (elfeed-protocol-enable))
322 ;; Read and write email using mu4e
325 ;; :ensure-system-package mu ;; Install from aur
327 (setq mail-user-agent 'mu4e-user-agent)
328 ;; Also use mu4e when called from gnus-dired-attach
329 (setq gnus-dired-mail-mode 'mu4e-user-agent
330 mu4e-get-mail-command "mbsync io"
331 mu4e-update-interval 600
332 mu4e-use-fancy-chars t
333 mu4e-view-show-images t
334 mu4e-sent-folder "/Sent"
335 mu4e-drafts-folder "/Drafts"
336 mu4e-trash-folder "/Trash"
337 message-kill-buffer-on-exit t
338 ;;Fixing duplicate UID errors when using mbsync and mu4e
339 mu4e-change-filenames-when-moving t)
340 ;; attach files to mu4e messages by marking the file(s) in dired and pressing C-c RET C-a
341 (add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode)
342 ;; Define all bookmarks starting with favourite query used in mailcount modeline
344 '(( :name "Last 24h's messages"
347 :query "date:24h..now AND NOT flag:trashed")
348 ( :name "Unread messages"
349 :query "flag:unread AND NOT flag:trashed"
351 ( :name "Today's messages"
352 :query "date:today..now AND NOT flag:trashed"
354 ( :name "Last 7 days"
355 :query "date:7d..now AND NOT flag:trashed"
358 ( :name "Messages with images"
359 :query "mime:image/* AND NOT flag:trashed"
361 ;; Create custom spam status header and show in message view
362 (add-to-list 'mu4e-header-info-custom
364 ( :name "Spam-Status" ;; long name, as seen in the message-view
365 :shortname "Spam" ;; short name, as seen in the headers view
366 :help "The Spam status" ;; tooltip
367 ;; uses mu4e-fetch-field which is rel. slow, so only appropriate
368 ;; for mu4e-view-fields, and _not_ mu4e-headers-fields
369 :function (lambda (msg)
370 (or (string-join (seq-take (split-string (or (mu4e-fetch-field msg "X-Spam-Status") "") " ") 2) " ") "")))))
371 (add-to-list 'mu4e-view-fields :spam-status)
372 ;; Resize image attachments when sending email
373 (defvar mu4e-resize-image-types '("jpg" "png" "svg" "jpeg")
374 "List of attached image types to resize.")
375 (defvar mu4e-inhibit-resize nil)
376 (defun mu4e-resize-image-attachments ()
377 (unless mu4e-inhibit-resize
380 (mapconcat #'identity mu4e-resize-image-types "\\|")))
382 (message-goto-body-1)
383 (while (re-search-forward
384 (format "<#part.+\\(filename=\"\\)\\(.+\\(\\.%s\\)\\)\""
387 (let* ((infile (match-string-no-properties 2))
388 (outfile (concat (temporary-file-directory)
389 (file-name-nondirectory infile))))
390 (push (format "magick convert %s -resize 1200x1200\\> %s"
391 (shell-quote-argument infile)
392 (shell-quote-argument outfile))
394 (replace-match outfile t t nil 2)))
395 (mapcar #'shell-command cmds)))))
396 (add-hook 'message-send-hook 'mu4e-resize-image-attachments)
397 (add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode) ;; Attach files to messages using dired C-c RET C-a
398 (defun mu4e-inhibit-resize()
400 (set (make-local-variable 'mu4e-inhibit-resize) t)))
402 ;; Load configuration for website
403 ;(load "mustache-html")
408 :hook (dired-mode . denote-dired-mode)
410 (("C-c n n" . denote)
411 ("C-c n r" . denote-rename-file)
412 ("C-c n l" . denote-link)
413 ("C-c n b" . denote-backlinks))
415 (setq denote-directory "/home/frederik/Nextcloud/notes/")
416 (denote-rename-buffer-mode 1))
418 (use-package nerd-icons
420 ;; The Nerd Font you want to use in GUI
421 ;; "Symbols Nerd Font Mono" is the default and is recommended
422 ;; but you can use any other Nerd Font if you want
423 ;; (nerd-icons-font-family "Symbols Nerd Font Mono")
426 ;; Dired configuration
427 (with-eval-after-load 'dired
429 ;; Set dired-x global variables here. For example:
430 ;; (setq dired-x-hands-off-my-keys nil)
432 (add-hook 'dired-mode-hook
434 ;; Set dired-x buffer-local variables here.
436 (dired-hide-details-mode 1)
437 (nerd-icons-dired-mode 1)
439 (setq delete-by-moving-to-trash t)
440 (setq dired-guess-shell-alist-user
441 '(("\\.\\(png\\|jpe?g\\|tiff\\)" "feh" "xdg-open")
442 ("\\.\\(mp[34]\\|m4a\\|ogg\\|flac\\|webm\\|mkv\\)" "mpv" "xdg-open")
445 ;; Use `vertico' package to get a vertical view of the minibuffer.
449 (setq vertico-resize nil)
452 ;; Persist history over Emacs restarts. Vertico sorts by history position.
453 (use-package savehist
457 ;; Use `marginalia' package. This will display useful
458 ;; annotations next to entries in the minibuffer. For example, when
459 ;; using M-x it will show a brief description of the command as well
460 ;; as the keybinding associated with it (if any).
461 (use-package marginalia
466 ;; Use 'winner' mode to undo and redo windows changes
467 ;; using C-c <left> and C-c <right>.
473 ;; Use a different spell checker, always
477 (keymap-global-set "M-$" #'jinx-correct)
478 :hook (emacs-startup . global-jinx-mode))
480 (use-package powerthesaurus
484 (transient-define-prefix my/transient-spelling ()
488 ("y" "Synonyms" powerthesaurus-lookup-synonyms-dwim)
489 ("a" "Antonyms" powerthesaurus-lookup-antonyms-dwim)]
491 ("x" "Jinx" jinx-mode)
492 ("c" "Jinx correct" jinx-correct)]
494 ("d" "Lookup" dictionary-lookup-definition)]
496 ("q" "Quit" transient-quit-one)]])
498 ("C-c s" . my/transient-spelling))
504 (keymap-global-set "C-." #'embark-act)
505 (keymap-global-set "C-;" #'embark-dwim))
510 ;; Change default bindings to consult- ones
512 (;; C-x bindings in `ctl-x-map'
513 ("C-x b" . consult-buffer) ;; orig. switch-to-buffer
514 ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
515 ("C-x r b" . consult-bookmark) ;; orig. bookmark-jump
516 ;; Other custom bindings
517 ("M-y" . consult-yank-pop))) ;; orig. yank-pop
519 (use-package consult-mu
520 :ensure nil ;; cloned in
521 :load-path "~/.emacs.d/lisp/consult-mu"
522 :after (consult mu4e)
524 ;;maximum number of results shown in minibuffer
525 (consult-mu-maxnum 200)
526 ;;show preview when pressing any keys
527 (consult-mu-preview-key 'any)
528 ;;do not mark email as read when previewed
529 (consult-mu-mark-previewed-as-read nil)
530 ;;do not amrk email as read when selected. This is a good starting point to ensure you would not miss important emails marked as read by mistake especially when trying this package out. Later you can change this to t.
531 (consult-mu-mark-viewed-as-read nil)
532 ;; open the message in mu4e-view-buffer when selected.
533 (consult-mu-action #'consult-mu--view-action)
536 (use-package consult-denote
539 ;; Configure `world-clock'
543 (setq zoneinfo-style-world-list '(("Europe/Brussels" "Leuven")))
544 (add-to-list 'zoneinfo-style-world-list '("Australia/Perth" "Perth")))
547 ;; View PDFs in Emacs
548 (pdf-loader-install) ; On demand loading, leads to faster startup time
549 (setq pdf-misc-print-programm "/usr/bin/lpr")
557 ;; For `eat-eshell-mode'.
558 (add-hook 'eshell-load-hook #'eat-eshell-mode)
559 (setq eshell-visual-commands '()))
565 (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
567 (add-hook 'nov-mode-hook #'variable-pitch-mode))
569 ;; Set some preset fonts
570 (use-package fontaine
573 (setq fontaine-presets
575 :default-family "Iosevka Nerd Font"
577 :variable-pitch-family "Linux Biolinum O"
578 :variable-pitch-weight normal
579 :variable-pitch-height 1.1
580 :italic-family "Iosevka Etoile"
583 :default-family "Iosevka Nerd Font"
585 :variable-pitch-family "Literata"
586 :variable-pitch-weight normal
587 :variable-pitch-height 1.0
590 :default-family "Fira Mono Nerd Font"
592 :variable-pitch-family "Fira Sans Book"
593 :variable-pitch-weight normal
594 :variable-pitch-height 1.0
597 :default-family "Fira Mono Nerd Font"
599 :variable-pitch-family "Fira Sans Book"
600 :variable-pitch-weight normal
601 :variable-pitch-height 1.0
604 :variable-pitch-family "Libre Baskerville"
605 :variable-pitch-weight normal
606 :variable-pitch-height 1.0
609 :variable-pitch-family "Noto Serif"
610 :variable-pitch-weight normal
611 :variable-pitch-height 1.0
614 :variable-pitch-family "ETBembo"
615 :variable-pitch-weight normal
616 :variable-pitch-height 1.1
619 :variable-pitch-family "Literata"
620 :variable-pitch-weight normal
621 :variable-pitch-height 1.0
627 ("C-h D" . devdocs-lookup))
632 (require 'emms-setup)
633 (require 'emms-player-mpd)
634 (emms-all) ; don't change this to values you see on stackoverflow questions if you expect emms to work
635 (setq emms-player-list '(emms-player-mpd))
636 (add-to-list 'emms-info-functions 'emms-info-mpd)
637 (add-to-list 'emms-player-list 'emms-player-mpd)
639 ;; Socket is not supported
640 (setq emms-player-mpd-server-name "mea-hookani-pila")
641 (setq emms-player-mpd-server-port "6600")
642 (emms-player-mpd-connect))
646 ;; Might want to run this automatically
647 ;; using variable after-focus-change-function
648 (defun my/adjust-font-size-based-on-display ()
649 "Change size of fonts based on monitor."
651 (let* ((display-name (cdr (assq 'name (frame-monitor-attributes))))
652 (font-height (cond ((string-equal display-name "eDP-1") 140)
655 (set-face-attribute 'default (selected-frame) :height font-height)))