Inspired by https://gist.github.com/saulius/b9f8b784dd3350be3a04c0d932f6087e
Uses Emacs straight.el in combination with use-package.
Bootstrap straight.el
(require 'scroll-bar)
(setq package-archives
'(("gnu" . "http://elpa.gnu.org/packages/")
("melpa-stable" . "http://stable.melpa.org/packages/")
("melpa" . "http://melpa.org/packages/")))
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
Integrate straight with use-package.
(straight-use-package 'use-package)
;; Always ensure and defer
(setq use-package-always-ensure t)
(setq use-package-always-defer t)
(use-package no-littering
:straight t
:demand t)
Setup basic path related config variables.
(defvar config-dir user-emacs-directory
"The dir where config lives.")
(defvar config-cache-dir (expand-file-name ".cache" config-dir)
"The dir to keep temporary cache files.")
(defvar config-custom-package-dir (expand-file-name "packages" config-dir)
"The dir to download packages not available in melpa.")
(when (not (file-directory-p config-custom-package-dir))
(make-directory config-custom-package-dir))
Open this file
(defun open-config-file ()
"Open main config file"
(interactive)
(find-file (concat config-dir "main.org")))
UTF-8 all the things.
(set-language-environment "UTF-8")
(prefer-coding-system 'utf-8-unix)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-buffer-file-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
Store all backup and autosave files in the tmp dir.
(setq backup-directory-alist
`((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms
`((".*" ,temporary-file-directory t)))
Do not create symbolic lock files.
(setq create-lockfiles nil)
Make backups of files, even when they’re in version control.
(setq vc-make-backup-files t)
Do not really want to type yes or no each time, so: yes/no => y/n.
(defalias 'yes-or-no-p 'y-or-n-p)
No vc backends. I only use git with magit.
(setq vc-handled-backends nil)
No bell rings.
(setq ring-bell-function 'ignore)
Don’t ask to create a buffer.
(setq confirm-nonexistent-file-or-buffer nil)
Remove noise.
(scroll-bar-mode 0)
(menu-bar-mode -1)
Use a nice looking theme.
(use-package zenburn-theme
:straight t
:init
(load-theme 'zenburn t))
Borrow Spacemacs modeline.
(use-package spaceline
:straight t
:init
(require 'spaceline-config)
(spaceline-toggle-minor-modes-off)
(spaceline-toggle-workspace-number-off)
(spaceline-toggle-window-number-off)
(spaceline-toggle-anzu-off)
(spaceline-toggle-purpose-off)
(spaceline-toggle-buffer-position-off)
(spaceline-toggle-hud-off)
(spaceline-spacemacs-theme))
Interactively highlight which buffer is active by dimming the others.
(use-package dimmer
:straight t
:init
(setq dimmer-percent 0.1)
(dimmer-activate))
(use-package which-key
:straight t
:demand t
:config
(setq which-key-idle-delay 0.5)
(require 'which-key)
(which-key-mode)
(which-key-setup-side-window-bottom))
;; macros
(defvar jj-leader "SPC"
"Leader key")
(defvar jj-mode ","
"Leader key for mode specific bindings")
(use-package general
:straight t
:init
(general-evil-setup t)
(general-define-key
:prefix jj-leader
:states 'normal
"fed" 'open-config-file
"qq" 'save-buffers-kill-terminal
"fs" 'save-buffer
"ff" 'find-file
"bd" 'kill-this-buffer
"TAB" 'previous-buffer
"bn" 'next-buffer
"bb" 'ivy-switch-buffer
"bp" 'previous-buffer
"hdb" 'describe-bindings
"hdc" 'describe-char
"hdf" 'describe-function
"hdk" 'describe-key
"hdp" 'describe-package
"ws" 'split-window-vertically
"wv" 'split-window-horizontally
"wl" 'evil-window-right
"wk" 'evil-window-up
"wj" 'evil-window-down
"wh" 'evil-window-left
"wd" 'delete-window))
(use-package evil
:straight t
:demand t
:bind (:map evil-normal-state-map ("M-." . nil))
:init
(setq evil-intercept-esc 'always
evil-toggle-key "C-\\"
evil-normal-state-tag " N "
evil-insert-state-tag " I "
evil-emacs-state-tag " E "
evil-visual-state-tag " V "
evil-want-C-i-jump nil ;; make TAB work in console
evil-want-fine-undo t)
:config
(evil-mode))
(use-package evil-surround
:straight t
:after evil
:diminish global-evil-surround-mode
:config
(global-evil-surround-mode))
(use-package evil-collection
:after evil
:straight (evil-collection
:type git
:host github
:repo "jojojames/evil-collection")
:config
(evil-collection-init))
(use-package evil-matchit
:straight t
:after evil
:config
(global-evil-matchit-mode 1))
Evil multi-cursor
(use-package evil-mc
:straight t
:after evil
:config
(global-evil-mc-mode 1))
Do not convert spaces to tabs
(setq-default indent-tabs-mode nil)
Turn off wordwrap
(setq-default truncate-lines 1)
Auto add newline at the end of file.
(setq require-final-newline t)
Increase history sizes.
(setq
history-length 250 ;default is 30
kill-ring-max 5000 ;truncate kill ring after 5000 entries
mark-ring-max 5000) ;truncate mark ring after 5000 entries
Use TAB for completion.
(setq tab-always-indent 'complete)
Indentation Relative to Previous Lines. Indents the current line like the previous nonblank line
(setq indent-line-function 'indent-relative-maybe)
Make clipboard work for Mac
(use-package pbcopy
:straight t
:if (and (eq system-type 'darwin) (not (display-graphic-p)))
:init (turn-on-pbcopy))
Visualize blanks (TAB, (HARD) SPACE and NEWLINE).
(use-package whitespace
:straight t
:demand t
:diminish global-whitespace-mode
:hook (prog-mode . whitespace-mode)
:init
(nmap :prefix jj-leader
"t w" 'whitespace-mode)
:config
(setq whitespace-style '(face empty tabs lines-tail trailing))
(setq whitespace-line-column 80))
(use-package ws-butler
:straight t
:demand t
:diminish ws-butler-mode
:config
(add-hook 'prog-mode-hook 'ws-butler-mode))
(use-package smex
:straight t
:demand t
:bind (("M-x" . 'smex))
:config
(smex-initialize))
(use-package expand-region
:straight t
:init
(nmap :prefix jj-leader
"v" '(expand-region :which-key "expand region"))
(vmap
"v" 'er/expand-region)
:config
(setq expand-region-contract-fast-key "v"
expand-region-reset-fast-key "r"))
(use-package rainbow-delimiters
:straight t
:hook (prog-mode . rainbow-delimiters-mode))
(use-package evil-nerd-commenter
:straight t
:init
(vmap
"g c" 'evilnc-comment-or-uncomment-lines)
(nmap
"g c" '(evilnc-comment-or-uncomment-lines :which-key "Comment/uncomment lines")))
(use-package dumb-jump
:straight t
:general
(:keymaps 'normal
:prefix jj-leader
"j" '(:ignore t :wk "jump around")
"jg" 'dumb-jump-go
"jo" 'dumb-jump-go-other-window
"ji" 'dumb-jump-go-prompt
"jb" 'dumb-jump-back)
:custom
(dumb-jump-selector 'ivy))
(use-package avy
:straight t
:init
(vmap :prefix jj-leader
"SPC" 'avy-goto-char)
(nmap :prefix jj-leader
"SPC" 'avy-goto-char))
(use-package yasnippet
:straight t
:init
(yas-global-mode 1))
(use-package company
:straight t
:demand t
:diminish company-mode
:hook (after-init . global-company-mode)
:config
(setq company-tooltip-align-annotations t) ; aligns annotation to the right
(setq company-idle-delay 0.5)
(setq company-tooltip-limit 10)
(setq company-minimum-prefix-length 2)
;; invert the navigation direction if the the completion popup-isearch-match
;; is displayed on top (happens near the bottom of windows)
(setq company-tooltip-flip-when-above t))
(use-package flycheck
:straight t
:demand t
:commands (flycheck-mode flycheck-list-errors flycheck-buffer)
:hook (prog-mode . global-flycheck-mode)
:init
(nmap
"] e" 'flycheck-next-error
"[ e" 'flycheck-previous-error)
(nmap :prefix jj-leader
"e" '(:ignore t :which-key "lint errors")
"e l" '(flycheck-list-errors :which-key "list errors")
"e b" '(flycheck-buffer :which-key "check buffer")
"e v" '(flycheck-verify-setup :which-key "verify linter setup")
"e l" '(flycheck-list-errors :which-key "list-errors"))
:config
(setq flycheck-highlighting-mode 'lines))
(use-package ivy
:straight t
:diminish ivy-mode
:hook (after-init . ivy-mode)
:config
(setq ivy-use-virtual-buffers t
ivy-count-format "(%d/%d) "
ivy-wrap t
ivy-virtual-abbreviate 'full
ivy-initial-inputs-alist nil
ivy-use-selectable-prompt t))
(use-package counsel
:straight t
:diminish counsel-mode
:commands counsel-describe-face
:hook (ivy-mode . counsel-mode)
:general
([remap apropos] 'counsel-apropos)
([remap bookmark-jump] 'counsel-bookmark)
([remap describe-face] 'counsel-describe-face)
([remap describe-function] 'counsel-describe-function)
([remap describe-variable] 'counsel-describe-variable)
([remap execute-extended-command] 'counsel-M-x)
([remap find-file] 'counsel-find-file)
([remap find-library] 'counsel-find-library)
([remap info-lookup-symbol] 'counsel-info-lookup-symbol)
([remap imenu] 'counsel-imenu)
([remap recentf-open-files] 'counsel-recentf)
([remap org-capture] 'counsel-org-capture)
([remap swiper] 'counsel-grep-or-swiper))
(use-package swiper
:straight t
:after ivy
:bind ("C-s" . swiper)
:config
(setq swiper-action-recenter t))
(use-package ivy-hydra
:straight t
:after ivy
:commands (ivy-dispatching-done-hydra ivy--matcher-desc))
(use-package ivy-rich
:straight t
:after ivy
:init (ivy-rich-mode 1)
:hook (ivy-rich-mode . (lambda ()
(setq ivy-virtual-abbreviate
(or (and ivy-rich-mode 'abbreviate) 'name)))))
(use-package projectile
:straight t
:diminish projectile-mode
:init
(nmap :prefix jj-leader
"p" '(:ignore t :which-key "project")
"p s" '(counsel-projectile-rg :which-key "search in project")
"p r" '(projectile-replace :which-key "replace in project")
"p R" '(projectile-replace-regexp :which-key "replace regexp in project")
"p d" '(counsel-projectile-find-dir :which-key "jump to dir")
"p f" '(counsel-projectile :which-key "jump to file")
"p g" '(counsel-git-grep :which-key "git grep")
"p i" '(projectile-invalidate-cache :which-key "invalidate cache")
"p p" '(counsel-projectile-switch-project :which-key "other project")
"p b" '(counsel-projectile-switch-to-buffer :which-key "buffer"))
:config
(setq projectile-enable-caching nil
projectile-completion-system 'ivy
projectile-sort-order 'recentf)
(projectile-global-mode))
(use-package counsel-projectile
:straight t
:config
(counsel-projectile-mode))
(use-package magit
:straight t
:init
(nmap :prefix jj-leader
"g" '(:ignore t :which-key "git")
"g b" '(magit-blame :which-key "git blame")
"g l" '(magit-log-current :which-key "git log")
"g s" '(magit-status :which-key "git status"))
:config
(setq magit-display-buffer-function #'magit-display-buffer-fullframe-status-v1)
(setq magit-push-arguments (quote ("--force-with-lease")))
(with-eval-after-load 'magit-status
(define-key magit-status-mode-map "p" 'magit-push-popup)))
(use-package evil-magit
:straight t
:after magit)
(use-package git-timemachine
:straight t
:init
(nmap :prefix jj-leader
"g t" '(git-timemachine :which-key "git timemachine"))
(defadvice git-timemachine-mode (after toggle-evil activate)
"Turn off `evil-local-mode' when enabling
`git-timemachine-mode', and turn it back on when disabling
`git-timemachine-mode'."
(evil-local-mode (if git-timemachine-mode -1 1))))
(use-package org
:bind (("C-c c" . org-capture)
("C-c a" . org-agenda))
:config
(setq org-table-number-regexp "$a"))
(use-package lsp-mode
:straight t
:commands lsp)
(use-package py-isort
:straight t
:commands py-isort)
(use-package ccls
:straight t
:config
(setq ccls-executable "ccls")
(setq lsp-prefer-flymake nil)
:hook ((c-mode c++-mode objc-mode) .
(lambda () (require 'ccls) (lsp))))
(use-package vmd-mode
:straight t)
(use-package elpy
:straight t
:init
(elpy-enable)
:config
(setq python-shell-interpreter "ipython"
python-shell-interpreter-args "-i --simple-prompt")
)
(use-package py-isort
:straight t
:commands py-isort)
(use-package dockerfile-mode
:straight t
:mode ("Dockerfile\\'" . dockerfile-mode))
(use-package yaml-mode
:straight t
:mode ("\\.yml$" . yaml-mode))
(use-package terraform-mode
:straight t
:mode ("\\.tf$" . terraform-mode))
(use-package json-navigator
:straight t)