#+TITLE: Emacs configuration file #+AUTHOR: Marc #+BABEL: :cache yes #+PROPERTY: header-args :tangle yes * 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 :PROPERTIES: :ID: a14d7c89-24ea-41ae-b185-944bab49aa02 :END: Emacs variables are dynamically scoped. That's unusual for most languages, so disable it here, too #+begin_src emacs-lisp ;;; init.el --- -*- lexical-binding: t -*- #+end_src * First start :PROPERTIES: :ID: 1c24d48e-0124-4a0b-8e78-82e4c531e818 :END: When pulling the repository the first time, an initial init.el needs to be setup. After start it will replace itself with the configuration from init.org #+BEGIN_SRC emacs-lisp :tangle no (require 'org') (find-file (concat user-emacs-directory "init.org")) (org-babel-tangle) (load-file (concat user-emacs-directory "init.el")) (byte-compile-file (concat user-emacs-directory "init.el")) #+END_SRC This function updates init.el whenever changes in init.org are made. The update will be active after saving. #+BEGIN_SRC emacs-lisp (defun me/tangle-init () "If the current buffer is 'init.org', the code blocks are tangled, and the tangled file is compiled." (when (equal (buffer-file-name) (expand-file-name (concat user-emacs-directory "init.org"))) ;; avoid running hooks (let ((prog-mode-hook nil)) (org-babel-tangle) (byte-compile-file (concat user-emacs-directory "init.el")) (load-file user-init-file)))) (add-hook 'after-save-hook 'me/tangle-init) #+END_SRC 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/ #+begin_src emacs-lisp (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)) #+end_src #+BEGIN_SRC emacs-lisp (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 '("org" . "https://orgmode.org/elpa/") t) ; fix for bug 34341 (setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3") (when (< emacs-major-version 27) (package-initialize)) #+END_SRC #+BEGIN_SRC emacs-lisp (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (eval-when-compile (require 'use-package)) (require 'bind-key) (setq use-package-verbose nil) (use-package diminish :ensure t) #+END_SRC 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 #+begin_src emacs-lisp (setq byte-compile-warnings '(cl-functions)) #+end_src * Default settings :PROPERTIES: :ID: 3512d679-d111-4ccd-8372-6fc2acbc0374 :END: #+BEGIN_SRC emacs-lisp (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* (string-equal (system-name) "PMTS01") "Is emacs running at work on the remote system?") #+END_SRC #+BEGIN_SRC emacs-lisp (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/")) (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/")) (setq recentf-save-file (concat MY--PATH_USER_LOCAL "recentf")) ;; exclude some dirs from spamming recentf (use-package recentf :config (recentf-mode) (setq recentf-exclude '(".*-autoloads\\.el\\" "[/\\]\\.elpa/"))) (setq custom-file (concat MY--PATH_USER_LOCAL "custom.el")) ;; don't spam init.e with saved customization settings (setq abbrev-file-name (concat MY--PATH_USER_GLOBAL "abbrev_defs")) (setq backup-directory-alist `((".*" . ,temporary-file-directory))) (setq auto-save-file-name-transforms `((".*" ,temporary-file-directory))) (setq save-abbrevs 'silently) ;; don't bother me with asking for abbrev saving (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 (save-place-mode 1) ;; saves position in file when it's closed (setq save-place-forget-unreadable-files nil) ;; checks if file is readable before saving position (set-charset-priority 'unicode) (setq locale-coding-system 'utf-8) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (set-selection-coding-system 'utf-8) (setq default-process-coding-system '(utf-8-unix . utf-8-unix)) (if *sys/windows* (prefer-coding-system 'utf-8-dos) (prefer-coding-system 'utf-8)) (blink-cursor-mode -1) ;; turn off blinking cursor (column-number-mode t) (setq uniquify-buffer-name-style 'forward) (setq-default indent-tabs-mode nil) ;; avoid tabs in place of multiple spaces (they look bad in tex) (setq-default indicate-empty-lines t) ;; show empty lines (setq scroll-margin 5 ;; smooth scrolling scroll-conservatively 10000 scroll-preserve-screen-position 1 scroll-step 1) (global-hl-line-mode t) ;; highlight current line (menu-bar-mode 0) ;; disable menu bar (tool-bar-mode 0) ;; disable tool bar (scroll-bar-mode 0) ;; disable scroll bar #+END_SRC 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 #+begin_src emacs-lisp (use-package bookmark :custom (bookmark-default-file (concat MY--PATH_USER_LOCAL "bookmarks"))) #+end_src Some windows specific stuff #+BEGIN_SRC emacs-lisp (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))) #+END_SRC * visuals ** Font :PROPERTIES: :ID: dc8eb670-e6bb-4bfb-98f0-aae1860234fb :END: #+BEGIN_SRC emacs-lisp (when *sys/linux* (set-face-font 'default "Hack-10")) (when *work_remote* (set-face-font 'default "Lucida Sans Typewriter-11")) #+END_SRC ** Themes :PROPERTIES: :ID: 9ccf37c0-6837-43cb-bed8-5a353799d8b1 :END: #+BEGIN_SRC emacs-lisp (defun my/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" 'my/toggle-theme) #+END_SRC Windows Theme: #+BEGIN_SRC emacs-lisp (when *sys/windows* (load-theme 'tango)) (when *sys/linux* (load-theme 'plastic)) #+END_SRC ** line wrappings :PROPERTIES: :ID: 14ae933e-2941-4cc3-82de-38f90f91bfd3 :END: #+BEGIN_SRC emacs-lisp (global-visual-line-mode) (diminish 'visual-line-mode) (use-package adaptive-wrap :ensure t :config (add-hook 'visual-line-mode-hook #'adaptive-wrap-prefix-mode)) ; :init ; (when (fboundp 'adaptive-wrap-prefix-mode) ; (defun my/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 'my/activate-adaptive-wrap-prefix-mode))) #+END_SRC ** line numbers :PROPERTIES: :ID: 7b969436-98c9-4b61-ba7a-9fb22c9781ad :END: #+BEGIN_SRC emacs-lisp (use-package display-line-numbers :init (add-hook 'prog-mode-hook 'display-line-numbers-mode) (add-hook 'org-src-mode-hook '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)) ; (add-hook 'emacs-lisp-mode-hook 'display-line-numbers-mode) #+END_SRC ** misc :PROPERTIES: :ID: a2873138-16ee-4990-89a2-26eab778ea74 :END: #+BEGIN_SRC emacs-lisp (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 (use-package rainbow-delimiters :ensure t :hook ((prog-mode . rainbow-delimiters-mode))) #+END_SRC * undo :PROPERTIES: :ID: d57621b2-5472-4c89-a520-b4133db0b9af :END: #+BEGIN_SRC emacs-lisp (use-package undo-tree :ensure t :diminish undo-tree-mode :init (global-undo-tree-mode 1)) #+END_SRC * ace-window #+begin_src emacs-lisp (use-package ace-window :ensure t :bind (:map global-map ("C-x o" . ace-window))) #+end_src * imenu-list :PROPERTIES: :ID: 0ae27ec9-5d77-43cf-ac76-5e12cc959046 :END: A minor mode to show imenu in a sidebar. Call imenu-list-smart-toggle. [[https://github.com/bmag/imenu-list][Source]] #+BEGIN_SRC emacs-lisp (use-package imenu-list :ensure t :defer t :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) ) #+END_SRC * which-key :PROPERTIES: :ID: a880f079-b3a3-4706-bf1e-5f6c680101f1 :END: #+BEGIN_SRC emacs-lisp (use-package which-key :ensure t :diminish which-key-mode :defer t :config (which-key-mode) (which-key-setup-side-window-right-bottom) (which-key-setup-minibuffer) (setq which-key-idle-delay 0.5)) #+END_SRC * Evil :PROPERTIES: :ID: 80ca70e2-a146-46db-b581-418d655dc1fc :END: #+BEGIN_SRC emacs-lisp (use-package evil :ensure t :defer .1 ;; don't block emacs when starting, load evil immediately after startup :config (evil-mode 1)) #+END_SRC * General (key mapper) :PROPERTIES: :ID: a20f183f-d41a-4dff-bc37-3bc4e25c8036 :END: #+BEGIN_SRC emacs-lisp (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")) #+END_SRC * ivy / counsel / swiper :PROPERTIES: :ID: 55c74ba9-7761-4545-8ddd-087d6ee33e4b :END: #+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 #+begin_src emacs-lisp (use-package autorevert :diminish auto-revert-mode) #+end_src * company :PROPERTIES: :ID: 944563b6-b04a-44f2-9b21-a6a3e200867c :END: #+BEGIN_SRC emacs-lisp (use-package company :defer 1 :diminish :defer t :bind (("C-" . company-complete) :map company-active-map ("RET" . nil) ([return] . nil) ("TAB" . company-complete-selection) ([tab] . company-complete-selection) ("" . company-complete-common)) :hook (after-init . global-company-mode) :config (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)) (use-package company-box :ensure t :diminish :defer t :init (add-hook 'company-mode-hook 'company-box-mode)) #+END_SRC * orgmode ** org :PROPERTIES: :ID: b89d7639-080c-4168-8884-bd5d8965f466 :END: #+BEGIN_SRC emacs-lisp (use-package org :ensure org-plus-contrib :mode (("\.org$" . org-mode)) :diminish org-indent-mode :defer t :hook (org-mode . my/org-company) (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) :config (defun my/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 #+END_SRC ** languages :PROPERTIES: :ID: ad3af718-d0db-448c-9f75-eb9e250c2862 :END: 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 #+begin_src emacs-lisp (use-package ob-org :defer t :ensure org-plus-contrib :commands (org-babel-execute:org org-babel-expand-body:org)) (use-package ob-python :defer t :ensure org-plus-contrib :commands (org-babel-execute:python)) (use-package ob-js :defer t :ensure org-plus-contrib :commands (org-babel-execute:js)) (use-package ob-shell :defer t :ensure org-plus-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-plus-contrib :commands (org-babel-execute:emacs-lisp org-babel-expand-body:emacs-lisp)) (use-package ob-lisp :defer t :ensure org-plus-contrib :commands (org-babel-execute:lisp org-babel-expand-body:lisp)) (use-package ob-gnuplot :defer t :ensure org-plus-contrib :commands (org-babel-execute:gnuplot org-babel-expand-body:gnuplot)) (use-package ob-sqlite :defer t :ensure org-plus-contrib :commands (org-babel-execute:sqlite org-babel-expand-body:sqlite)) (use-package ob-latex :defer t :ensure org-plus-contrib :commands (org-babel-execute:latex org-babel-expand-body:latex)) (use-package ob-R :defer t :ensure org-plus-contrib :commands (org-babel-execute:R org-babel-expand-body:R)) (use-package ob-scheme :defer t :ensure org-plus-contrib :commands (org-babel-execute:scheme org-babel-expand-body:scheme)) #+end_src ** habits :PROPERTIES: :ID: fcc91d0a-d040-4910-b2cf-3221496a3842 :END: #+BEGIN_SRC emacs-lisp (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) #+END_SRC ** org-id :PROPERTIES: :ID: c4017c45-d650-410c-8bd4-bc3cf42bbbb9 :END: Currently it causes some debugger errors "not a standard org time string", so it's disabled #+BEGIN_SRC emacs-lisp ;; (use-package org-id ;; :config ;; (setq org-id-link-to-org-use-id t) ;; (org-id-update-id-locations)) ;; update id file .org-id-locations on startup #+END_SRC ** org-agenda :PROPERTIES: :ID: 03b67efb-4179-41e5-bc2e-c472b13f8be6 :END: Custom keywords, depending on environment #+BEGIN_SRC emacs-lisp (when *work_remote* (setq org-todo-keywords '((sequence "OPEN" "TODO" "UNCLEAR" "|" "DONE" "IMPOSSIBLE" "CANCELLED")))) #+END_SRC Add some key bindings #+BEGIN_SRC emacs-lisp (bind-key "C-c l" 'org-store-link) (bind-key "C-c c" 'org-capture) (bind-key "C-c a" 'org-agenda) #+END_SRC Sort agenda by deadline and priority #+BEGIN_SRC emacs-lisp (setq org-agenda-sorting-strategy (quote ((agenda deadline-up priority-down) (todo priority-down category-keep) (tags priority-down category-keep) (search category-keep)))) #+END_SRC Customize the org agenda #+BEGIN_SRC emacs-lisp (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:"))))))) #+END_SRC ** *TODO* org-super-agenda ** org-caldav :PROPERTIES: :ID: 6bd24369-0d04-452f-85a0-99914dfb74ff :END: Vorerst deaktiviert, Nutzen evtl. nicht vorhanden #+BEGIN_SRC emacs-lisp ;;(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"))) #+END_SRC ** journal :PROPERTIES: :ID: a1951e18-d862-4198-9652-016e979053c8 :END: [[https://github.com/bastibe/org-journal][Source]] #+BEGIN_SRC emacs-lisp (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))) #+END_SRC * Programming ** misc #+begin_src emacs-lisp (use-package eldoc :diminish eldoc-mode :defer t) #+end_src ** Magit / Git :PROPERTIES: :ID: d3589460-317f-40f6-9056-053be9ba3217 :END: 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 #+BEGIN_SRC emacs-lisp (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:/Eigene Dateien/Tools/Git/bin/git.exe") ) :bind (("C-x g" . magit-status))) #+END_SRC ** LSP :PROPERTIES: :ID: 06ad00e0-44a6-4bfb-ba6f-b1672811e053 :END: 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 #+BEGIN_SRC emacs-lisp (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-file-watch-threshold 5000) (lsb-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) :bind (:map lsp-mode-map ("C-c C-f" . lsp-format-buffer)) :hook (((python-mode js-mode js2-mode typescript-mode web-mode ) . lsp) (lsp-mode . lsp-enable-which-key-integration) (lsp-mode . lsp-diagnostics-modeline-mode)) :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 nil 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))) (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)) #+END_SRC ** yasnippet :PROPERTIES: :ID: 935d89ef-645e-4e92-966f-2fe3bebb2880 :END: For useful snippet either install yasnippet-snippets or get them from here [[https://github.com/AndreaCrotti/yasnippet-snippets][Github]] #+begin_src emacs-lisp (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 "" yas-minor-mode-map)) #+end_src ** hippie expand :PROPERTIES: :ID: c55245bc-813d-4816-a0ca-b4e2e793e28b :END: With hippie expand I am able to use yasnippet and emmet at the same time with the same key. #+begin_src emacs-lisp (use-package hippie-exp :defer t :bind ("C-" . hippie-expand) :config (setq hippie-expand-try-functions-list '(yas-hippie-try-expand emmet-expand-line))) #+end_src ** flycheck :PROPERTIES: :ID: 3d8f2547-c5b3-46d0-91b0-9667f9ee5c47 :END: #+BEGIN_SRC emacs-lisp (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 #+END_SRC ** Projectile :PROPERTIES: :ID: a90329fd-4d36-435f-8308-a2771ac4c320 :END: Manage projects and jump quickly between its files #+BEGIN_SRC emacs-lisp (defun set-workon_home() (setenv "WORKON_HOME" (projectile-project-root)) (message "set workon_home")) (use-package projectile :ensure t ; :defer 1.0 :diminish ; :hook (projectile-after-switch-project . (lambda () ; (set-workon_home) ; (message "set workon_home"))) ;; for pyvenv to auto activate environment ; :hook (projectile-after-switch-project #'set-workon_home) :bind-keymap ("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 t) ; (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)) #+END_SRC ** smartparens :PROPERTIES: :ID: 997ec416-33e6-41ed-8c7c-75a7bc47d285 :END: #+BEGIN_SRC emacs-lisp (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-" . sp-slice-sexp-killing-backward) ("C-S-" . 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)) #+END_SRC ** lisp :PROPERTIES: :ID: a2bc3e08-b203-49d3-b337-fb186a14eecb :END: #+BEGIN_SRC emacs-lisp (use-package elisp-mode :defer t :hook (elisp-mode . my/elisp-company) :config (defun my/elisp-company () (set (make-local-variable 'company-backends) '(company-capf company-files)))) #+END_SRC ** web :PROPERTIES: :ID: c0b0b4e4-2162-429f-b80d-6e5334b1290e :END: 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\to\node;%path% #+BEGIN_SRC emacs-lisp (use-package web-mode :ensure t :defer t :mode ("\\.phtml\\'" "\\.tpl\\.php\\'" "\\.djhtml\\'" "\\.[t]?html?\\'") :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) (add-hook 'web-mode-hook 'smartparens-mode)) #+END_SRC Emmet offers snippets, similar to yasnippet. Default completion is C-j [[https://github.com/smihica/emmet-mode#usage][Github]] #+begin_src emacs-lisp (use-package emmet-mode :ensure t :defer t :hook ((web-mode . emmet-mode) (css-mode . emmet-mode)) :config (unbind-key "C-" emmet-mode-keymap)) #+end_src *** JavaScript npm install -g typescript-language-server typescript maybe only typescript? #+begin_src emacs-lisp (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 add-node-modules-path ; :ensure t ; :defer t ; :hook (((js2-mode rsjx-mode) . add-node-modules-path))) (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))) (use-package prettier-js :ensure t :after (rjsx-mode) :defer t :diminish prettier-js-mode :hook (((js2-mode rsjx-mode) . prettier-js-mode))) #+end_src ** YAML :PROPERTIES: :ID: 95413247-04d5-4e02-8431-06c162ec8f3b :END: #+begin_src emacs-lisp (use-package yaml-mode :if *sys/linux* :ensure t :defer t :mode ("\\.yml$" . yaml-mode)) #+end_src ** R #+BEGIN_SRC emacs-lisp (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"))) #+END_SRC ** Python :PROPERTIES: :ID: 8c76fcd1-c57c-48ab-8af0-aa782de6337f :END: 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]' für andere language servers https://github.com/emacs-lsp/lsp-mode#install-language-server #+BEGIN_SRC emacs-lisp (use-package lsp-python-ms :if *sys/linux* :ensure t :defer t :custom (lsp-python-ms-auto-install-server t)) (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))))) ;) #+END_SRC * beancount ** Installation :PROPERTIES: :ID: 2c329043-b7a9-437d-a5cf-f2ad6514be91 :END: #+BEGIN_SRC shell sudo su cd /opt python3 -m venv beancount source ./beancount/bin/activate pip3 install wheel pip3 install beancount sleep 100 echo "shell running!" deactivate #+END_SRC #+BEGIN_SRC emacs-lisp (use-package beancount :if *sys/linux* :load-path "user-global/elisp" ; :ensure t :defer t :mode ("\\.beancount$" . beancount-mode) :hook (beancount-mode . my/beancount-company) :init (add-hook 'beancount-mode-hook 'company/beancount-mode-hook) :config (defun my/beancount-company () (set (make-local-variable 'company-backends) '(company-beancount))) (setq beancount-filename-main "/home/marc/Archiv/Finanzen/Transaktionen/transactions.beancount")) #+END_SRC To support org-babel, check if it can find the symlink to ob-beancount.el #+BEGIN_SRC shell 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 #+END_SRC Fava is strongly recommended. #+BEGIN_SRC shell cd /opt python3 -m venv fava source ./fava/bin/activate pip3 install wheel pip3 install fava deactivate #+END_SRC Start fava with fava my_file.beancount It is accessable on this URL: [[http://127.0.0.1:5000][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? #+begin_src emacs-lisp (setq gc-cons-threshold (* 2 1000 1000)) #+end_src