X-Git-Url: http://git.vanrenterghem.biz/Dotty.git/blobdiff_plain/1f0ec8efee18504483a1a88bfcd395f7b5846949..93531ffa52dfea23aa60d9ee1668f0277f66334a:/emacs/.emacs.d/init.el diff --git a/emacs/.emacs.d/init.el b/emacs/.emacs.d/init.el index ae30d66..ddb78c4 100644 --- a/emacs/.emacs.d/init.el +++ b/emacs/.emacs.d/init.el @@ -6,20 +6,43 @@ (add-to-list 'load-path "~/.emacs.d/lisp/") -;; Use a dark theme now -;(load-theme 'wheatgrass) +(tool-bar-mode -1) -;; Use light theme -;;(load-theme 'leuven t) -(require 'modus-themes) -(setq modus-themes-mixed-fonts t) -(load-theme 'modus-operandi t) -(variable-pitch-mode) -(define-key global-map (kbd "") #'modus-themes-toggle) +;; Configure printing using CUPS network printer +(setq lpr-switches + (append '("-o raw" + "-o media=A4") + lpr-switches)) -(require 'orderless) -(setq completion-styles '(orderless basic) - completion-category-overrides '((file (styles basic partial-completion)))) +;; Enable the melpa archive for packages +(use-package package + :config + (setq package-enable-at-startup nil) + (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) + (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t) + (add-to-list 'package-archives + '("elpy" . "http://jorgenschaefer.github.io/packages/"))) + +(use-package system-packages + :ensure t) + +(use-package modus-themes + :ensure t + :demand t ;; Without this, the theme load is deferred due to the + ;; bind keyword below + :init + ;; Add all customisation prior to loading the themes + (setq modus-themes-mixed-fonts t) + :config + (modus-themes-select 'modus-vivendi-tinted) + (variable-pitch-mode) + :bind ("" . modus-themes-toggle)) + +(use-package orderless + :ensure t + :config + (setq completion-styles '(orderless basic) + completion-category-overrides '((file (styles basic partial-completion))))) ;; follow links to version-controlled files without confirming vc-follow-symlinks t @@ -31,26 +54,99 @@ vc-follow-symlinks t (setq inferior-julia-program-name "/usr/bin/julia") ;; enable autocomplete -(add-hook 'after-init-hook 'global-company-mode) - -(require 'org) - -;; Automatically flow lines based on window width and use -;; variable width fonts in org-mode. -(add-hook 'org-mode-hook 'visual-line-mode) -(add-hook 'org-mode-hook 'variable-pitch-mode) - -;; Auctex -(load "auctex.el" nil t t) -(load "preview-latex.el" nil t t) +(use-package company + :ensure t + :bind(:map company-active-map + ("" . nil) + ("RET" . nil) + ("C-" . company-complete-selection) + ([tab] . company-complete-common) + ("TAB" . company-complete-common)) + :config + (setq ispell-complete-word-dict + (expand-file-name (concat user-emacs-directory "aspell_words.txt"))) + ;(defun my/text-mode-hook () + ; (setq-local company-backends +; '((company-dabbrev company-ispell :separate) + ; company-files))) + ; (add-hook 'text-mode-hook #'my/text-mode-hook) + (global-company-mode 1)) + +(use-package org + :ensure t + :bind + (("C-c c" . org-capture) + ("C-c l" . org-store-link) + ("C-c a" . org-agenda)) + :custom + (org-default-notes-file "~/Nextcloud/notes/inbox.org") + (org-agenda-files `(,org-default-notes-file "~/Nextcloud/notes/calendar.org")) + (org-capture-bookmark nil) + ;; Capture templates + (org-capture-templates + '(("f" "Fleeting note" item + (file+headline org-default-notes-file "Notes") + "* %?\nEntered on %U\n %i\n %a") + ("b" "Tax receipt" item + (file "~/Documents/belastingen/FY24-25.org") + "* %t %a\n") + ("p" "Permanent note" plain + (file denote-last-path) + #'denote-org-capture + :no-save t + :immediate-finish nil + :kill-buffer t + :jump-to-captured t) + ("t" "New task" entry + (file+headline org-default-notes-file "Tasks") + "* TODO %i%?") + ("e" "Email follow-up" entry (file+headline org-default-notes-file "Tasks") + "* TODO %:fromname: %a %?\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\"))"))) + ;; Agenda views + (org-agenda-custom-commands + '(("P" "Expired calendar events" ((tags "TIMESTAMP<=\"\""))) + ("n" "Agenda and all TODOs" ((agenda "") (alltodo ""))))) + :config + (setq org-agenda-skip-scheduled-if-done t) + (setq org-agenda-skip-deadline-if-done t) + (setq org-agenda-start-on-weekday nil) + ;; Automatically flow lines based on window width and use + ;; variable width fonts in org-mode. + (add-hook 'org-mode-hook 'visual-line-mode) + (add-hook 'org-mode-hook 'variable-pitch-mode) + ;; org-mode support for R and LaTeX + (org-babel-do-load-languages + 'org-babel-load-languages + '((R . t) + (latex . t)))) + +(use-package org-caldav + :ensure t + :config + (setq org-caldav-url "https://owncloud.vanrenterghem.biz/remote.php/dav/calendars/frederik") + (setq org-caldav-calendar-id "orgmode") + ;; Org filename where new entries from calendar stored + (setq org-caldav-inbox "~/Nextcloud/notes/calendar.org") + ;; Additional Org files to check for calendar events + (setq org-caldav-files nil) + ;; Usually a good idea to set the timezone manually + (setq org-icalendar-timezone "Australia/Perth")) + +(use-package tex + :ensure auctex + :config + (setq TeX-auto-save t + TeX-parse-self t + TeX-view-program-selection + '(((output-dvi has-no-display-manager) + "dvi2tty") + ((output-dvi style-pstricks) + "dvips and gv") + (output-dvi "xdvi") + (output-pdf "PDF Tools") + (output-html "xdg-open")))) +;; (load "preview-latex.el" nil t t) -;; org-mode support for R and LaTeX -(org-babel-do-load-languages - 'org-babel-load-languages - '((R . t) - (latex . t))) -;; Security risk - This is somewhat ill-advised it appears -(setq org-confirm-babel-evaluate nil) ;; Automatically switch to various modes (setq auto-mode-alist @@ -71,17 +167,11 @@ vc-follow-symlinks t ("\\.py\\'" . python-mode) ("\\.R\\'" . R-mode) ("\\.org\\'" . org-mode) + ("\\.tex\\'" . latex-mode) ("\\.sh\\'" . shell-script-mode) ("\\.hs\\'" . haskell-mode) ("\\.el\\'" . emacs-lisp-mode))) -;; Enable the melpa archive for packages -(require 'package) -(setq package-enable-at-startup nil) -(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) -(add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t) -(add-to-list 'package-archives - '("elpy" . "http://jorgenschaefer.github.io/packages/")) (custom-set-variables ;; custom-set-variables was added by Custom. @@ -90,11 +180,11 @@ vc-follow-symlinks t ;; If there is more than one, they won't work right. '(browse-url-browser-function 'browse-url-firefox) '(custom-safe-themes - '("0cf95236abcf59e05b1ea69b4edd53d293a5baec4fe4c3484543fee99bfd2204" "80b00f3bf7cdbdca6c80aadfbbb03145f3d0aacf6bf2a559301e61109954e30a" default)) - '(denote-directory "/home/frederik/Nextcloud/notes/" t) + '("8d146df8bd640320d5ca94d2913392bc6f763d5bc2bb47bed8e14975017eea91" "9a977ddae55e0e91c09952e96d614ae0be69727ea78ca145beea1aae01ac78d2" "0cf95236abcf59e05b1ea69b4edd53d293a5baec4fe4c3484543fee99bfd2204" "80b00f3bf7cdbdca6c80aadfbbb03145f3d0aacf6bf2a559301e61109954e30a" default)) '(org-export-backends '(ascii html icalendar latex md odt)) '(package-selected-packages - '(emms mpdel-embark libmpdel pass password-store fontaine osm orderless embark-consult embark consult jinx dired-preview ftable flx nerd-icons-dired nerd-icons all-the-icons-dired marginalia vertico denote ox-rss org-ql org-contrib mustache org-static-blog haskell-mode julia-mode elfeed-protocol ack company magit auctex lsp-mode elpy ## org htmlize leuven-theme lua-mode ess-smart-underscore ess-R-data-view ess))) + '(straight calfw calfw-org engrave-faces org-caldav nov eat mu4e ellama emms mpdel-embark libmpdel pass password-store fontaine osm orderless embark-consult embark consult jinx dired-preview ftable flx nerd-icons-dired nerd-icons all-the-icons-dired marginalia vertico denote ox-rss org-ql org-contrib mustache org-static-blog haskell-mode julia-mode elfeed-protocol ack company magit auctex lsp-mode elpy ## org htmlize leuven-theme lua-mode ess-smart-underscore ess-R-data-view ess)) + '(use-package-compute-statistics t)) (custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. @@ -120,40 +210,55 @@ vc-follow-symlinks t ;;; use pass (~/.password-store) ;;; (see The Unix password store) -(auth-source-pass-enable) +(use-package pass + :ensure t + :config + (auth-source-pass-enable) + (setq pass-username-field "Username")) ;; Elfeed news reader from Nextcloud -(require 'elfeed) -(require 'elfeed-protocol) - -(setq elfeed-use-curl nil) -(elfeed-set-timeout 36000) -(setq elfeed-protocol-feeds '( - ("owncloud+https://frederik@owncloud.vanrenterghem.biz" :use-authinfo t) +(use-package elfeed + :ensure t + :config + (setq elfeed-use-curl nil) + (elfeed-set-timeout 36000) + (define-key elfeed-search-mode-map (kbd "*") (lambda () (interactive) (apply 'elfeed-search-toggle-all '(star)))) + (define-key elfeed-show-mode-map (kbd "*") (lambda () (interactive) (apply 'elfeed-show-tag '(star)))) + (add-hook 'elfeed-show-mode 'variable-pitch-mode)) + +(use-package elfeed-protocol + :ensure t + :after elfeed + :config + (setq elfeed-protocol-feeds '( + ("owncloud+https://frederik@owncloud.vanrenterghem.biz" :use-authinfo t) )) -(elfeed-protocol-enable) -(define-key elfeed-search-mode-map (kbd "*") (lambda () (interactive) (apply 'elfeed-search-toggle-all '(star)))) -(define-key elfeed-show-mode-map (kbd "*") (lambda () (interactive) (apply 'elfeed-show-tag '(star)))) -(add-hook 'elfeed-show-mode 'variable-pitch-mode) + (elfeed-protocol-enable)) + ;; Read and write email using mu4e -(require 'mu4e) -(setq mail-user-agent 'mu4e-user-agent) -;; Also use mu4e when called from gnus-dired-attach -(setq gnus-dired-mail-mode 'mu4e-user-agent) -(setq mu4e-get-mail-command "mbsync io") -(setq mu4e-update-interval 600) -(setq mu4e-use-fancy-chars t) -(setq mu4e-view-show-images t) -(setq mu4e-sent-folder "/Sent" - mu4e-drafts-folder "/Drafts" - mu4e-trash-folder "/Trash") -(setq message-kill-buffer-on-exit t) -;; attach files to mu4e messages by marking the file(s) in dired and pressing C-c RET C-a -(add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode) -;; Define all bookmarks starting with favourite query used in mailcount modeline -(setq mu4e-bookmarks - '(( :name "Last 24h's messages" +(use-package mu4e + :ensure nil + ;; :ensure-system-package mu ;; Install from aur + :config + (setq mail-user-agent 'mu4e-user-agent) + ;; Also use mu4e when called from gnus-dired-attach + (setq gnus-dired-mail-mode 'mu4e-user-agent + mu4e-get-mail-command "mbsync io" + mu4e-update-interval 600 + mu4e-use-fancy-chars t + mu4e-view-show-images t + mu4e-sent-folder "/Sent" + mu4e-drafts-folder "/Drafts" + mu4e-trash-folder "/Trash" + message-kill-buffer-on-exit t + ;;Fixing duplicate UID errors when using mbsync and mu4e + mu4e-change-filenames-when-moving t) + ;; attach files to mu4e messages by marking the file(s) in dired and pressing C-c RET C-a + (add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode) + ;; Define all bookmarks starting with favourite query used in mailcount modeline + (setq mu4e-bookmarks + '(( :name "Last 24h's messages" :key ?l :favorite y :query "date:24h..now AND NOT flag:trashed") @@ -170,57 +275,69 @@ vc-follow-symlinks t ( :name "Messages with images" :query "mime:image/* AND NOT flag:trashed" :key ?p))) - -;; Create custom spam status header and show in message view -(add-to-list 'mu4e-header-info-custom - '(:spam-status . - ( :name "Spam-Status" ;; long name, as seen in the message-view - :shortname "Spam" ;; short name, as seen in the headers view - :help "The Spam status" ;; tooltip - ;; uses mu4e-fetch-field which is rel. slow, so only appropriate - ;; for mu4e-view-fields, and _not_ mu4e-headers-fields - :function (lambda (msg) - (or (string-join (seq-take (split-string (or (mu4e-fetch-field msg "X-Spam-Status") "") " ") 2) " ") ""))))) -(add-to-list 'mu4e-view-fields :spam-status) - -;; Resize image attachments when sending email -(defvar mu4e-resize-image-types '("jpg" "png" "svg" "jpeg") - "List of attached image types to resize.") - -(defvar mu4e-inhibit-resize nil) - -(defun mu4e-resize-image-attachments () - (unless mu4e-inhibit-resize - (let (cmds - (image-types - (mapconcat #'identity mu4e-resize-image-types "\\|"))) - (save-excursion - (message-goto-body-1) - (while (re-search-forward - (format "<#part.+\\(filename=\"\\)\\(.+\\(\\.%s\\)\\)\"" - image-types) - nil t) - (let* ((infile (match-string-no-properties 2)) - (outfile (concat (temporary-file-directory) - (file-name-nondirectory infile)))) - (push (format "magick convert %s -resize 1200x1200\\> %s" - (shell-quote-argument infile) - (shell-quote-argument outfile)) - cmds) - (replace-match outfile t t nil 2))) - (mapcar #'shell-command cmds))))) - -(add-hook 'message-send-hook 'mu4e-resize-image-attachments) - -(defun mu4e-inhibit-resize() - (interactive) - (set (make-local-variable 'mu4e-inhibit-resize) t)) + ;; Create custom spam status header and show in message view + (add-to-list 'mu4e-header-info-custom + '(:spam-status . + ( :name "Spam-Status" ;; long name, as seen in the message-view + :shortname "Spam" ;; short name, as seen in the headers view + :help "The Spam status" ;; tooltip + ;; uses mu4e-fetch-field which is rel. slow, so only appropriate + ;; for mu4e-view-fields, and _not_ mu4e-headers-fields + :function (lambda (msg) + (or (string-join (seq-take (split-string (or (mu4e-fetch-field msg "X-Spam-Status") "") " ") 2) " ") ""))))) + (add-to-list 'mu4e-view-fields :spam-status) + ;; Resize image attachments when sending email + (defvar mu4e-resize-image-types '("jpg" "png" "svg" "jpeg") + "List of attached image types to resize.") + (defvar mu4e-inhibit-resize nil) + (defun mu4e-resize-image-attachments () + (unless mu4e-inhibit-resize + (let (cmds + (image-types + (mapconcat #'identity mu4e-resize-image-types "\\|"))) + (save-excursion + (message-goto-body-1) + (while (re-search-forward + (format "<#part.+\\(filename=\"\\)\\(.+\\(\\.%s\\)\\)\"" + image-types) + nil t) + (let* ((infile (match-string-no-properties 2)) + (outfile (concat (temporary-file-directory) + (file-name-nondirectory infile)))) + (push (format "magick convert %s -resize 1200x1200\\> %s" + (shell-quote-argument infile) + (shell-quote-argument outfile)) + cmds) + (replace-match outfile t t nil 2))) + (mapcar #'shell-command cmds))))) + (add-hook 'message-send-hook 'mu4e-resize-image-attachments) + (defun mu4e-inhibit-resize() + (interactive) + (set (make-local-variable 'mu4e-inhibit-resize) t))) ;; Load configuration for website ;(load "mustache-html") ;; Denote config -(setq denote-directory "/home/frederik/Nextcloud/notes/") +(use-package denote + :ensure t + :hook (dired-mode . denote-dired-mode) + :bind + (("C-c n n" . denote) + ("C-c n r" . denote-rename-file) + ("C-c n l" . denote-link) + ("C-c n b" . denote-backlinks)) + :config + (setq denote-directory "/home/frederik/Nextcloud/notes/") + (denote-rename-buffer-mode 1)) + +(use-package nerd-icons + ;; :custom + ;; The Nerd Font you want to use in GUI + ;; "Symbols Nerd Font Mono" is the default and is recommended + ;; but you can use any other Nerd Font if you want + ;; (nerd-icons-font-family "Symbols Nerd Font Mono") + ) ;; Dired configuration (with-eval-after-load 'dired @@ -242,35 +359,172 @@ vc-follow-symlinks t (".*" "xdg-open"))) ;; Use `vertico' package to get a vertical view of the minibuffer. -(setq vertico-resize nil) -(vertico-mode 1) +(use-package vertico + :ensure t + :config + (setq vertico-resize nil) + (vertico-mode 1)) + +;; Persist history over Emacs restarts. Vertico sorts by history position. +(use-package savehist + :init + (savehist-mode)) ;; Use `marginalia' package. This will display useful ;; annotations next to entries in the minibuffer. For example, when ;; using M-x it will show a brief description of the command as well ;; as the keybinding associated with it (if any). -(marginalia-mode 1) +(use-package marginalia + :ensure t + :config + (marginalia-mode 1)) ;; Use 'winner' mode to undo and redo windows changes ;; using C-c and C-c . -(winner-mode 1) +(use-package winner + :ensure t + :config + (winner-mode 1)) ;; Use a different spell checker, always -(add-hook 'emacs-startup-hook #'global-jinx-mode) -(keymap-global-set "M-$" #'jinx-correct) +(use-package jinx + :ensure t + :config + (keymap-global-set "M-$" #'jinx-correct) + :hook (emacs-startup . global-jinx-mode)) -;; Bind embark -(keymap-global-set "C-." #'embark-act) -(keymap-global-set "C-;" #'embark-dwim) -;; Change default bindings to consult- ones -(keymap-set ctl-x-map "b" #'consult-buffer) -(global-set-key (kbd "M-y") 'consult-yank-pop) +;; Bind embark +(use-package embark + :ensure t + :config + (keymap-global-set "C-." #'embark-act) + (keymap-global-set "C-;" #'embark-dwim)) + +(use-package consult + :ensure t + :config + ;; Change default bindings to consult- ones + :bind + (;; C-x bindings in `ctl-x-map' + ("C-x b" . consult-buffer) ;; orig. switch-to-buffer + ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window + ("C-x r b" . consult-bookmark) ;; orig. bookmark-jump + ;; Other custom bindings + ("M-y" . consult-yank-pop))) ;; orig. yank-pop + +(use-package consult-mu + :ensure nil ;; cloned in + :load-path "~/.emacs.d/lisp/consult-mu" + :after (consult mu4e) + :custom + ;;maximum number of results shown in minibuffer + (consult-mu-maxnum 200) + ;;show preview when pressing any keys + (consult-mu-preview-key 'any) + ;;do not mark email as read when previewed + (consult-mu-mark-previewed-as-read nil) + ;;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. + (consult-mu-mark-viewed-as-read nil) + ;; open the message in mu4e-view-buffer when selected. + (consult-mu-action #'consult-mu--view-action) + ) ;; Configure `world-clock' - -(with-eval-after-load 'time +(use-package time + :ensure nil + :config (setq zoneinfo-style-world-list '(("Europe/Brussels" "Leuven"))) (add-to-list 'zoneinfo-style-world-list '("Australia/Perth" "Perth"))) +;; View PDFs in Emacs +(pdf-loader-install) ; On demand loading, leads to faster startup time +(setq pdf-misc-print-programm "/usr/bin/lpr") + +(use-package magit + :ensure t) + +(use-package eat + :ensure t + :config + ;; For `eat-eshell-mode'. + (add-hook 'eshell-load-hook #'eat-eshell-mode) + (setq eshell-visual-commands '())) + +;; Read ePub files +(use-package nov + :ensure t + :init + (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)) + :config + (add-hook 'nov-mode-hook #'variable-pitch-mode)) + +;; Set some preset fonts +(use-package fontaine + :ensure t + :config + (setq fontaine-presets + '((regular-1 + :default-family "Iosevka Nerd Font" + :default-height 120 + :variable-pitch-family "Linux Biolinum O" + :variable-pitch-weight normal + :variable-pitch-height 1.1 + :italic-family "Iosevka Etoile" + :line-spacing 1) + (large-1 + :default-family "Iosevka Nerd Font" + :default-height 150 + :variable-pitch-family "Linux Biolinum O" + :variable-pitch-weight normal + :variable-pitch-height 1.1 + :italic-family "Iosevka Etoile" + :line-spacing 1) + (regular-2 + :default-family "Fira Mono Nerd Font" + :default-height 140 + :variable-pitch-family "Fira Sans Book" + :variable-pitch-weight normal + :variable-pitch-height 1.0 + :line-spacing 1) + (large-2 + :default-family "Fira Mono Nerd Font" + :default-height 140 + :variable-pitch-family "Fira Sans Book" + :variable-pitch-weight normal + :variable-pitch-height 1.0 + :line-spacing 1) + (ereader-Baskerville + :variable-pitch-family "Libre Baskerville" + :variable-pitch-weight normal + :variable-pitch-height 1.0 + :line-spacing 1) + (ereader-Noto-Serif + :variable-pitch-family "Noto Serif" + :variable-pitch-weight normal + :variable-pitch-height 1.0 + :line-spacing 1) + (ereader-Bembo-Tufte + :variable-pitch-family "ETBembo" + :variable-pitch-weight normal + :variable-pitch-height 1.1 + :line-spacing 1) + (ereader-Literata + :variable-pitch-family "Literata" + :variable-pitch-weight normal + :variable-pitch-height 1.0 + :line-spacing 1)))) + +;; Custom functions + +;; Might want to run this automatically +;; using variable after-focus-change-function +(defun my/adjust-font-size-based-on-display () + "Change size of fonts based on monitor." + (interactive) + (let* ((display-name (cdr (assq 'name (frame-monitor-attributes)))) + (font-height (cond ((string-equal display-name "eDP-1") 140) + (t 120) ;; default + ))) + (set-face-attribute 'default (selected-frame) :height font-height)))