46 KiB
Emacs configuration file
- TODOS
- Header
- First start
- Performance Optimization
- Default settings
- Appearance
- Bookmarks
- recentf
- savehist
- undo
- ace-window
- imenu-list
- which-key
- abbrev
- Evil
- General (key mapper)
- Vertico & Orderless
- Consult
- Marginalia
- Embark
- Helm
- ivy / counsel / swiper
- misc
- company
- orgmode
- Programming
- beancount
- Stuff after everything else
TODOS
-
early-init.el? What to outsource here?
-
Paket exec-path-from-shell, um PATH aus Linux auch in emacs zu haben
-
Smart mode line?
-
Theme
-
evil-collection or custom in init file?
-
Hydra
-
General
-
(defalias 'list-buffers 'ibuffer) ;; change default to ibuffer
-
ido?
-
treemacs (for linux)
-
treemacs-evil?
-
treemacs-projectile windmove?
-
tramp (in linux)
-
visual-regexp
-
org configuration: paths
-
org custom agenda
-
org-ql (related to org agendas)
-
org configuration: everything else
-
beancount configuration from config.org
-
CONTINUE TODO from config.org at Programming
-
all-the-icons?
Header
Emacs variables are dynamically scoped. That's unusual for most languages, so disable it here, too
;;; init.el --- -*- lexical-binding: t -*-
First start
These functions updates config.el whenever changes in config.org are made. The update will be active after saving.
(defun me/tangle-config () "Export code blocks from the literate config file asynchronously." (interactive) ;; prevent emacs from killing until tangle-process finished (add-to-list 'kill-emacs-query-functions (lambda () (or (not (process-live-p (get-process "tangle-process"))) (y-or-n-p "\"me/tangle-config\" is running; kill it? ")))) ;; tangle config asynchronously ;; async only on linux because bash is called (if *sys/linux* (me/async-process (format "emacs %s --batch --eval '(org-babel-tangle nil \"%s\")'" config-org config-el) "tangle-process") (format "emacs %s --batch --eval '(org-babel-tangle nil \"%s\")'" config-org config-el)) (message "reloading user-init-file") (load-file config-el)) (add-hook 'org-mode-hook (lambda () (if (equal (buffer-file-name) config-org) (me/add-local-hook 'after-save-hook 'me/tangle-config)))) (defun me/add-local-hook (hook function) "Add buffer-local hook." (add-hook hook function :local t)) (defun me/async-process (command &optional name filter) "Start an async process by running the COMMAND string with bash. Return the process object for it. NAME is name for the process. Default is \"async-process\". FILTER is function that runs after the process is finished, its args should be \"(process output)\". Default is just messages the output." (make-process :command `("bash" "-c" ,command) :name (if name name "async-process") :filter (if filter filter (lambda (process output) (message output))))) ; (lambda (process output) (message (s-trim output)))))) ;; Examples: ;; ;; (me/async-process "ls") ;; ;; (me/async-process "ls" "my ls process" ;; (lambda (process output) (message "Output:\n\n%s" output))) ;; ;; (me/async-process "unknown command")
A small function to measure start up time. Compare that to emacs -q –eval='(message "%s" (emacs-init-time))' (roughly 0.27s) https://blog.d46.us/advanced-emacs-startup/
(add-hook 'emacs-startup-hook (lambda () (message "Emacs ready in %s with %d garbage collections." (format "%.2f seconds" (float-time (time-subtract after-init-time before-init-time))) gcs-done))) ;(setq gc-cons-threshold (* 50 1000 1000))
(require 'package) (add-to-list 'package-archives '("elpa" . "https://elpa.gnu.org/packages/") t) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t) (add-to-list 'package-archives '("nongnu" . "https://elpa.nongnu.org/nongnu/") t) ; fix for bug 34341 (setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3") (when (< emacs-major-version 27) (package-initialize))
(unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (eval-when-compile (setq use-package-enable-imenu-support t) (require 'use-package)) (require 'bind-key) (setq use-package-verbose nil) (use-package diminish :ensure t)
cl is deprecated in favor for cl-lib, some packages like emmet still depend on cl. Shut off the compiler warning about it. Maybe turn it on again at some point before the next major emacs upgrade
(setq byte-compile-warnings '(cl-functions))
Performance Optimization
Garbage Collection
Make startup faster by reducing the frequency of garbage collection. Set gc-cons-threshold (default is 800kb) to maximum value available, to prevent any garbage collection from happening during load time.
(setq gc-cons-threshold most-positive-fixnum)
Restore it to reasonable value after init. Also stop garbage collection during minibuffer interaction (helm etc.)
(defconst 1mb 1048576) (defconst 20mb 20971520) (defconst 30mb 31457280) (defconst 50mb 52428800) (defun me/defer-garbage-collection () (setq gc-cons-threshold most-positive-fixnum)) (defun me/restore-garbage-collection () (run-at-time 1 nil (lambda () (setq gc-cons-threshold 30mb)))) (add-hook 'emacs-startup-hook 'me/restore-garbage-collection 100) (add-hook 'minibuffer-setup-hook 'me/defer-garbage-collection) (add-hook 'minibuffer-exit-hook 'me/restore-garbage-collection) (setq read-process-output-max 1mb) ;; lsp-mode's performance suggest
File Handler
(defvar default-file-name-handler-alist file-name-handler-alist) (setq file-name-handler-alist nil) (add-hook 'emacs-startup-hook (lambda () (setq file-name-handler-alist default-file-name-handler-alist)) 100)
Others
;; Resizing the emacs frame can be a terriblu expensive part of changing the font. ;; By inhibiting this, we easily hale startup times with fonts that are larger ;; than the system default. (setq frame-inhibit-implied-resize t)
Default settings
paths
(defconst *sys/gui* (display-graphic-p) "Is emacs running in a gui?") (defconst *sys/linux* (string-equal system-type 'gnu/linux) "Is the system running Linux?") (defconst *sys/windows* (string-equal system-type 'windows-nt) "Is the system running Windows?") (defconst *home_desktop* (string-equal (system-name) "marc") "Is emacs running on my desktop?") (defconst *home_laptop* (string-equal (system-name) "laptop") "Is emacs running on my laptop?") (defconst *work_local* (string-equal (system-name) "PMPCNEU08") "Is emacs running at work on the local system?") (defconst *work_remote* (or (string-equal (system-name) "PMTS01") (string-equal (system-name) "PMTSNEU01")) "Is emacs running at work on the remote system?")
(defvar MY--PATH_USER_LOCAL (concat user-emacs-directory "user-local/")) (defvar MY--PATH_USER_GLOBAL (concat user-emacs-directory "user-global/")) (add-to-list 'custom-theme-load-path (concat MY--PATH_USER_GLOBAL "themes")) (when *sys/linux* (defconst MY--PATH_ORG_FILES (expand-file-name "~/Archiv/Organisieren/")) (defconst MY--PATH_ORG_FILES_MOBILE (expand-file-name "~/Archiv/Organisieren/mobile/")) (defconst MY--PATH_ORG_JOURNAl (expand-file-name "~/Archiv/Organisieren/Journal/")) (defconst MY--PATH_ORG_ROAM (file-truename "~/Archiv/Organisieren/"))) (when *work_remote* (defconst MY--PATH_ORG_FILES "p:/Eigene Dateien/Notizen/") (defconst MY--PATH_ORG_FILES_MOBILE nil) ;; hacky way to prevent "free variable" compiler error (defconst MY--PATH_ORG_JOURNAL nil) ;; hacky way to prevent "free variable" compiler error (defconst MY--PATH_START "p:/Eigene Dateien/Notizen/") (defconst MY--PATH_ORG_ROAM (expand-file-name "p:/Eigene Dateien/Notizen/"))) (setq custom-file (concat MY--PATH_USER_LOCAL "custom.el")) ;; don't spam init.e with saved customization settings (setq backup-directory-alist `((".*" . ,temporary-file-directory))) (setq auto-save-file-name-transforms `((".*" ,temporary-file-directory)))
sane defaults
(setq-default create-lockfiles nil) ;; disable lock files, can cause trouble in e.g. lsp-mode (defalias 'yes-or-no-p 'y-or-n-p) ;; answer with y and n (setq custom-safe-themes t) ;; don't ask me if I want to load a theme (setq sentence-end-double-space nil) ;; don't coun two spaces after a period as the end of a sentence. (delete-selection-mode t) ;; delete selected region when typing (use-package saveplace :config (save-place-mode 1) ;; saves position in file when it's closed :custom (save-place-file (concat MY--PATH_USER_LOCAL "places"))) (setq save-place-forget-unreadable-files nil) ;; checks if file is readable before saving position (global-set-key (kbd "RET") 'newline-and-indent) ;; indent after newline (setq save-interprogram-paste-before-kill t) ;; put replaced text into killring
Browser
(setq browse-url-function 'browse-url-generic browse-url-generic-program "firefox")
Appearance
Defaults
(set-charset-priority 'unicode) (setq-default locale-coding-system 'utf-8 default-process-coding-system '(utf-8-unix . utf-8-unix)) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (set-selection-coding-system 'utf-8) (if *sys/windows* (prefer-coding-system 'utf-8-dos) (prefer-coding-system 'utf-8)) (setq-default bidi-paragraph-direction 'left-to-right bidi-inhibit-bpa t ;; both settings reduce line rescans uniquify-buffer-name-style 'forward indent-tabs-mode nil ;; avoid tabs in place of multiple spaces (they look bad in tex) indicate-empty-lines t ;; show empty lines scroll-margin 5 ;; smooth scrolling scroll-conservatively 10000 scroll-preserve-screen-position 1 scroll-step 1 ring-bell-function 'ignore ;; disable pc speaker bell visible-bell t) (global-hl-line-mode t) ;; highlight current line (blink-cursor-mode -1) ;; turn off blinking cursor (column-number-mode t)
Remove redundant UI
(menu-bar-mode -1) ;; disable menu bar (tool-bar-mode -1) ;; disable tool bar (scroll-bar-mode -1) ;; disable scroll bar
Font
(when *sys/linux* (set-face-font 'default "Hack-10")) (when *work_remote* (set-face-font 'default "Lucida Sans Typewriter-11"))
Themes
(defun me/toggle-theme () (interactive) (when (or *sys/windows* *sys/linux*) (if (eq (car custom-enabled-themes) 'tango-dark) (progn (disable-theme 'tango-dark) (load-theme 'tango)) (progn (disable-theme 'tango) (load-theme 'tango-dark))))) (bind-key "C-c t" 'me/toggle-theme)
Windows Theme:
(when *sys/windows* (load-theme 'tango)) (when *sys/linux* (load-theme 'plastic))
line wrappings
(global-visual-line-mode) (diminish 'visual-line-mode) (use-package adaptive-wrap :ensure t :hook (visual-line-mode . adaptive-wrap-prefix-mode)) ; :init ; (when (fboundp 'adaptive-wrap-prefix-mode) ; (defun me/activate-adaptive-wrap-prefix-mode () ; "Toggle `visual-line-mode' and `adaptive-wrap-prefix-mode' simultaneously." ; (adaptive-wrap-prefix-mode (if visual-line-mode 1 -1))) ; (add-hook 'visual-line-mode-hook 'me/activate-adaptive-wrap-prefix-mode)))
line numbers
(use-package display-line-numbers :init :hook ((prog-mode org-src-mode) . display-line-numbers-mode) :config (setq-default display-line-numbers-type 'visual display-line-numbers-current-absolute t display-line-numbers-with 4 display-line-numbers-widen t))
misc
(use-package rainbow-mode :ensure t :diminish :hook ((org-mode emacs-lisp-mode) . rainbow-mode)) (use-package delight :ensure t) (show-paren-mode t) ;; show other part of brackets (setq blink-matching-paren nil) ;; not necessary with show-paren-mode, bugs out on C-s counsel-line (use-package rainbow-delimiters :ensure t :hook (prog-mode . rainbow-delimiters-mode))
Bookmarks
Usage:
-
C-x r m (bookmark-set): add bookmark
-
C-x r l (list-bookmark): list bookmarks
-
C-x r b (bookmark-jump): open bookmark
Edit bookmarks (while in bookmark file):
-
d: mark current item
-
x: delete marked items
-
r: rename current item
-
s: save changes
(use-package bookmark :custom (bookmark-default-file (concat MY--PATH_USER_LOCAL "bookmarks")))
Some windows specific stuff
(when *sys/windows* (remove-hook 'find-file-hook 'vc-refresh-state) ; (progn ; (setq gc-cons-threshold (* 511 1024 1024) ; gc-cons-percentage 0.5 ; garbage-collection-messages t ; (run-with-idle-timer 5 t #'garbage-collect)) (when (boundp 'w32-pipe-read-delay) (setq w32-pipe-read-delay 0)) (when (boundp 'w32-get-true-file-attributes) (setq w32-get-true-file-attributes nil)))
recentf
Exclude some dirs from spamming recentf
(use-package recentf :config (recentf-mode) :custom (recentf-exclude '(".*-autoloads\\.el\\'" "[/\\]\\elpa/" "COMMIT_EDITMSG\\'")) (recentf-save-file (concat MY--PATH_USER_LOCAL "recentf")) (recentf-max-menu-items 600) (recentf-max-saved-items 600))
savehist
(use-package savehist :config (savehist-mode) :custom (savehist-file (concat MY--PATH_USER_LOCAL "history")))
undo
(use-package undo-tree :ensure t :diminish undo-tree-mode :init (global-undo-tree-mode 1) :custom (undo-tree-auto-save-history nil))
ace-window
(use-package ace-window :ensure t :bind (:map global-map ("C-x o" . ace-window)))
imenu-list
A minor mode to show imenu in a sidebar. Call imenu-list-smart-toggle. Source
(use-package imenu-list :ensure t :demand t ; otherwise mode loads too late and won't work on first file it's being activated on :config (setq imenu-list-focus-after-activation t imenu-list-auto-resize t imenu-list-position 'right) :bind (:map global-map ([f9] . imenu-list-smart-toggle)) :custom (org-imenu-depth 4))
which-key
(use-package which-key :ensure t :diminish which-key-mode :defer t :hook (after-init . which-key-mode) :config (which-key-setup-side-window-bottom) (setq which-key-idle-delay 0.5))
abbrev
(use-package abbrev :diminish abbrev-mode :hook ((text-mode org-mode) . abbrev-mode) :init (setq abbrev-file-name (concat MY--PATH_USER_GLOBAL "abbrev_tables.el")) :config (if (file-exists-p abbrev-file-name) (quietly-read-abbrev-file)) (setq save-abbrevs 'silently)) ;; don't bother me with asking for abbrev saving
Evil
(use-package evil :ensure t :defer .1 ;; don't block emacs when starting, load evil immediately after startup :init (setq evil-want-C-i-jump nil) ;; prevent evil from blocking TAB in org tree expanding :config (evil-mode 1))
General (key mapper)
(use-package general :ensure t) (general-define-key :states 'normal :keymaps 'imenu-list-major-mode-map "RET" '(imenu-list-goto-entry :which-key "goto") "TAB" '(hs-toggle-hiding :which-key "collapse") "d" '(imenu-list-display-entry :which-key "show") "q" '(imenu-list-quit-window :which-key "quit"))
Vertico & Orderless
Vertico is a completion ui. Orderless orders the suggestions by recency. The package prescient orders by frequency. Vertico Github Orderless Github
;; completion ui (use-package vertico :ensure t :init (vertico-mode)) (use-package orderless :ensure t :init (setq completion-styles '(orderless basic) completion-category-defaults nil completion-category-overrides '((file (styles partial-completion)))))
Consult
(use-package consult :ensure t :bind (("C-x C-r" . consult-recent-file) ("C-x b" . consult-buffer) ("C-s" . consult-line)) :config ;; disable preview for some commands and buffers ;; and enable it by M-. ;; see https://github.com/minad/consult#use-package-example (consult-customize consult-theme :preview-key '(debounce 0.2 any) consult-ripgrep consult-git-grep consult-grep consult-bookmark consult-recent-file consult-xref consult--source-bookmark consult--source-file-register consult--source-recent-file consult--source-project-recent-file :preview-key (kbd "M-.")))
Marginalia
Github Adds additional information to the minibuffer
(use-package marginalia :ensure t :init (marginalia-mode) :bind (:map minibuffer-local-map ("M-A" . marginalia-cycle)) :custom ;; switch by 'marginalia-cycle (marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil)))
Embark
Does stuff in the minibuffer results
(use-package embark :ensure t :bind (("C-S-a" . embark-act) ("C-h B" . embark-bindings)) :init (setq prefix-help-command #'embark-prefix-help-command) :config ;; hide modeline of the embark live/completions buffers (add-to-list 'display-buffer-alist '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" nil (window-parameters (mode-line-format . none))))) (use-package embark-consult :ensure t :after (embark consult) :demand t :hook (embark-collect-mode . embark-consult-preview-minor-mode))
Helm
As an alternative if I'm not happy with selectrum & co begin_src emacs-lisp (use-package helm :ensure t :hook (helm-mode . helm-autoresize-mode) ;; :bind ;; (("M-x" . helm-M-x) ;; ("C-s" . helm-occur) ;; ("C-x C-f" . helm-find-files) ;; ("C-x C-b" . helm-buffers-list) ;; ("C-x b" . helm-buffers-list) ;; ("C-x C-r" . helm-recentf) ;; ("C-x C-i" . helm-imenu)) :config (helm-mode) :custom (helm-split-window-inside-p t) ;; open helm buffer inside current window (helm-move-to-line-cycle-in-source t) (helm-echo-input-in-header-line t) (helm-autoresize-max-height 20) (helm-autoresize-min-height 5) ) end_src
ivy / counsel / swiper
+BEGIN_SRC emacs-lisp ; (require 'ivy) (use-package ivy :ensure t :diminish (ivy-mode . "") :defer t :init (ivy-mode 1) :bind ("C-r" . ivy-resume) ;; overrides isearch-backwards binding :config (setq ivy-use-virtual-buffers t ;; recent files and bookmarks in ivy-switch-buffer ivy-height 20 ;; height of ivy window ivy-count-format "%d/%d" ;; current and total number ivy-re-builders-alist ;; regex replaces spaces with * '((t . ivy–regex-plus))))
; make counsel-M-x more descriptive (use-package ivy-rich :ensure t :defer t :init (ivy-rich-mode 1))
(use-package counsel :ensure t :defer t :bind (("M-x" . counsel-M-x) ("C-x C-f" . counsel-find-file) ("C-x C-r" . counsel-recentf) ("C-x b" . counsel-switch-buffer) ("C-c C-f" . counsel-git) ("C-c h f" . counsel-describe-function) ("C-c h v" . counsel-describe-variable) ("M-i" . counsel-imenu))) ; :map minibuffer-local-map ;;currently mapped to evil-redo ; ("C-r" . 'counsel-minibuffer-history)))
(use-package swiper :ensure t :bind ("C-s" . swiper))
(use-package ivy-hydra :ensure t) +END_SRC
misc
(use-package autorevert :diminish auto-revert-mode)
company
(use-package company :defer 1 :diminish :defer t :bind (("C-<tab>" . company-complete) :map company-active-map ("RET" . nil) ([return] . nil) ("TAB" . company-complete-selection) ([tab] . company-complete-selection) ("<right>" . company-complete-common) ("<escape>" . company-abort)) :hook (after-init . global-company-mode) (emacs-lisp-mode . me/company-elisp) (org-mode . me/company-org) :config (defun me/company-elisp () (message "set up company for elisp") (set (make-local-variable 'company-backends) '(company-capf ;; capf needs to be before yasnippet, or lsp fucks up completion for elisp company-yasnippet company-dabbrev-code company-files))) (defun me/company-org () (set (make-local-variable 'company-backends) '(company-capf company-files)) ;; (add-hook 'completion-at-point-functions 'pcomplete-completions-at-point nil t) (message "setup company for org")) (setq company-idle-delay .2 company-minimum-prefix-length 1 company-require-match nil company-show-numbers t company-tooltip-align-annotations t)) (use-package company-statistics :ensure t :after company :defer t :init (setq company-statistics-file (concat MY--PATH_USER_LOCAL "company-statistics-cache.el"));~/.emacs.d/user-dir/company-statistics-cache.el") :config (company-statistics-mode 1)) (use-package company-dabbrev :ensure nil :after company :defer t :config (setq-default company-dabbrev-downcase nil)) ;; adds a info box right of the cursor with doc of the function (use-package company-box :ensure t :diminish :defer t :hook (company-mode . company-box-mode)) ; :init ; (add-hook 'company-mode-hook 'company-box-mode))
orgmode
some notes
copy file path within emacs
Enter dired-other-window place cursor on the file M-0 w (copy absolute path) C-u w (copy relative path)
Archiving
C-c C-x C-a
To keep the subheading structure when archiving, set the properties of the superheading.
* FOO :PROPERTIES: :ARCHIVE: %s_archive::* FOO ** DONE BAR ** TODO BAZ
When moving BAR to archive, it will go to FILENAME.org_archive below the heading FOO. Other examples
org
(use-package org :ensure org-contrib :pin gnu :mode (("\.org$" . org-mode)) :diminish org-indent-mode :defer t :hook (org-mode . org-indent-mode) (org-source-mode . smartparens-mode) ; :init ; (add-hook 'org-mode-hook 'company/org-mode-hook) ; (add-hook 'org-src-mode-hook 'smartparens-mode) ; (add-hook 'org-mode-hook 'org-indent-mode) :bind (:map org-mode-map ("S-<right>" . org-shiftright) ("S-<left>" . org-shiftleft)) :config (defun me/org-company () (set (make-local-variable 'company-backends) '(company-capf company-files)) (add-hook 'completion-at-point-functions 'pcomplete-completions-at-point nil t) (message "company/org-mode-hook")) (setq org-modules (quote (org-id org-habit org-tempo ;; easy templates ))) (setq org-default-notes-file (concat MY--PATH_ORG_FILES "notes.org") org-agenda-files (list (concat MY--PATH_ORG_FILES "notes.org") (concat MY--PATH_ORG_FILES "projects.org") (concat MY--PATH_ORG_FILES "tasks.org"))) (when *sys/linux* (nconc org-agenda-files (directory-files-recursively MY--PATH_ORG_FILES_MOBILE "\\.org$"))) (setq org-id-locations-file (concat MY--PATH_USER_LOCAL ".org-id-locations") org-log-into-drawer "LOGBOOK") ;; some display customizations (setq org-pretty-entities t org-startup-truncated t org-startup-align-all-tables t) ;; some source code blocks customizations (setq org-src-window-setup 'current-window ;; C-c ' opens in current window org-src-fontify-natively t ;; use syntax highlighting in code blocks org-src-preserve-indentation t ;; no extra indentation org-src-tab-acts-natively t) (setq org-log-done 'time ;; create timestamp when task is done org-blank-before-new-entry '((heading) (plain-list-item)))) ;; prevent new line before new item
languages
Set some languages and disable confirmation for evaluating code blocks C-c C-c
+BEGIN_SRC emacs-lisp (org-babel-do-load-languages 'org-babel-load-languages '((emacs-lisp . t) (gnuplot . t) (js . t) (latex . t) (lisp . t) (python . t) (shell . t) (sqlite . t) (org . t) (R . t) (scheme . t)))
(setq org-confirm-babel-evaluate nil) +END_SRC Another setup, because org-babel-do-load-languages requires eager loading
(use-package ob-org :defer t :ensure org-contrib :commands (org-babel-execute:org org-babel-expand-body:org)) (use-package ob-python :defer t :ensure org-contrib :commands (org-babel-execute:python)) (use-package ob-js :defer t :ensure org-contrib :commands (org-babel-execute:js)) (use-package ob-shell :defer t :ensure org-contrib :commands (org-babel-execute:sh org-babel-expand-body:sh org-babel-execute:bash org-babel-expand-body:bash)) (use-package ob-emacs-lisp :defer t :ensure org-contrib :commands (org-babel-execute:emacs-lisp org-babel-expand-body:emacs-lisp)) (use-package ob-lisp :defer t :ensure org-contrib :commands (org-babel-execute:lisp org-babel-expand-body:lisp)) (use-package ob-gnuplot :defer t :ensure org-contrib :commands (org-babel-execute:gnuplot org-babel-expand-body:gnuplot)) (use-package ob-sqlite :defer t :ensure org-contrib :commands (org-babel-execute:sqlite org-babel-expand-body:sqlite)) (use-package ob-latex :defer t :ensure org-contrib :commands (org-babel-execute:latex org-babel-expand-body:latex)) (use-package ob-R :defer t :ensure org-contrib :commands (org-babel-execute:R org-babel-expand-body:R)) (use-package ob-scheme :defer t :ensure org-contrib :commands (org-babel-execute:scheme org-babel-expand-body:scheme))
habits
(require 'org-habit) ;;TODO Lösung ohne require finden, scheint mir nicht ideal zu sein, nur um ein org-modul zu aktivieren ;; (add-to-list 'org-modules "org-habit") (setq org-habit-graph-column 80 org-habit-preceding-days 30 org-habit-following-days 7 org-habit-show-habits-only-for-today nil)
org-agenda
Custom keywords, depending on environment
(when *work_remote* (setq org-todo-keywords '((sequence "OPEN" "TODO" "UNCLEAR" "|" "DONE" "IMPOSSIBLE" "CANCELLED"))))
Add some key bindings
(bind-key "C-c l" 'org-store-link) (bind-key "C-c c" 'org-capture) (bind-key "C-c a" 'org-agenda)
Sort agenda by deadline and priority
(setq org-agenda-sorting-strategy (quote ((agenda deadline-up priority-down) (todo priority-down category-keep) (tags priority-down category-keep) (search category-keep))))
Customize the org agenda
(defun me--org-skip-subtree-if-priority (priority) "Skip an agenda subtree if it has a priority of PRIORITY. PRIORITY may be one of the characters ?A, ?B, or ?C." (let ((subtree-end (save-excursion (org-end-of-subtree t))) (pri-value (* 1000 (- org-lowest-priority priority))) (pri-current (org-get-priority (thing-at-point 'line t)))) (if (= pri-value pri-current) subtree-end nil))) (setq org-agenda-custom-commands '(("c" "Simple agenda view" ((tags "PRIORITY=\"A\"" ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) (org-agenda-overriding-header "Hohe Priorität:"))) (agenda "" ((org-agenda-span 7) (org-agenda-start-on-weekday nil) (org-agenda-overriding-header "Nächste 7 Tage:"))) (alltodo "" ((org-agenda-skip-function '(or (me--org-skip-subtree-if-priority ?A) (org-agenda-skip-if nil '(scheduled deadline)))) (org-agenda-overriding-header "Sonstige Aufgaben:")))))))
TODO
org-caldav
Vorerst deaktiviert, Nutzen evtl. nicht vorhanden
;;(use-package org-caldav ;; :ensure t ;; :config ;; (setq org-caldav-url "https://nextcloud.cloudsphere.duckdns.org/remote.php/dav/calendars/marc" ;; org-caldav-calendar-id "orgmode" ;; org-caldav-inbox (expand-file-name "~/Archiv/Organisieren/caldav-inbox") ;; org-caldav-files (concat MY--PATH_ORG_FILES "tasks")))
journal
Ggf. durch org-roam-journal ersetzen
(use-package org-journal :if *sys/linux* :ensure t :defer t :config ;; feels hacky, but this way compiler error "assignment to free variable" disappears (when (and (boundp 'org-journal-dir) (boundp 'org-journal-enable-agenda-integration)) (setq org-journal-dir MY--PATH_ORG_JOURNAl org-journal-enable-agenda-integration t)))
org-roam
Github Um Headings innerhalb einer Datei zu verlinken:
-
org-id-get-create im Heading,
-
org-roam-node-insert in der verweisenden Datei
Bei Problemen wie unique constraint org-roam-db-clear-all org-roam-db-sync
(use-package org-roam :ensure t :defer t :init (setq org-roam-v2-ack t) :config (require 'org-roam-dailies) ;; ensure the keymap is available (org-roam-db-autosync-mode) :custom (org-roam-directory MY--PATH_ORG_ROAM) (org-roam-completion-everywhere t) (org-roam-capture-templates '(("d" "default" plain "%?" :if-new (file+head "notes/%<%Y%m%d%H%M%S>-${plug}.org" "#+title: ${title}\n") :unnarrowed t) ("n" "ndefault" plain "%?" :if-new (file+head "ideas/%<%Y%m%d%H%M%S>-${plug}.org" "#+title: ${title}\n") :unnarrowed t) )) :bind (("C-c n l" . org-roam-buffer-toggle) ("C-c n f" . org-roam-node-find) ("C-c n i" . org-roam-node-insert) :map org-mode-map ("C-M-i" . completion-at-point) :map org-roam-dailies-map ("Y" . org-roam-dailies-capture-yesterday) ("T" . org-roam-dailies-capture-tomorrow)) :bind-keymap ("C-c n d" . org-roam-dailies-map)) (use-package org-roam :if (eq *sys/windows* t) :init (setq exec-path (append exec-path '("P:/Tools/sqlite"))) (use-package emacsql-sqlite3 :ensure t :init (setq emacsql-sqlite3-binary "P:/Tools/sqlite/sqlite3.exe")) :config (add-to-list 'org-roam-capture-templates '("t" "telephone call" plain "%?" :if-new (file+head "telephone/%<%Y%m%d%H%M%S>-${plug}.org" "#+title: CALL %<%Y-%m-%d %H:%M> ${title}\n") :unnarrowed t) ("p" "new Project" plain "** ${title}\n :PROPERTIES:\n :ID: %(org-id-uuid)\n:END:\n%u\n" :target (file+olp "projects.org" ("Active"))) ("s" "Sicherheitenmeldung" plain "*** TODO [#A] Sicherheitenmeldung ${title}\n :PROPERTIES:\n :ID: %(org-id-uuid)\n:END:\n%u\n" :target (file+olp "tasks.org" ("Todos" "Sicherheitenmeldungen"))) ("m" "Monatsbericht" plain "*** TODO [#A] Monatsbericht ${title}\n :PROPERTIES:\n :ID: %(org-id-uuid)\n:END:\n%u\n" :target (file+olp "tasks.org" ("Todos" "Monatsberichte")))) :custom (org-roam-database-connector 'sqlite3))
TODO Verzeichnis außerhalb roam zum Archivieren (u.a. für erledigte Monatsmeldungen etc.)
Programming
misc
(use-package eldoc :diminish eldoc-mode :defer t)
Magit / Git
Little crash course in magit:
-
magit-init to init a git project
-
magit-status (C-x g) to call the status window
In status buffer:
-
s stage files
-
u unstage files
-
U unstage all files
-
a apply changes to staging
-
c c commit (type commit message, then C-c C-c to commit)
-
b b switch to another branch
-
P u git push
-
F u git pull
(use-package magit :ensure t :defer t :init ; set git-path in work environment (if (string-equal user-login-name "POH") (setq magit-git-executable "P:/Tools/Git/bin/git.exe") ) :bind (("C-x g" . magit-status)))
LSP
Configuration for the language server protocol ACHTUNG Dateipfad muss absolut sein, symlink im Pfad führt zumindest beim ersten Start zu Fehlern beim lsp Sobald der lsp einmal lief, kann zukünftig der symlink-Pfad genommen werden. Getestet wurde die funktionierende Datei selbst und neu erstellte Dateien im selben Pfad. TODO Unterverzeichnisse wurden noch nicht getestet
(setq read-process-output-max (* 1024 1024)) ;; support reading large blobs of data for LSP's sake (use-package lsp-mode :defer t :commands (lsp lsp-execute-code-action) :custom (lsp-auto-guess-root nil) (lsp-prefer-flymake nil) ; use flycheck instead (lsp-prefer-capf t) (lsp-file-watch-threshold 5000) (lsp-print-performance t) (lsp-log-io nil) ; enable log only for debug (lsp-enable-folding t) ; default, maybe evil-matchit instead for performance? (lsp-diagnostics-modeline-scope :project) (lsp-enable-file-watchers nil) (lsp-session-file (concat MY--PATH_USER_LOCAL "lsp-session")) (lsp-eslint-library-choices-file (concat MY--PATH_USER_LOCAL "lsp-eslint-choices")) :bind (:map lsp-mode-map ("C-c C-f" . lsp-format-buffer)) :hook (((python-mode js-mode js2-mode typescript-mode web-mode ) . lsp-deferred) (lsp-mode . lsp-enable-which-key-integration) (lsp-mode . lsp-diagnostics-modeline-mode) (web-mode . #'lsp-flycheck-enable)) ;; enable flycheck-lsp for web-mode locally :config (setq lsp-diagnostics-package :none)) ; disable flycheck-lsp for most modes ;; (add-hook 'web-mode-hook #'lsp-flycheck-enable)) ; enable flycheck-lsp for web-mode locally (use-package lsp-ui :after lsp-mode :ensure t :defer t :diminish :commands lsp-ui-mode :config (setq lsp-ui-doc-enable t lsp-ui-doc-header t lsp-ui-doc-include-signature t lsp-ui-doc-position 'top lsp-ui-doc-border (face-foreground 'default) lsp-ui-sideline-enable t lsp-ui-sideline-ignore-duplicate t lsp-ui-sideline-show-code-actions nil) (when *sys/gui* (setq lsp-ui-doc-use-webkit t)) ;; workaround hide mode-line of lsp-ui-imenu buffer (defadvice lsp-ui-imenu (after hide-lsp-ui-imenu-mode-line activate) (setq mode-line-format nil))) ;;NO LONGER SUPPORTED, USE company-capf / completion-at-point ;(use-package company-lsp ; :requires company ; :defer t ; :ensure t ; :config ; ;;disable client-side cache because lsp server does a better job ; (setq company-transformers nil ; company-lsp-async t ; company-lsp-cache-candidates nil))
yasnippet
For useful snippet either install yasnippet-snippets or get them from here Github
(use-package yasnippet :ensure t :defer t :diminish yas-minor-mode :config (setq yas-snippet-dirs (list (concat MY--PATH_USER_GLOBAL "snippets"))) (yas-global-mode t) (yas-reload-all) (unbind-key "TAB" yas-minor-mode-map) (unbind-key "<tab>" yas-minor-mode-map))
hippie expand
With hippie expand I am able to use yasnippet and emmet at the same time with the same key.
(use-package hippie-exp :defer t :bind ("C-<return>" . hippie-expand) :config (setq hippie-expand-try-functions-list '(yas-hippie-try-expand emmet-expand-line)))
flycheck
(use-package flycheck :ensure t :hook ((css-mode . flycheck-mode) (emacs-lisp-mode . flycheck-mode) (python-mode . flycheck-mode)) :defer 1.0 :init (setq flycheck-emacs-lisp-load-path 'inherit) :config (setq-default flycheck-check-synta-automatically '(save mode-enabled) flycheck-disable-checkers '(emacs-lisp-checkdoc) eldoc-idle-delay .1 ;; let eldoc echo faster than flycheck flycheck-display-errors-delay .3)) ;; this way any errors will override eldoc messages
Projectile
Manage projects and jump quickly between its files
(use-package projectile :ensure t ; :defer 1.0 :diminish :bind (("C-c p" . projectile-command-map)) ;:preface :init (setq-default projectile-cache-file (concat MY--PATH_USER_LOCAL "projectile-cache") projectile-known-projects-file (concat MY--PATH_USER_LOCAL "projectile-bookmarks")) :config (projectile-mode) ; (add-hook 'projectile-after-switch-project-hook #'set-workon_home) (setq-default projectile-completion-system 'ivy projectile-enable-caching t projectile-mode-line '(:eval (projectile-project-name)))) ;; requires ripgrep on system for rg functions ;(use-package counsel-projectile ; :ensure t ; :config (counsel-projectile-mode) (setq ivy-use-virtual-buffers t ;; recent files and bookmarks in ivy-switch-buffer) ;(use-package helm-projectile ; :ensure t ; :hook ; (projectile-mode . helm-projectile))
smartparens
(use-package smartparens :ensure t :diminish smartparens-mode :bind (:map smartparens-mode-map ("C-M-f" . sp-forward-sexp) ("C-M-b" . sp-backward-sexp) ("C-M-a" . sp-backward-down-sexp) ("C-M-e" . sp-up-sexp) ("C-M-w" . sp-copy-sexp) ("M-k" . sp-kill-sexp) ("C-M-<backspace>" . sp-slice-sexp-killing-backward) ("C-S-<backspace>" . sp-slice-sexp-killing-around) ("C-]" . sp-select-next-thing-exchange)) :config (setq sp-show-pair-from-inside nil sp-escape-quotes-after-insert nil) (require 'smartparens-config))
lisp
(use-package elisp-mode :defer t)
web
apt install npm sudo npm install -g vscode-html-languageserver-bin evtl alternativ typescript-language-server?
Unter Windows: Hier runterladen: https://nodejs.org/dist/latest/ und in ein Verzeichnis entpacken. Optional: PATH erweitern unter Windows (so kann exec-path-from-shell den Pfad ermitteln): PATH=P:\path→\node;%path%
(use-package web-mode :ensure t :defer t :mode ("\\.phtml\\'" "\\.tpl\\.php\\'" "\\.djhtml\\'" "\\.[t]?html?\\'") :hook (web-mode . smartparens-mode) :init (if *work_remote* (setq exec-path (append exec-path '("P:/Tools/node")))) :config (setq web-mode-enable-auto-closing t web-mode-enable-auto-pairing t))
Emmet offers snippets, similar to yasnippet. Default completion is C-j Github
(use-package emmet-mode :ensure t :defer t :hook ((web-mode . emmet-mode) (css-mode . emmet-mode)) :config (unbind-key "C-<return>" emmet-mode-keymap))
JavaScript
npm install -g typescript-language-server typescript maybe only typescript? npm install -g prettier
(use-package rjsx-mode :ensure t :mode ("\\.js\\'" "\\.jsx'")) ; :config ; (setq js2-mode-show-parse-errors nil ; js2-mode-show-strict-warnings nil ; js2-basic-offset 2 ; js-indent-level 2) ; (setq-local flycheck-disabled-checkers (cl-union flycheck-disable-checkers ; '(javascript-jshint)))) ; jshint doesn"t work for JSX (use-package tide :ensure t :after (rjsx-mode company flycheck) ; :hook (rjsx-mode . setup-tide-mode) :config (defun setup-tide-mode () "Setup function for tide." (interactive) (tide-setup) (flycheck-mode t) (setq flycheck-check-synta-automatically '(save mode-enabled)) (tide-hl-identifier-mode t))) ;; needs npm install -g prettier (use-package prettier-js :ensure t :after (rjsx-mode) :defer t :diminish prettier-js-mode :hook ((js2-mode rsjx-mode) . prettier-js-mode))
YAML
(use-package yaml-mode :if *sys/linux* :ensure t :defer t :mode ("\\.yml$" . yaml-mode))
R
(use-package ess :ensure t :defer t :init (if *work_remote* (setq exec-path (append exec-path '("P:/Tools/R/bin/x64")) org-babel-R-command "P:/Tools/R/bin/x64/R --slave --no-save")))
Python
Systemseitig muss python-language-server installiert sein: apt install python3-pip python3-setuptools python3-wheel apt install build-essential python3-dev pip3 install 'python-language-server[all]'
Statt obiges: npm install -g pyright
für andere language servers https://github.com/emacs-lsp/lsp-mode#install-language-server
;(use-package lsp-python-ms ; :if *sys/linux* ; :ensure t ; :defer t ; :custom (lsp-python-ms-auto-install-server t)) (use-package lsp-pyright :ensure t :after lsp-mode :defer t :hook (python-mode . (lambda () (require 'lsp-pyright) (lsp-deferred))) ; :custom ; (lsp-pyright-auto-import-completions nil) ; (lsp-pyright-typechecking-mode "off") ) (use-package python :if *sys/linux* :delight "π " :defer t :bind (("M-[" . python-nav-backward-block) ("M-]" . python-nav-forward-block))) (use-package pyvenv :if *sys/linux* :ensure t :defer t :after python :hook ((python-mode . pyvenv-mode) (python-mode . (lambda () (if-let ((pyvenv-directory (find-pyvenv-directory (buffer-file-name)))) (pyvenv-activate pyvenv-directory)) (lsp)))) :custom (pyvenv-default-virtual-env-name "env") (pyvenv-mode-line-indicator '(pyvenv-virtual-env-name ("[venv:" pyvenv-virtual-env-name "]"))) :preface (defun find-pyvenv-directory (path) "Check if a pyvenv directory exists." (cond ((not path) nil) ((file-regular-p path) (find-pyvenv-directory (file-name-directory path))) ((file-directory-p path) (or (seq-find (lambda (path) (file-regular-p (expand-file-name "pyvenv.cfg" path))) (directory-files path t)) (let ((parent (file-name-directory (directory-file-name path)))) (unless (equal parent path) (find-pyvenv-directory parent)))))))) ;; manage multiple python version ;; needs to be installed on system ; (use-package pyenv-mode ; :ensure t ; :after python ; :hook ((python-mode . pyenv-mode) ; (projectile-switch-project . projectile-pyenv-mode-set)) ; :custom (pyenv-mode-set "3.8.5") ; :preface ; (defun projectile-pyenv-mode-set () ; "Set pyenv version matching project name." ; (let ((project (projectile-project-name))) ; (if (member project (pyenv-mode-versions)) ; (pyenv-mode-set project) ; (pyenv-mode-unset))))) ;)
beancount
Installation
sudo su cd /opt python3 -m venv beancount source ./beancount/bin/activate pip3 install wheel pip3 install beancount sleep 100 echo "shell running!" deactivate
(use-package beancount :if *sys/linux* :load-path "user-global/elisp" ; :ensure t :defer t :mode ("\\.beancount$" . beancount-mode) :hook (beancount-mode . me/beancount-company) :init (add-hook 'beancount-mode-hook 'company/beancount-mode-hook) :config (defun me/beancount-company () (set (make-local-variable 'company-backends) '(company-beancount))) (setq beancount-filename-main "/home/marc/Archiv/Finanzen/Transaktionen/transactions.beancount"))
To support org-babel, check if it can find the symlink to ob-beancount.el
orgpath=`find /home/marc/.emacs.d/elpa/ -type d -name "org-plus*" -print` beansym="$orgpath/ob-beancount.el bean="/home/marc/Archiv/Programmierprojekte/Lisp/beancount-mode/ob-beancount.el" if [ -h "$beansym" ] then echo "$beansym found" elif [ -e "$bean" ] then echo "creating symlink" ln -s "$bean" "$beansym" else echo "$bean not found, symlink creation aborted" fi
Fava is strongly recommended.
cd /opt python3 -m venv fava source ./fava/bin/activate pip3 install wheel pip3 install fava deactivate
Start fava with fava my_file.beancount
It is accessable on this URL: Fava Beancount-mode can start fava and open the URL right away.
Stuff after everything else
Set garbage collector to a smaller value to let it kick in faster. Maybe a problem on Windows?
;(setq gc-cons-threshold (* 2 1000 1000))