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.
 

37 KiB

Emacs configuration file

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

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)

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

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

Default settings

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

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

visuals

Font

(when *sys/linux*
  (set-face-font 'default "Hack-10"))
(when *work_remote*
  (set-face-font 'default "Lucida Sans Typewriter-11"))

Themes

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

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

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

undo

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

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

which-key

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

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

ivy / counsel / swiper

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

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))
  :hook
  (after-init . global-company-mode)
  (emacs-lisp-mode . my/company-elisp)
  (org-mode . my/company-org)
  :config
  (defun my/company-elisp ()
    (message "set up company for elisp")
    (set (make-local-variable 'company-backends)
         '(company-yasnippet
            company-capf
            company-dabbrev-code
            company-files)))
  (defun my/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

org

(use-package org
  :ensure org-plus-contrib
  :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)
  :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

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

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

Currently it causes some debugger errors "not a standard org time string", so it's disabled

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

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

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

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

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

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

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

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?\\'")
 :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))

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]'

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

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