.emacs.d/init.el

484 lines
14 KiB
EmacsLisp

;;; init.el --- tastytea's Emacs init file.
;;; Commentary:
;;; I am using this file with Emacs 26, but most of it will probably work with
;;; Emacs 24 and above.
;;; Code:
;;;;;;;;;;;;;;;;;;;; Packages ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'package)
;; (add-to-list 'package-archives
;; '("melpa-stable" . "https://stable.melpa.org/packages/") t)
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
;; Add path for custom packages
(add-to-list 'load-path "~/.emacs.d/custom-packages/")
;; Install use-package if necessary
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(eval-when-compile
(require 'use-package))
;; Always install packages if they are not present
(require 'use-package-ensure)
(setq use-package-always-ensure t)
;; ;; Benchmark initialization
;; (use-package benchmark-init
;; :config
;; ;; To disable collection of benchmark data after init is done.
;; (add-hook 'after-init-hook 'benchmark-init/deactivate))
;; Update packages if at least auto-package-update-interval (7) days have passed
(use-package auto-package-update
:config
(setq auto-package-update-delete-old-versions t)
;; (setq auto-package-update-hide-results t)
(auto-package-update-maybe))
;;;;;;;;;;;;;;;;;;;; Global variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Determine if we run on a slow computer
(defvar slow-computer nil)
(if (member (system-name) '("steuerbeamter" "azimuth" "localhost"))
(setq slow-computer t)) ; localhost is schnibble
;;;;;;;;;;;;;;;;;;;; Configure some essential things ;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Accelerate startup by not printing so much
(setf inhibit-startup-screen t
inhibit-startup-echo-area-message t
inhibit-startup-message t)
;; Just type y/n instead of yes/no when prompted
(defalias 'yes-or-no-p 'y-or-n-p)
;; Hide toolbar
(tool-bar-mode -1)
;; Save cursor position
(save-place-mode 1)
;; Delete selection when you start to write
(delete-selection-mode t)
;; Save minibuffer history
(savehist-mode t)
;; Show column numbers in modeline
(column-number-mode t)
;; Save backups in ~/.emacs.d/ and keep more versions
(setq backup-directory-alist
`(("." . ,(concat user-emacs-directory "backups"))))
(setq delete-old-versions t
kept-new-versions 6
;; kept-old-versions 2
version-control t)
;; Needed for do-all-symbols
(use-package cl)
;; Personal information
(setq user-login-name "tastytea"
user-mail-address "tastytea@tastytea.de")
;; kill-region (cut) and kill-ring-save (copy) act on the current line if no
;; text is visually selected
;; https://www.emacswiki.org/emacs/WholeLineOrRegion
(put 'kill-ring-save 'interactive-form
'(interactive
(if (use-region-p)
(list (region-beginning) (region-end))
(list (line-beginning-position) (line-beginning-position 2)))))
(put 'kill-region 'interactive-form
'(interactive
(if (use-region-p)
(list (region-beginning) (region-end))
(list (line-beginning-position) (line-beginning-position 2)))))
;; Banish customizations to another file
(setq custom-file (concat user-emacs-directory "custom.el"))
;; Scoll 1 line at a time
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1)))
;; Delete old buffers
;; https://www.emacswiki.org/emacs/CleanBufferList
(use-package midnight
:config
(setq midnight-period (* 1 60 60) ; Clean every 1 hours
clean-buffer-list-delay-general 1 ; Clean normal bufs after 1d
clean-buffer-list-delay-special (* 30 60) ; Clean special bufs after 30m
clean-buffer-list-kill-regexps ; Add these to special buffers
(nconc clean-buffer-list-kill-regexps
'("\\`magit-?.*: .+\\'"))))
(setq midnight-period 600)
;;;;;;;;;;;;;;;;;;;; Keybindings ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Scroll in other window
(global-set-key (kbd "S-<prior>") 'scroll-other-window-down)
(global-set-key (kbd "S-<next>") 'scroll-other-window)
;; Switch window
(global-set-key (kbd "C-<tab>") 'other-window)
;; Reduce whitespace around point to 0 or 1, according to context
(global-set-key (kbd "C-S-<delete>") 'fixup-whitespace)
;;;;;;;;;;;;;;;;;;;; Programming / RTags ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(unless slow-computer
(use-package rtags
:if (executable-find "llvm-config")
:if (executable-find "clang++")
:config
(unless (and (rtags-executable-find "rc") (rtags-executable-find "rdm"))
(progn
(message "RTags is not installed!")
(rtags-install)))
(define-key c-mode-base-map (kbd "M-.") 'rtags-find-symbol-at-point)
(define-key c-mode-base-map (kbd "M-,") 'rtags-find-references-at-point)
(define-key c-mode-base-map (kbd "M-?") 'rtags-display-summary)
(rtags-enable-standard-keybindings)
:hook
(c++-mode . (rtags-start-process-unless-running))
(c-mode . (rtags-start-process-unless-running))
(kill-emacs . rtags-quit-rdm)))
(use-package flycheck-rtags
:after (flycheck rtags)
:defer nil
:config
;; ensure that we use only rtags checking
;; https://github.com/Andersbakken/rtags#optional-1
(defun setup-flycheck-rtags ()
(flycheck-select-checker 'rtags)
(setq-local flycheck-highlighting-mode nil)) ; Can't disable RTags overlay
:hook
(c-mode-hook . #'setup-flycheck-rtags)
(c++-mode-hook . #'setup-flycheck-rtags))
(use-package company-rtags
:after (company rtags)
:config
;; (setq rtags-autostart-diagnostics t)
;; (rtags-diagnostics)
(setq rtags-completions-enabled t)
(push 'company-rtags company-backends))
;;;;;;;;;;;;;;;;;;;; Programming / other ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Syntax checking
(unless slow-computer
(use-package flycheck
:config
(global-flycheck-mode)))
;; Autocompletion
(unless slow-computer
(use-package company
:hook
(after-init . global-company-mode)))
;; Fuzzy autocompletion
(use-package company-flx
:after company
:config
(company-flx-mode +1))
;; cmake integration
(unless slow-computer
(use-package cmake-ide
:config
(setq cmake-ide-build-dir "build")
(cmake-ide-setup)))
;; Indentation
(setq-default indent-tabs-mode nil
tab-width 4)
(setq c-default-style "linux"
c-basic-offset 4)
;; Project management
(unless slow-computer
(use-package projectile
:after neotree
:config
(projectile-mode +1)
(setq projectile-switch-project-action 'neotree-projectile-action
projectile-project-compilation-dir "build"
projectile-project-configure-cmd
"cmake -DCMAKE_BUILD_TYPE=Debug
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G 'Unix Makefiles' .."
projectile-project-compilation-cmd "cmake --build .")
:bind
("C-c p" . 'projectile-command-map)))
;; Debugger
(use-package realgud
:config
(defun load-realgud ()
(load-library "realgud"))
:hook
(c++-mode . load-realgud)
(c-mode . load-realgud))
;; Highlight TODO, FIXME, NOTE and so on.
(use-package hl-todo
:config
(global-hl-todo-mode t))
;; Better commenting
(use-package smart-comment
:bind
("C-x c" . smart-comment))
;; Toggle betweeen beginning/end of line and beginning/end of code
(use-package mwim
:bind
("<home>" . mwim-beginning-of-line-or-code)
("<end>" . mwim-end-of-line-or-code))
;; Auto-type closing brackets
(electric-pair-mode t)
;; Folding
(add-hook 'prog-mode-hook #'hs-minor-mode)
(use-package fold-dwim
:bind
("<f7>" . fold-dwim-toggle)
("C-x t" . fold-dwim-toggle))
;;;;;;;;;;;;;;;;;;;; Appearance ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Icons (required by doom)
(use-package all-the-icons
:config
(unless (file-exists-p "~/.local/share/fonts/all-the-icons.ttf")
(all-the-icons-install-fonts t)))
;; Theme
(unless slow-computer
(use-package doom-themes
:after (all-the-icons neotree)
:config
(load-theme 'doom-molokai t)
(doom-themes-neotree-config)
:custom
(doom-neotree-file-icons 'icons)))
;; Modeline
(use-package doom-modeline
:after all-the-icons
:config
(setq doom-modeline-minor-modes t)
:hook (after-init . doom-modeline-mode))
;; Misc
(set-face-font 'default "Source Code Pro")
(global-hl-line-mode t)
(global-display-line-numbers-mode)
(size-indication-mode)
(setq show-trailing-whitespace t) ; Doesn't work with fill-column-indicator
(show-paren-mode t)
;;;;;;;;;;;;;;;;;;;; Misc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Directory tree
(use-package neotree
:demand t
:after all-the-icons
:custom
(neo-smart-open t)
(neo-show-updir-line t) ; Disabled by doom-themes?
(neo-window-width 30)
;; (setq neo-theme (if (display-graphic-p) 'icons 'arrow))
:bind
("<f8>" . neotree-toggle))
(unless slow-computer
(use-package git-commit))
(use-package magit
:bind
("C-x g" . magit-status)
("C-x M-g" . magit-dispatch))
;; Draw line in column 80
(use-package fill-column-indicator
:after company
:config
;; ;; TODO: Find out why I can't put this in :init or :config
;; (define-globalized-minor-mode global-fci-mode fci-mode
;; (lambda () (fci-mode t)))
;; (global-fci-mode t)
;; Fix bug with fci + company
(defun on-off-fci-before-company(command)
(when (string= "show" command)
(turn-off-fci-mode))
(when (string= "hide" command)
(turn-on-fci-mode)))
(advice-add 'company-call-frontends :before #'on-off-fci-before-company)
;; Add global fci-mode
:hook
(prog-mode . fci-mode)
(text-mode . fci-mode)
:custom
(fci-rule-column 80))
;; Interactive substring matching
(use-package ido
:config
(ido-mode t)
(ido-everywhere t))
(use-package flx-ido
:after ido
:config
(flx-ido-mode t)
(setq ido-enable-flex-matching t
ido-ignore-extensions t
ido-use-virtual-buffers t)) ; Keep log of recently opened files
;; Tab bar
(unless slow-computer
(use-package tabbar-ruler
:after projectile
:init
(setq tabbar-ruler-global-tabbar t)
:config
;; (tabbar-ruler-group-by-projectile-project) ; Group by projectile
;; (tabbar-ruler-group-buffer-groups) ; Group by file type
(tabbar-ruler-group-user-buffers) ; Group by frame
;; (mode-icons-mode 0) ; Disable modeline symbols
(setq tabbar-ruler-swap-faces nil) ; Swap tab colors
;; I have to define these 2 times, don't know why.
(set-face-attribute 'tabbar-selected nil
:background "gray11"
:foreground "light gray"
:family "Sans Serif"
:bold t)
(set-face-attribute 'tabbar-unselected nil
:background "gray18"
:foreground "dark gray"
:family "Sans Serif"
:italic t)
:bind
("C-<prior>" . 'tabbar-ruler-tabbar-backward-tab)
("C-<next>" . 'tabbar-ruler-tabbar-forward-tab)
:custom-face
;; I Have to define these 2 times, don't know why.
(tabbar-selected (nil
:background "gray11"
:foreground "light gray"
:family "Sans Serif"
:bold t))
(tabbar-unselected (nil
:background "gray18"
:foreground "dark gray"
:family "Sans Serif"
:italic t))))
;; Keybinding for whitespace, don't visualise newlines
(use-package whitespace
:config
(delete 'newline-mark whitespace-style)
:bind
("C-x w" . 'whitespace-mode))
;; Spell checking
(use-package flyspell
:config
(defun toggle-flyspell ()
"Toggle flyspell-mode and run flyspell-buffer after activating"
(interactive)
(if (bound-and-true-p flyspell-mode)
(flyspell-mode 0)
(flyspell-mode)
(flyspell-buffer)))
(setq ispell-dictionary "english")
:bind
("<f6>" . toggle-flyspell)
:hook
(c++-mode . flyspell-prog-mode)
(c-mode . flyspell-prog-mode))
;; Multiple cursors
(use-package multiple-cursors
:init
(global-unset-key (kbd "M-<down-mouse-1>"))
:bind
("C-x M-m" . mc/edit-lines)
("M-<mouse-1>" . mc/add-cursor-on-click))
;;;;;;;;;;;;;;;;;;;; File formats ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-package adoc-mode
:mode (("\\.adoc" . adoc-mode)))
(use-package markdown-mode
:mode
(("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:init
(setq markdown-command "markdown2"))
(use-package crontab-mode
:defer t
:mode
(("/cron\\.d/" . crontab-mode))
("\\`'/etc/crontab\\'" . crontab-mode))
(use-package nginx-mode
:defer t)
(use-package company-nginx
:after nginx-mode
:config
:hook
(nginx-mode #'company-nginx-keywords))
;;;;;;;;;;;;;;;;;;;; Server / Remote editing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Edit remote files
(unless slow-computer
(use-package tramp
:config
;; ssh is faster than scp and supports ports
(setq tramp-default-method "ssh")
;; Add verification code support
(customize-set-variable
'tramp-password-prompt-regexp
(concat
"^.*"
(regexp-opt
'("passphrase" "Passphrase"
"password" "Password"
"Verification code")
t)
".*:\0? *"))
;; Respect remote PATH
(add-to-list 'tramp-remote-path 'tramp-own-remote-path)))
;; Run server if:
;; - Our EUID is not 0
;; - We are not logged in via SSH
;; - It is not already running
(unless (equal (user-real-uid) 0)
(unless (getenv "SSH_CONNECTION")
(use-package server
:init
(setq server-use-tcp t
server-port 51313
server-auth-key
"phahw2ohVoh0oopheish7IVie9desh8aequeenei3uo8wahShe%thuadaeNa4ieh")
:config
(unless (server-running-p)
(server-start))
)))
(provide 'init)
;;; init.el ends here