Skip to content

Latest commit

 

History

History
3455 lines (3260 loc) · 127 KB

myinit.org

File metadata and controls

3455 lines (3260 loc) · 127 KB

My Literate emacs config

This is my config file for emacs!

speedups

gc-cons threshold

The gc-cons-threshold is set to a superlarge number for faster startup time. It is reset at reset gc-cons-threshold.

(setq gc-cons-threshold 402653184
      gc-cons-percentage 0.6)

SOME figure out optimal GC-cons threshold for my system

  • State “SOME” from “NEXT” [2024-09-20 Fri 18:43]

make long lines faster

I like to write my org-mode scientific papers such that each line has one sentence. This allows me to make more meaningful git commits per line. Often, these lines are quite long, however, and this makes emacs very slow. https://emacs.stackexchange.com/questions/598/how-do-i-prevent-extremely-long-lines-making-emacs-slow

(setq-default bidi-paragraph-direction 'left-to-right)
(setq-default bidi-inhibit-bpa t)
(global-so-long-mode 1)
;; (setq-default bidi-display-reordering nil)  ;; officially unsupported

package archive

use-package

Use-package is an amazing resource to clean up my init file and have it play nice on both my desktop and laptop.

(eval-when-compile
  (require 'use-package))
(setq use-package-always-ensure t)
(setq use-package-verbose t)
(use-package diminish)  ; to abbreviate lines from the mode-line
(use-package delight)  ; to omit lines from the mode-line
(use-package bind-key)  ; for easy keybindings

dirvar

define dirvars ‘org-in-file’, ‘org-gtd-file’, etc.

(defvar org-in-file "~/org/inbox.org"
  "GTD Inbox")
(defvar org-gtd-file "~/org/todo.org"
  "Personal TODO's")
(defvar org-tickler-file "~/org/tickler.org"
  "Tickler")
(defvar org-clumped-file "~/org/clumpednotes.org"
  "Work TODO's")
(defvar org-notes-file "~/org/notes.org"
  "General Notes and Protocols")
(defvar org-someday-file "~/org/someday.org"
  "Someday/Maybe")
(defvar org-journal-file "~/org/journal.org"
  "Journal")
(defvar org-lists-file "~/org/lists.org"
  "Lists of Movies etc.")
(defvar org-cal-file "~/org/calendars/gcal.org"
  "Google Calendar")
(setq my/org-roam-files
      (directory-files "~/SurfDrive/bibliography/notes/daily" t "org$"))

interface

turn off UI elements and small tweaks

(setq inhibit-splash-screen t)
;; (setq initial-major-mode 'org-mode)
(setq large-file-warning-threshold 100000000) ;; change to ~100 MB
(scroll-bar-mode -1)   ; turn off the scroll bar
(tool-bar-mode -1)     ; turn off the tool bar
(menu-bar-mode -1)     ; turn off the menu
(setq visible-bell 1)  ; turn off beeps, make them flash!
(global-hl-line-mode t)
;; typing
(setq-default fill-column 79)
(setq sentence-end-double-space nil)
;; typed text will replace highlighted region
(delete-selection-mode 1)
;; backspace deletes one character instead of one column
(global-set-key (kbd "DEL") 'backward-delete-char)
;; remove trailing whitespace before save
(add-hook 'before-save-hook 'delete-trailing-whitespace)
;; prefer utf-8
(prefer-coding-system 'utf-8-unix)

(blink-cursor-mode 0)
;; (setq mouse-wheel-progressive-speed nil)

;; automatically re-open files that have been changed on disk
(global-auto-revert-mode 1)
(setq global-auto-revert-non-file-buffers t)

(defalias 'yes-or-no-p 'y-or-n-p)
(setq use-dialog-box nil) ; do not use graphical ui dialog boxes but use echo area (esp. for org-pomodoro)

;; always follow symlinks w/o asking
(require 'vc-hooks)
(setq vc-follow-symlinks t)

auto-save

(setq auto-save-default t  ;; let's try autosave for a while
      backup-inhibited t
      confirm-nonexistent-file-or-buffer nil
      create-lockfiles nil)

auto-save when I exit normal mode

(defun my-save-if-bufferfilename ()
  (if (buffer-file-name)
      (progn (save-buffer))
        (message "no file is associated to this buffer: do nothing")))
;; this may be a bit too slow, especially with my whitespace remove hook.
;(add-hook 'evil-insert-state-exit-hook 'my-save-if-bufferfilename)

history

(recentf-mode 1)
;; Save what you enter into minibuffer prompts
(setq history-length 25)
(savehist-mode 1)
;; Remember and restore the last cursor location of opened files
(save-place-mode 1)

play nice with parentheses

(electric-pair-mode 1) ; auto-insert matching bracket
(show-paren-mode 1)    ; turn on paren match highlighting

change appearance

line spacing, underline

(setq-default line-spacing 0)
(setq x-underline-at-descent-line t)

rainbow-delimiters

matching parenthesis are highlighted with rainbow colours.

(use-package rainbow-delimiters
  :hook ((prog-mode LaTeX-mode) . rainbow-delimiters-mode))

set the theme

prot’s modus themes

(use-package modus-themes
  :init
  (setq modus-themes-bold-constructs t
        modus-themes-italic-constructs t
        modus-themes-mixed-fonts t
        modus-themes-subtle-line-numbers t
        modus-themes-tabs-accented t
        modus-themes-variable-pitch-ui t
        modus-themes-inhibit-reload t
        modus-themes-fringes '(subtle)
        modus-themes-lang-checkers nil
        modus-themes-mode-line '(4)
        modus-themes-markup '(background italic)
        modus-themes-syntax '(faint)
        modus-themes-intense-hl-line '(accented)
        modus-themes-paren-match '(bold intense)
        modus-themes-links '(neutral-underline background)
        modus-themes-prompts '(intense bold)
        modus-themes-completions '(opinionated)
        modus-themes-mail-citations nil
        modus-themes-region '(bg-only no-extend)
        modus-themes-diffs '(desaturated)
        modus-themes-org-blocks 'tinted-background
        modus-themes-org-agenda
        '((header-block . (variable-pitch 1.3))
          (header-date . (grayscale workaholic bold-today 1.1))
          (event . (accented varied))
          (scheduled . rainbow)
          (habit . traffic-light))
        modus-themes-headings
        '((1 . (variable-pitch 1.3))
          (2 . (variable-pitch 1.1))
          (3 . (variable-pitch semibold)))))

circadian: dark theme at night, light theme during the day

(use-package circadian
  :custom
  ;; current location on earth for auto toggle between light and dark theme
  (calendar-latitude 52.08) ;; Utrecht
  (calendar-longitude 5.11)
  ;; (calendar-latitude 21.25) ;; Honolulu
  ;; (calendar-longitude -157.8)
  ;; (calendar-latitude 40.5) ;; New York
  ;; (calendar-longitude -74.5)
  (circadian-themes '((:sunrise . modus-operandi)
                      (:sunset  . modus-vivendi)))
  :config
  (circadian-setup))

set variable font

;; (set-face-attribute 'default nil :family "Noto Mono" :height 130)
(set-face-attribute 'default nil :family "Noto Sans Mono" :height 150)
(set-face-attribute 'variable-pitch nil :family "Noto Serif" :height 1.0)
;;Tex Gyre Pagella
(set-face-attribute 'fixed-pitch nil :family "Noto Sans Mono" :height 1.0)

rainbow-mode

Highlight hex colours!

(use-package rainbow-mode
  :defer t
  :hook (html-mode r-mode))

emojify

Show plain-text emoji like :) as images, but also unicode and :slight-smile:. :D https://github.com/iqbalansari/emacs-emojify

(use-package emojify
  :hook (mu4e-mode . emojify-mode))

pulse

Highlight the current line when changing focus. It’s like beacon-mode but native! from https://karthinks.com/software/batteries-included-with-emacs/

(defun pulse-line (&rest _)
      "Pulse the current line."
      (pulse-momentary-highlight-one-line (point)))

(dolist (command '(scroll-up-command scroll-down-command
                   recenter-top-bottom other-window))
  (advice-add command :after #'pulse-line))

visual-fill-column-mode

This allows me to write nicely on a widescreen monitor in a single buffer.

(use-package visual-fill-column
  :hook (org-mode . visual-fill-column-mode)
  :custom
  (global-visual-line-mode t)
  ;; (global-visual-fill-column-mode t)
  ;; (visual-fill-column-width 115) ;; instead prefer fill-column-width
  (split-window-preferred-function 'visual-fill-column-split-window-sensibly)
  (visual-fill-column-center-text t))

define new org-todo faces

org-todo-next

(defface org-todo-next
  '((((class color) (min-colors 16) (background light))
     (:family "Noto Sans Mono" :foreground "light goldenrod yellow"
		:bold t :background "red"))
    (((class color) (min-colors 16) (background dark))
     (:family "Noto Sans Mono" :foreground "light goldenrod yellow"
		:bold t :background "red"))
    (((class color) (min-colors 8) (background light))
     (:family "Noto Sans Mono" :foreground "light goldenrod yellow"
		:bold t :background "red"))
    (((class color) (min-colors 8) (background dark))
     (:family "Noto Sans Mono" :foreground "light goldenrod yellow"
		:bold t :background "red"))
    (t (:inverse-video t :bold t)))
    "Face for NEXT TODO keyword"
    :group 'org-faces)

org-todo-waiting

(defface org-todo-waiting
  '((((class color) (min-colors 16) (background light))
     (:family "Noto Sans Mono" :foreground "dim gray" :bold t
     :background "yellow"))
    (((class color) (min-colors 16) (background dark))
     (:family "Noto Sans Mono" :foreground "dim gray" :bold t
     :background "yellow"))
    (((class color) (min-colors 8) (background light))
     (:family "Noto Sans Mono" :foreground "dim gray" :bold t
     :background "yellow"))
    (((class color) (min-colors 8) (background dark))
     (:family "Noto Sans Mono" :foreground "dim gray" :bold t
     :background "yellow"))
    (t (:inverse-video t :bold t)))
  "Face for WAIT TODO keyword"
  :group 'org-faces)

org-todo-tick

(defface org-todo-tick
  '((((class color) (min-colors 16) (background light))
     (:family "Noto Sans Mono" :bold t :background "light slate blue"))
    (((class color) (min-colors 16) (background dark))
     (:family "Noto Sans Mono" :bold t :background "light slate blue"))
    (((class color) (min-colors 8)  (background light))
     (:family "Noto Sans Mono" :bold t :background "light slate blue"))
    (((class color) (min-colors 8)  (background dark))
     (:family "Noto Sans Mono" :bold t :background "light slate blue"))
    (t (:inverse-video t :bold t)))
  "Face for TICK TODO keyword"
  :group 'org-faces)

org-todo-someday

(defface org-todo-someday
  '((((class color) (min-colors 16) (background light))
     (:family "Noto Sans Mono" :foreground "ghost white" :bold t
     :background "deep sky blue"))
    (((class color) (min-colors 16) (background dark))
     (:family "Noto Sans Mono" :foreground "ghost white" :bold t
     :background "deep sky blue"))
    (((class color) (min-colors 8) (background light))
     (:family "Noto Sans Mono" :foreground "ghost white" :bold t
     :background "deep sky blue"))
    (((class color) (min-colors 8) (background dark))
     (:family "Noto Sans Mono" :foreground "ghost white" :bold t
     :background "deep sky blue"))
    (t (:inverse-video t :bold t)))
  "Face for SOME TODO keyword"
  :group 'org-faces)

org-done-done

(defface org-done-done
  '((((class color) (min-colors 16) (background light))
     (:family "Noto Sans Mono" :foreground "green4" :bold t
     :background "pale green"))
    (((class color) (min-colors 16) (background dark))
     (:family "Noto Sans Mono" :foreground "green4" :bold t
     :background "pale green"))
    (((class color) (min-colors 8))
     (:family "Noto Sans Mono" :foreground "green"
     :background "pale green"))
    (t (:bold t)))
  "Face used for todo keywords that indicate DONE items."
  :group 'org-faces)

org-done-cancelled

(defface org-done-cancelled
  '((((class color) (min-colors 16) (background light))
     (:family "Noto Sans Mono" :foreground "dim gray" :bold t
     :background "gray"))
    (((class color) (min-colors 16) (background dark))
     (:family "Noto Sans Mono" :foreground "dim gray" :bold t
     :background "gray"))
    (((class color) (min-colors 8))
     (:family "Noto Sans Mono" :foreground "dim gray"
     :background "gray"))
    (t (:bold t)))
  "Face used for todo keywords that indicate CANC items."
  :group 'org-faces)

version control

diff-hl

Highlight diffs of current version-controlled buffer in the margin. Quite cool!

(use-package diff-hl
  :init
  (global-diff-hl-mode)
  (setq diff-hl-gutter-mode t)
  (diff-hl-flydiff-mode +1)
  :hook (magit-post-refresh . diff-hl-magit-post-refresh))

magit

git porcelain, essential!

(use-package magit
  :commands magit-status
  :config
  (customize-set-variable 'magit-diff-refine-hunk t)
  ;; :after with-editor
  )

org-make-toc for publishing table of contents on github

https://github.com/alphapapa/org-make-toc

(use-package org-make-toc
  :defer t)

browsing the documentation

helpful

beautiful help functions https://github.com/Wilfred/helpful

(use-package helpful
  :commands (helpful-callable helpful-function helpful-variable helpful-mode))

demos

Insert demos after describe function https://github.com/xuchunyang/elisp-demos

(use-package elisp-demos
  :after helpful
  :config
  (advice-add 'helpful-update :after #'elisp-demos-advice-helpful-update))

which-key

(use-package which-key
  :config (which-key-mode))

custom functions/keyboard shortcuts

revert buffer

(global-set-key (kbd "<f5>") 'revert-buffer)

fetch calendar

(defun fetch-calendar ()
  (when (internet-up-p) (org-gcal-fetch)))

org-agenda recent open loops

(defun my-org-agenda-recent-open-loops ()
  (interactive)
  (let ((org-agenda-start-with-log-mode t)
        (org-agenda-use-time-grid nil))
    (fetch-calendar)
    (org-agenda-list nil (org-read-date nil nil "-2d") 4)
    (beginend-org-agenda-mode-goto-beginning)))

get-labels in current buffer

from JKitchin’s blog

(defun get-labels ()
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (let ((matches '()))
      (while (re-search-forward "label:\\([a-zA-z0-9:-]*\\)" (point-max) t)
        (add-to-list 'matches (match-string-no-properties 1) t))
      matches)))

this allows the yasnippet template to autocomplete ref: with all the labels in the buffer.

make-capture-frame

If we call make-capture-frame from anywhere, it creates a new frame named capture which I can decorate using my window manager, and which disappears after the capturing is complete.

Sources:

(defun make-capture-frame ()
  "Create a new frame and org-capture."
  (interactive)
  ;; (require 'cl-lib)
  (make-frame '((name . "capture")))
  (select-frame-by-name "capture")
  (delete-other-windows)
  (cl-letf (((symbol-function 'switch-to-buffer-other-window) #'switch-to-buffer))
            (condition-case err
                (org-capture nil "x")
              (user-error (when (string= (cadr err) "Abort")
                            (delete-frame))))))

(defadvice org-capture-finalize
    (after delete-capture-frame activate)
  "Advice capture-finalize to close the frame"
  (if (equal "capture" (frame-parameter nil 'name))
      (delete-frame)))

org-babel ANSI colours

https://emacs.stackexchange.com/questions/44664/apply-ansi-color-escape-sequences-for-org-babel-results This will apply the ANSI colour escape codes to source block outputs.

However, it will not store the results so it won’t show on export or the next time you open the file. The text will be plain, colourless, instead.

I still prefer this option because I have colours during my session/in the ESS process.

(defun my/babel-ansi ()
  (when-let ((beg (org-babel-where-is-src-block-result nil nil)))
    (save-excursion
      (goto-char beg)
      (when (looking-at org-babel-result-regexp)
        (let ((end (org-babel-result-end))
              (ansi-color-context-region nil))
          (ansi-color-apply-on-region beg end))))))
(add-hook 'org-babel-after-execute-hook #'my/babel-ansi)

internet stuffs

internet up

(defun internet-up-p (&optional host)
  (= 0 (call-process "ping" nil nil nil "-c" "1" "-W" "1"
                     (if host host "www.google.com"))))

firefox as default browser

(setq browse-url-generic-program (executable-find "firefox")
      browse-url-browser-function 'browse-url-generic)

allow editing text fields in firefox

from https://chainsawriot.com/postmannheim/2022/12/16/aoe16.html

(use-package atomic-chrome
  :config
  (atomic-chrome-start-server)
  (setq atomic-chrome-buffer-open-style 'full)
  (setq atomic-chrome-url-major-mode-alist
        '(("github\\.com" . poly-markdown+r-mode)
          ("overleaf\\.com" . latex-mode))))

evil

Evil allows me to use vi(m) keybindings in emacs.

evil

vim emulator

(use-package evil
  :init
  (setq evil-want-integration t)
  (setq evil-want-keybinding nil) ; this is needed for evil-collection
  ;; (setq evil-want-C-i-jump t) ; jump forward instead of tab insert
  (setq evil-want-Y-yank-to-eol t)
  (setq evil-v$-excludes-newline t) ; make v$ consistent with $ as motion
  (setq evil-want-fine-undo t) ;; make smaller undo steps within insert mode
  (customize-set-variable 'evil-respect-visual-line-mode nil)
  ;; TODO: decide if I want to use undo-tree?
  (customize-set-variable 'evil-undo-system nil)
  ;; (setq evil-cross-lines t)
  ;; (setq evil-want-C-u-scroll t) ; C-u scrolls up half page
  :config
  (evil-mode 1))

evil-collection

(use-package evil-collection
  :after evil vterm
  :config
  ;; (add-hook 'evil-insert-state-entry-hook #'vterm-reset-cursor-point nil t)
  (evil-collection-init))

evil-org

https://github.com/Somelauw/evil-org-mode evil keymap for org-mode

(use-package evil-org
  :demand ; do not defer
  :after (:any org evil)
  :init
  (fset 'evil-redirect-digit-argument 'ignore)
  :delight evil-org-mode
  :hook (((org-mode org-agenda-mode). evil-org-mode)
         (evil-org-mode . (lambda ()
                            (evil-org-set-key-theme
                             '(textobjects
                               insert
                               navigation
                               ;; calendar ; M-h M-l next/previous day etc.
                               additional
                               shift
                               todo ;; heading
                               ))))
         ;; I want to immediately type when I capture or log
         (org-log-buffer-setup . evil-insert-state)
         (org-capture-mode . evil-insert-state)
         (yas-before-expand-snippet . evil-insert-state))
  :config
  (require 'evil-org-agenda)
  (evil-org-agenda-set-keys)
  ;; TODO: rewrite to :bind syntax?
  (evil-define-key 'motion 'org-agenda-mode-map (kbd "[") 'org-agenda-earlier)
  (evil-define-key 'motion 'org-agenda-mode-map (kbd "]") 'org-agenda-later))

evil-commentary

https://github.com/linktohack/evil-commentary comment/uncomment with gc over on systemcrafters they use evil-nerd-commentary, which has different keybindings by default main one: M-; or <leader>lc

this uses gc <word>

(use-package evil-commentary
  :config
  (evil-commentary-mode))

evil-magit

  • Note taken on [2024-10-20 Sun 20:18]
    no longer works, changed evil-magit to magit so my config can live on?
evil keybindings for magit
(use-package magit
  ; :after (magit evil)
  :hook
  (git-commit-mode . evil-insert-state)
  (magit-mode . turn-off-evil-snipe-override-mode)
  :config
  (evil-set-initial-state 'magit-log-edit-mode 'insert))

short-doc

No idea why but suddently I’ve been getting issues about the function define-short-documentation-group not existing. This may fix it?

(require 'shortdoc)

org-mode

my gtd and inbox files finding functions

org-in-file and org-gtd-file are defined in emacsdirs.el (private file).

;; TODO: figure out how to do this in a less stupid way
(defun open-gtd-file ()
  "Open the GTD file."
  (interactive)
  (find-file org-gtd-file))
(defun open-inbox-file ()
  "Open the inbox file."
  (interactive)
  (find-file org-in-file))
(defun open-clumped-file ()
   "Open the clumped file."
   (interactive)
   (find-file org-clumped-file))

setup

(use-package org
  :demand ; do not defer
  :ensure nil ; use the org-mode version included in Emacs
  ;; I had this setup before, but the org archive has been deprecated since version 9.6:
  ;; IMPORTANT: please install Org from GNU ELPA as Org ELPA will close
  ;; :ensure org-plus-contrib ; this is version 9.4.6
  ;; :delight org-indent-mode

keybindings

:bind
(("C-c l" . org-store-link)
 ("C-c a" . org-agenda)
 ("C-c c" . org-capture)
 ("C-c g" . open-gtd-file)
 ("C-c i" . open-inbox-file)
 ("C-c t" . open-clumped-file)
 ("C-c !" . org-time-stamp-inactive))

hook

:hook (
       (org-mode . variable-pitch-mode)
       ;; update last-modified upon save
       (before-save . zp/org-set-last-modified)
       ;; set created property on captures
       (org-capture-prepare-finalize . zp/org-capture-set-created-property)
       ;; disable highlighting of matches in sparse trees so that customized TODO faces remain displayed :)
       (org-occur . (lambda () (org-remove-occur-highlights nil nil nil)))
       ;; make sure the tags in the org-agenda aren't line-wrapped
       (org-agenda-mode . (lambda ()
                                 (visual-line-mode -1)
                                 (toggle-truncate-lines 1)))
       (org-babel-after-execute . org-redisplay-inline-images)
       (org-babel-after-execute . my/babel-ansi)
       )

start with custom

:custom

basics

(org-ctrl-k-protect-subtree t)
(org-return-follows-link t)
;; (setf org-special-ctrl-a/e t) ; I use evil's 0 and $ anyway
;; folded drawers no longer ruin new entries
(org-list-allow-alphabetical t) ; allow a. b. c. lists
(org-M-RET-may-split-line '((default . nil)))
;; (org-display-remote-inline-images 'cache)
;; (org-startup-with-inline-images t)

org-latex export settings

basic latex settings

;; (org-highlight-latex-and-related '(native script entities)) this gives me errors now <2023-07-18 Tue>
;; (org-latex-src-block-backend 'engraved)
;; (org-preview-latex-default-process 'dvipng)
;; (setq org-latex-default-figure-position 'htbp)
(org-latex-pdf-process
 (list "latexmk -pdflatex='lualatex -shell-escape -interaction nonstopmode' -pdf -f %f"))
(org-latex-prefer-user-labels t)
(org-export-with-sub-superscripts '{})
(org-use-sub-superscripts '{})

clocking/logging

(org-check-running-clock t)
(org-log-note-clock-out t)
(org-log-done 'time)
(org-log-into-drawer t)
;; (org-clock-auto-clockout-timer (* 10 60))

theming

(org-tags-column -65)
(org-startup-indented t)
(org-startup-folded 'content)
(org-agenda-block-separator "")
(org-fontify-emphasized-text t)
      ;; org-fontify-todo-headline t ;; might be nice, but needs customisation of org-headline-todo face
(org-fontify-whole-heading-line t)
(org-fontify-quote-and-verse-blocks t)
(org-pretty-entities t)
(org-ellipsis "") ;▼ … ◦
(org-hide-emphasis-markers t)

file associations

(org-file-apps
 '((auto-mode . emacs)
   ("\\.x?html?\\'" . "xdg-open %s")
   ("\\.pdf\\'" . (lambda (file link)
                    (org-pdftools-open link)))
   ("\\.mp4\\'" . "xdg-open %s")
   ("\\.webm\\'" . "xdg-open %s")
   ("\\.mkv\\'" . "xdg-open %s")
   ("\\.pdf.xoj\\'" . "xournal %s")))

GTD stuff

org-agenda

;; (setq org-agenda-files (list "<file1.org> etc."))
(calendar-week-start-day 1) ; 0:Sunday, 1:Monday
(org-deadline-warning-days 14)
(org-agenda-span 'day)
;; exclude scheduled items from all todo's in list
(org-agenda-todo-ignore-scheduled t)
;; (setq org-agenda-todo-ignore-deadlines t)
;; (setq org-agenda-todo-ignore-timestamp t)
;; (setq org-agenda-todo-ignore-with-date t)
;;(setq org-agenda-prefix-format "  %-17:c%?-12t% s") ; TODO: see if I like the default
(org-agenda-include-all-todo nil)

agenda files

all the org-files in my org-directory

;(setq org-directory "~/org/") ;; changed org-roam capture
(org-agenda-files (append
                   (directory-files-recursively "~/org" "\\.org$")
                   my/org-roam-files))

refile targets

swyper makes refiling amazing!

(org-refile-targets (quote ((nil :maxlevel . 9)  ;; current file
                                 (org-gtd-file :maxlevel . 6)
                                 (org-tickler-file :maxlevel . 2)
                                 (org-notes-file :maxlevel . 2)
                                 (org-lists-file :maxlevel . 2)
                                 (org-someday-file :maxlevel . 2)
                                 (org-clumped-file :maxlevel . 6)
                                 ;; (my/org-roam-files :maxlevel . 1) ;; comment out since org-roam-refile
                                 )))
(org-outline-path-complete-in-steps nil)   ;; Refile in a single go
(org-refile-use-outline-path 'file)            ;; Show full paths for refiling
(org-refile-allow-creating-parent-nodes 'confirm)

agenda filters

Filter tasks by context (sorted by todo state)

(org-agenda-sorting-strategy
      '((agenda habit-down time-up priority-down todo-state-up category-keep)
        (todo todo-state-up priority-down category-keep)
        (tags priority-down todo-state-up category-keep)
        (search category-keep)))
(org-agenda-custom-commands
      '(("i" "Inbox" tags "inbox")
        ("I" "Important"
         ((tags "PRIORITY=\"A\"/prj"
                ((org-agenda-overriding-header "High-priority projects:")))
          (tags "PRIORITY=\"A\"/!-prj"
                ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
                 (org-agenda-overriding-header "High-priority unfinished tasks:")))))
        ;; ("A" agenda*)
        ;; https://protesilaos.com/codelog/2021-12-09-emacs-org-block-agenda/
        ("A" "new block agenda"
         ((tags-todo "*"
                     ((org-agenda-skip-function '(org-agenda-skip-if nil '(timestamp)))
                      (org-agenda-skip-function
                       `(org-agenda-skip-entry-if
                         'notregexp ,(format "\\[#%s\\]" (char-to-string org-priority-highest))))
                      (org-agenda-block-separator nil)
                      (org-agenda-overriding-header "Important tasks without a date")))
          (todo "WAIT"
                 ((org-agenda-overriding-header "\nTasks on hold")))
          (agenda ""
                  ((org-agenda-block-separator nil)
                   (org-agenda-span 1)
                   (org-deadline-warning-days 0)
                   (org-scheduled-past-days 0)
                   (org-deadline-past-days 0)
                   (org-agenda-day-face-function (lambda (date) 'org-agenda-date))
                   (org-agenda-format-date "%A %-e %B %Y")
                   (org-agenda-overriding-header "\nToday's agenda")))
          (agenda ""
                  ((org-agenda-start-on-weekday nil)
                   (org-agenda-start-day "+1d")
                   (org-agenda-span 7)
                   (org-deadline-warning-days 0)
                   (org-agenda-block-separator nil)
                   (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
                   (org-agenda-overriding-header "\nNext seven days")))
          (agenda ""
                  ((org-agenda-time-grid nil)
                   (org-agenda-start-on-weekday nil)
                   (org-agenda-start-day "+7d")
                   (org-agenda-span 14)
                   (org-agenda-show-all-dates nil)
                   (org-deadline-warning-days 0)
                   (org-agenda-block-separator nil)
                   (org-agenda-entry-types '(:deadline))
                   (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
                   (org-agenda-overriding-header "\nUpcoming deadlines (+14d)")))
          (agenda ""
                  ((org-agenda-overriding-header "\nOverdue")
                   (org-agenda-time-grid nil)
                   (org-agenda-block-separator nil)
                   (org-agenda-start-on-weekday nil)
                   (org-agenda-show-all-dates nil)
                   (org-agenda-format-date "")  ;; Skip the date
                   (org-agenda-span 1)
                   (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
                   (org-agenda-entry-types '(:deadline :scheduled))
                   (org-scheduled-past-days 999)
                   (org-deadline-past-days 999)
                   (org-deadline-warning-days 0)))))
        ("n" "Next Actions" todo "NEXT")
        ("w" "Waiting" todo "WAIT")
        ;; ("s" "Someday/Maybe" todo "SOME")
        ("j" "Projects" tags "prj/-SOME-DONE-CANC")
        ("W" "Work" tags-todo "-Personal/!-WAIT"
         ((org-agenda-todo-ignore-scheduled t)))
        ("P" "Personal" tags-todo "-Work/!-WAIT"
         ((org-agenda-todo-ignore-scheduled t)))
        ("g" . "GTD contexts")
        ("gh" "Home" tags-todo "@home")
        ("gk" "Klusjes/Craft" tags-todo "@klusje")
        ("go" "Office" tags-todo "@office")
        ("ge" "Errands" tags-todo "@errands")
        ("gl" "Laboratory" tags-todo "@lab")
        ;; ("gt" "Travel" tags-todo "@travel")
        ("gt" "Teams" tags-todo "@teams")
        ("gc" "Computer" tags-todo "@computer")
        ("gB" "Phone" tags-todo "@phone")
        ("gm" "e-mail" tags-todo "@email")
        ("gb" "Bank" tags-todo "@bank")
        ("gw" "Write" tags-todo "@write")
        ("gp" "Program" tags-todo "@program")
        ("gC" "Create/Plot" tags-todo "@createplot")
        ("gr" "Read" tags-todo "@read")
        ("gg" "Research" tags-todo "@research")
        ("gs" "Schedule" tags-todo "@schedule")
        ("ga" "Agenda" tags-todo "@agenda")
        ("E" . "Energy")
        ("Ef" "Focus" tags-todo "@focus")
        ("Ed" "Braindead" tags-todo "@braindead")
        ("D" "DataSteward" tags-todo "DataSteward")
        ("p" . "People")
        ("pm" "Martin" tags-todo "Martin")
        ("pr" "Richard" tags-todo "Richard")
        ("pl" "Line" tags-todo "Line")
        ("pa" "Anne" tags-todo "Anne")
        ("pf" "FEST" tags-todo "FEST")
        ("pi" "Inigo" tags-todo "Inigo")))

stuck projects

(org-tags-exclude-from-inheritance '("prj")
 org-stuck-projects '("+prj/-CANC-SOME-DONE"
                      ("NEXT" "WAIT" "TICK") ()))  ;;  "SOME"
(org-hierarchical-todo-statistics nil) ;; look for not-done tasks recursively
;; (org-provide-todo-statistics '(("NEXT", "TICK") ("CANC", "SOME", "DONE", "WAIT")))

capture templates

customize capture templates

(org-capture-templates
 '(;("a" "Appointment" entry (file org-in-file)
                                        ; "* %?\n  %^T\n")
   ("t" "Todo" entry (file org-in-file)
    "* %?\n%a" :add-created t)
   ("x" "simple" entry (file org-in-file)
    "* %?" :add-created t)
   ("T" "Todo-nolink-tag" entry (file org-in-file)
    "* %? %^G\n" :add-created t)
   ("m" "Email" entry (file org-in-file)
    "* %? from %:from on %:subject :@email:\n %i\n %a\n" :add-created t)
   ("w" "Website" entry (file org-in-file)
    "* %?\nEntered on %U\n %i\n %a")
   ("r" "Weekly Review" entry (file "~/org/log.org")
    (file "~/org/weekly_review.org") :clock-in t :clock-keep t :jump-to-captured t)
   ("p" "Protocol" entry (file org-in-file)
    "* %:description%? :@web:\n[[%:link][%:description]]\n#+begin_quote\n%:initial\n#+end_quote\n" :add-created t)
   ("L" "Protocol Link" entry (file org-in-file)
    "* %:description%? :@web:\n[[%:link][%:description]]" :add-created t)
   ("j" "Journal" entry (file+olp+datetree org-journal-file)
    "* %?\nEntered on %U\n %i\n %a")))

states

(org-todo-keywords
 '((sequence "NEXT(n)" "WAIT(w!/!)" "TICK(t)" "SOME(s!/!)" "|"
             "DONE(d)" "CANC(c)")))

prettify the todo keywords

(org-todo-keyword-faces
 '(("NEXT" . org-todo-next)
   ("WAIT" . org-todo-waiting)
   ("TICK" . org-todo-tick)
   ("SOME" . org-todo-someday)
   ("DONE" . org-done-done)
   ("CANC" . org-done-cancelled)))

prettify the org-modern todo keyword faces

(org-modern-todo-faces
 '(("NEXT" . org-todo-next)
   ("WAIT" . org-todo-waiting)
   ("TICK" . org-todo-tick)
   ("SOME" . org-todo-someday)
   ("DONE" . org-done-done)
   ("CANC" . org-done-cancelled)))

context tags

(org-fast-tag-selection-single-key t)
(org-tag-alist '(("prj" . ?j)
                 (:startgroup . nil)
                 ("@home" . ?h)
                 ("@office" . ?o)
                 ("@errands" . ?e)
                 ("@lab" . ?l)
                 (:endgroup . nil)
                 ("@computer" . ?c)  ;; general in case I can't decide
                 ("@klusje" . ?k)    ;; crafts, things that require my toolbox
                 ("@phone" . ?B)     ;; b for Dutch "bellen"
                 ("@email" . ?m)
                 ("@teams" . ?t)
                 ("@bank" . ?b)      ;; I need my little reader thingie
                 ("@write" . ?w)
                 ("@program" . ?p)
                 ("@createplot" . ?C)
                 ("@read" . ?r)
                 ("@research" . ?g)
                 ("@schedule" . ?s)
                 ("@agenda" . ?a)    ;; things to discuss
                 ;; ("@admin" . ??) ;; do I want admin? which key should it use?
                 (:startgroup . nil)
                 ("@focus" . ?f)
                 ("@braindead" . ?d)
                 (:endgroup . nil)
                 (:startgroup . nil)
                 ("Work" . ?W) ("Personal" . ?P)
                 (:endgroup . nil)
                 ;; ("DataSteward" . ?D)
                 ;; tags to accompany the @agenda context
                 ("Family" . ?F)
                 ("Martin" . ?M)
                 ("Richard" . ?R)
                 ("Line" . ?L)
                 ("Inigo" . ?I)
                 ("Niels" . ?N)))

org src blocks

(org-src-fontify-natively t)
(org-src-tab-acts-natively t)
(org-src-window-setup 'current-window)

config start

:config

effort estimates

(add-to-list 'org-global-properties
             '("Effort_ALL". "0:05 0:15 0:30 1:00 2:00 3:00 4:00"))

habits

(add-to-list 'org-modules 'org-habit t)

exporting

org-babel languages

(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (dot . t)
   (python . t)
   (latex . t)
   (shell . t)
   ;; (stan . t)
   (latex . t)
   (R . t)
   (julia . t)
   ;; (julia-vterm . t)
   ))

org-export odt

(require 'ob-org)

ox-extra

org-export ignore headlines with :ignore: tag

(use-package org-contrib
  :config
  (require 'ox-extra)
  (ox-extras-activate '(ignore-headlines)))

ox-latex

(require 'ox-latex)

org-latex-packages

  • Note taken on [2023-06-05 Mon 14:55]
    I’ve re-enabled this and added biblatex default options
(customize-set-variable 'org-latex-packages-alist
      '(("version=4" "mhchem" t)
        ("" "siunitx" t)
        ("giveninits=true,uniquename=false,uniquelist=false,citestyle=authoryear-comp,bibstyle=authoryear-comp,date=year,hyperref=true,mincitenames=1,maxcitenames=2,backend=biber,backref,doi=true,url=false,isbn=false" "biblatex" t)
        ("" "amsmath" t)
        ("" "hyperref" t)
        ;; cleveref must be loaded after hyperref and amsmath
        ("capitalise,nameinlink,noabbrev" "cleveref" t)))
;; append colorlinks, allcolors, hidelinks here
;; (customize-set-value 'org-latex-hyperref-template "
;; \\hypersetup{\n pdfauthor={%a},\n pdftitle={%t},\n pdfkeywords={%k},
;;  pdfsubject={%d},\n pdfcreator={%c},\n pdflang={%L},\n colorlinks=true}\n")  % colorlinks=true,
;; % allcolors=blue,%

org bibliography

;; (customize-set-variable 'org-cite-global-bibliography '("/home/japhir/SurfDrive/bibliography/references.bib"))
(setq org-cite-csl-styles-dir "~/Zotero/styles")
;; (setq org-cite-csl--fallback-style-file "/home/japhir/Zotero/styles/paleoceanography.csl") ; doesn't have a bibliography style!
(setq org-cite-csl--fallback-style-file "/home/japhir/Zotero/styles/apa.csl")
;; (setq org-cite-csl--fallback-style-file "/home/japhir/Zotero/styles/nature.csl")
;; use biblatex for latex and csl for html.
(setq org-cite-export-processors '((latex biblatex)
                                   (t csl)))
;; (setq org-cite-biblatex-options bibstyle=authoryear-comp)
(add-to-list 'load-path "/usr/bin/vendor_perl/")

latejx class ijkarticle

(add-to-list 'org-latex-classes
       '("ijkarticle"
"\\documentclass{article}"
                 ("\\section{%s}" . "\\section*{%s}")
                 ("\\subsection{%s}" . "\\subsection*{%s}")
                 ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
                 ("\\paragraph{%s}" . "\\paragraph*{%s}")
                 ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))

add emacs and R source blocks

Nice answer on how to have point on a blank line in code block

(add-to-list 'org-structure-template-alist
             '("se" . "src emacs-lisp
"))
;; TODO figure out how to add multiple items to the list
(add-to-list 'org-structure-template-alist
             '("sr" . "src R
"))
(add-to-list 'org-structure-template-alist
             '("sc" . "src c
"))
(add-to-list 'org-structure-template-alist
             '("sp" . "src python
"))
(add-to-list 'org-structure-template-alist
             '("sj" . "src julia
"))
(add-to-list 'org-structure-template-alist
             '("ss" . "src sh
"))

patch ox-html so that export with id links works

https://gist.github.com/jethrokuan/d6f80caaec7f49dedffac7c4fe41d132

(defun org-html--reference (datum info &optional named-only)
  "Return an appropriate reference for DATUM.
DATUM is an element or a `target' type object.  INFO is the
current export state, as a plist.
When NAMED-ONLY is non-nil and DATUM has no NAME keyword, return
nil.  This doesn't apply to headlines, inline tasks, radio
targets and targets."
  (let* ((type (org-element-type datum))
         (user-label
          (org-element-property
           (pcase type
             ((or `headline `inlinetask) :CUSTOM_ID)
             ((or `radio-target `target) :value)
             (_ :name))
           datum))
         (user-label (or user-label
                         (when-let ((path (org-element-property :ID datum)))
                           (concat "ID-" path)))))
    (cond
     ((and user-label
           (or (plist-get info :html-prefer-user-labels)
               ;; Used CUSTOM_ID property unconditionally.
               (memq type '(headline inlinetask))))
      user-label)
     ((and named-only
           (not (memq type '(headline inlinetask radio-target target)))
           (not user-label))
      nil)
     (t
      (org-export-get-reference datum info)))))

org-protocol

(require 'org-protocol)

close use-package org

)

org-num settings

(customize-set-variable 'org-num-skip-unnumbered t)
(customize-set-variable 'org-num-skip-commented t)
(customize-set-variable 'org-num-skip-tags '("ignore" "nolatex" "noexport"))

org-modern

(use-package org-modern
  :after org
  :config (global-org-modern-mode 1))

ob-async

allow asyncronous code block evaluation https://github.com/astahlman/ob-async

(use-package ob-async
  :after org)

org-pomodoro

got the function from this github issue

(use-package org-pomodoro
  :after org
  :bind ("C-c p" . org-pomodoro)
  :hook (org-pomodoro-break-finished . org-pomodoro-prompt)
  :custom
  (org-pomodoro-manual-break t)
  (org-pomodoro-long-break-length 15)
  :config
  (defun org-pomodoro-prompt ()
    (interactive)
    (org-clock-goto)
    (if (y-or-n-p "Start a new pomodoro?")
        (progn
          (org-pomodoro))))
  )

org-pdftools

used to be org-pdfview

(use-package org-pdftools
  :after (org pdf-tools)
  :hook (org-mode . org-pdftools-setup-link))

org-appear

dive into links/formatted entries https://github.com/awth13/org-appear

(use-package org-appear
  ;; :straight (org-appear :type git :host github :repo "awth13/org-appear")
  :hook (org-mode . org-appear-mode)
  :custom
  (org-appear-autoentities t)
  (org-appear-autolinks t)
  (org-appear-autosubmarkers t)
  (org-appear-delay 1))

presenting

org-tree-slide-mode

(use-package org-tree-slide
  :after org
  :bind (:map org-mode-map ("<f9>" . org-tree-slide-mode)))

writing

easy symbol insertion

By default C-x 8 o = ° and C-x 8 m = µ. So:

(global-set-key (kbd "C-x 8 a") (lambda () (interactive) (insert "α")))
(global-set-key (kbd "C-x 8 b") (lambda () (interactive) (insert "β")))
(global-set-key (kbd "C-x 8 d") (lambda () (interactive) (insert "δ")))
(global-set-key (kbd "C-x 8 D") (lambda () (interactive) (insert "Δ")))

I also use compose-key, mapped to right alt with some custom settings for <ralt> g d, resulting in δ, for example.

all-the-icons

https://github.com/domtronn/all-the-icons.el

(use-package all-the-icons)
(setq inhibit-compacting-font-caches t)

all-the-icons-dired

(use-package all-the-icons-dired
  :after (dired all-the-icons)
  :hook (dired-mode . all-the-icons-dired-mode))

yasnippet

usefull snippets for me: org-mode (fig_, )

(use-package yasnippet
  :init
  (yas-global-mode 1)
  :delight yas-mode
  :config
  (require 'warnings)
  (add-to-list 'warning-suppress-types '(yasnippet backquote-change))
  (setq yas-indent-line t))

ispell: spell-checking

(use-package ispell
  :config
  (setq ispell-dictionary "british-ize-w_accents"))

flyspell

(use-package flyspell
  :hook (;(org-mode . flyspell-mode)
         (prog-mode . flyspell-prog-mode))
  :config
  (add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:"))
  (add-to-list 'ispell-skip-region-alist '("#\\+begin_abstract" . "#\\+end_abstract"))
  (add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC"))
  (add-to-list 'ispell-skip-region-alist '("#\\+begin_src" . "#\\+end_src"))
  (add-to-list 'ispell-skip-region-alist '("^#\\+begin_example " . "#\\+end_example$"))
  (add-to-list 'ispell-skip-region-alist '("^#\\+BEGIN_EXAMPLE " . "#\\+END_EXAMPLE$")))

org-ref

I use most of the minimal setup in this init-ivy config. Note that I’ve stopped using ivy, however.

bibtex

; (add-hook 'bibtex-mode-hook 'flyspell-mode)
(setq bibtex-user-optional-fields
      '(("keywords" "Keywords to describe the entry" "")
        ("file" "Link to document file." ":"))
      bibtex-align-at-equal-sign t)
(setq bibtex-dialect 'biblatex)

org-ref itself

https://github.com/jkitchin/org-ref/blob/master/org-ref.org

(use-package org-ref
  :after org ;ivy-bibtex
  :init
  (require 'bibtex)
  :bind
  (:map org-mode-map
        ("s-[" . org-ref-insert-link-hydra/body)
        ("C-c ]" . org-ref-insert-link))
  :hook
  (org-export-before-parsing . org-ref-glossary-before-parsing)
  (org-export-before-parsing . org-ref-acronyms-before-parsing)
  :init
  ;(require 'org-ref-ivy)
  ;; (setq org-ref-insert-link-function 'org-ref-insert-link-hydra/body
  ;;       org-ref-insert-cite-function 'org-ref-cite-insert-ivy
  ;;       org-ref-default-citation-link 'parencite
  ;;       org-ref-insert-label-function 'org-ref-insert-label-link
  ;;       org-ref-insert-ref-function 'org-ref-insert-ref-link
  ;;       org-ref-cite-onclick-function (lambda (_) (org-ref-citation-hydra/body))
  ;;       )
  ;; (require 'org-ref-archiv)
  ;; (require 'org-ref-scopus)
  ;; (require 'org-ref-wos)
  )

open zotero pdf at point

from the manual

(setq bibtex-completion-pdf-field "file")

(defun my/org-ref-open-pdf-at-point ()
  "Open the pdf for bibtex key under point if it exists."
  (interactive)
  (let* ((results (org-ref-get-bibtex-key-and-file))
    (key (car results))
    (pdf-file (car (bibtex-completion-find-pdf-in-field key))))
    (if (file-exists-p pdf-file)
       (org-open-file pdf-file)
      (message "No PDF found for %s" key))))

(setq org-ref-open-pdf-function 'my/org-ref-open-pdf-at-point)
;; (setq org-ref-get-pdf-filename-function 'bibtex-completion-find-pdf-in-field)

(global-set-key (kbd "<f8>") 'my/org-ref-open-pdf-at-point)

note-taking

pdf-tools

(use-package pdf-tools
  :magic ("%PDF" . pdf-view-mode)
  :load-path "/usr/share/emacs/site-lisp/pdf-tools"
  :init
  (pdf-tools-install)
  :custom
  ;(pdf-loader-install)
  (pdf-view-display-size 'fit-width)
  :bind
  ;; swiper doesn't play nice with pdf-tools, so I disable it.
  ;(:map pdf-view-mode-map ("C-s" . isearch-forward))
 )

org-noter

https://github.com/weirdNox/org-noter

(use-package org-noter
  :config
  :bind (;(:map org-mode-map ("C-c o" . org-noter))
         (:map org-noter-notes-mode-map
               ("C-c k" . org-noter-pdftools-create-skeleton)
               ("C-c q" . org-noter-kill-session)))
  :custom
  ;; org-noter-notes-window-location 'horizontal-split
   ;; Please stop opening frames
   (org-noter-always-create-frame nil)
   (org-noter-kill-frame-at-session-end nil)
   ;; I want to see the whole file
   (org-noter-hide-other nil)
   ;; Everything is relative to the main notes file
   (org-noter-notes-search-path "~/SurfDrive/bibliography/notes/")
  (require 'org-noter-pdftools))

(use-package org-pdftools
  :hook (org-mode . org-pdftools-setup-link))

(use-package org-noter-pdftools
  :after org-noter
  :config
  ;; Add a function to ensure precise note is inserted
  (defun org-noter-pdftools-insert-precise-note (&optional toggle-no-questions)
    (interactive "P")
    (org-noter--with-valid-session
     (let ((org-noter-insert-note-no-questions (if toggle-no-questions
                                                   (not org-noter-insert-note-no-questions)
                                                 org-noter-insert-note-no-questions))
           (org-pdftools-use-isearch-link t)
           (org-pdftools-use-freepointer-annot t))
       (org-noter-insert-note (org-noter--get-precise-info)))))

  ;; fix https://github.com/weirdNox/org-noter/pull/93/commits/f8349ae7575e599f375de1be6be2d0d5de4e6cbf
  (defun org-noter-set-start-location (&optional arg)
    "When opening a session with this document, go to the current location.
With a prefix ARG, remove start location."
    (interactive "P")
    (org-noter--with-valid-session
     (let ((inhibit-read-only t)
           (ast (org-noter--parse-root))
           (location (org-noter--doc-approx-location (when (called-interactively-p 'any) 'interactive))))
       (with-current-buffer (org-noter--session-notes-buffer session)
         (org-with-wide-buffer
          (goto-char (org-element-property :begin ast))
          (if arg
              (org-entry-delete nil org-noter-property-note-location)
            (org-entry-put nil org-noter-property-note-location
                           (org-noter--pretty-print-location location))))))))
  (with-eval-after-load 'pdf-annot
    (add-hook 'pdf-annot-activate-handler-functions #'org-noter-pdftools-jump-to-note)))

org-roam

docs here How to Take Smart Notes

(use-package org-roam
  :demand ; do not defer
  :commands (org-roam-buffer-toggle-display
             org-roam-find-file
             org-roam-graph
             org-roam-insert
             org-roam-switch-to-buffer
             org-roam-dailies-date
             org-roam-dailies-today
             org-roam-dailies-tomorrow
             org-roam-dailies-yesterday)
  :bind (("C-c n f" . org-roam-node-find)
         ("C-c n d" . org-roam-dailies-capture-today)
         :map org-roam-mode-map
         ("<mouse-1>" . org-roam-visit-thing)
         :map org-mode-map
         (("C-c n l" . org-roam-buffer-toggle)
          ("C-c n g" . org-roam-graph)
          ("C-c n i" . org-roam-node-insert)
          :map evil-normal-state-map ;; is there an evil map within org-mode?
          ("g[" . org-roam-dailies-goto-previous-note)
          ("g]" . org-roam-dailies-goto-next-note)))
  :custom
  ;; the file-truename part makes it follow symbolic links!
  (org-roam-directory (file-truename "~/SurfDrive/bibliography/notes/"))
  (org-roam-dailies-directory "daily/")
  (org-id-link-to-org-use-id 'create-if-interactive)
  ;; (org-roam-completion-everywhere t) ;; this was a bit excessive
  (org-roam-verbose nil) ; https://youtu.be/fn4jIlFwuLU
  (org-roam-buffer-no-delete-other-windows t) ; make org-roam buffer sticky
  (org-roam-capture-templates
   '(("d" "default" plain
      "%?"
      :if-new  (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
                                 "#+title: ${title}\n#+created: %U\n#+last_modified:\n")
      :immediate-finish t
      :unnarrowed t)
     ("p" "people" plain
        "%?"
        :if-new  (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
                            "#+title: ${title}\n#+created: %U\n#+last_modified:\n\n#+filetags: people")
        :immediate-finish t
        :unnarrowed t)
     ("r" "bibliography reference" plain
      (file "/home/japhir/ArchConfigs/org-roam-bibtex-capture.org")
      :if-new
      (file+head "${citekey}.org" "#+title: ${citekey}: ${title}\n")
      :add-created t
      :unnarrowed t)))
  (org-roam-capture-ref-templates
   '(("r" "ref" plain
      "%?"
      :if-new (file+head "${citekey.org}"
                         "#+title: ${citekey}: ${title}\n")
      :immediate-finish t
      :add-created t
      :unnarrowed t)))
  (org-roam-dailies-capture-templates
   '(("d" "default" entry
      "* %?"
      :if-new (file+head "%<%Y-%m-%d>.org"
                         "#+title: %<%Y-%m-%d>\n#+created: %U\n#+last_modified: %U\n")
      :add-created t
      :jump-to-captured t)))
  :config
  ;; (org-roam-setup)
  (add-to-list 'display-buffer-alist
               '("\\*org-roam\\*"
                 (display-buffer-in-direction)
                 (direction . right)
                 ;; (window-width . 0.33)
                 (window-height . fit-window-to-buffer)))
  (org-roam-db-autosync-mode)
  (require 'org-roam-protocol))

org-roam-create-note-from-headline

https://org-roam.discourse.group/t/creating-an-org-roam-note-from-an-existing-headline/978

(defun org-roam-create-note-from-headline ()
  "Create an Org-roam note from the current headline and jump to it.

Normally, insert the headline’s title using the ’#title:’ file-level property
and delete the Org-mode headline. However, if the current headline has a
Org-mode properties drawer already, keep the headline and don’t insert
‘#+title:'. Org-roam can extract the title from both kinds of notes, but using
‘#+title:’ is a bit cleaner for a short note, which Org-roam encourages."
  (interactive)
  (let ((title (nth 4 (org-heading-components)))
        (has-properties (org-get-property-block)))
    (org-cut-subtree)
    (org-roam-find-file title nil nil 'no-confirm)
    (org-paste-subtree)
    (unless has-properties
      (kill-line)
      (while (outline-next-heading)
        (org-promote)))
    (goto-char (point-min))
    (when has-properties
      (kill-line)
      (kill-line))))

zaeph’s CREATED and LAST_MODIFIED properties

https://github.com/zaeph/.emacs.d/blob/master/lisp/zp-org.el#L140

(defvar zp/org-created-property-name "CREATED"
    "The name of the org-mode property that stores the creation date of the entry")

(defun zp/org-set-created-property (&optional active name)
  "Set a property on the entry giving the creation time.
By default the property is called CREATED. If given, the ‘NAME’
argument will be used instead. If the property already exists, it
will not be modified.
If the function sets CREATED, it returns its value."
  (interactive)
  (let* ((created (or name zp/org-created-property-name))
         (fmt (if active "<%s>" "[%s]"))
         (now (format fmt (format-time-string "%Y-%m-%d %a %H:%M"))))
    (unless (org-entry-get (point) created nil)
      (org-set-property created now)
      now)))

set it after capture

(defun zp/org-capture-set-created-property ()
  "Conditionally set the CREATED property on captured trees."
  (let ((add-created (plist-get org-capture-plist :add-created))
        (type (plist-get org-capture-current-plist :type)))
    (when (and (not org-note-abort)
               (eq type 'entry)
               add-created)
      (unless (buffer-narrowed-p)
        (error "Cannot add CREATED when buffer is not narrowed"))
      (save-excursion
        (goto-char (point-min))
        (zp/org-set-created-property)))))

set time-file property

(defun zp/org-set-time-file-property (property &optional anywhere pos)
  "Set the time file PROPERTY in the preamble.
When ANYWHERE is non-nil, search beyond the preamble.
If the position of the file PROPERTY has already been computed,
it can be passed in POS."
  (when-let ((pos (or pos
                      (zp/org-find-time-file-property property))))
    (save-excursion
      (goto-char pos)
      (if (looking-at-p " ")
          (forward-char)
        (insert " "))
      (delete-region (point) (line-end-position))
      (let* ((now (format-time-string "[%Y-%m-%d %a %H:%M]")))
        (insert now)))))

org-find-time-file-property

(defun zp/org-find-time-file-property (property &optional anywhere)
  "Return the position of the time file PROPERTY if it exists.
When ANYWHERE is non-nil, search beyond the preamble."
  (save-excursion
    (goto-char (point-min))
    (let ((first-heading
           (save-excursion
             (re-search-forward org-outline-regexp-bol nil t))))
      (when (re-search-forward (format "^#\\+%s:" property)
                               (if anywhere nil first-heading)
                               t)
        (point)))))

org-has-time-file-property-p

(defun zp/org-has-time-file-property-p (property &optional anywhere)
  "Return the position of time file PROPERTY if it is defined.
As a special case, return -1 if the time file PROPERTY exists but
is not defined."
  (when-let ((pos (zp/org-find-time-file-property property anywhere)))
    (save-excursion
      (goto-char pos)
      (if (and (looking-at-p " ")
               (progn (forward-char)
                      (org-at-timestamp-p 'lax)))
          pos
        -1))))

set last modified

(defun zp/org-set-last-modified ()
  "Update the LAST_MODIFIED file property in the preamble."
  (when (derived-mode-p 'org-mode)
    (zp/org-set-time-file-property "LAST_MODIFIED")))

SOME COMMENT org-roam-ui

  • State “SOME” from [2024-09-20 Fri 18:32]
this is actually really cool but I rarely use it! https://github.com/org-roam/org-roam-ui
(use-package org-roam-ui
    :after org-roam
    ;; :hook
    ;;         normally we'd recommend hooking orui after org-roam, but since org-roam does not have
    ;;         a hookable mode anymore, you're advised to pick something yourself
    ;;         if you don't care about startup time, use
    ;; :hook (after-init . org-roam-ui-mode)
    :config
    (setq org-roam-ui-sync-theme t
          org-roam-ui-follow t
          org-roam-ui-update-on-save t
          org-roam-ui-open-on-start t))

extend default completion packages

https://protesilaos.com/codelog/2024-02-17-emacs-modern-minibuffer-packages/

vertico

(use-package vertico
  :custom
  (vertico-cycle t)
  (vertico-resize nil)
  :init
  (vertico-mode 1))

it also likes savehist-mode, which I already had enabled.

marginalia

(use-package marginalia
  :init
  (marginalia-mode))

orderless

(use-package orderless
  :ensure t
  :custom
  (completion-styles '(orderless basic))
  (completion-category-defaults nil)
  (completion-category-overrides '((file (styles partial-completion)))))

consult

(use-package consult
  :bind (;; A recursive grep
         ("C-c s" . consult-ripgrep) ;; previously counsel-rg
         ;; Search for files names recursively
         ("C-x f" . consult-find)
         ;; Search through the outline (headings) of the file
         ("C-c o" . consult-outline)
         ;; Search the current buffer
         ("C-s" . consult-line) ;; previously swiper
         ;; Switch to another buffer, or bookmarked file, or recently
         ;; opened file.
         ("C-x b" . consult-buffer)))

embark

(use-package embark
  :bind (("C-." . embark-act)
         :map minibuffer-local-map
         ("C-c C-c" . embark-collect)
         ("C-c C-e" . embark-export)))

embark-consult

(use-package embark-consult)

wgrep

(use-package wgrep
  :bind ( :map grep-mode-map
          ("e" . wgrep-change-to-wgrep-mode)
          ("C-x C-q" . wgrep-change-to-wgrep-mode)
          ("C-c C-c" . wgrep-finish-edit)))

corfu

autocompletion replacement!
(use-package corfu
  :init
  (global-corfu-mode)
  :config
  (unless (display-graphic-p)
    (when (require 'corfu-terminal nil :noerror)
      (corfu-terminal-mode +1)))

  ;; Setup corfu for popup like completion
  (customize-set-variable 'corfu-cycle t)        ; Allows cycling through candidates
  (customize-set-variable 'corfu-auto t)         ; Enable auto completion
  (customize-set-variable 'corfu-auto-prefix 2)  ; Complete with less prefix keys

  (when (require 'corfu-popupinfo nil :noerror)

    (corfu-popupinfo-mode 1)
    (eldoc-add-command #'corfu-insert)
    (keymap-set corfu-map "M-p" #'corfu-popupinfo-scroll-down)
    (keymap-set corfu-map "M-n" #'corfu-popupinfo-scroll-up)
    (keymap-set corfu-map "M-d" #'corfu-popupinfo-toggle))
  :custom
  (text-mode-ispell-word-completion nil))

dabbrev

;; Use Dabbrev with Corfu!
(use-package dabbrev
  ;; Swap M-/ and C-M-/
  :bind (("M-/" . dabbrev-completion)
         ("C-M-/" . dabbrev-expand))
  :config
  (add-to-list 'dabbrev-ignored-buffer-regexps "\\` ")
  ;; Since 29.1, use `dabbrev-ignored-buffer-regexps' on older.
  (add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode)
  (add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode)
  (add-to-list 'dabbrev-ignored-buffer-modes 'tags-table-mode))

cape

completion at point
(use-package cape
  :bind ("M-+" . cape-prefix-map)
  :init
  ;; Add useful defaults completion sources from cape
  (add-hook 'completion-at-point-functions #'cape-dabbrev)
  (add-hook 'completion-at-point-functions #'cape-dict)
  (add-hook 'completion-at-point-functions #'cape-file)
  (add-hook 'completion-at-point-functions #'cape-history)
  :config
  ;; Silence the pcomplete capf, no errors or messages!
  ;; Important for corfu
  (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent)

  ;; Ensure that pcomplete does not write to the buffer
  ;; and behaves as a pure `completion-at-point-function'.
  (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)

  ;; No auto-completion or completion-on-quit in eshell
  (defun crafted-completion-corfu-eshell ()
    "Special settings for when using corfu with eshell."
    (setq-local corfu-quit-at-boundary t
                corfu-quit-no-match t
                corfu-auto nil)
    (corfu-mode))
  (add-hook 'eshell-mode-hook #'crafted-completion-corfu-eshell))

system

vterm

(use-package vterm)
;; (define-key vterm-mode-map (kbd "C-c C-l") #'vterm-clear)

systemd

(use-package systemd
  :defer t)

dired

(use-package dired-single)

(use-package dired
  :ensure nil
  :commands (dired dired-jump)
  :bind (("C-x C-j" . dired-jump))
  :custom ((dired-listing-switches "-agho --group-directories-first --time-style=iso"))
  :config
  (evil-collection-define-key 'normal 'dired-mode-map
    "h" 'dired-single-up-directory
    "l" 'dired-single-buffer))

(use-package dired-open
  :config
  (setq dired-open-extensions '(("png" . "imv")
                                ("mkv" . "mpv")
                                ("mp4" . "mpv"))))

(use-package dired-hide-dotfiles
  :hook (dired-mode . dired-hide-dotfiles-mode)
  :config
  (evil-collection-define-key 'normal 'dired-mode-map
    "H" 'dired-hide-dotfiles-mode))

emacs-pkgbuild-mode

Install it with Pacman

sudo pacman -S emacs-pkgbuild-mode

Then load it into emacs when opening a PKGBUILD file

(use-package pkgbuild-mode
   :ensure nil
   :defer t
   :load-path "/usr/share/emacs/site-lisp/"
   :mode "/PKGBUILD$")

email

smtp

(use-package smtpmail
  :ensure nil
  :custom
  ;; default config from https://www.djcbsoftware.nl/code/mu/mu4e/Gmail-configuration.html#Settings
  (message-send-mail-function 'smtpmail-send-it)
  (starttls-use-gnutls t)
  (smtp-stream-type 'starttls))

use oauth2ms

https://github.com/harishkrupo/oauth2ms/blob/main/steps.org I have to use this repo to access my work’s office365 account through XOAUTH2

 ;;; Call the oauth2ms program to fetch the authentication token
  (defun fetch-access-token ()
    (with-temp-buffer
	(call-process "/home/japhir/bin/oauth2ms" nil t nil "--encode-xoauth2")
	(buffer-string)))

  ;;; Add new authentication method for xoauth2
  (cl-defmethod smtpmail-try-auth-method
    (process (_mech (eql xoauth2)) user password)
    (let* ((access-token (fetch-access-token)))
	(smtpmail-command-or-throw
	 process
	 (concat "AUTH XOAUTH2 " access-token)
	 235)))

  ;;; Register the method
  (with-eval-after-load 'smtpmail
    (add-to-list 'smtpmail-auth-supported 'xoauth2))

mu4e

install it with pacman mu

(use-package mu4e
  :ensure nil
  :load-path "/usr/share/emacs/site-lisp/mu4e/"
  :commands mu4e
  :bind (("C-c m" . mu4e) ("C-c C-o" . shr-browse-url))
  :hook ((mu4e-view-mode mu4e-compose-mode) . visual-line-mode)
  :config
  (require 'mu4e)  ;; somehow this is needed, because otherwise calling org-store-link doesn't work
  (require 'mu4e-org)
  ;; Use Ivy for mu4e completions (maildir folders, etc)
  ; (setq mu4e-completing-read-function #'ivy-completing-read)

  ;; send email using smtp
  ;; see https://www.djcbsoftware.nl/code/mu/mu4e/Gmail-configuration.html#Settings
  ;; see also the smtp heading
  (require 'smtpmail)
  (setq mail-user-agent 'mu4e-user-agent
        message-send-mail-function 'smtpmail-send-it
        send-mail-function 'smtpmail-send-it
        ;; this is the same for both mail clients
        smtpmail-default-smtp-server "smtp.gmail.com"
        smtpmail-smtp-service 587
        smtpmail-stream-type 'starttls
        starttls-use-gnutls t
        starttls-gnutls-program "gnutls-cli"
        starttls-extra-arguments nil
        smtpmail-auth-credentials (expand-file-name "~/.authinfo")
        smtpmail-debug-info t
        smtpmail-debug-verb t)

  (setq user-full-name "Ilja J. Kocken")

  (setq mu4e-contexts
        (list
          ;; University of Hawaii
          (make-mu4e-context
           :name "hawaii"
           :enter-func (lambda () (mu4e-message "Switch to Hawaiʻi context"))
           :match-func (lambda (msg)
                         (when msg
                           (string-prefix-p "/hawaii" (mu4e-message-field msg :maildir))))
           :vars '((user-mail-address . "ikocken@hawaii.edu")
                   (message-user-organization . "University of Hawaiʻi at Mānoa")
                   ;; sending email
                   (smtpmail-smtp-user . "ikocken@hawaii.edu")
                   (smtpmail-smtp-server . "smtp.gmail.com")
                   (smtpmail-smtp-service . 587)
                   ;; (smtpmail-starttls-credentials . '(("smtp.gmail.com" 587 nil nil)))
                   ;; (smtpmail-auth-credentials . '(("smtp.gmail.com" 587 "ikocken@hawaii.edu" nil)))
                   (mu4e-drafts-folder . "/hawaii/Drafts")
                   (mu4e-sent-folder . "/hawaii/Sent")
                   (mu4e-refile-folder . "/hawaii/Archive")
                   (mu4e-trash-folder . "/hawaii/Trash")
                   (mu4e-compose-signature .
                                           (concat
                                            "Dr. Ilja J. Kocken | Postdoc Researcher at SOEST |\n"
                                            "University of Hawaii at Mānoa | 1000 Pope Road |\n"
                                            "MSB 504 | Honolulu, HI 96822, USA\n"))
                   (mu4e-maildir-shortcuts .
                                           (("/hawaii/Inbox" . ?i)
                                            ;; ("/hawaii/Drafts" . ?d) ; not synched!
                                            ("/hawaii/Trash" . ?t)
                                            ;; ("/hawaii/Sent Mail" . ?s) ; deleted!
                                            ;; ("/hawaii/Junk Email" . ?t)
                                            ("/hawaii/Archive" . ?r)))
                     ;; delete gmail sent items because they're also stored in All Mail/Archive.
                   (mu4e-sent-messages-behavior . delete)))

          ;; Utrecht University
          (make-mu4e-context
           :name "solismail"
           :match-func (lambda (msg)
                         (when msg
                           (string-prefix-p "/solismail" (mu4e-message-field msg :maildir))))
           :vars '((user-mail-address . "i.j.kocken@uu.nl")
                   (message-user-organization . "Utrecht University")
                   ;; sending email
                   (smtpmail-smtp-user . "i.j.kocken@uu.nl")
                   (smtpmail-smtp-server . "smtp.office365.com")
                   (smtpmail-smtp-service . 587)
                   (smtpmail-stream-type . starttls)
                   (smtpmail-starttls-credentials . (("outlook.office365.com" 587 "i.j.kocken@uu.nl" nil)))
                   (smtpmail-auth-credentials . (("outlook.office365.com" 587 "i.j.kocken@uu.nl" nil)))
                   (mu4e-drafts-folder . "/solismail/Drafts")
                   (mu4e-sent-folder . "/solismail/Sent")
                   (mu4e-refile-folder . "/solismail/Archive")
                   (mu4e-trash-folder . "/solismail/Trash")
                   (mu4e-compose-signature .
                                           (concat
                                            "Dr. Ilja Kocken\n"
                                            "Utrecht University | Vening Meinesz Gebouw A |\n"
                                            "Princetonlaan 8a, 3584 CB Utrecht, the Netherlands\n"))
                   (mu4e-maildir-shortcuts .
                                           (("/solismail/Inbox" . ?i)
                                            ;;("/NEXT" . ?n)
                                            ;; ("/solismail/Waiting" . ?w)
                                            ;; ("/solismail/Drafts" . ?c)
                                            ("/solismail/Trash" . ?t)
                                            ("/solismail/news" . ?n)
                                            ("/solismail/Important backlog" . ?l)
                                            ("/solismail/Sent" . ?s)
                                            ;; ("/solismail/Spam" . ?t)
                                            ("/solismail/Archive" . ?r)))
                   ))

          (make-mu4e-context
           :name "gmail"
           :enter-func (lambda () (mu4e-message "Switch to Personal context"))
           :match-func (lambda (msg)
                         (when msg
                           (string-prefix-p "/gmail" (mu4e-message-field msg :maildir))))
           :vars '((user-mail-address . "iljakocken@gmail.com")
                   (message-user-organization . "Personal")
                   ;; sending email
                   (smtpmail-stream-type . starttls)
                   (smtpmail-smtp-user . "iljakocken@gmail.com")
                   (smtpmail-smtp-server . "smtp.gmail.com")
                   (smtpmail-smtp-service . 587)
                   ;; (smtpmail-starttls-credentials . '(("smtp.gmail.com" 587 nil nil)))
                   ;; (smtpmail-auth-credentials . '(("smtp.gmail.com" 587 "iljakocken@gmail.com" nil)))
                   (mu4e-drafts-folder . "/gmail/Drafts")
                   (mu4e-sent-folder . "/gmail/Sent")
                   (mu4e-refile-folder . "/gmail/Archive")
                   (mu4e-trash-folder . "/gmail/Trash")
                   (mu4e-compose-signature .
                                           (concat
                                            "Ilja"))
                   (mu4e-maildir-shortcuts .
                                           (("/gmail/Inbox" . ?i)
                                            ;; ("/gmail/Drafts" . ?d) ; not synched!
                                            ("/gmail/Trash" . ?t)
                                            ;; ("/gmail/Sent" . ?s) ; deleted!
                                            ;; ("/gmail/Junk Email" . ?t)
                                            ("/gmail/Archive" . ?r)))
                     ;; delete gmail sent items because they're also stored in All Mail/Archive.
                   (mu4e-sent-messages-behavior . delete)))

          ))

  (setq mu4e-context-policy 'pick-first) ;; default to hawaii gmail

  (setq mu4e-change-filenames-when-moving t ; important for isync
        mu4e-headers-date-format "%Y-%m-%d %H:%M"
        mu4e-headers-fields
        '((:date          .  17)
          (:flags         .   5)
          (:from          .  22)
          (:subject       .  nil))
        mu4e-get-mail-command "env PATH=/usr/bin:/home/japhir/bin: mbsync -a"
        mu4e-headers-include-related t
        mu4e-compose-format-flowed t  ; plain-text nice to read on phone
        ;; use-hard-newlines t             ; above doesn't work for Outlooks, so disabled for colleagues
        mu4e-confirm-quit nil
        mu4e-view-show-images t)

   ;; if you press a V on an email you open it in the browser
  (add-to-list 'mu4e-view-actions '("View in browser" . mu4e-action-view-in-browser) t)
  ;; use imagemagick, if available
  ;; (when (fboundp 'imagemagick-register-types)
  ;;   (imagemagick-register-types))
  (setq mu4e-org-link-query-in-headers-mode nil)

  ;; maybe I want this at some point? currently not working, mu must have changed it query syntax
  (add-to-list 'mu4e-bookmarks
               '(:name "All Inboxes"
                 :query "maildir:/hawaii/Inbox OR maildir:/solismail/inbox OR maildir:/gmail/Inbox"
                       :key ?i))
  (add-to-list 'mu4e-bookmarks
               '(:name "All sent mail"
                 :query "from:ikocken@hawaii.edu OR from:iljakocken@gmail.com OR from:i.j.kocken@uu.nl"
                 :key ?s))
  )

science packages

ess

https://ess.r-project.org/ emacs speaks statistics, work with R etc.

insert pipe |> function

(defun japhir/insert-r-pipe ()
  "Insert the pipe operator in R, |>"
  (interactive)
  (just-one-space 1)
  (insert "|>")
  (reindent-then-newline-and-indent))

ess use-package

(use-package ess
  ;; :load-path "/usr/share/emacs/site-lisp/ess"
  :init (require 'ess-site)  ;; seems like this is needed to load the minor modes as well keybindings don't work without it
  :hook (
         ((ess-r-mode inferior-ess-r-mode) . electric-layout-mode)
         ;; (ess-r-post-run . (lambda ()
         ;;    (ess-load-file (make-temp-file nil nil nil
         ;;                                "Sys.setenv(\"DISPLAY\"=\":0.0\")")))
         )
  :commands R
  :bind (:map ess-r-mode-map
         (";" . ess-insert-assign)
         ;; RStudio equivalents
         ("M--" . ess-insert-assign)
         ("C-S-m" . japhir/insert-r-pipe)
         :map inferior-ess-r-mode-map
         (";" . ess-insert-assign)
         ("M--" . ess-insert-assign)
         ("C-S-m" . japhir/insert-r-pipe))
  :config
  (defun my-org-confirm-babel-evaluate (lang body)
    (not (or (string= lang "R")
             (string= lang "python")
             (string= lang "elisp")
             (string= lang "emacs-lisp")
             (string= lang "julia")
             (string= lang "stan")
             (string= lang "sh")
             (string= lang "latex"))))
  (setq ess-use-ido nil) ; disable ido, so that vertico etc. are used
  (add-to-list 'display-buffer-alist
               '(("\\*R:"
                  display-buffer-in-side-window
                  (inhibit-same-window . t)
                  (side . right)
                  ;; (slot . 2)
                  ;; (window-width . 0.5)
                  )))
  :custom
  ;; display-buffer-alist
        ;; '(("*R Dired*"
        ;;    (display-buffer-reuse-window display-buffer-in-side-window)
        ;;    (side . right)
        ;;    (slot . -1)
        ;;    (window-width . 0.33))
        ;;   ("*R:"
        ;;    (display-buffer-reuse-window display-buffer-in-side-window)
        ;;    (slot . 2)
        ;;    (window-width . 0.5))
        ;;   ("*Help*"
        ;;    (display-buffer-reuse-window display-buffer-in-side-window)
        ;;    (side . right)
        ;;    (slot . 1)
        ;;    (window-width . 0.33)))
        ;; ess-help-own-frame 'one
        ;; ess-auto-width 'window
  (org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate)
  (ess-style 'RStudio)
  ;; (ess-use-auto-complete nil)
  ;; (ess-use-company t) ; I now use corfu!
  (ess-indent-with-fancy-comments nil)
  (ess-pdf-viewer-pref 'emacsclient)
  (inferior-R-args "--no-restore-history --no-save")
  (ess-ask-for-ess-directory nil)
  (ess-R-font-lock-keywords
        (quote
         ((ess-R-fl-keyword:modifiers)
          (ess-R-fl-keyword:fun-defs . t)
          (ess-R-fl-keyword:keywords . t)
          (ess-R-fl-keyword:assign-ops . t)
          (ess-R-fl-keyword:constants . t)
          (ess-R-fl-keyword:fun-cals . t)
          (ess-R-fl-keyword:numbers)
          (ess-R-fl-keyword:operators . t)
          (ess-R-fl-keyword:delimiters)
          (ess-R-fl-keyword:=)
          (ess-R-fl-keyword:F&T)))))

ess-view

GioBo/ess-view: A small package to view dataframes within spreadsheet softwares allows you to quickly look at dataframes in a spreadsheet software (in my case LibreOffice)

(use-package ess-view
  :after ess)

electric-spacing operator

Put spaces around operators such as +, -, etc.

(use-package electric-operator
  :hook ((R-mode ess-r-mode inferior-ess-r-mode) . electric-operator-mode)
  :config
  (electric-operator-add-rules-for-mode 'stan-mode
                                        (cons "," ", ")
                                        (cons "~" " ~ "))

  (electric-operator-add-rules-for-mode 'ess-r-mode
                                        (cons ".+" " . + ")
                                        ;; these should never have spacing around them
                                        (cons ":" ":") ;; for ranges, should not add space
                                        (cons "::" "::") ;; to call a function from a package
                                        (cons ":::" ":::") ;; to call an internal function from a package
                                        (cons ":=" " := ") ;; walrus operator
                                        (cons "? " "?")
                                        (cons "){" ") {")
                                        (cons "}else{" "} else {")
                                        (cons "for(" "for (")
                                        (cons "if(" "if (")
                                        (cons "while(" "while (")
                                        (cons "{{" " {{ ") ;; curly-curly tidyverse
                                        (cons "}}" " }} ")
                                        (cons "!!" " !!")
                                        (cons "!!!" " !!!")
                                        (cons "^" "^") ;;
                                        (cons "|>" " |> ") ;; r 4.0 built-in pipe
                                        )
  :custom
  (electric-operator-R-named-argument-style 'spaced))

compilation window height

(setq compilation-window-height 15)

flycheck

  • Note taken on [2024-10-08 Tue 11:44]
    this makes larger org-mode files very very slow
(use-package flycheck
  ;; :init (global-flycheck-mode)
)

julia

(use-package julia-mode) ;; for syntax highlighting
(use-package julia-repl ;; for fancy REPL
  :after vterm
  :hook
  (julia-mode . julia-repl-mode)
  (julia-repl . #'julia-repl-use-emacsclient)
  ;; (add-hook 'julia-mode-hook 'julia-repl-mode)
  :config
  (setq julia-repl-switches "--threads 4")
  (setq vterm-kill-buffer-on-exit nil)
  ;; after julia-repl but before using it
  (julia-repl-set-terminal-backend 'vterm))
(use-package org-contrib
  :init
  (require 'ob-julia)
  :commands org-babel-execute:julia
  :config
  ;; (setq org-babel-julia-command-arguments
  ;;       `("--sysimage"
  ;;         ,(when-let ((img "~/.local/lib/julia.so")
  ;;                     (exists? (file-exists-p img)))
  ;;            (expand-file-name img))
  ;;         "--threads"
  ;;         ,(number-to-string (- (doom-system-cpus) 2))
  ;;         "--banner=no"))
  )

stan

https://mc-stan.org/ check out this worg entry on working inline with stan models! https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-stan.html

(use-package stan-mode
  :mode ("\\.stan\\'" . stan-mode)
  :hook (stan-mode . stan-mode-setup)
  :config
  (setq stan-indentation-offset 2)
  ;; I've used cmdstanr to install cmdstan because it's not in my repositories
  ;; don't forget to update this after updating from within an R session!
  (setq org-babel-stan-cmdstan-directory  "/home/japhir/.cmdstan/cmdstan-2.32.2"))

;; (use-package company-stan
;;   :hook (stan-mode . company-stan-setup))

(use-package eldoc-stan
  :hook (stan-mode . eldoc-stan-setup))

(use-package flycheck-stan
  :hook ((stan-mode . flycheck-stan-stanc2-setup)
         (stan-mode . flycheck-stan-stanc3-setup))
  :config
  (setq flycheck-stanc-executable nil)
  (setq flycheck-stanc3-executable nil))

;;; stan-snippets.el
(use-package stan-snippets
  :hook (stan-mode . stan-snippets-initialize)
  ;;
  :config
  ;; No configuration options as of now.
  )

markdown-mode

markdown mode for writing

(use-package markdown-mode :defer t)

polymode

for working with .Rmd files etc.

(use-package polymode :defer t)
(use-package poly-markdown :defer t)
(use-package poly-R)

mermaid

(use-package ob-mermaid
  :custom
  (ob-mermaid-cli-path "/usr/bin/mmdc"))

LaTeX (AUCTeX, RefTeX)

for working with \LaTeX

;(load "auctex.el" nil t t)
;(load "preview-latex.el" nil t t)
(use-package tex
  :load-path "/usr/share/emacs/site-lisp/auctex/"
  :hook
  (LaTeX-mode . turn-on-reftex)
  ;; (LaTeX-mode . turn-on-auto-fill) ;; I actually don't like this!
  (LaTeX-mode . prettify-symbols-mode)
  (LaTeX-mode . visual-fill-column-mode)

  (LaTeX-mode . menu-bar--display-line-numbers-mode-relative)
  :init
  (setq TeX-auto-save t)
  (setq TeX-parse-self t)
  (setq-default TeX-master nil)
  (setq reftex-plug-into-AUCTeX t))

secret directories

These are all the settings that require secret directories, such as my org agenda files and google overwrite the settings with “<…>” syntax above.

;; (use-package emacsdirs)
(load "~/.emacs.d/secretdirs.el" t)

NEXT tree-sitter

https://www.masteringemacs.org/article/how-to-get-started-tree-sitter
(use-package tree-sitter-langs)

(require 'treesit)
(global-tree-sitter-mode)
(add-hook 'ess-r-mode-hook #'tree-sitter-hl-mode)
(add-hook 'c-mode-hook #'tree-sitter-hl-mode)
(add-hook 'rust-mode-hook #'tree-sitter-hl-mode)
;; (add-hook 'ess-r-mode-hook #'tree-sitter-indent-mode)
(customize-set-variable 'treesit-font-lock-level 4)
;; (use-package tree-sitter-indent)
;; (use-package tree-sitter-ispell)
;; (use-package tree-sitter-ess-r
;;   :hook (ess-r-mode-hook . tree-sitter-ess-r-mode-activate))
(setq major-mode-remap-alist
 '((bash-mode . bash-ts-mode)
   (c-mode . rust-c-mode)
   (python-mode . python-ts-mode)
   (rust-mode . rust-ts-mode)))

(use-package evil-textobj-tree-sitter
  ;; copied from https://github.com/meain/evil-textobj-tree-sitter README
  :config
  ;; bind `function.outer`(entire function block) to `f` for use in things like `vaf`, `yaf`
  (define-key evil-outer-text-objects-map "f" (evil-textobj-tree-sitter-get-textobj "function.outer"))
  ;; bind `function.inner`(function block without name and args) to `f` for use in things like `vif`, `yif`
  (define-key evil-inner-text-objects-map "f" (evil-textobj-tree-sitter-get-textobj "function.inner"))
  ;; You can also bind multiple items and we will match the first one we can find
  (define-key evil-outer-text-objects-map "a" (evil-textobj-tree-sitter-get-textobj ("conditional.outer" "loop.outer")))
  ;; The first arguemnt to `evil-textobj-tree-sitter-get-textobj' will be the capture group to use
  ;; and the second arg will be an alist mapping major-mode to the corresponding query to use.
  (define-key evil-outer-text-objects-map "m" (evil-textobj-tree-sitter-get-textobj "import"
                                                '((python-mode . [(import_statement) @import])
                                                  (c-mode . [(preproc_include) @import]))))
  ;; Goto start of next function
  (define-key evil-normal-state-map (kbd "]f") (lambda ()
                                                 (interactive)
                                                 (evil-textobj-tree-sitter-goto-textobj "function.outer")))
  ;; Goto start of previous function
  (define-key evil-normal-state-map (kbd "[f") (lambda ()
                                                 (interactive)
                                                 (evil-textobj-tree-sitter-goto-textobj "function.outer" t)))
  ;; Goto end of next function
  (define-key evil-normal-state-map (kbd "]F") (lambda ()
                                                 (interactive)
                                                 (evil-textobj-tree-sitter-goto-textobj "function.outer" nil t)))
  ;; Goto end of previous function
  (define-key evil-normal-state-map (kbd "[F") (lambda ()
                                                 (interactive)
                                                 (evil-textobj-tree-sitter-goto-textobj "function.outer" t t)))
  )

reset gc-cons-threshold

(setq gc-cons-threshold 16777216
      gc-cons-percentage 0.1)