Simon's GNU Emacs Configuration
6131 Words
10 October 2023
This is my emacs configuration. Do with is as you will. This configuration is a
work in progress, so anything can break at any point. You can also find this
file in my dots.
PACKAGE MANAGEMENT
Configuration for Elpaca An Elisp Package Manager:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
(setq elpaca-core-date '(20240101))
(defvar elpaca-installer-version 0.7)
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
:ref nil :depth 1
:files (:defaults "elpaca-test.el" (:exclude "extensions"))
:build (:not elpaca--activate-package)))
(let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory))
(build (expand-file-name "elpaca/" elpaca-builds-directory))
(order (cdr elpaca-order))
(default-directory repo))
(add-to-list 'load-path (if (file-exists-p build) build repo))
(unless (file-exists-p repo)
(make-directory repo t)
(when (< emacs-major-version 28) (require 'subr-x))
(condition-case-unless-debug err
(if-let ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
((zerop (apply #'call-process `("git" nil ,buffer t "clone"
,@(when-let ((depth (plist-get order :depth)))
(list (format "--depth=%d" depth) "--no-single-branch"))
,(plist-get order :repo) ,repo))))
((zerop (call-process "git" nil buffer t "checkout"
(or (plist-get order :ref) "--"))))
(emacs (concat invocation-directory invocation-name))
((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
"--eval" "(byte-recompile-directory \".\" 0 'force)")))
((require 'elpaca))
((elpaca-generate-autoloads "elpaca" repo)))
(progn (message "%s" (buffer-string)) (kill-buffer buffer))
(error "%s" (with-current-buffer buffer (buffer-string))))
((error) (warn "%s" err) (delete-directory repo 'recursive))))
(unless (require 'elpaca-autoloads nil t)
(require 'elpaca)
(elpaca-generate-autoloads "elpaca" repo)
(load "./elpaca-autoloads")))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))
|
GENERAL BEHAVIOUR
General settings
1
2
|
(global-display-line-numbers-mode t)
(setq display-line-numbers-type 'relative)
|
Undo Tree
1
2
3
4
5
|
(use-package undo-tree
:ensure t
:init
(global-undo-tree-mode)
)
|
Consult
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
(use-package consult
:ensure t
:bind (
("C-s" . consult-line) ;; Line search
("M-y" . consult-yank-pop) ;; Yank pop
("C-x b" . consult-buffer) ;; Buffer switch
("C-x 4 b" . consult-buffer-other-window) ;; Buffer switch in other window
("C-x 5 b" . consult-buffer-other-frame) ;; Buffer switch in other frame
("M-g g" . consult-goto-line) ;; Go to line
("M-g M-g" . consult-goto-line) ;; Go to line
("M-g o" . consult-outline) ;; Outline navigation
("M-g m" . consult-mark) ;; Mark navigation
("M-g k" . consult-global-mark) ;; Global mark navigation
("M-s r" . consult-ripgrep) ;; Ripgrep search
("M-s l" . consult-locate) ;; Locate file
("M-s g" . consult-grep) ;; Grep search
)
:init
(setq register-preview-delay 0.5
register-preview-function #'consult-register-format)
:config
;; Optionally configure other settings here
(consult-customize consult-theme
:preview-key '(:debounce 0.2 any))
(consult-customize consult-buffer
consult-buffer-other-window
consult-buffer-other-frame
:preview-key "M-.")
)
|
Hydra
Sticky bindings: Hydra
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
(use-package hydra
:ensure t
:config
;; Define a hydra for consult commands
(defhydra hydra-consult (:color blue :hint nil)
"
Consult Commands
^Search^ ^Navigate^ ^Misc^
^^^^^^^^——————————————————————————————————————————————
[_s_] Search Line [_l_] Line [_m_] Mark
[_r_] Ripgrep [_b_] Buffer [_h_] Outline
[_g_] Grep [_f_] Buffer (other) [_t_] Theme
[_o_] Locate [_p_] Projectile [_q_] Quit
"
("s" consult-line)
("r" consult-ripgrep)
("g" consult-grep)
("o" consult-locate)
("l" consult-line)
("b" consult-buffer)
("f" consult-buffer-other-window)
("P" consult-projectile-switch-project)
("pf" consult-projectile-find-file)
("pp" consult-projectile-switch-project)
("pb" consult-projectile-switch-to-buffer)
("pq" projectile-run-command)
("m" consult-mark)
("h" consult-outline)
("t" consult-theme)
("q" nil :exit t))
)
|
Projectile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
(use-package projectile
:ensure t
:init
(projectile-mode +1) ; Enable projectile globally
:config
(setq projectile-project-search-path '("~/Projects/")) ; Adjust path as needed
(setq projectile-completion-system 'default)
(setq projectile-project-root-files-bottom-up (append projectile-project-root-files-bottom-up
'(".git")))
;; Define the Projectile Hydra
(defhydra hydra-projectile (:color blue :hint nil)
"
Projectile Commands
^Files^ ^Buffers^ ^Project^
^^^^^^————————————————————————————————————————————————————————————————————
[_f_] Find File [_b_] Switch to Buffer [_p_] Switch Project
[_F_] Find File in Known Projects [_k_] Kill Project Buffers [_D_] Discover Projects
[_r_] Recent File [_s_] Save Project Buffers [_i_] Invalidate Cache
[_d_] Find Directory [_a_] Ag (Search) [_q_] Quit
"
("f" projectile-find-file)
("F" projectile-find-file-in-known-projects)
("r" projectile-recentf)
("d" projectile-find-dir)
("b" projectile-switch-to-buffer)
("k" projectile-kill-buffers)
("s" projectile-save-project-buffers)
("p" projectile-switch-project)
("D" projectile-discover-projects-in-directory)
("i" projectile-invalidate-cache)
("a" projectile-ag)
("q" nil "quit" :color red :exit t)))
|
Evil Mode
I like vim key bindings: EVIL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
(elpaca elpaca-use-package
(elpaca-use-package-mode)
(setq elpaca-use-package-by-default t))
(elpaca-wait)
(use-package evil
:init
(setq evil-set-undo-system 'undo-tree)
(setq evil-want-keybinding nil)
(setq evil-want-integration t)
(setq evil-vsplit-window-right t)
(setq evil-split-window-below t)
(setq evil-want-C-i-jump nil)
:config
(evil-mode 1)
(define-key evil-normal-state-map (kbd "u") 'undo-tree-undo)
(define-key evil-normal-state-map (kbd "U") 'undo-tree-redo))
(use-package evil-collection
:after evil
:config
(setq evil-collection-mode-list '(dashboard dired ibuffer))
(evil-collection-init)
(with-eval-after-load 'doomlike
(evil-define-key 'normal 'global (kbd "SPC") 'doomlike/body)))
|
General
1
2
|
(require 'ido)
(ido-mode t)
|
Avy
Jumping around the buffer: avy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
(use-package avy
:ensure t
:config
(defhydra hydra-avy (:color blue :hint nil)
"
Avy Goto
^Char^ ^Line^ ^Word^ Description
^^^^^——————————————————————————————————————-
[_c_] [_l_] [_w_] Jump To
[_C_] [_L_] [_W_] Go To
"
("c" avy-goto-char)
("l" avy-goto-line)
("w" avy-goto-word-0)
("C" avy-goto-char-2)
("L" avy-goto-line-above)
("W" avy-goto-word-1)
("q" nil :exit t)))
|
Ivy
1
2
3
4
5
6
7
8
9
10
|
(use-package ivy
:ensure t
:config
(ivy-mode 1))
(use-package counsel
:ensure t)
(use-package swiper
:ensure t)
|
Tabs
Spell Checking
1
2
3
4
|
(setq ispell-program-name "hunspell")
(setq ispell-program-name (executable-find "hunspell"))
(setq ispell-local-dictionary "en_US")
(setq ispell-personal-dictionary "~/.config/dictionary/personal_dict")
|
External Programs
1
2
3
4
5
6
7
|
(use-package openwith
:config
(openwith-mode t)
(setq openwith-associations '(("\\.pdf\\'" "zathura" (file))))
;; Open PDF files externally
(add-to-list 'auto-mode-alist '("\\.pdf\\'" . openwith-open-pdf-externally)))
|
Neo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
(use-package neotree
:ensure t
:config
(add-hook 'neo-after-create-hook
(lambda (_)
(setq-local display-line-numbers nil)))
(defhydra hydra-neotree (:color blue :hint nil)
"
NeoTree Commands
^Navigation^ ^Actions^ ^Toggle^ ^Misc^
^^^^^^^^—————————————————————————————————————————
[_n_] Next Line [_C_] Create [_t_] Tree [_r_] Refresh
[_p_] Prev Line [_D_] Delete [_h_] Hidden [_s_] Change Root
[_q_] Quit
"
("n" neotree-next-line)
("p" neotree-previous-line)
("C" neotree-create-node)
("D" neotree-delete-node)
("t" neotree-toggle)
("h" neotree-hidden-file-toggle :which-key "Toggle Hidden Files")
("s" neotree-change-root)
("r" neotree-refresh)
("q" nil :exit t))
)
|
Bookmarks
Doom Like Shortcuts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
(defun my-doomlike-hint ()
"Dynamically generate hint string for the doomlike Hydra."
(concat
"\n"
" ┌───────────────────┬───────────────────┬──────────────┬─────────────────────────┐ \n"
" │ g → GTD │ b → Bookmark │ c → Consult │ │ \n"
" │ f → File │ i → iBuffer │ j → jump │ n → Split Window │ \n"
" │ o → Open │ p → Projectile │ r → Roam │ t → Neotree │ \n"
" │ T → Theme │ x → Capture │ g → GTD │ . → Open (find-file) │ \n"
" └───────────────────┴───────────────────┴──────────────┴─────────────────────────┘ \n"
(when (or (eq major-mode 'LaTeX-mode)(eq major-mode 'org-mode)) " l → LaTeX Command\n")))
(defhydra doomlike (:color red :hint nil :exit t)
"
%s(my-doomlike-hint)"
("g" hydra-gtd/body :exit t) ;; GTD Hydra
("c" hydra-consult/body :exit t)
("b" my/bookmark/body :exit t)
("j" hydra-avy/body :exit t)
("f" my/file-open/body :exit t)
("m" magit-status :exit t)
("o" my/open-buffer/body :exit t)
("p" hydra-projectile/body :exit t)
("t" hydra-neotree/body :exit t)
("i" ibuffer :exit t)
("l" (when (eq major-mode 'LaTeX-mode) (my/latex-hydra/body)) :exit t)
("n" my/split-window/body :exit t)
("r" my-org-roam-hydra/body :exit t)
("T" my/theme/body :exit t)
("x" org-capture :exit t)
("." find-file :exit t))
;; Bind doomlike hydra to SPC
(with-eval-after-load 'evil
(evil-define-key 'normal 'global (kbd "SPC") 'doomlike/body))
|
Hydras
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
(with-eval-after-load 'hydra
(defhydra my/file-open (:color red :hint nil :exit t)
"
^Open File^
——————————————
_c_ -> Config.org"
("c" (find-file "~/.config/emacs/config.org")
))
(defhydra my/bookmark (:color red :hint nil :exit t)
"
^Bookmark^
——————————————
_o_ -> Bookmark List
_s_ -> Bookmark Set"
("o" bookmark-bmenu-list)
("s" bookmark-set))
(defhydra my/split-window (:color red :hint nil :exit t)
"
^Split Window^
——————————————
_j_ -> Split Below
_l_ -> Split Right"
("j" split-window-below)
("l" split-window-right))
(defhydra my/theme (:color red :hint nil :exit t)
"
^Theme Management^
——————————————
_t_ -> Toggle Theme"
("t" toggle-solarized-theme))
(defhydra my/open-buffer (:color red :hint nil :exit t)
"
^Open Buffer^
——————————————
_t_ -> neotree"
("t" (find-file "~/.config/emacs/config.org")
)))
|
Window Movement
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
(use-package winum
:ensure t
:config
;; Automatically enable winum-mode
(winum-mode))
(global-set-key (kbd "M-0") 'winum-select-window-0)
(global-set-key (kbd "M-1") 'winum-select-window-1)
(global-set-key (kbd "M-2") 'winum-select-window-2)
(global-set-key (kbd "M-3") 'winum-select-window-3)
(global-set-key (kbd "M-4") 'winum-select-window-4)
(global-set-key (kbd "M-5") 'winum-select-window-5)
(global-set-key (kbd "M-6") 'winum-select-window-6)
(global-set-key (kbd "M-7") 'winum-select-window-7)
(global-set-key (kbd "M-8") 'winum-select-window-8)
(global-set-key (kbd "M-9") 'winum-select-window-9)
(global-set-key (kbd "M-l") 'evil-window-right)
(global-set-key (kbd "M-h") 'evil-window-left)
(global-set-key (kbd "M-k") 'evil-window-up)
(global-set-key (kbd "M-j") 'evil-window-down)
|
Transient
Folding
1
2
3
|
(use-package origami
:ensure t
:hook (rust-mode . origami-mode))
|
IBuffer
1
|
;;; emacs/ibuffer/config.el -*- lexical-binding: t; -*-
|
Org Mode
Org mode configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
;; Enable automatic line wrapping in org mode
(setq org-src-preserve-indentation t)
(setq org-tags-column 80)
(setq org-indent-indentation-per-level 5)
(setq org-ellipsis "⤵")
(add-hook 'org-mode-hook
(lambda ()
(setq fill-column 80) ; Set the desired line width
(turn-on-auto-fill)))
;; Configure visual line mode for org mode
(add-hook 'org-mode-hook 'visual-line-mode)
(add-hook 'org-mode-hook (lambda () (display-line-numbers-mode -1)))
(add-to-list 'org-structure-template-alist
'("s" "#+NAME: ?\n#+BEGIN_SRC \n\n#+END_SRC"))
(setq org-confirm-babel-evaluate nil)
(defun org-icons ()
"Beautify org mode keywords."
(setq prettify-symbols-alist '(
("[#A]" . "")
("[#B]" . "")
("[#C]" . "")
("[ ]" . "")
("[X]" . "")
("[-]" . "")
("#+BEGIN_SRC" . "")
("#+END_SRC" . "")
("#+begin_src" . "")
("#+end_src" . "")
(":ATTENDEES:" . "")
(":AUTHORS:" . "")
(":authors:" . "")
(":PROPERTIES:" . "")
("#+OPTIONS" . "")
(":END:" . "―")
("#+STARTUP:" . "")
("#+TITLE: " . "")
("#+title: " . "")
("#+RESULTS:" . "")
("#+DESCRIPTION:" . "")
("#+NAME:" . "")
("#+ROAM_TAGS:" . "")
("#+FILETAGS:" . "")
(":FILETAGS:" . "")
("#+HTML_HEAD:" . "")
("#+hugo_custom_front_matter:" . "")
("#+AUTHOR:" . "")
("#+author:" . "")
("#+SUBTITLE:" . "")
(":EFFORT:" . "")
(":COMPLETED:" . "")
(":SCHEDULED:" . "")
(":URL:" . "")
(":HEART:" . "")
(":PHONE:" . "")
(":EMAIL:" . "")
(":ADDRESS:" . "")
(":PERSON:" . "")
("ACADEMIC" . "")
(":DEADLINE:" . "")))
(prettify-symbols-mode))
(add-hook 'org-mode-hook #'org-icons)
(use-package org-superstar
:config
(setq org-superstar-special-todo-items t)
(add-hook 'org-mode-hook (lambda ()
(org-superstar-mode 1))))
(defface my-ligature-face
'((t (:family "Fira Code" :height 1.0))) ;; Replace "Fira Code" with the name of your desired font
"Face for ligature"
:group 'org-faces)
(use-package org-appear
:hook (org-mode . org-appear-mode))
(setq org-startup-indented t
org-pretty-entities t
org-hide-emphasis-markers t
org-startup-with-inline-images t
org-image-actual-width '(300))
(setq org-format-latex-options (plist-put org-format-latex-options :scale 2.0))
;; Configure org-mode to open links in the same buffer
(setq org-return-follows-link t)
(defun my-org-mode-keys ()
(when (bound-and-true-p evil-local-mode)
(evil-define-key 'normal org-mode-map (kbd "RET") 'org-open-at-point)))
(add-hook 'org-mode-hook 'my-org-mode-keys)
;; Configure evil-mode to open links in the same buffer
(setq org-structure-template-alist
'(("c" . "comment\n")
("e" . "example\n")
("E" . "export")
("h" . "export html\n")
("l" . "export latex\n")
("q" . "quote\n")
("s" . "src")
("se" . "src emacs-lisp\n")
("v" . "verse\n")))
(use-package org-sticky-header
:ensure t
:hook (org-mode . org-sticky-header-mode)
:config
(setq org-sticky-header-full-path 'full
org-sticky-header-outline-path 'breadcrumb))
|
1
2
3
4
|
(setq org-cite-activate-plain-format "\\cite{%l}")
(add-to-list 'load-path "~/.config/emacs/site-lisp")
(load "~/.config/emacs/site-lisp/org-pretty-table.el")
(add-hook 'org-mode-hook #'org-pretty-table-mode)
|
Org-clock
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
(setq org-clock-clocktable-default-properties
'(:maxlevel 3
:scope file
:block today
:tstart "<today>"
:tend "<tomorrow>"
:stepskip0 t
:step nil
:step-width 1
:properties ("CATEGORY")
:fileskip0 nil
:hidefiles t
:emphasize nil
:link t
:narrow 40
:indent nil
:formula nil
:timestamp nil
:formula-formula nil
:link-fmt "[[%s][%s]]"
:block-fmt ""
:properties-fmt ""
:tags nil
:tags-fmt nil
:narrow-fmt ""
:clock-summaries nil
:fileskip0summary nil
:compact nil
:compact-fmt ""
:sort nil
:sort-fmt ""
:show-properties nil
:level nil
:level-fmt ""
:scope-agenda-text ""
:table-line-above "--"
:table-line-below "--"))
|
Babel
Install the org-contrib
packge to get more languages
1
2
|
(use-package org-contrib
:ensure t)
|
1
2
3
4
5
6
7
|
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(python . t)
(shell . t)
))
(setq org-confirm-babel-evaluate nil)
|
Darkroom mode
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
(use-package darkroom
:ensure t
:config
(setq darkroom-margins 0.2) ; Adjust the margin size to your preference
(setq darkroom-fringes-outside-margins t) ; Set to t if you want fringes outside the margins
(setq darkroom-mode-line 'light) ; Use 'light for a light mode-line
(setq darkroom-text-scale-increase 2) ; Set to the desired text scale increase
:bind
("<f12>" . darkroom-tentative-mode) ; Bind to a keybinding of your choice
:hook
(darkroom-mode . (lambda ()
(if darkroom-mode
(display-line-numbers-mode -1)
(display-line-numbers-mode 1)))
)
)
|
Org Roam
Other Org Modes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
; (elpaca `(org-drill
; :host github
; :repo "SimonSekavcnik/org-drill"
; :branch "fix-time-stamp-format"))
(elpaca `(org-drill :path "/home/simon/Projects/org-drill"))
(use-package org-drill
:after org
:ensure t
:config
;; Enable org-drill when Org mode is loaded
(with-eval-after-load 'org
(require 'org-drill))
;; Customize org-drill settings
(setq org-drill-spaced-repetition-algorithm 'sm2
org-drill-add-random-noise-to-intervals-p t
org-drill-adjust-intervals-for-early-and-late-repetitions-p t
org-drill-maximum-items-per-session 30
org-drill-learn-fraction 0.25
org-drill-allow-visible-cloze-p t)
;; Customize org-drill faces (optional)
(custom-set-faces
'(org-drill-cloze-face ((t (:foreground "red" :weight bold))))
'(org-drill-done-cloze-face ((t (:foreground "green" :weight bold))))))
|
- Anki editor
1
2
|
(use-package anki-connect
:ensure t)
|
Bibliography
-
Org Roam Bibtex (ORB)
1
2
3
4
|
(use-package org-roam-bibtex
:after org-roam
:config
(require 'org-ref)) ; optional: if using Org-ref v2 or v3 citation links
|
-
Org Ref
-
Citar
-
Helm-Bibtexo
1
2
3
4
5
6
7
8
9
10
11
|
(use-package helm-bibtex
:ensure t
:config
(define-key org-mode-map (kbd "C-c c") 'helm-bibtex)
(setq bibtex-completion-notes-template-multiple-files
":PROPERTIES:\n:ID: %(org-id-new)\n:END:\n#+TITLE: ${author-or-editor} (${year}): ${title}\n:FILETAGS: NOTES PAPER\n\n [[/home/simon/Work/.library/pdfs/][PDF]]\n ${file} \n TEST")
(setq bibtex-completion-bibliography "~/Work/.library/ref.bib"
bibtex-completion-library-path "~/Work/.library/pdfs"
bibtex-completion-notes-path "~/.roam"))
(setq org-cite-follow-processor 'helm-bibtex-org-cite-follow)
(setq org-cite-global-bibliography '("~/Work/.library/ref.bib"))
|
LaTeX
- Helpers for Hydra
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
(defun my/latex-compile ()
"Compile the document using LatexMk."
(interactive)
(TeX-save-document (TeX-master-file))
(TeX-command "LatexMk" 'TeX-master-file -1))
(defun my/biber-compile ()
"Compile the document using Biber."
(interactive)
(TeX-save-document (TeX-master-file))
(TeX-command "Biber" 'TeX-master-file -1))
(defun my/latex-view()
"Compile the document using LatexMk."
(interactive)
(TeX-save-document (TeX-master-file))
(TeX-command "View" 'TeX-master-file -1))
|
- Hydra
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
(setq org-latex-to-pdf-process (list "latexmk -pdf %f"))
(defun test/latex (a))
(with-eval-after-load 'hydra
(defhydra my/latex-hydra (:hint nil :exit t)
"
^LaTeX Commands^
—————————————————————
_b_ → compile biber
_c_ → cite (TAB to choose)
_e_ → environment
_f_ → preview fragment
_F_ → preview document
_l_ → compile latex
_m_ → macro
_v_ → view pdf
"
("b" my/biber-compile :exit t)
("c" helm-bibtex :exit t)
("e" LaTeX-environment :exit t)
("f" preview-at-point :exit t)
("F" preview-document :exit t)
("l" my/latex-compile :exit t)
("m" TeX-insert-macro :exit t)
("v" my/latex-view :exit t)
))
|
AUCTex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
(defun my/latex-mode-hook ()
(advice-add #'TeX-command-master :before (lambda (&rest r) (save-buffer)))
(push (list 'output-pdf "Zathura") TeX-view-program-selection))
(use-package auctex
:ensure (auctex :pre-build (("./autogen.sh")
("./configure" "--without-texmf-dir" "--with-lispdir=.")
("make")))
:mode (("\\.tex\\'" . LaTeX-mode))
:defer t
:hook
(LaTeX-mode . my/latex-mode-hook)
(LaTeX-mode . turn-on-prettify-symbols-mode)
:bind (:map LaTeX-mode-map
("C-c b" . my/vertico-bibtex))
)
(add-hook 'LaTeX-mode-hook 'turn-on-reftex) ; Enable RefTeX with AUCTeX
(setq reftex-plug-into-AUCTeX t)
|
References
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
(use-package marginalia
:ensure t
:config
(marginalia-mode 1))
(defun my/bibtex-generate-autokey (&rest r)
(let* ((names (bibtex-autokey-get-names))
(year (bibtex-autokey-get-year))
(title (bibtex-autokey-get-title)))
(capitalize (format "%s%s" names year))))
(advice-add #'bibtex-generate-autokey :around #'my/bibtex-generate-autokey)
(defun my/vertico-bibtex--get-field (key candidate)
"return the field matching KEY in CANDIDATE"
(alist-get key (cdr candidate) nil nil #'string=))
(defun vertico-bibtex--maybe-truncate (field len)
(if field
(substring field 0 (min len (length field)))
field))
(defun my/vertico-bibtex--build-map (candidates)
(mapcar
(lambda (cand)
(let* ((key (my/vertico-bibtex--get-field "=key=" cand))
(title (vertico-bibtex--maybe-truncate
(my/vertico-bibtex--get-field "title" cand)
35))
(author (vertico-bibtex--maybe-truncate
(aif (my/vertico-bibtex--get-field "author" cand)
(string-replace " and " ", " it) it)
40))
(book (my/vertico-bibtex--get-field "booktitle" cand))
(journal (my/vertico-bibtex--get-field "journal" cand)))
`(,key . (:title ,title :author ,author :journal ,(or journal book)))))
candidates))
(defun my/vertico-bibtex (&optional arg)
"insert a bibtex citation at point using `completing-read`. if
ARG is non-nil, refresh the bibtex-completion cache"
(interactive "P")
(when arg
(bibtex-completion-clear-cache))
(bibtex-completion-init)
(let* ((candidates (bibtex-completion-candidates))
(map (my/vertico-bibtex--build-map candidates))
(keys (mapcar #'car map))
(completion-extra-properties
(list
:annotation-function
(lambda (key)
(let ((obj (alist-get key map nil nil #'string=)))
(marginalia--fields
((plist-get obj :title) :width 35 :truncate 0.5 :face 'marginalia-string)
((plist-get obj :author) :width 40 :truncate 0.5 :face 'marginalia-documentation)
((plist-get obj :journal) :width 30 :truncate 0.5 :face 'marginalia-value))))))
(selection (completing-read "Insert citation: " keys)))
(when selection
(insert selection))))
(defun my/vertico-bibtex (&optional arg)
"insert a bibtex citation at point using `completing-read`. if
ARG is non-nil, refresh the bibtex-completion cache"
(interactive "P")
(when arg
(bibtex-completion-clear-cache))
(bibtex-completion-init)
(let* ((candidates (bibtex-completion-candidates))
(map (my/vertico-bibtex--build-map candidates))
(keys (mapcar #'car map))
(completion-extra-properties
(list
:annotation-function
(lambda (key)
(let ((obj (alist-get key map nil nil #'string=)))
(marginalia--fields
((plist-get obj :title) :width 35 :truncate 0.5 :face 'marginalia-string)
((plist-get obj :author) :width 40 :truncate 0.5 :face 'marginalia-documentation)
((plist-get obj :journal) :width 30 :truncate 0.5 :face 'marginalia-value))))))
(selection (completing-read "Insert citation: " keys)))
(when selection
(insert selection))))
(defmacro aif (cnd then else)
"anaphoric if from paul graham's on lisp. bind the result of CND
to IT for use in the THEN and ELSE clauses"
`(let ((it ,cnd))
(if it ,then ,else)))
|
Ox
- Ox hugo
1
2
3
|
(use-package ox-hugo
:ensure t
:after ox)
|
Mu4E
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
(use-package mu4e
:ensure nil
:init
(add-to-list 'load-path "/usr/local/share/emacs/site-lisp/mu4e")
(require 'mu4e)
:config
(setq mu4e-change-filenames-when-moving t)
(setq mu4e-update-interval (* 10 60))
(setq mu4e-maildir "~/.mail/")
(setq mu4e-attachment-dir "~/Downloads")
(setq mu4e-update-interval 300) ; Update interval (seconds)
(setq mu4e-index-cleanup t) ; Cleanup after indexing
(setq mu4e-index-update-error-warning t) ; Warnings during update
(setq mu4e-index-update-in-background t) ; Background update
(setq mu4e-change-filenames-when-moving t) ; Needed for mbsync
(setq mu4e-index-lazy-check nil) ; Don't be lazy, index everything
(setq mu4e-completing-read-function 'completing-read)
(setq mu4e-contexts (list
(make-mu4e-context
:name "gmail"
:match-func (lambda (msg) (when msg
(string-prefix-p "/gmail" (mu4e-message-field msg :maildir))))
:vars `((msmtp-account . "jdm204-personal")
(user-mail-address . "simon.sekavcnik@gmail.com")
(mu4e-trash-folder . "/[Gmail]/Bin")
(mu4e-sent-folder . "/[Gmail]/Sent Mail")
(mu4e-drafts-folder . "/[Gmail]/Drafts")))
))
(setq
mu4e-headers-unread-mark '("u" . "️")
mu4e-headers-attach-mark '("a" . "")
mu4e-headers-replied-mark '("r" . "")
mu4e-headers-new-mark '("N" . "⭐")
mu4e-headers-signed-mark '("S" . "✒️")
mu4e-headers-trashed-mark '("T" . "❎️")
mu4e-headers-draft-mark '("d" . "")
mu4e-headers-flagged-mark '("f" . "🏴")
mu4e-headers-list-mark '("l" . "️")
mu4e-headers-seen-mark '("s" . "")
mu4e-headers-encrypted-mark '("e" . "")))
|
Magit
Magit is a git client for emacs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
(use-package magit
:ensure t
:config
(defhydra hydra-magit (:color blue :hint nil)
"
Magit Commands
^^^^^————————————————————————————————————————————
[_s_] Status [_b_] Blame
[_c_] Commit [_l_] Log
[_d_] Diff [_p_] Pull
[_P_] Push [_f_] Fetch
[_q_] Quit Hydra
"
("s" magit-status)
("b" magit-blame)
("c" magit-commit)
("l" magit-log)
("d" magit-diff)
("p" magit-pull)
("P" magit-push)
("f" magit-fetch)
("q" nil :exit t))
)
|
Keep Emacs Clean
1
2
3
4
5
6
7
8
9
|
(setq backup-directory-alist `(("." . ,(expand-file-name "/home/simon/.tmp/backups/" user-emacs-directory))))
;; auto-save-mode doesn't create the path automatically!
(make-directory (expand-file-name "/home/simon/.tmp/auto-saves/" user-emacs-directory) t)
(setq auto-save-list-file-prefix (expand-file-name "/home/simon/.tmp/auto-saves/sessions/" user-emacs-directory)
auto-save-file-name-transforms `((".*" ,(expand-file-name "/home/simon/.tmp/auto-saves/" user-emacs-directory) t)))
(setq create-lockfiles nil)
|
Flyspell
APPEARANCE
Theme
Using the Solaized theme
1
2
3
4
|
(use-package solarized-theme
:config
(load-theme 'solarized-dark t)) ; Choose 'solarized-light' for light theme
|
A function to change the theme
1
2
3
4
5
6
7
8
9
10
|
(defun toggle-solarized-theme ()
"Toggle between 'solarized-dark' and 'solarized-light' themes."
(interactive)
(if (eq (car custom-enabled-themes) 'solarized-dark)
(progn
(disable-theme 'solarized-dark)
(load-theme 'solarized-light t))
(progn
(disable-theme 'solarized-light)
(load-theme 'solarized-dark t))))
|
1
|
(setq org-src-fontify-natively t)
|
1
2
3
4
|
(set-frame-font "Fira Code")
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
|
Enable Ligatures
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
(use-package ligature
:ensure t
:config
;; Enable the www ligature in every possible major mode
(ligature-set-ligatures 't '("www"))
;; Enable ligatures in programming modes
(ligature-set-ligatures 'prog-mode '("www" "**" "***" "**/" "*>" "*/" "\\\\" "\\\\\\" "{-" "::"
":::" ":=" "!!" "!=" "!==" "-}" "----" "-->" "->" "->>"
"-<" "-<<" "-~" "#{" "#[" "##" "###" "####" "#(" "#?" "#_"
"#_(" ".-" ".=" ".." "..<" "..." "?=" "??" ";;" "/*" "/**"
"/=" "/==" "/>" "//" "///" "&&" "||" "||=" "|=" "|>" "^=" "$>"
"++" "+++" "+>" "=:=" "==" "===" "==>" "=>" "=>>" "<="
"=<<" "=/=" ">-" ">=" ">=>" ">>" ">>-" ">>=" ">>>" "<*"
"<*>" "<|" "<|>" "<$" "<$>" "<!--" "<-" "<--" "<->" "<+"
"<+>" "<=" "<==" "<=>" "<=<" "<>" "<<" "<<-" "<<=" "<<<"
"<~" "<~~" "</" "</>" "~@" "~-" "~>" "~~" "~~>" "%%"))
(global-ligature-mode 't)
)
|
Display Line Numbers and Truncate lines
1
2
|
(global-display-line-numbers-mode 1)
(global-visual-line-mode t)
|
Initial Screen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
(use-package dashboard
:ensure t
:config
(add-hook 'elpaca-after-init-hook #'dashboard-insert-startupify-lists)
(add-hook 'elpaca-after-init-hook #'dashboard-initialize)
(dashboard-setup-startup-hook))
(setq dashboard-icon-type 'all-the-icons)
;; Set the title
(setq dashboard-banner-logo-title "Simon's Emacs")
;; Set the banner
;;(setq dashboard-startup-banner [VALUE])
;; Value can be
;; - nil to display no banner
;; - 'official which displays the official emacs logo
;; - 'logo which displays an alternative emacs logo
;; - 1, 2 or 3 which displays one of the text banners
;; - "path/to/your/image.gif", "path/to/your/image.png" or "path/to/your/text.txt" which displays whatever gif/image/text you would prefer
;; - a cons of '("path/to/your/image.png" . "path/to/your/text.txt")
;; Content is not centered by default. To center, set
(setq dashboard-center-content t)
;; To disable shortcut "jump" indicators for each section, set
(setq dashboard-show-shortcuts nil)
|
MODES
Ledger
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
;; Ledger Mode Configuration
(use-package ledger-mode
:ensure t
:mode ("\\.ledger\\'" . ledger-mode)
:config
(setq ledger-clear-whole-transactions 1
ledger-mode-should-check-version nil
ledger-report-auto-refresh t)
;; Keybindings for Ledger mode
(define-key ledger-mode-map (kbd "C-c C-a") 'ledger-add-transaction)
(define-key ledger-mode-map (kbd "C-c C-c") 'ledger-toggle-current)
(define-key ledger-mode-map (kbd "C-c C-r") 'ledger-reconcile)
(define-key ledger-mode-map (kbd "C-c C-d") 'ledger-delete-current-transaction)
(define-key ledger-mode-map (kbd "C-c C-e") 'ledger-edit-transaction)
(define-key ledger-mode-map (kbd "C-c C-l") 'ledger-run-report)
;; Flycheck integration
(add-hook 'ledger-mode-hook
(lambda ()
(flycheck-mode)
(setq-local flycheck-checker 'ledger)))
;; Custom reports
(setq ledger-reports
'(("bal" "%(binary) -f %(ledger-file) bal")
("reg" "%(binary) -f %(ledger-file) reg")
("payee" "%(binary) -f %(ledger-file) reg @%(payee)")
("account" "%(binary) -f %(ledger-file) reg %(account)")))
;; Function to run the custom reports
(defun ledger-run-report (report-name)
"Run a custom ledger report."
(interactive (list (completing-read "Report: " (mapcar 'car ledger-reports))))
(ledger-report report-name)))
|
PROGRAMING
Yasnipet
1
2
3
4
5
6
7
8
|
(use-package yasnippet
:ensure t
:init
(setq yas-snippet-dirs '("~/.config/emacs/snippets"))
:config
(yas-reload-all)
(yas-global-mode 1)
(add-hook 'org-mode-hook #'yas-minor-mode))
|
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
(use-package python-mode
:mode ("\\.py\\'" . python-mode)
:interpreter ("python" . python-mode)
:hook (python-mode . lsp-deferred)
:config
(setq python-indent-offset 4))
;; Install and configure LSP mode for code completion and linting
(use-package lsp-mode
:commands (lsp lsp-deferred)
:hook
(lsp-mode . lsp-enable-which-key-integration)
(svelte-mode . lsp-deferred)
:custom
(lsp-diagnostics-provider :capf)
(lsp-headerline-breadcrumb-enable t)
(lsp-headerline-breadcrumb-segments '(project file symbols))
(lsp-lens-enable nil)
(lsp-disabled-clients '((python-mode . pyls)))
:init
(setq lsp-keymap-prefix "C-c l") ;; Or 'C-l', 's-l'
:config
)
;; Optional: Install and configure lsp-ui for additional features
(use-package lsp-ui
:hook (lsp-mode . lsp-ui-mode)
:config
(setq lsp-ui-doc-enable nil) ; Disable the documentation popup
(setq lsp-ui-sideline-enable t) ; Show symbol information in the sideline
(setq lsp-ui-sideline-show-hover t))
;; Optional: Install and configure flycheck for on-the-fly syntax checking
(use-package flycheck
:ensure t
:hook (lsp-mode . flycheck-mode))
(defun my-python-mode-keys ()
(when (bound-and-true-p evil-local-mode)
(evil-define-key 'normal python-mode-map (kbd "TAB") 'hs-toggle-hiding)))
(use-package company
:after lsp-mode
:hook (lsp-mode . company-mode)
:bind (:map company-active-map
("<tab>" . company-complete-selection))
(:map lsp-mode-map
("<tab>" . company-indent-or-complete-common))
:custom
(company-minimum-prefix-length 1)
(company-idle-delay 0.0))
(use-package company-box
:hook (company-mode . company-box-mode))
(add-hook 'python-mode-hook 'my-python-mode-keys)
(use-package pyvenv
:config
(pyvenv-mode 1))
(use-package elpy
:ensure t
:init
(elpy-enable)
:config
;(setq elpy-formatter 'autopep8)
;(setq elpy-formatter 'yapf)
)
|
Javascript
1
2
3
4
5
6
7
|
(add-hook 'js-mode-hook
(lambda ()
(setq js-indent-level 2)))
(add-hook 'js-jsx-mode-hook
(lambda ()
(setq js-jsx-indent-level 2)))
|
Rust
1
2
3
4
5
6
7
8
9
10
11
|
;; Rust mode and dependencies
(use-package ob-rust)
(use-package rust-mode
:mode "\\.rs\\'"
:config
;; Set indentation to 4 spaces
(setq rust-indent-offset 4)
;; Enable auto-formatting on save
(add-hook 'rust-mode-hook
(lambda () (add-hook 'before-save-hook 'rust-format-buffer nil t))))
(add-hook 'rust-mode-hook 'eglot-ensure)
|
Docker
1
2
3
4
|
;; Dockerfile mode
(use-package dockerfile-mode
:ensure t
:mode ("Dockerfile\\'" . dockerfile-mode))
|
1
2
3
4
|
;; Docker-compose mode
(use-package docker-compose-mode
:ensure t
:mode ("docker-compose\\.yml\\'" . docker-compose-mode))
|
1
2
3
4
|
;; Docker-related settings
(use-package docker
:ensure t
:bind ("C-c d" . docker))
|
Jenkins
1
2
3
4
5
6
7
8
9
10
11
|
(use-package jenkinsfile-mode
:ensure t
:mode (("Jenkinsfile\\'" . jenkinsfile-mode))
:config
(setq jenkinsfile-mode-indent-offset 4)
(add-hook 'jenkinsfile-mode-hook #'yas-minor-mode)
(add-hook 'jenkinsfile-mode-hook
(lambda ()
(setq-local flycheck-command-wrapper-function
(lambda (command) (append '("sh") command))))
))
|
Golang
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
(use-package go-mode
:ensure t
:mode
("\\.go\\'" . go-mode) ; Associate .go files with go-mode
("\\.proto\\'" . go-mode) ; Associate .proto files with go-mode
:hook
(go-mode . (lambda ()
(setq tab-width 2)
(setq indent-tabs-mode nil)
(add-hook 'before-save-hook 'gofmt-before-save nil t))))
(use-package company-go
:ensure t
:hook
(go-mode . (lambda ()
(set (make-local-variable 'company-backends) '(company-go))
(company-mode))))
|
Web
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
(use-package svelte-mode
:ensure t
:mode "\\.svelte\\'")
(use-package typescript-mode
:ensure t
:mode "\\.ts\\'")
(use-package emmet-mode
:ensure t
:hook
(html-mode . emmet-mode)
(css-mode . emmet-mode)
(svelte-mode . emmet-mode)
(web-mode . emmet-mode))
(add-hook 'svelte-mode-hook #'yas-minor-mode)
|
CUSTOM BEHAVIOUR
ORG MODE
TUM BEAMER
1
2
3
4
5
6
7
8
9
10
11
12
13
|
(eval-after-load "ox-latex"
;; update the list of LaTeX classes and associated header (encoding, etc.)
;; and structure
'(add-to-list 'org-latex-classes
`("beamer"
,(concat "\\documentclass[presentation]{tumbeamer}\n"
"[DEFAULT-PACKAGES]"
"[PACKAGES]"
"[EXTRA]\n")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))))
|
GTD
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
(defhydra hydra-gtd (:color blue :hint nil)
"
GTD Commands
^Agenda^ ^Capture^ ^View^
^^^^^^^^———————————————————————————————————————————————————
[_a_] Agenda [_t_] Capture Task [_v_] View All
[_t_] Todo [_p_] Capture Project [_g_] Go to
[_s_] Schedule [_i_] Capture Inbox [_q_] Quit
[_S_] Capture Someday
"
("a" org-agenda)
("t" org-todo)
("s" org-schedule)
("p" gtd/capture-project)
("S" gtd/capture-someday)
("i" gtd/capture-inbox)
("d" org-deadline)
("t" gtd/capture-task)
("r" org-refile)
("v" org-agenda-list)
("g" org-goto)
("q" nil :exit t))
|
1
2
3
|
(setq org-todo-keywords
'((sequence "INBOX(i)" "SCHED(s)" "NEXT(n)" "WAIT(w@/!)" "|" "DONE(d!)" "CANC(c)")
(sequence "PLAN(p)" "ACTIVE(a)" "REVIEW(v)" "WAIT(w@/!)" "HOLD(h)" "|" "DONE(d!)" "CANC(k@)")))
|
GTD Capture
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
(defun gtd/capture-project ()
"Capture a new project into an Org-Roam node and add the node to `org-agenda-files`."
(interactive)
;; Use `org-roam-node-read` to either select an existing node or create a new one
(let* ((node (org-roam-node-read)) ;; Prompt to select an existing node
(file-path (org-roam-node-file node))) ;; Get the file path of the selected node
;; If the file-path is nil or the file doesn't exist, create a new node file
(unless (and file-path (file-exists-p file-path)) ;; Create the file manually using `org-roam-capture-`
(setq file-path (expand-file-name
(concat (org-roam-node-slug node) ".org")
org-roam-directory))
(unless (file-exists-p file-path)
(with-temp-buffer
(insert (format "#+title: %s\n#+FILETAGS: GTD\n" (org-roam-node-title node)))
(write-file file-path))))
;; Use `org-roam-capture-` to capture the task in the selected or newly created node
(org-roam-capture- :node node
:templates `(("t" "GTD TASK" plain
"* INBOX %?\n :PROPERTIES:\n :CREATED: %U\n :END:\n"
:target (file+head ,file-path ""))))
;; Optionally add the file to `org-agenda-files`
(message "Captured project task in %s" file-path)))
(defun gtd/capture-task ()
"Capture a new task in an existing Org-Roam GTD Node and add the file to `org-agenda-files`."
(interactive)
;; Use `org-roam-node-find` to select an existing node, but capture the selected node instead of opening it
(let* ((node (org-roam-node-read nil #'gtd/org-roam-gtd-only nil nil nil)) ;; Prompt to select an existing GTD-tagged node
(file-path (org-roam-node-file node))) ;; Get the file path of the selected node
;; Use `org-roam-capture-` to capture the task in the selected node
(org-roam-capture- :node node
:templates '((
"i" "Inbox Task" plain
"\n** INBOX %^{Task Title}\n:PROPERTIES:\n:CREATED: %U\n:END:\n%?"
:if-new (file+head+olp file-path "" ("Tasks")))))
(message "Trying to add to the org agenda files")
(gtd/add-to-org-agenda-files file-path)))
(defun gtd/schedule ()
"Prompt the user to pick a schedule date or skip it."
(let ((schedule (org-read-date nil nil nil "Schedule: ")))
(if (string-empty-p schedule)
""
(format ":SCHEDULED: <%s>" schedule))))
(defun gtd/deadline ()
"Prompt the user to pick a schedule date or skip it."
(let ((schedule (org-read-date nil nil nil "Schedule: ")))
(if (string-empty-p schedule)
""
(format ":DEADLINE: <%s>" schedule))))
(defun gtd/capture-inbox ()
"Capture a new task as a heading in the Org-roam inbox file."
(interactive)
(org-roam-capture- :node (org-roam-node-create)
:templates '(("i" "Inbox Task" plain "\n* NEXT %^{Task Title}\n:PROPERTIES:\n:CREATED: %U\n%(gtd/schedule)\n%(gtd/deadline)\n:END:\n%?"
:target (file+head "inbox.org" "")))))
(defun gtd/capture-someday ()
"Capture a new task as a heading in the Org-roam someday file."
(interactive)
(org-roam-capture- :node (org-roam-node-create)
:templates '(("s" "Someday Task" plain "\n* WAITING %^{Task Title}\n:PROPERTIES:\n:CREATED: %U\n:END:\n%?"
:target (file+head "someday.org" "")))))
|
1
2
3
4
5
6
7
8
9
10
11
|
(defun gtd/add-to-org-agenda-files (file)
"Append FILE to `org-agenda-files` if it's not already present."
(interactive "fSelect file to add to `org-agenda-files`: ")
(let ((expanded-file (expand-file-name file)))
(unless (member expanded-file org-agenda-files)
(setq org-agenda-files (append org-agenda-files (list expanded-file)))
(message "Added %s to `org-agenda-files`" expanded-file))))
(defun gtd/org-roam-gtd-only (node)
(let ((tags (org-roam-node-tags node)))
(member "GTD" tags)))
|
Copy done tasks to dailies
After a task was completed it is copied to the TODAY dailies file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
(defun gtd/org-copy-to-daily ()
(interactive)
(let ((org-refile-keel t) ;; Set this to nil to delete the original!
(org-roam-dailies-capture-templates
'(("t" "tasks" entry "%?"
:if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title:%<%Y-%m-%d>\n" ("Completed Tasks")))))
(org-after-refile-insert-hook #'save-buffer)
today-file
pos)
(save-window-excursion
(org-roam-dailies--capture (current-time) t)
(setq today-file (buffer-file-name))
(setq pos (point)))
(unless (equal (file-truename today-file)
(file-truename (buffer-file-name)))
(org-refile nil nil (list "Completed Tasks" today-file nil pos)))))
(add-to-list 'org-after-todo-state-change-hook
(lambda ()
(when (equal org-state "DONE")
(gtd/org-copy-to-daily))))
|
Org Agenda
Prefix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
(defun my/org-agenda-get-roam-title ()
"Return the SHORT_TITLE property or the Org-roam title of the file corresponding to the current agenda item."
(let* ((marker (org-get-at-bol 'org-hd-marker))
(file (buffer-file-name marker))
(short-title (if file
(with-current-buffer (org-get-agenda-file-buffer file)
(org-with-wide-buffer
(goto-char (point-min))
(when (re-search-forward "^#\\+SHORT_TITLE:[ \t]*\\(.*\\)$" nil t)
(match-string-no-properties 1)))))))
(if (and short-title (not (string-empty-p short-title)))
short-title
(if file
(my/org-roam-get-title file)
""))))
(defun my/org-roam-get-title (file)
"Get the title from the Org-roam FILE.
If the title is not found, return the base name of the file."
(with-temp-buffer
(insert-file-contents file)
(goto-char (point-min))
(if (re-search-forward "^#\\+title: \\(.*\\)$" nil t)
(match-string 1)
(file-name-base file))))
(setq org-agenda-prefix-format
'((agenda . " %i %-12(my/org-agenda-get-roam-title) %?-12t% s")
(todo . " %i %-12(my/org-agenda-get-roam-title) ")
(tags . " %i %-12(my/org-agenda-get-roam-title) ")
(search . " %i %-12(my/org-agenda-get-roam-title) ")))
|
Views
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
(setq org-agenda-hide-tags-regexp "\\(GTD\\|INBOX\\|PROJECT\\)")
(defun gtd/skip-if-next ()
"Skip entries that are in the NEXT state."
(let ((subtree-end (save-excursion (org-end-of-subtree t))))
(if (string= (org-get-todo-state) "NEXT")
subtree-end
nil)))
(setq org-agenda-custom-commands
'(("g" "Custom Day Agenda"
((agenda ""
((org-agenda-span 'day)
(org-deadline-warning-days 0)
(org-agenda-use-time-grid t)
(org-agenda-overriding-header "My Custom Day Agenda")
(org-agenda-time-grid '((daily today remove-match)
(0800 1000 1200 1400 1600 1800)
"......" "----------------"))))
(todo "NEXT"
((org-agenda-overriding-header "Next Tasks")
(org-agenda-sorting-strategy '(priority-down))))
(alltodo ""
((org-agenda-overriding-header "All Tasks")
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'regexp ":PROJECT:" 'todo '("NEXT" "SCHED")))))
(alltodo ""
((org-agenda-overriding-header "All Active Projects")
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'notregexp ":PROJECT:"))))))))
(with-eval-after-load 'org-agenda
;; Remap j and k to move down and up
(define-key org-agenda-mode-map (kbd "j") 'org-agenda-next-line)
(define-key org-agenda-mode-map (kbd "k") 'org-agenda-previous-line)
;; Remap l and h to move forward and backward (day-wise)
(define-key org-agenda-mode-map (kbd "l") 'org-agenda-later)
(define-key org-agenda-mode-map (kbd "h") 'org-agenda-earlier))
|
Notification
1
2
3
4
5
6
7
8
9
10
|
(use-package org-alert
:ensure t
:custom (alert-default-style 'notifications)
:config
(setq org-alert-interval 10
org-alert-notify-cutoff 10
org-alert-notify-after-event-cutoff 10)
;(setq org-alert-time-match-string
; "\\(?:SCHED\\|DEADLINE\\):.*?<.*?\\([0-9]\\{2\\}:[0-9]\\{2\\}\\).*>")
)
|
GERMAN
1
2
|
(use-package anki-editor
:ensure t)
|