54 KiB
Meine Emacs-Konfiguration
- Benutzerangaben
- Secrets
- Start
- Konfigurationsdatei
- Look and Feel
- Tools
- Org
- Programming
- Notes
Benutzerangaben
Name und Emailadresse
(setq user-full-name "Ariane Troche")
(setq user-mail-address "ariane@familie-troche.de")
Secrets
Mit einem GPG (GnuPG) Schlüssel lassen sich private Dateien verschlüsseln. Emacs hilft beim Verschlüsseln und Entschlüsseln: Keeping Secrets in Emacs with GnuPG
(setq auth-sources
'((:source "~/.secrets/.authinfo.gpg")))
Start
Startfenster
Einige Einstellungen, die den Startbildschirm betreffen:
Splash Screen
Der übliche Emacs-Startbildschirm soll nicht angezeigt werden. Damit öffnet sich direkt der scratch-Buffer, welcher komplett leer sein soll.
(setq inhibit-splash-screen t)
(setq initial-scratch-message nil)
Scrollbar, Toolbar, Menubar
Scrollbar, Toolbar und Menubar werden ausgeblendet.
(scroll-bar-mode -1)
(tool-bar-mode -1)
(menu-bar-mode -1)
Vollbildschirm
Das Fenster wird im Vollbild geöffnet.
(setq initial-frame-alist '((fullscreen . maximized)))
Server
Damit beim Start von Emacs nicht immer ein neuer Prozess gestartet wird, wird Emacs hier schon als Server aufgesetzt. Using Emacs as a Server
(server-start)
Backup und Autosave
Die Backup- und Autosave-Dateien stören eher, da ich sie noch nie gebraucht habe, sollen sie erst gar nicht angelegt werden. Help keeping ~/.emacs.d clean
(use-package no-littering
:config
(with-eval-after-load 'recentf
(add-to-list 'recentf-exclude no-littering-var-directory)
(add-to-list 'recentf-exclude no-littering-etc-directory))
(setq auto-save-file-name-transforms ; autosaved-file-name~
`((".*" ,(no-littering-expand-var-file-name "auto-save/") t))
custom-file (no-littering-expand-etc-file-name "custom.el"))
(if (file-exists-p custom-file)
(load-file custom-file))
;; no-littering changes default snippets directory, so i changed it back.
(add-to-list 'yas-snippet-dirs
(expand-file-name "snippets" user-emacs-directory)))
Konfigurationsdatei
Konfigurationsdatei
Ich bastel sehr gerne an meiner Konfigurationsdatei herum. Mit <f1> kann ich sie ganz schnell öffnen und mit <f2> neu laden.
| Key | Funktion |
|---|---|
| F1 | Öffne Konfigurationsdatei in anderem Fenster |
| F2 | Konfiguration neu laden, ohne Emacs-Neustart |
;; Pfade
(setq artr/file-init (expand-file-name "init.el" user-emacs-directory))
(setq artr/file-config (expand-file-name "config.org" user-emacs-directory))
;; Öffnen
(defun artr/find-config-file ()
"Edit my init file in another window."
(interactive)
(find-file artr/file-config))
;; Laden
(defun artr/reload-emacs-configuration ()
"Reload init.el"
(interactive)
(load-file artr/file-init))
;; Keys
(global-set-key (kbd "<f1>") 'artr/find-config-file)
(global-set-key (kbd "<f2>") 'artr/reload-emacs-configuration)
Neustart
Mit <F12> kann ich Emacs neu starten.
| Key | Funktion |
|---|---|
| F12 | Emacs-Neustart |
(use-package restart-emacs
:ensure t
:bind ("<f12>" . 'restart-emacs))
Look and Feel
Font
| Key | Funktion |
|---|---|
| C– | Schriftgröße schrittweise verkleinern |
| C-* | Schriftgröße schrittweise vergrößern |
| C-0 | Schriftgröße auf Default zurücksetzen |
Font
;; for unicode
(when (display-graphic-p)
(set-fontset-font "fontset-default" nil
(font-spec :size 20 :name "Symbola")))
;; for emoji
(set-fontset-font
t
'(#x1f300 . #x1fad0)
(cond
((member "Noto Color Emoji" (font-family-list)) "Noto Color Emoji")
((member "Noto Emoji" (font-family-list)) "Noto Emoji")
((member "Segoe UI Emoji" (font-family-list)) "Segoe UI Emoji")
((member "Symbola" (font-family-list)) "Symbola")
((member "Apple Color Emoji" (font-family-list)) "Apple Color Emoji")))
;; font to use
(defconst artr/default-font-family "Source Code Pro")
(defconst artr/default-font-size 100)
(defconst artr/default-icon-size 15)
(set-face-attribute 'default nil
:family artr/default-font-family
:height artr/default-font-size)
Schriftgröße anpassen
(defun artr/adjust-font-size (height)
"Adjust font size by given height. If height is '0', reset font
size. This function also handles icons and modeline font sizes."
(interactive "nHeight ('0' to reset): ")
(let ((new-height (if (zerop height)
artr/default-font-size
(+ height (face-attribute 'default :height)))))
(set-face-attribute 'default nil :height new-height)
(set-face-attribute 'mode-line nil :height new-height)
(set-face-attribute 'mode-line-inactive nil :height new-height)
(message "Font size: %s" new-height))
(let ((new-size (if (zerop height)
artr/default-icon-size
(+ (/ height 5) treemacs--icon-size))))
(when (fboundp 'treemacs-resize-icons)
(treemacs-resize-icons new-size))
(when (fboundp 'company-box-icons-resize)
(company-box-icons-resize new-size))))
Schrift vergrößern
(defun artr/increase-font-size ()
"Increase font size by 0.5 (5 in height)."
(interactive)
(artr/adjust-font-size 5))
Schrift verkleinern
(defun artr/decrease-font-size ()
"Decrease font size by 0.5 (5 in height)."
(interactive)
(artr/adjust-font-size -5))
Schriftgröße zurücksetzen
(defun artr/reset-font-size ()
"Reset font size according to the `artr/default-font-size'."
(interactive)
(artr/adjust-font-size 0))
Keybindings
(global-set-key (kbd "C--") 'artr/decrease-font-size)
(global-set-key (kbd "C-*") 'artr/increase-font-size)
(global-set-key (kbd "C-0") 'artr/reset-font-size)
Icons
(use-package all-the-icons)
Modeline
doom-modeline - A fancy and fast mode-line inspired by minimalism design. A minor-mode menu for the mode line - minions anzu.el - displays match information in the mode-line in various search modes
(use-package doom-modeline
:custom (doom-modeline-icon t)
(doom-modeline-minor-modes t)
(doom-modeline-unicode-fallback t)
(doom-modeline-mu4e nil)
(doom-modeline-buffer-encoding nil)
:init
:hook (after-init . doom-modeline-mode))
(use-package minions
:hook (doom-modeline-mode . minions-mode))
(use-package anzu
:after isearch
:config (global-anzu-mode))
Theme
Dired
(use-package dired
:ensure nil
:config
;; Always delete and copy recursively
(setq dired-recursive-deletes 'always
dired-recursive-copies 'always)
(when (executable-find "ls")
;; Using `insert-directory-program'
(setq ls-lisp-use-insert-directory-program t)
;; Show directory first
(setq dired-listing-switches "-alh --group-directories-first")))
;; Show git info in dired
(use-package dired-git-info
:bind (:map dired-mode-map
(")" . dired-git-info-mode)))
;; Allow rsync from dired buffers
(use-package dired-rsync
:bind (:map dired-mode-map
("C-c C-r" . dired-rsync)))
;;Icons
(use-package all-the-icons-dired
:hook (dired-mode . all-the-icons-dired-mode))
Text
Textbreite
(setq-default fill-column 90)
(setq column-number-mode t)
(use-package virtual-auto-fill
:hook (text-mode . virtual-auto-fill-mode))
Whitespace
Das Löschen der überflüssigen Leerzeichen beim Speichern verträgt sich nicht mit Roam, wo die Datei bereits nach 2 Sekunden (org-roam-db-update-idle-seconds) gespeichert wird. Entweder muss diese Zeit erhöht werden, oder das Löschen der Leerzeichen an anderer Stelle passieren.
;; (use-package whitespace
;; :hook (before-save . whitespace-cleanup))
;; (setq-default sentence-end-double-space nil)
Tabulators
(setq-default
indent-tabs-mode nil ; Use spaces instead of tabs
tab-width 4)
Copy/Paste
(delete-selection-mode)
Klammern
(show-paren-mode 1)
Fenster
teilen
Funktionen/Tastenkombination um neue Fenster zu erzeugen. Wenn ein neues Fenster erzeugt wird auch direkt dahin wechseln.
| Key | Funktion |
|---|---|
| C-1 | Alle anderen Fenster schließen |
| C-2 | Neues Fenster unterhalb |
| C-3 | Neues Fenster daneben |
(defun artr/split-window-below-and-switch ()
"Split the window below, then switch to the new window."
(interactive)
(split-window-below)
(other-window 1))
(defun artr/split-window-right-and-switch ()
"Split the window right, then switch to the new window."
(interactive)
(split-window-right)
(other-window 1))
(global-set-key (kbd "C-1") 'delete-other-windows)
(global-set-key (kbd "C-2") 'artr/split-window-below-and-switch)
(global-set-key (kbd "C-3") 'artr/split-window-right-and-switch)
wechseln
ace-window Bei mehr als 2 Fenstern in der Konfiguration werden die Fenster "durchnummeriert". So können Aktionen gezielt durchgeführt werden. Die möglichen Aktionen werden mit ? aufgelistet. Bei 2 Fenstern wird das Fenster einfach gewechselt.
| Key | Funktion |
|---|---|
| M-o | ace-windows (? zeigt mögliche Aktionen) |
| M-O | ace-swap-windows |
(use-package ace-window
:init (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)
aw-scope 'frame)
:bind (("M-o" . ace-window)
("M-O" . ace-swap-window)))
anordnen
| Key | Funktion |
|---|---|
| C-c <left> | vorherige Fensterkonfiguration |
| C-c <right> | nächste Fensterkonfiguration |
(use-package winner
:config (winner-mode))
eyebrowse Es können Fensterkonfigurationen angelegt und wiederhergestellt werden. Das Speichern der Konfigurationen passiert in sogenannten Slots, die von 0,… durchnummeriert werden. Mit C-c w 0 kann dann direkt die zugehörige Konfiguration wiederhergestellt werden.
| Key | Funktion |
|---|---|
| C-c w | key-map |
| C-c w n | neue Fensterkonfiguration |
| C-c w . | Fensterkonfiguration wechseln |
| C-c w , | Fensterkonfiguration benennen |
(use-package eyebrowse
:bind (("C-c w ." . eyebrowse-switch-to-window-config)
("C-c w ," . eyebrowse-rename-window-config)
("C-c w DEL" . eyebrowse-close-window-config)
("C-c w k" . eyebrowse-close-window-config)
("C-c w n" . eyebrowse-create-window-config))
:init (setq eyebrowse-keymap-prefix (kbd "C-c w")
eyebrowse-wrap-around t
eyebrowse-mode-line-style 'always
eyebrowse-mode-line-separator "|")
(eyebrowse-mode t))
bezeichnen
Die Fenster werden mit "Projektname | Dateiname" bezeichnet.
(setq-default frame-title-format
'((:eval
(let ((project-name (projectile-project-name)))
(unless (string= "-" project-name)
(format "%s| " project-name))))
"%b")) ; project-name| file-name
Treemacs
Treemacs - a tree layout file explorer for Emacs
(use-package treemacs
:diminish
:commands (treemacs-follow-mode
treemacs-filewatch-mode
treemacs-fringe-indicator-mode
treemacs-git-mode
treemacs)
:bind (([f8] . treemacs)
("M-0" . treemacs-select-window)
("C-x 1" . treemacs-delete-other-windows)
("C-x t 1" . treemacs-delete-other-windows)
("C-x t t" . treemacs)
("C-x t b" . treemacs-bookmark)
("C-x t C-t" . treemacs-find-file)
("C-x t M-t" . treemacs-find-tag)))
(use-package treemacs-magit
:after magit
:commands treemacs-magit--schedule-update
:hook ((magit-post-commit
git-commit-post-finish
magit-post-stage
magit-post-unstage)
. treemacs-magit--schedule-update))
Tools
Magit
Magit ist ein git-Client für Emacs: Magit User Manual
(use-package magit
:bind ("C-x g" . magit-status))
(use-package git-gutter
:config
(global-git-gutter-mode +1))
Helpful
Helpful - Eine Context-Hilfe mit mehr Informationen
(use-package helpful
:bind (([remap describe-function] . helpful-callable)
([remap describe-variable] . helpful-variable)
([remap describe-key] . helpful-key)
:map emacs-lisp-mode-map
("C-c C-d" . helpful-at-point)))
Helm
A Package in a league of its own: Helm Helm ist eine Schnittstelle, mit der man in einer Auswahl von Kandidaten suchen und filtern kann. Diese Schnittstelle kann in verschiedensten Anwendungen eingesetzt werden, wie z.B. Dateien, Buffer, Funktionen, Variablen und noch vieles mehr. Es gibt viele Erweiterungen für Helm.
| Key | Aktion |
|---|---|
| M-x | Funktionsaufruf |
| C-c h | helm-mini mit Buffer, Recent-Files und Bookmarks |
| C-h a | Tastenkombinationen |
| C-x C-f | Datei |
| C-x b | Buffer |
| C-x f | Recent-Files |
| C-x c b | Bookmarks |
| C-x c SPC | Mark-Rings |
| M-y | Kill-Ring |
| C-x c o | Suche in Datei mit Occur |
| C-x c s | Suche in Datei mit Swoop |
(use-package helm
:demand
:bind ("M-x" . helm-M-x)
("C-h a" . helm-apropos)
("C-c h" . helm-mini)
("C-x C-f" . helm-find-files)
("C-x f" . helm-recentf)
("C-x b" . helm-buffers-list)
("C-x c b" . helm-filtered-bookmarks)
("C-x c o" . helm-occur)
("C-x c s" . helm-swoop)
("C-x c SPC" . helm-all-mark-rings)
("M-y" . helm-show-kill-ring)
:preface (require 'helm-config)
:config (helm-mode 1))
(use-package helm-icons
:after helm
:config
(treemacs-resize-icons artr/default-icon-size)
:init
(setq helm-icons-provider 'all-the-icons)
(helm-icons-enable))
(use-package helm-swoop
:after helm
:chords
("js" . helm-swoop)
("jp" . helm-swoop-back-to-last-point)
:init
(bind-key "M-m" 'helm-swoop-from-isearch isearch-mode-map))
(use-package helm-descbinds
:init
(setq helm-descbinds-window-style 'split-window)
:bind ("C-h b" . helm-descbinds))
Company
(use-package company
:bind ("M-/" . company-complete)
:hook (after-init . global-company-mode)
:init (setq company-idle-delay 0))
(use-package helm-company
:after company helm
:bind (:map company-mode-map
("C-:" . helm-company)
:map company-active-map
("C-:" . helm-company)))
Snippets
Mit Yasnippet lassen sich Templates definieren und mit einer Tastenkombination belegen. Die Templates werden im Ordner snippets jeweils unter einem Mode-spezifischen Ordner gespeichert.
(setq yas-snippet-dirs (append yas-snippet-dirs '("~/.emacs.d/snippets")))
Das Paket yasnippet-snippets stellt eine Auswahl an Templates zur Verfügung. Mit helm-c-yasnippet lassen sich die Snippets mit Helm durchsuchen und filtern.
| Key | Aktion |
|---|---|
| C-c & C-n | neues Template anlegen |
| C-c & C-s | Template einfügen |
| C-c & C-v | Template öffnen |
| C-c y | Templates auswählen |
(use-package yasnippet
:diminish yas-minor-mode
:hook (after-init . yas-global-mode))
(use-package yasnippet-snippets
:after yasnippet)
(append yas-snippet-dirs '("~/.emacs.d/snippets"))
(use-package helm-c-yasnippet
:bind (("C-c y" . helm-yas-complete)))
Projectile
(use-package projectile
:config
(define-key projectile-mode-map (kbd "s-p") 'projectile-command-map)
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
(projectile-mode 1)
:init
(setq projectile-completion-system 'helm))
Which-Key
(use-package which-key
:init
(which-key-mode))
Org
Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system.
https://de.wikipedia.org/wiki/Org-mode
Konfiguration
Dateien und Ordner
(setq artr/dir-nextcloud "~/Nextcloud/")
(setq artr/dir-org (concat artr/dir-nextcloud "Notes/org/"))
(setq artr/dir-notes (concat artr/dir-nextcloud "Notes/org/notes/"))
(setq artr/dir-journal (concat artr/dir-org "journal/"))
(setq artr/dir-archive (concat artr/dir-org "archives/"))
(setq artr/dir-gtd (concat artr/dir-org "gtd/"))
(setq artr/dir-home (concat artr/dir-gtd "home/"))
(setq artr/dir-parcit (concat artr/dir-gtd "parcit/"))
(setq artr/file-inbox (concat artr/dir-org "inbox.org"))
(setq artr/file-areas (concat artr/dir-home "areas.org"))
(setq artr/file-projects (concat artr/dir-home "projects.org"))
(setq artr/file-grocery (concat artr/dir-home "grocery.org"))
(setq artr/file-meals (concat artr/dir-home "meals.org"))
(setq artr/file-calendar (concat artr/dir-home "calendar.org"))
Basics
(use-package org
:ensure org-plus-contrib
:mode (("\\.org\\'" . org-mode))
:bind
;; ("\C-cl" . 'org-store-link)
("\C-ca" . 'org-agenda)
("\C-cb" . 'org-switchb)
("\C-ct" . 'org-todo)
:init
(add-to-list 'org-modules 'org-contacts t)
(add-to-list 'org-modules 'ol-notmuch t)
(add-to-list 'org-modules 'org-tempo t)
(add-to-list 'org-modules 'org-habit t)
(add-to-list 'org-modules 'org-checklist t)
;; Ein bisschen größerer Abstand zwischen den Zeilen
(add-hook 'org-mode-hook
'(lambda () (setq line-spacing 0.3)))
:config
;; Symbole als Symbole anzeigen
(setq org-pretty-entities t)
;; Emphasise
(setq org-hide-emphasis-markers t)
;; Folding Symbol
;; (setq org-ellipsis " ⏷")
;; Refile bis Level 3 und Suche mit helm
(setq org-refile-use-outline-path 'file)
(setq org-outline-path-complete-in-steps nil)
(setq org-completion-use-ido nil)
(setq org-refile-targets '((org-agenda-files :maxlevel . 5)))
(setq org-return-follows-link t)
;; Code-Blocks
(setq org-src-fontify-natively t)
(setq org-src-tab-acts-natively t)
(setq org-confirm-babel-evaluate nil)
(org-babel-do-load-languages
'org-babel-load-languages
'((latex . t)
(plantuml . t)
(python . t)
(shell . t)
(calc . t)
(ditaa . t)
(org . t)))
;; Ditaa und PlantUML
(setq
org-plantuml-jar-path "/usr/share/plantuml/plantuml.jar"
org-ditaa-jar-path "/usr/share/ditaa/ditaa.jar")
;; Archive
(setq org-archive-location (concat artr/dir-archive "%s::"))
;; Speed-Commands
(setq org-use-speed-commands t
org-speed-commands-user
'(("N" org-narrow-to-subtree)
("A" org-archive-subtree)
("W" widen)
("k" org-cut-subtree)
("m" org-mark-subtree)))
(setq org-agenda-window-setup 'current-window))
Kalender
Unerwünschte Kalender ausblenden
(setq holiday-hebrew-holidays nil)
(setq holiday-islamic-holidays nil)
(setq holiday-bahai-holidays nil)
(setq holiday-oriental-holidays nil)
(setq holiday-solar-holidays nil)
Die Woche beginnt am Montag und deutsche Wochentage und Monate
(setq calendar-week-start-day 1
calendar-day-name-array ["Sonntag" "Montag" "Dienstag"
"Mittwoch" "Donnerstag" "Freitag" "Samstag"]
calendar-day-header-array ["So" "Mo" "Di" "Mi" "Do" "Fr" "Sa"]
calendar-month-name-array ["Januar" "Februar" "März" "April" "Mai" "Juni"
"Juli" "August" "September" "Oktober" "November" "Dezember"])
Feiertage (NRW)
(setq holiday-general-holidays
'((holiday-fixed 1 1 "Neujahr")
(holiday-fixed 5 1 "1. Mai")
(holiday-fixed 10 3 "Tag der Deutschen Einheit")))
(setq holiday-christian-holidays
'((holiday-float 12 0 -4 "1. Advent" 24)
(holiday-float 12 0 -3 "2. Advent" 24)
(holiday-float 12 0 -2 "3. Advent" 24)
(holiday-float 12 0 -1 "4. Advent" 24)
(holiday-fixed 12 25 "1. Weihnachtstag")
(holiday-fixed 12 26 "2. Weihnachtstag")
(holiday-easter-etc -48 "Rosenmontag")
(holiday-easter-etc -2 "Karfreitag")
(holiday-easter-etc 0 "Ostersonntag")
(holiday-easter-etc +1 "Ostermontag")
(holiday-easter-etc +39 "Christi Himmelfahrt")
(holiday-easter-etc +49 "Pfingstsonntag")
(holiday-easter-etc +50 "Pfingstmontag")
(holiday-easter-etc +60 "Fronleichnam")
(holiday-fixed 11 1 "Allerheiligen")))
Bullets
Zeigt unterschiedliche Bullets für die Org-Mode Levels.
(use-package org-superstar
:ensure t
:hook (org-mode . org-superstar-mode)
:init
(setq org-superstar-headline-bullets-list '("⚫" "⚫" "⚫" "⚫"))
(setq org-hide-leading-stars nil)
(setq org-superstar-leading-bullet ?\s))
TODO
TODO-Keywords
Meine TODO-Sequenz. Die Keywords haben folgende Bedeutung:
- TODO
- Eine offene Aufgabe
- NEXT
- Eine priorisierte Aufgabe
- WAITING
- Eine delegierte Aufgabe
- EXPIRED
- Eine abgelaufene Aufgabe
- DONE
- Eine erledigte Aufgabe
- CANCELED
- Eine gestrichene Aufgabe
(setq org-todo-keywords
'((sequence "TODO(t)" "NEXT(n)" "WAITING(w)" "EXPIRED"
"|" "DONE(x!)" "CANCELLED(c)")))
(setq org-log-into-drawer t)
Capture
Mit den Capture-Templates lassen sich schnell Dinge erfassen und an der gewünschten Stelle speichern. Ich nutze als Speicherort vor allem die Inbox diese sollte ich dann spätestens am Abend im Daily-Review leeren. In der Inbox wird folgendes gespeichert
- TODO (C-c c ia)
- Eine einfache Aufgabe in der Inbox
- Email (C-c c ie)
- Eine Mail aus Notmuch, die ich zu beantworten habe
- Link
- Eine Internetseite, die ich noch lesen möchte
Für Internetseiten habe ich mehrere Möglichkeiten
- org-cliplink (C-c c l)
- URL aus der Zwischenablage direkt in Inbox speichern
- org-protocol (C-c c w)
- Link wird direkt aus dem Browser in Inbox gespeichert
DOCT
(use-package doct
;;recommended: defer until calling doct
:commands (doct))
Templates
(setq org-default-notes-file artr/file-inbox)
(global-set-key (kbd "C-c c") 'org-capture)
(setq org-capture-templates
(doct '(("org-protocol-capture"
:keys "w"
:file artr/file-inbox
:todo-state "TODO"
:headline "Internet"
:template "* %{todo-state} [[%:link][%:description]]\n\n %i"
:immediate-finish t)
("Inbox" :keys "i"
:file artr/file-inbox
:prepend t
:todo-state "TODO"
:children (("Aufgabe" :keys "a"
:headline "Aufgaben"
:template "* %{todo-state} %?")
("Email" :keys "e"
:headline "Emails"
:template "* %{todo-state} Mail: %a")
("Internet" :keys "i"
:headline "Internet"
:template "* %{todo-state} %(org-cliplink-capture)"
:immediate-finish t)
)))))
Agenda
Konfiguration
;; Agenda-Dateien
(setq org-directory artr/dir-org)
(setq org-agenda-files ())
(add-to-list 'org-agenda-files artr/dir-home)
(add-to-list 'org-agenda-files artr/dir-parcit)
(add-to-list 'org-agenda-files artr/file-inbox)
;; Fensterverhalten
;;(setq org-agenda-window-setup 'current-window)
(setq org-agenda-restore-windows-after-quit t)
;; Vordefinierte Agendas zurücksetzen
(setq org-agenda-custom-commands nil)
;; Darstellung
(setq org-agenda-compact-blocks nil)
(setq org-agenda-block-separator (string-to-char "-"))
(setq org-habit-graph-column 45)
;; Skip
(setq org-agenda-skip-function-global '(artr/skip-entry-if-tag "skip"))
(setq org-agenda-skip-deadline-if-done t)
(setq org-agenda-skip-scheduled-if-done t)
;; Bulk Functions
(setq org-agenda-bulk-custom-functions '((?C (lambda nil (org-agenda-todo "")))))
;; Stuck Projects
(setq org-stuck-projects
'("+LEVEL=1+Projekt={.}-DONE" ("NEXT" "TODO") nil ""))
Funktionen
Skip-Funktionen
(defun artr/skip-entry-if-tag (tag)
"Alle Einträge mit dem Tag tag werden ignoriert."
(let ((subtree-end (save-excursion (org-end-of-subtree t))))
(if (member tag
(split-string
(or (org-entry-get (point) "ALLTAGS") "")
":"))
subtree-end
nil)))
Mouse-Face
(add-hook 'org-agenda-finalize-hook
(lambda () (remove-text-properties
(point-min) (point-max) '(mouse-face t))))
Super-Agenda
(use-package org-super-agenda
:after org-agenda
:init
(org-super-agenda-mode))
Agendas
Gruppierung
(add-to-list 'org-agenda-custom-commands
'("g" . "Getting Things Done...") t)
(add-to-list 'org-agenda-custom-commands
'("p" . "Planung...") t)
Aufgaben
** ACTIVE Übersicht
(add-to-list 'org-agenda-custom-commands
'("g1" "(1) Übersicht - Heute"
((agenda "" ((org-agenda-overriding-header "Heute")
(org-agenda-span 'day)
(org-super-agenda-groups
'((:name "Termine..."
:time-grid t)
(:name "Jeden Tag..."
:habit t)
(:name "Heute..."
:scheduled today)
(:name "Überfällig..."
:scheduled past)
(:name "Bald..."
:scheduled future)
(:discard (:anything t))))))
(alltodo "" ((org-agenda-overriding-header "Refile")
(org-agenda-files (list artr/file-inbox))
(org-agenda-sorting-strategy '(alpha-up))))
(todo "TODO" ((org-agenda-overriding-header "Areas")
(org-agenda-files (list artr/file-areas))
(org-agenda-todo-ignore-scheduled t)
(org-super-agenda-groups
'((:auto-group t))))))) t)
Die nächsten 3 Tage
Zeigt alle Termine und Aufgaben, die in den nächsten 3 Tagen geplant sind.
(add-to-list 'org-agenda-custom-commands
'("g2" "(2) Übersicht - Die nächsten 3 Tage"
((agenda "" ((org-agenda-overriding-header "Die nächsten 3 Tage")
(org-agenda-span 4))))) t)
Mahlzeiten
(add-to-list 'org-agenda-custom-commands
'("g3" "(3) Übersicht - Mahlzeiten für diese Woche"
((todo "TODO|DONE" ((org-agenda-overriding-header "Mahlzeiten")
(org-agenda-files (list artr/file-meals))
(org-super-agenda-groups
'((:auto-planning))))))) t)
Einkaufsliste
(add-to-list 'org-agenda-custom-commands
'("g4" "(4) Übersicht - Einkaufsliste"
((alltodo "" ((org-agenda-overriding-header "Einkaufsliste")
(org-agenda-files (list artr/file-grocery))
(org-super-agenda-groups
'((:auto-parent))))))) t)
Projekte
(add-to-list 'org-agenda-custom-commands
'("g5" "(5) Übersicht - Projekte"
((stuck "" ((org-agenda-overriding-header "Stuck")))
(todo "TODO" ((org-agenda-overriding-header "offen")
(org-agenda-skip-function '(or (artr/skip-entry-if-tag "DAILY") (artr/skip-entry-if-tag "RECURRING")))
(org-super-agenda-groups
'((:auto-property "Projekt")))))
(tags-todo "DAILY|+RECURRING|+TODO=\"NEXT\""
((org-agenda-overriding-header "geplant")
(org-super-agenda-groups
'((:auto-property "Projekt")))))
(todo "DONE" ((org-agenda-overriding-header "erledigt")
(org-super-agenda-groups
'((:auto-property "Projekt"))))))
((org-agenda-files (list artr/file-projects)))) t)
Kategorien
Farben für Kategorien
- Achtung: es wird jede Zeile eingefärbt, wenn sie nur das entsprechende Wort enthält. Das ist eventuell zu verbessern. Kann man dies auf Kategorie einschränken?
(add-hook 'org-agenda-finalize-hook
(lambda ()
(save-excursion
(color-org-header "Geburtstag:" "violet red")
(color-org-header "Feiertag:" "orchid")
(color-org-header "Ferien:" "medium orchid")
)))
(defun color-org-header (tag color)
""
(interactive)
(goto-char (point-min))
(while (re-search-forward tag nil t)
(add-text-properties (match-beginning 0) (point-at-eol) `(face (:foreground, color)))))
Breaking down Tasks
Checkbox
(defun artr/org-checkbox-todo ()
"Switch header TODO state to DONE when all checkboxes are ticked, to TODO otherwise"
(let ((todo-state (org-get-todo-state)) beg end)
(unless (not todo-state)
(save-excursion
(org-back-to-heading t)
(setq beg (point))
(end-of-line)
(setq end (point))
(goto-char beg)
(if (re-search-forward "\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"
end t)
(if (match-end 1)
(if (equal (match-string 1) "100%")
(unless (string-equal todo-state "DONE")
(org-todo 'done))
(unless (string-equal todo-state "TODO")
(org-todo 'todo)))
(if (and (> (match-end 2) (match-beginning 2))
(equal (match-string 2) (match-string 3)))
(unless (string-equal todo-state "DONE")
(org-todo 'done))
(unless (string-equal todo-state "TODO")
(org-todo 'todo)))))))))
(add-hook 'org-checkbox-statistics-hook 'artr/org-checkbox-todo)
Todos
(defun artr/org-summary-todo (n-done n-not-done)
"Switch entry to DONE when all subentries are done, to TODO otherwise."
(let (org-log-done org-log-states) ; turn off logging
(org-todo (if (= n-not-done 0) "DONE" "TODO"))))
(add-hook 'org-after-todo-statistics-hook 'artr/org-summary-todo)
Einkaufsliste
(defun artr/clean-grocery ()
"Entfernt in der Datei grocery.org alle CLOSED-Einträge und Leerzeilen"
(interactive)
(save-window-excursion
(find-file-at-point artr/file-grocery)
(outline-next-heading)
(flush-lines "CLOSED:.*")
(flush-lines "^$")))
Erweiterungen
Org-Rifle
Org-Rifle stellt Funktionen zum Suchen in Org-Dateien zur Verfügung
(use-package helm-org-rifle
:ensure t
:bind
("C-c r r" . helm-org-rifle)
("C-c r a" . helm-org-rifle-agenda-files)
("C-c r b" . helm-org-rifle-current-buffer)
("C-c r d" . helm-org-rifle-directories))
Org-Helm
Stellt folgende Funktionen zur Verfügung:
- helm-org-agenda-files-headings
- Suche in Überschriften aller Org-Agenda-Dateien
- helm-org-in-buffer-headings
- Suche in Überschriften der aktuellen Org-Datei
- helm-org-capture-templates
- Suche in Capture-Templates
(use-package helm-org
:ensure t
:bind
("C-c f b" . helm-org-in-buffer-headings)
("C-c f a" . helm-org-agenda-files-headings)
:init
:config
(add-to-list 'helm-completing-read-handlers-alist
'(org-capture . helm-org-completing-read-tags))
(add-to-list 'helm-completing-read-handlers-alist
'(org-set-tags-command . helm-org-completing-read-tags))
)
Org-Cliplink
Mit Org-Cliplink lassen sich URLs aus der Zwischenablage direkt als Link in ein Dokument einfügen. Die Beschreibung des Links ist der Titel der Webpage.
(use-package org-cliplink
:ensure t
:bind ("C-x c i" . org-cliplink))
Org-Notmuch
Schnittstelle zu Notmuch. So lassen sich Links zu Emails erstellen. Achtung: Das Paket heißt jetzt ol-notmuch und nicht org-notmuch
(use-package ol-notmuch
:ensure nil
:after org)
Org-CalDav
Ich übertrage meine Termine aus der Datei kalender.org in meinen Nextcloud-Klalender. Es gibt einen Familienkalender und jedes Familienmitglied hat seinen eigenen Kalender. Für den Tennisverein und die IGP gibt es jeweils einen eigenen Kalender.
(use-package org-caldav
:ensure t
:init
;; This is the sync on close function; it also prompts for save after syncing so
;; no late changes get lost
(defun org-caldav-sync-at-close ()
(org-caldav-sync)
(save-some-buffers))
;; This is the delayed sync function; it waits until emacs has been idle for
;; "secs" seconds before syncing. The delay is important because the caldav-sync
;; can take five or ten seconds, which would be painful if it did that right at save.
;; This way it just waits until you've been idle for a while to avoid disturbing
;; the user.
(defvar org-caldav-sync-timer nil
"Timer that `org-caldav-push-timer' used to reschedule itself, or nil.")
(defun org-caldav-sync-with-delay (secs)
(when org-caldav-sync-timer
(cancel-timer org-caldav-sync-timer))
(setq org-caldav-sync-timer
(run-with-idle-timer
(* 1 secs) nil 'org-caldav-sync)))
;; Actual calendar configuration edit this to meet your specific needs
(setq org-icalendar-timezone "Europe/Berlin")
(setq org-caldav-url "https://cloud.troche.koeln/remote.php/dav/calendars/ariane")
(setq org-caldav-exclude-tags ())
(setq org-caldav-files ())
(add-to-list 'org-caldav-exclude-tags "skip")
(add-to-list 'org-caldav-files (concat artr/dir-home "calendar.org"))
(setq org-caldav-calendars
'((:calendar-id "ariane"
:inbox (concat org-directory "caldav/inbox-ariane.org")
:select-tags ("ariane"))
(:calendar-id "markus"
:inbox (concat org-directory "caldav/inbox-markus.org")
:select-tags ("markus"))
(:calendar-id "jonathan"
:inbox (concat org-directory "caldav/inbox-jonathan.org")
:select-tags ("jonathan"))
(:calendar-id "philipp"
:inbox (concat org-directory "caldav/inbox-philipp.org")
:select-tags ("philipp"))
(:calendar-id "kilian"
:inbox (concat org-directory "caldav/inbox-kilian.org")
:select-tags ("kilian"))
(:calendar-id "familie"
:inbox (concat org-directory "caldav/inbox-familie.org")
:select-tags ("familie"))
(:calendar-id "igp"
:inbox (concat org-directory "caldav/inbox-igp.org")
:select-tags ("igp"))
(:calendar-id "tggwv"
:inbox (concat org-directory "caldav/inbox-tggwv.org")
:select-tags ("tggwv"))
))
:config
(setq org-icalendar-alarm-time 0)
(setq org-caldav-save-directory "~/.emacs.d/caldav/"))
;; Add the delayed save hook with a five minute idle timer
;; (add-hook 'after-save-hook
;; (lambda ()
;; (when (eq major-mode 'org-mode)
;; (org-caldav-sync-with-delay 300)))))
Org-Journal
Funktionen
Funktionen zur Berechnung eines Zeitwerts
(defun iso-week-to-time (year week day)
"Gibt zu m Input 'Jahr - Woche - Tag' den Internen Zeitwert zurück, gerechnet vom 01.01.1970"
(pcase-let ((`(,m ,d ,y)
(calendar-gregorian-from-absolute
(calendar-iso-to-absolute (list week day year)))))
(encode-time 0 0 0 d m y)))
(defun iso-beginning-of-week (year week)
"Gibt den internen Zeitwert zurück zum 1. Tag der angegebenen Woche und dem angegegbenen Jahr"
(iso-week-to-time year week 1))
(defun iso-end-of-week (year week)
"Gibt den internen Zeitwert zurück zum 1. Tag der angegebenen Woche und dem angegegbenen Jahr"
(iso-week-to-time year week 7))
(defun iso-next-month ()
(org-read-date nil t "+1m"))
Hilfsfunktionen zum Erzeugen der Titel
(defun artr/journal-weekly-header (time)
"Definiert den Titel für ein Weekly-Journal im Format 'Woche 04 (20.01-26.01.2020)'"
(let ((week (string-to-number (format-time-string "%W" time)))
(year (string-to-number (format-time-string "%Y" time))))
(concat
"#+TITLE: Journal: "
(format-time-string "Woche %V (%d.%m-" (iso-beginning-of-week year week))
(format-time-string "%d.%m.%Y)" (iso-end-of-week year week))
"\n#+STARTUP: folded")))
(defun artr/journal-monthly-header (time)
"Definiert den Titel für ein Monthly-Journal im Format '2020 Februar'"
(concat
"#+TITLE: Journal: "
(format-time-string "%Y - %B" time)
"\n#+STARTUP: folded"))
(defun artr/org-journal-file-header (time)
"Definiert den Titel eines Journal-Eintrags."
(concat
(pcase org-journal-file-type
(`daily "#+TITLE: Daily Journal\n#+STARTUP: showeverything")
(`weekly (artr/journal-weekly-header time))
(`monthly (artr/journal-monthly-header time))
(`yearly "#+TITLE: Yearly Journal\n#+STARTUP: folded"))))
Jornal für nächsten Monat
Konfiguration
Org-Journal zum führen eines Tagebuchs. Ich habe pro Monat eine Datei. Ich nutze folgende Funktionen:
| Key | Aktion |
|---|---|
| C-c n j | Neuer Eintrag mit aktuellem Zeitstempel |
| C-c n t | Öffne Eintrag von heute und erzeuge einen neuen Eintrag |
(use-package org-journal
:bind
("C-c n j" . org-journal-new-entry)
("C-c n t" . org-journal-today)
:config
(setq org-journal-dir artr/dir-journal
org-journal-file-type 'monthly
org-journal-file-format "journal-%Y-%m-%b.org"
org-journal-carryover-items nil
org-journal-date-format "%A, %d.%B %Y"
org-journal-date-prefix "* ")
(defun org-journal-today ()
(interactive)
(org-journal-new-entry t))
(setq org-journal-file-header 'artr/org-journal-file-header))
Org-Books
(use-package org-books
:ensure t
:init (setq org-books-file (concat artr/dir-gtd "books.org")))
Programming
Zeilennummerierung
Anzeige der Zeilennummern am Rand:
(use-package display-line-numbers
:ensure nil
:hook (prog-mode . display-line-numbers-mode))
Einzug
Die Einzüge werden als Linien dargestellt:
(use-package highlight-indent-guides
:diminish
:hook (prog-mode . highlight-indent-guides-mode)
:init (setq highlight-indent-guides-method 'character
highlight-indent-guides-responsive 'top))
Klammern
(add-hook 'prog-mode-hook 'electric-pair-local-mode)
(use-package rainbow-delimiters
:hook
(prog-mode . rainbow-delimiters-mode))
Elisp
(use-package highlight-defined
:hook (emacs-lisp-mode . highlight-defined-mode))
(use-package paredit
:config
(add-hook 'emacs-lisp-mode-hook #'paredit-mode)
;; enable in the *scratch* buffer
(add-hook 'lisp-interaction-mode-hook #'paredit-mode)
(add-hook 'ielm-mode-hook #'paredit-mode)
(add-hook 'lisp-mode-hook #'paredit-mode)
(add-hook 'eval-expression-minibuffer-setup-hook #'paredit-mode))
Plantuml
(use-package plantuml-mode
:custom
(plantuml-jar-path "/usr/share/plantuml/plantuml.jar")
:mode "\\.uml\\'")
Git
(use-package git-gutter
:config
(global-git-gutter-mode +1))
Java
Environment Setup
Für einige Betriebssysteme werden die Umgebungsvariablen nicht korrekt geladen. Das Paket exec-path-from-shell initialisiert die Variablen.
(use-package exec-path-from-shell)
(exec-path-from-shell-initialize)
;; Java-HOME
(setenv "JAVA_HOME" "/usr/lib/jvm/java-11-openjdk-amd64")
;; Java-Executable
(setq lsp-java-java-path "/usr/lib/jvm/java-11-openjdk-amd64/bin/java")
Run Code
Das Package quickrun ermöglich es Code auszuführen, wenn eine main-Methode existiert.
(use-package quickrun)
Check Code
(use-package flycheck
:init (global-flycheck-mode))
Debugging
(use-package dap-mode
:ensure t
:after (lsp-mode)
:functions dap-hydra/nil
:config
(require 'dap-java)
:bind (:map lsp-mode-map
("<f5>" . dap-debug)
("M-<f5>" . dap-hydra))
:hook ((dap-mode . dap-ui-mode)
(dap-session-created . (lambda (&_rest) (dap-hydra)))
(dap-terminated . (lambda (&_rest) (dap-hydra/nil)))))
(use-package dap-java
:ensure nil
:after (lsp-java))
Language Server Protocol (LSP)
Grundkonfiguration
(use-package lsp-mode
:hook (
(lsp-mode . lsp-enable-which-key-integration)
(java-mode . #'lsp-deferred)
)
:init (setq
lsp-keymap-prefix "C-c l" ; this is for which-key integration documentation, need to use lsp-mode-map
lsp-enable-file-watchers nil
read-process-output-max (* 1024 1024) ; 1 mb
lsp-completion-provider :capf
lsp-idle-delay 0.500
)
:config
(setq lsp-intelephense-multi-root nil) ; don't scan unnecessary projects
(with-eval-after-load 'lsp-intelephense
(setf (lsp--client-multi-root (gethash 'iph lsp-clients)) nil))
;; :global/:workspace/:file
(setq lsp-modeline-diagnostics-scope :workspace)
(define-key lsp-mode-map (kbd "C-c l") lsp-command-map))
Erweiterungen
LSP-UI
(use-package lsp-ui
:ensure t
:after (lsp-mode)
:bind (:map lsp-ui-mode-map
([remap xref-find-definitions] . lsp-ui-peek-find-definitions)
([remap xref-find-references] . lsp-ui-peek-find-references))
:init (setq lsp-ui-doc-delay 1.5
lsp-ui-doc-position 'bottom
lsp-ui-doc-max-width 100))
LSP-Helm
(use-package helm-lsp
:ensure t
:after (lsp-mode)
:commands (helm-lsp-workspace-symbol)
:init (define-key lsp-mode-map [remap xref-find-apropos] #'helm-lsp-workspace-symbol))
LSP-Java
(use-package lsp-java
:config (add-hook 'java-mode-hook 'lsp))
Compilation
(setq compilation-scroll-output t)
(add-hook 'compilation-filter-hook
(lambda () (ansi-color-apply-on-region (point-min) (point-max))))
(add-hook 'compilation-mode-hook
(lambda () (buffer-face-set :weight 'light :height 100)))
Notes
Deft
(use-package deft
:after org
:bind
("C-c n d" . deft)
:custom
(deft-recursive t)
(deft-use-filter-string-for-filename t)
(deft-default-extension "org")
(deft-directory artr/dir-notes)
(deft-current-sort-method 'title))
Roam
Org-Roam zum Aufbau einer Wissensdatenbank. Es werden Dokumente angelegt und verlinkt. Folgende Funktionen nutze ich:
- (C-c n f)
- Öffnet / Erstellt ein Dokument
- (C-c n i)
- Fügt einen Dokumenten-Link ein
- (C-c n l)
- Zeigt alle Back-Links
- (C-c n g)
- Zeigt die Roam-Graphik im Browser
(use-package org-roam
:hook
(after-init . org-roam-mode)
:custom
(org-roam-directory artr/dir-notes)
:bind
(:map org-roam-mode-map
(("C-c n l" . org-roam)
("C-c n f" . org-roam-find-file)
("C-c n g" . org-roam-show-graph))
:map org-mode-map
(("C-c n i" . org-roam-insert))))
(setq org-roam-capture-templates
'(("d" "default" plain (function org-roam--capture-get-point)
"%?"
:file-name "note-${slug}"
:head "#+TITLE: ${title}\n\n- Content ::\n- Tags ::\n- Links ::\n"
:unnarrowed t
:immediate-finish)))
Journal
Org-Journal zum führen eines Tagebuchs. Ich habe pro Monat eine Datei. Ich nutze folgende Funktionen:
- (C-c n j)
- Neuer Eintrag mit aktuellem Zeitstempel
- (C-c n t)
- Öffne Tagebucheintrag von heute und erzeuge neuen Eintrag
(use-package org-journal
:ensure t
:bind
("C-c n j" . org-journal-new-entry)
("C-c n t" . org-journal-today)
:custom
(org-journal-file-type 'monthly)
(org-journal-file-format "journal-%Y-%m-%b.org")
(org-journal-dir artr/dir-journal)
(org-journal-carryover-items nil)
(org-journal-date-format "%A, %d.%B %Y")
(org-journal-date-prefix "* ")
:config
(defun org-journal-today ()
(interactive)
(org-journal-new-entry t))
(setq org-journal-file-header 'artr/org-journal-file-header))