You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

26 KiB

Emacs configuration file

TODOS

  • 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

  • ace-window

  • windmove?

  • tramp (in linux)

  • visual-regexp

  • org configuration: paths

  • org custom agenda

  • org configuration: everything else

  • beancount configuration from config.org

  • CONTINUE TODO from config.org at Programming

First start

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

(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"))

This function updates init.el whenever changes in init.org are made. The update will be active after saving.

  (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)
  (require 'package)

  ;; bug before emacs 26.3
  (when (version< emacs-version "26.3")
      (setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3"))
  (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)

  (package-initialize)
  (unless (package-installed-p 'use-package)
    (package-refresh-contents)
    (package-install 'use-package))

  (setq use-package-verbose nil)

  (eval-when-compile
    (require 'use-package))
  (require 'bind-key)
  (use-package diminish
    :ensure t)

Default settings

  (defvar me/whoami
    (if (string-equal (system-name) "PMTS01")
	"work_remote"
      (if (string-equal (system-name) "laptop")
	  "home_laptop"
	(if (string-equal (system-name) "PMPCNEU08")
	    "work_local"
	  "home_desktop"))))
  (defvar MY--PATH_USER_LOCAL  (expand-file-name "~/.emacs.d/user-local/"))
  (defvar MY--PATH_USER_GLOBAL (expand-file-name "~/.emacs.d/user-global/"))
  (pcase me/whoami
    ("home"
     (progn
       (defvar MY--PATH_ORG_FILES (expand-file-name "~/Archiv/Organisieren/"))
       (defvar MY--PATH_ORG_FILES_MOBILE (expand-file-name "~/Archiv/Organisieren/mobile/"))
       (defvar MY--PATH_ORG_JOURNAl (expand-file-name "~/Archiv/Organisieren/Journal/"))))
    ("home_laptop"
     (progn
       (defvar MY--PATH_ORG_FILES (expand-file-name "~/Archiv/Organisieren/"))
       (defvar MY--PATH_ORG_FILES_MOBILE (expand-file-name "~/Archiv/Organisieren/mobile/"))
       (defvar MY--PATH_ORG_JOURNAL (expand-file-name "~/Archiv/Organisieren/Journal/"))))
    ("work_remote"
     (progn
       (defvar MY--PATH_ORG_FILES   "p:/Eigene Dateien/Notizen/")
       (defvar MY--PATH_START       "p:/Eigene Dateien/Notizen/"))))

  (setq bookmark-default-file (concat MY--PATH_USER_LOCAL "bookmarks"))
  (setq recentf-save-file (concat MY--PATH_USER_LOCAL "recentf"))
  (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

  (setq locale-coding-system 'utf-8)
  (set-terminal-coding-system 'utf-8)
  (set-keyboard-coding-system 'utf-8)
  (set-selection-coding-system 'utf-8)
  (if (eq system-type 'windows-nt)
      (prefer-coding-system 'utf-8-dos)
    (prefer-coding-system 'utf-8))
  (blink-cursor-mode -1) ;; turn off blinking cursor
  (show-paren-mode t) ;; show other part of brackets
  (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

Some windows specific stuff

  (when (eq system-type 'windows-nt)
    (remove-hook 'find-file-hooks '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))

visuals

Font

  (if (string-equal system-type "gnu/linux")
      (set-face-font 'default "Hack-10"))

line wrappings

  (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)))

line numbers

  (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)

misc

  (use-package rainbow-mode
    :ensure t
    :diminish
    :hook ((org-mode
            emacs-lisp-mode) . rainbow-mode))

undo

(use-package undo-tree
:ensure t
:diminish undo-tree-mode
:init
(global-undo-tree-mode 1))

imenu-list

A minor mode to show imenu in a sidebar. Call imenu-list-smart-toggle. Source

(use-package imenu-list
  :ensure 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))
  )

which-key

  (use-package which-key
    :ensure t
    :diminish which-key-mode
    :config
    (which-key-mode)
    (which-key-setup-side-window-right-bottom)
    (which-key-setup-minibuffer)
    (setq which-key-idle-delay 0.5))

Evil

  (use-package evil
    :ensure t
    :defer .1 ;; don't block emacs when starting, load evil immediately after startup
    :config
    (evil-mode 1))

General (key mapper)

  (use-package general
    :ensure t)

  (general-define-key
   :states 'normal
   :keymaps 'imenu-list-major-mode-map
   (kbd "RET") '(imenu-list-goto-entry :which-key "goto")
   (kbd "TAB") '(hs-toggle-hiding :which-key "collapse")
   "d" '(imenu-list-display-entry :which-key "show")
   "q" '(imenu-list-quit-window :which-key "quit"))

orgmode

org

(use-package org
  :ensure org-plus-contrib
  :mode (("\.org$" . org-mode))
  :init
  (add-hook 'org-mode-hook 'company/org-mode-hook)
  (add-hook 'org-src-mode-hook 'smartparens-mode)
  :config
  (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 MY--PATH_ORG_FILES
                               MY--PATH_ORG_FILES_MOBILE)
        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))

languages

  (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)
     ))

  (defun me--org-confirm-babel-evaluate (lang body)
    "Do not confirm evaluation for these languages."
    (not (or (string= lang "python")
             (string= lang "ipython")
             (string= lang "emacs-lisp")
             (string= lang "R")
             (string= lang "latex")
             (string= lang "sqlite"))))
  (setq org-confirm-babel-evaluate 'me--org-confirm-babel-evaluate)

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-id

  (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

org-agenda

Custom keywords, depending on environment

(pcase me/whoami
  ("work_remote")
  (setq org-todo-keywords
        '((sequence "OPEN" "TODO" "UNCLEAR" "|" "DONE" "IMPOSSIBLE"))))

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-super-agenda

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

Source

(unless (string-equal me/whoami "work-remote")
  (use-package org-journal
    :ensure t
    :defer t
    :config
    (setq org-journal-dir MY--PATH_ORG_JOURNAL
          org-journal-enable-agenda-integration t)))

ivy / counsel / swiper

;  (require 'ivy)
  (use-package ivy
    :ensure t
    :diminish
    (ivy-mode . "")
    :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))))

  (use-package counsel
    :ensure t
    :bind*
    (("M-x" . counsel-M-x)
     ("C-x C-f" . counsel-find-file)
     ("C-x C-r" . counsel-recentf)
     ("C-c C-f" . counsel-git)
     ("C-c h f" . counsel-describe-function)
     ("C-c h v" . counsel-describe-variable)
     ("M-i" . counsel-imenu)))

  (use-package swiper
    :ensure t
    :bind
    ("C-s" . swiper))

(use-package ivy-hydra
:ensure t)

company

;  (require 'company)
  (use-package company
    :defer 1
    :bind
    (:map company-active-map
	  ("RET" . nil)
	  ([return] . nil)
	  ("TAB" . company-complete-selection)
	  ([tab] . company-complete-selection)
	  ("<right>" . company-complete-common))
    :config
    (global-company-mode 1)
    (setq-default
     company-idle-delay .2
     company-minimum-prefix-length 1
     company-require-match nil
     company-show-numbers t
     company-tooltip-align-annotations t))

;  (require 'company-statistics)
  (use-package company-statistics
    :ensure t
    :after company
    :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
    :config
    (setq-default company-dabbrev-downcase nil))

  (use-package company-box
    :ensure t
    :init
    (add-hook 'company-mode-hook 'company-box-mode))

company backends

    (defun company/org-mode-hook()
      (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"))

    (defun company/elisp-mode-hook()
      (set (make-local-variable 'company-backends)
           '((company-elisp company-dabbrev) company-capf company-files))
      (message "company/elisp-mode-hook"))

  (defun company/beancount-mode-hook()
    (set (make-local-variable 'company-backends)
         '(company-beancount)))

Programming

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:/Eigene Dateien/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

  (use-package lsp-mode
    :defer t
    :commands lsp
    :custom
    (lsp-auto-guess-root nil)
    (lsp-prefer-flymake nil) ; use flycheck instead
    (lsp-file-watch-threshold 2000)
    :bind (:map lsp-mode-map ("C-c C-f" . lsp-format-buffer))
    :hook ((python-mode
            js-mode
            js2-mode
            typescript-mode
            web-mode) . lsp))

  (use-package lsp-ui
    :after lsp-mode
    :ensure 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 (display-graphic-p)
      (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))

flycheck

  (use-package flycheck
    :ensure t
    :hook
    ((css-mode . flycheck-mode)
     (emacs-lisp-mode . flycheck-mode)
     (python-mode . flycheck-mode))
    :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 t
    :bind
    (("C-c p p" . projectile-switch-project)
     ("C-c p c" . projectile-command-map)
     ("C-c p s s" . projectile-ag))
    :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)
    (setq-default projectile-completion-system 'ivy
                  projectile-enable-caching t
                  projectile-mode-line '(:eval (projectile-project-name))))

smartparens

(use-package smartparens
  :ensure t
  :diminish smartparens-mode
  :config
  (setq sp-show-pair-from-inside nil)
  (require 'smartparens-config))

lisp

  (add-hook 'emacs-lisp-mode-hook 'company/elisp-mode-hook)

web

apt install npm sudo npm install -g vscode-html-languageserver-bin evtl alternativ typescript-language-server?

  (use-package web-mode
    :ensure t
    :defer t
    :mode
    ("\\.phtml\\'"
     "\\.tpl\\.php\\'"
     "\\.djhtml\\'"
     "\\.[t]?html?\\'")
    :config
    (setq web-mode-enable-auto-closing t
          web-mode-enable-auto-pairing t)
    (add-hook 'web-mode-hook 'smartparens-mode))

Python

Systemseitig muss python-language-server installiert sein: pip3 install 'python-language-server[all]'

für andere language servers https://github.com/emacs-lsp/lsp-mode#install-language-server

(if (string-equal system-type "gnu/linux")
   (defun my/postactivatehook ()
     (setq lsp-python-ms-extra-paths pyvenv-virtual-env))
 
 (use-package pyvenv
   :ensure t
   :config
   (setenv "WORKON_HOME" (expand-file-name "~/Archiv/Programmierprojekte/Python/virtualenv/"))
   (add-hook 'pyvenv-post-activate-hooks 'my/postactivatehook))

 (use-package virtualenvwrapper
   :ensure t
   :hook (venv-postmkvirtualenv . (lambda() (shell-command "pip3 install importmagic epc")))
   :config
   (setq venv-location (expand-file-name "~/Archiv/Programmierprojekte/Python/virtualenv/")))

 (use-package lsp-python-ms
   :ensure t
   :after lsp-mode python))
  ; :custom (lsp-python-executable-cmd "python3"))

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
  (if (string-equal system-type "gnu/linux")
      (use-package beancount
        :load-path "user-local/elisp"
;        :ensure t
        :defer t
        :mode
        ("\\.beancount$" . beancount-mode)
        :init
        (add-hook 'beancount-mode-hook 'company/beancount-mode-hook)
  ;    (add-hook 'beancount-mode-hook (pyvenv-activate "/opt/beancount"))
    ;  (setenv "PATH"
    ;          (concat "/opt/beancount/bin:"
    ;                  (getenv "PATH")))
        :config
        (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.