Utility Functions
std::what-face
(defun std::what-face (point)
"Reveal face at POINT."
(interactive "d")
(let ((face (or (get-char-property (point) 'read-face-name)
(get-char-property (point) 'face))))
(if face (message "Face: %s" face) (message "No face at %d" point))))
(global-set-key (kbd "C-x ö") #'std::what-face)std::what-major-mode
(defun std::what-major-mode ()
"Reveal current major mode."
(interactive)
(message "%s" major-mode))
(global-set-key (kbd "C-x ä") #'std::what-major-mode)std::edit-org-user-config
(defun std::edit-org-user-config ()
"Edit the org user config file, in the current window."
(interactive)
(find-file-existing (concat (getenv "SPACEMACSDIR") "/user-config.org")))
(evil-leader/set-key
"feo" #'std::edit-org-user-config)std::def-key-for-maps
(defun std::def-key-for-maps (key cmd keymaps)
"Bind KEY to CMD for all keymaps in MAPS."
(dolist (keymap keymaps)
(define-key keymap key cmd)))std::eval-last-sexp
(defun std::eval-last-sexp ()
(interactive)
(if (and (evil-normal-state-p)
(string= ")" (string (or (char-after) 0))))
(save-excursion
(forward-char)
(call-interactively 'eval-last-sexp))
(call-interactively 'eval-last-sexp)))
(global-set-key (kbd "C-x C-e") #'std::eval-last-sexp)
(spacemacs/set-leader-keys-for-major-mode 'emacs-lisp-mode
"ee" #'std::eval-last-sexp)std::org-files
(defun std::org-files ()
(interactive)
(helm :prompt "Org File: "
:buffer "*helm org files*"
:sources (helm-build-sync-source "Org Files"
:candidates (--map (cons (f-filename it) it) (f-files org-directory))
:action #'find-file-existing
:filtered-candidate-transformer 'helm-fuzzy-highlight-matches)))
(spacemacs/set-leader-keys
"aof" #'std::org-files)std::evil-paste
As shown in the spacemacs FAQ
(defun std::evil-paste-after ()
(interactive)
(let ((evil-this-register ?0))
(call-interactively 'evil-paste-after)))
(defun std::evil-paste-before ()
(interactive)
(let ((evil-this-register ?0))
(call-interactively 'evil-paste-before)))
(define-key evil-visual-state-map "p" #'std::evil-paste-after)
(define-key evil-visual-state-map "P" #'std::evil-paste-after)std::fold-defun
(defun std::fold-defun ()
(interactive)
(save-excursion
(end-of-line)
(beginning-of-defun)
(end-of-line)
(evil-close-fold)))
(define-key evil-normal-state-map (kbd "züf") #'std::fold-defun)Config tangle & compilation
To save on startup time the config file is only loaded on boot. Tangling and compilation is
instead run as part of kill-emacs-hook, relieving the need to load all of org and tangle the
config before emacs may be used.
The function to tangle and recompile the config, running only if the org file was recently modified.
(autoload #'org-babel-tangle-file "ob-tangle")
(defun std::do-recompile (org-file el-file)
(interactive)
(org-babel-tangle-file org-file el-file "emacs-lisp")
(byte-recompile-file el-file t 0 nil))
(defun std::config-tangle-and-recompile ()
(let* ((dir (getenv "SPACEMACSDIR"))
(el-file (concat dir "/user-config.el"))
(org-file (file-chase-links (concat dir "/user-config.org"))))
(when (or (not (file-exists-p el-file))
(time-less-p (->> el-file (file-attributes) (nth 5))
(->> org-file (file-attributes) (nth 5))))
(std::do-recompile org-file el-file))))Advice to insert reload before spacemacs’ layer syncing.
(defun std::layer-sync-config-tangle-advice (&rest _)
(std::config-tangle-and-recompile))Insert retangle before both quitting emacs and reloading the config.
(add-hook 'kill-emacs-hook #'std::config-tangle-and-recompile)
(advice-add #'dotspacemacs/sync-configuration-layers :after #'std::layer-sync-config-tangle-advice)Layer configurations
Evil
Fitting cursor state colors
(setq
evil-normal-state-cursor '("#ab3737" box)
evil-insert-state-cursor '("#33aa33" bar)
evil-visual-state-cursor '("#a374a8" box)
evil-motion-state-cursor '("#c97449" box)
evil-operator-state-cursor '("#00688b" (hbar . 5))
evil-emacs-state-cursor '("#339999" bar)
evil-resize-state-cursor '("#ffdb1a" box))kj key-chord
(setq-default evil-escape-key-sequence "kj")Custom text objects
(evil-define-text-object std::evil::defun-object (count &optional beg end type)
"Evil defun text object."
(let ((start) (finish))
(mark-defun)
(setq start (region-beginning)
finish (region-end))
(deactivate-mark)
(evil-range start finish type )))
(define-key evil-operator-state-map "üf" #'std::evil::defun-object)Settings
(setq evil-move-beyond-eol t
evil-want-fine-undo t
evil-lisp-state-enter-lisp-state-on-command nil)Elisp
Functions
std::elisp::repl-buffer
The elisp repl window refuses to be controlled by shackle, so we’ll do it manually.
(defun std::elisp::repl-buffer (&optional arg)
(interactive "P")
(let* ((w (get-buffer-window))
(h (window-height w)))
(split-window-below)
(other-window 1)
(-if-let (repl-buf (get-buffer "*ielm*"))
(switch-to-buffer repl-buf)
(ielm))
(set-window-text-height (get-buffer-window) (round (* 0.33 h)))
(when arg (select-window w))))std::elisp::fold-all-top-level-forms
(defun std::elisp::fold-all-top-level-forms ()
(interactive)
(save-excursion
(save-match-data
(evil-with-state 'insert
(goto-char (point-min))
(while (search-forward-regexp (rx bol "(") nil t)
(evil-close-fold))))))Keybinds
(spacemacs/set-leader-keys-for-major-mode 'emacs-lisp-mode
"'" #'std::elisp::repl-buffer
"C" #'std::elisp::fold-all-top-level-forms)Auto Completion
Global Activation
(global-company-mode t)Settings
Company Settings
(with-eval-after-load 'company
(setq
company-abort-manual-when-too-short t
company-auto-complete nil
company-async-timeout 10
company-dabbrev-code-ignore-case nil
company-dabbrev-downcase nil
company-dabbrev-ignore-case nil
company-etags-ignore-case nil
company-idle-delay 10
company-minimum-prefix-length 2
company-require-match nil
company-selection-wrap-around t
company-show-numbers t
company-tooltip-flip-when-above nil))Tooltip
The tooltip will look vastly better if we set a minimum width and properly align annotations.
(with-eval-after-load 'company
(setq
company-tooltip-minimum-width 70
company-tooltip-align-annotations t
company-tooltip-margin 2))Backend Priority
The completions provided by combined backends should be sorted, so as to avoid interspersing semantic completion candidates with dumb code-dabbrevs
(with-eval-after-load 'company
(defconst std::company::backend-priorities
'((company-fish-shell . 10)
(company-shell . 11)
(company-shell-env . 12)
(company-anaconda . 10)
(company-capf . 50)
(company-yasnippet . 60)
(company-keywords . 70)
(company-files . 80)
(company-dabbrev-code . 90)
(company-dabbrev . 100))
"Alist of backends' priorities. Smaller number means higher priority.")
(defun std::company::priority-of-backend (backend)
"Will retrieve priority of BACKEND.
Defauts to 999 if BACKEND is nul or has no priority defined."
(let ((pr (cdr (assoc backend std::company::backend-priorities))))
(if (null pr) 999 pr)))
(defun std::company::priority-compare (c1 c2)
"Compares the priorities of C1 & C2."
(let* ((b1 (get-text-property 0 'company-backend c1))
(b2 (get-text-property 0 'company-backend c2))
(p1 (std::company::priority-of-backend b1))
(p2 (std::company::priority-of-backend b2))
(diff (- p1 p2)))
(< diff 0)))
(defun std::company::sort-by-backend-priority (candidates)
"Will sort completion CANDIDATES according to their priorities."
(sort (delete-dups candidates) #'std::company::priority-compare)))The priority sorting is only used in major modes which use combined backends
(defun std::company::use-completions-priority-sorting ()
(setq-local company-transformers '(company-flx-transformer company-sort-by-occurrence std::company::sort-by-backend-priority)))
(--each '(rust-mode-hook fish-mode-hook python-mode-hook)
(add-hook it #'std::company::use-completions-priority-sorting))Quickhelp
Quickhelp makes company’s modemaps unreliable, so we rewrite the underlying keymap while company is active
(with-eval-after-load 'company-quickhelp
(defun std::company::off (arg)
"Use default keys when company is not active. ARG is ignored."
(std::def-key-for-maps
(kbd "C-j") #'electric-newline-and-maybe-indent
(list evil-normal-state-map evil-insert-state-map))
(std::def-key-for-maps
(kbd "C-k") #'kill-line
(list evil-normal-state-map evil-insert-state-map))
(std::def-key-for-maps
(kbd "C-l") #'yas-expand
(list evil-insert-state-map)))
(defun std::company::on (arg)
"Use company's keys when company is active.
Necessary due to company-quickhelp using global key maps.
ARG is ignored."
(std::def-key-for-maps
(kbd "C-j") #'company-select-next
(list evil-normal-state-map evil-insert-state-map))
(std::def-key-for-maps
(kbd "C-k") #'company-select-previous
(list evil-normal-state-map evil-insert-state-map))
(std::def-key-for-maps
(kbd "C-l") #'company-quickhelp-manual-begin
(list evil-insert-state-map)))
(add-hook 'company-completion-started-hook #'std::company::on)
(add-hook 'company-completion-finished-hook #'std::company::off)
(add-hook 'company-completion-cancelled-hook #'std::company::off)
(define-key company-active-map (kbd "C-l") #'company-quickhelp-manual-begin))Company Flx
(with-eval-after-load 'company
(company-flx-mode t)
(setq company-flx-limit 400))Bindings
(global-set-key (kbd "C-SPC") #'company-complete)
(global-set-key (kbd "C-@") #'company-complete)Org
Functions
org-switch-to-buffer-other-window
Org thinks it’s a good idea to disable display-buffer-alist when displaying its buffers. I don’t.
I want my buffers’ display behaviour to be handled by shackle. All of them. No exceptions.
(with-eval-after-load 'org
(defun org-switch-to-buffer-other-window (&rest args)
"Same as the original, but lacking the wrapping
call to `org-no-popups'"
(apply 'switch-to-buffer-other-window args)))std::org::capture-std-target
(with-eval-after-load 'org
(defun std::org::capture-std-target ()
`(file+headline
,(concat org-directory "Capture.org")
,(if (s-equals? (system-name) "a-laptop")
"Ideen"
"Postfach"))))Settings
Prerequisites
(setq-default org-directory "~/Dropbox/Org/"
org-default-notes-file (concat org-directory "Capture.org"))Additional modules
(with-eval-after-load 'org
(add-to-list 'org-modules 'org-habit)
(require 'org-habit))Better looking TODO keywords
(with-eval-after-load 'org
(setq-default org-todo-keywords '((sequence "[TODO]" "|" "[DONE]"))))No `special` behaviour.
(with-eval-after-load 'org
(setq
org-special-ctrl-a nil
org-special-ctrl-k nil
org-special-ctrl-o nil
org-special-ctrl-a/e nil
org-ctrl-k-protect-subtree nil))Agenda
(with-eval-after-load 'org-agenda
(add-to-list 'org-agenda-files (concat org-directory "NT.org"))
(pcase (system-name)
("a-laptop" (add-to-list 'org-agenda-files (concat org-directory "Privat.org")))
("nt-laptop" (message "TODO")))
(setq
org-agenda-skip-scheduled-if-deadline-is-shown t
org-agenda-span 14
org-agenda-window-frame-fractions '(0.7 . 0.7)
org-agenda-window-setup 'current-window
org-deadline-warning-days 10
org-extend-today-until 2))Habits
(with-eval-after-load 'org-habit
(setq org-habit-graph-column 70
org-habit-show-habits-only-for-today nil))Bullets
Use only one bullet for headings (original = “◉” “○” “✸” “✿”)
(with-eval-after-load 'org
(setq-default org-bullets-bullet-list '("✿")))Also use ascii bullets for simple lists
(font-lock-add-keywords
'org-mode
'(("^ +\\([-*]\\) " (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))Capture
(with-eval-after-load 'org
(setq org-capture-templates
`(("t" "Idee/Todo" entry
,(std::org::capture-std-target)
"** [TODO] %?\n %U"))))Other/Sort later
(with-eval-after-load 'org
(setq
calendar-date-style 'european
org-tags-column 85
org-src-window-setup 'other-window
org-log-done 'time
org-ellipsis " "
org-startup-align-all-tables t
org-startup-indented t
org-log-into-drawer t
org-startup-folded t
org-table-use-standard-references nil
org-cycle-emulate-tab t
org-cycle-global-at-bob nil
org-M-RET-may-split-line nil
org-fontify-whole-heading-line nil
org-catch-invisible-edits 'error
org-refile-targets '((nil . (:maxlevel . 10)))
org-footnote-auto-adjust t)
(setq-default
org-display-custom-times nil
;; org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>")
))
;; org-catch-invisible-edits 'show
;; org-fontify-whole-heading-line nil
;; ;; org-hide-block-overlays
;; org-hide-emphasis-markers t
;; org-list-indent-offset 1
;; org-list-allow-alphabetical nil
;; org-src-fontify-natively t
;; org-startup-folded tBabel Languages
(with-eval-after-load 'org
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(shell . t)))
(with-eval-after-load 'python
org-babel-load-languages
'((python . t))))Font Locking
A small bit of custom font locking for ‘==>’
(defface std::result-face
`((t (:foreground "#886688" :bold t)))
"Face for '==>'.")
(font-lock-add-keywords
'org-mode
'(("==>" . 'std::result-face)))Keybinds
Showing content
(with-eval-after-load 'org
(spacemacs/set-leader-keys-for-major-mode 'org-mode
"rr" #'org-reveal
"rb" #'outline-show-branches
"rc" #'outline-show-children
"ra" #'outline-show-all))Headline Navigation
(with-eval-after-load 'org
(spacemacs/set-leader-keys-for-major-mode 'org-mode
"u" #'outline-up-heading
"M-u" #'helm-org-parent-headings
"j" #'outline-next-visible-heading
"k" #'outline-previous-visible-heading
"C-j" #'org-forward-heading-same-level
"C-k" #'org-backward-heading-same-level))Scheduling
(with-eval-after-load 'org
(spacemacs/set-leader-keys-for-major-mode 'org-mode
"s" nil
"ss" #'org-schedule
"st" #'org-time-stamp
"sd" #'org-deadline))(Sub)Tree
(with-eval-after-load 'org
(spacemacs/set-leader-keys-for-major-mode 'org-mode
"wi" #'org-tree-to-indirect-buffer
"wm" #'org-mark-subtree
"wd" #'org-cut-subtree
"wy" #'org-copy-subtree
"wY" #'org-clone-subtree-with-time-shift
"wp" #'org-paste-subtree
"wr" #'org-refile))Structure Editing
(with-eval-after-load 'org
(dolist (mode '(normal insert))
(evil-define-key mode org-mode-map
(kbd "M-RET") #'org-meta-return
(kbd "M-h") #'org-metaleft
(kbd "M-l") #'org-metaright
(kbd "M-j") #'org-metadown
(kbd "M-k") #'org-metaup
(kbd "M-H") #'org-shiftmetaleft
(kbd "M-L") #'org-shiftmetaright
(kbd "M-J") #'org-shiftmetadown
(kbd "M-K") #'org-shiftmetaup
(kbd "M-t") #'org-insert-todo-heading-respect-content)))Sparse Trees
(with-eval-after-load 'org
(spacemacs/set-leader-keys-for-major-mode 'org-mode
"7" #'org-sparse-tree
"8" #'org-occur
"M-j" #'next-error
"M-k" #'previous-error))Narrowing
(with-eval-after-load 'org
;;Spacemancs default *,n* needs to be removed first
(spacemacs/set-leader-keys-for-major-mode 'org-mode "n" nil)
(spacemacs/set-leader-keys-for-major-mode 'org-mode
"nb" #'org-narrow-to-block
"ne" #'org-narrow-to-element
"ns" #'org-narrow-to-subtree
"nw" #'widen))Insert Commands
(with-eval-after-load 'org
(spacemacs/set-leader-keys-for-major-mode 'org-mode
"if" #'org-footnote-new
"il" #'org-insert-link
"in" #'org-add-note
"id" #'org-insert-drawer
"iD" #'org-insert-property-drawer))Tables
(with-eval-after-load 'org
(defun std::org::table-recalc ()
"Reverse the prefix arg bevaviour of `org-table-recalculate', such that
by default the entire table is recalculated, while with a prefix arg recalculates
only the current cell."
(interactive)
(setq current-prefix-arg (not current-prefix-arg))
(call-interactively #'org-table-recalculate))
(defun std::org::table-switch-right ()
"Switch content of current table cell with the cell to the right."
(interactive)
(when (org-at-table-p)
(std::org::table-switch (org-table-current-line) (1+ (org-table-current-column)))))
(defun std::org::table-switch-left ()
"Switch content of current table cell with the cell to the left."
(interactive)
(when (org-at-table-p)
(std::org::table-switch (org-table-current-line) (1- (org-table-current-column)))))
(defun std::org::table-switch (x2 y2)
(let* ((p (point))
(x1 (org-table-current-line))
(y1 (org-table-current-column))
(t1 (org-table-get x1 y1))
(t2 (org-table-get x2 y2)))
(org-table-put x1 y1 t2)
(org-table-put x2 y2 t1 t)
(goto-char p)))
;; TODO: rebind clock
(spacemacs/set-leader-keys-for-major-mode 'org-mode "q" nil)
(spacemacs/set-leader-keys-for-major-mode 'org-mode
"qt" #'org-table-create-or-convert-from-region
"qb" #'org-table-blank-field
"qd" #'org-table-delete-column
"qc" #'org-table-insert-column
"qr" #'org-table-insert-row
"q-" #'org-table-insert-hline
"q0" #'org-table-sort-lines
"qy" #'org-table-copy-region
"qx" #'org-table-cut-region
"qp" #'org-table-paste-rectangle
"qo" #'org-table-toggle-coordinate-overlays
"qf" #'std::org::table-recalc
"q#" #'org-table-rotate-recalc-marks
"qg" #'org-plot/gnuplot
"qsl" #'std::org::table-switch-right
"qsh" #'std::org::table-switch-left)
(evil-leader/set-key-for-mode 'org-mode
"+" #'org-table-sum
"?" #'org-table-field-info))Toggles
(with-eval-after-load 'org
(spacemacs/set-leader-keys-for-major-mode 'org-mode
"zh" #'org-toggle-heading
"zl" #'org-toggle-link-display
"zx" #'org-toggle-checkbox
"zc" #'org-toggle-comment
"zt" #'org-toggle-tag
"zi" #'org-toggle-item
"zo" #'org-toggle-ordered-property))Other
(with-eval-after-load 'org
(spacemacs/set-leader-keys-for-major-mode 'org-mode
"0" #'org-sort
"#" #'org-update-statistics-cookies
"C-y" #'org-copy-visible
"C-p" #'org-set-property
"C-f" #'org-footnote-action
"C-o" #'org-open-at-point
"C-e" #'org-edit-special
"P" #'org-priority)
(evil-define-key 'normal org-mode-map
"-" #'org-cycle-list-bullet
"t" #'org-todo)
(define-key org-src-mode-map (kbd "C-x C-s") #'ignore)
(define-key org-src-mode-map (kbd "C-c C-c") #'org-edit-src-exit))Shell Scripts
Functions
std::fish-mode-hook
(defun std::fish::mode-hook ()
(setq imenu-generic-expression fish-mode-imenu-expr))
(add-hook 'fish-mode-hook #'std::fish::mode-hook)Settings
(with-eval-after-load 'company
(setq
company-shell-delete-duplicates nil
company-shell-modes nil
company-fish-shell-modes nil
company-shell-use-help-arg t))
(setq company-backends-fish-mode
'((company-dabbrev-code company-files company-shell company-shell-env company-fish-shell :with company-yasnippet)))
(defconst fish-mode-imenu-expr
(list
(list
"Function"
(rx (group-n 1 (seq bol "function" (1+ space)))
(group-n 2 (1+ (or alnum (syntax symbol)))) symbol-end)
2)
(list
"Variables"
(rx bol "set" (1+ space) (0+ "-" (1+ alpha) (1+ space))
(group-n 1 symbol-start (1+ (or word "_"))))
1)))Helm
Functions
std::org-helm-headings
(autoload 'helm-source-org-headings-for-files "helm-org")
(defun std::org-in-buffer-headings ()
"Slightly retooled ~helm-org-in-buffer-headings~ to have the candidates retain their fontification."
(interactive)
(helm :sources (helm-source-org-headings-for-files
(list (current-buffer)))
:candidate-number-limit 99999
:preselect (helm-org-in-buffer-preselect)
:truncate-lines helm-org-truncate-lines
:buffer "*helm org inbuffer*"))std::helm-semantic-or-imenu
(defun std::helm-semantic-or-imenu ()
"Same as `helm-semantic-or-imenu', but will call `std::org-helm-headings' in org-mode buffers."
(interactive)
(if (eq major-mode 'org-mode)
(std::org-in-buffer-headings)
(call-interactively #'helm-semantic-or-imenu)))Keybinds
(spacemacs/set-leader-keys
"hi" #'std::helm-semantic-or-imenu)Rust
Functions
std::rust::build-rusty-tags
(with-eval-after-load 'rust-mode
(defun std::rust::build-rusty-tags ()
(interactive)
(make-thread
#'(lambda ()
(let ((default-directory (projectile-project-root)))
(call-process-shell-command "rusty-tags emacs")
(call-process-shell-command "mv rusty-tags.emacs TAGS")
(message "Rusty tags rebuilt."))))))Keybinds
(with-eval-after-load "racer"
(evil-define-key 'normal racer-mode-map (kbd "M-.") #'racer-find-definition)
(evil-define-key 'insert racer-mode-map (kbd "M-.") #'racer-find-definition)
(evil-define-key 'normal racer-help-mode-map (kbd "q") #'kill-buffer-and-window)
(spacemacs/set-leader-keys-for-major-mode 'rust-mode
"f" #'rust-format-buffer
"a" #'rust-beginning-of-defun
"e" #'rust-end-of-defun
"d" #'racer-describe
"C-t" #'std::rust::build-rusty-tags))Settings
Add company-dabbrev-code to front row of completion backends.
(with-eval-after-load "rust-mode"
(setq company-backends-rust-mode
'((company-capf :with company-dabbrev-code company-yasnippet)
(company-dabbrev-code company-gtags company-etags company-keywords :with company-yasnippet)
(company-files :with company-yasnippet)
(company-dabbrev :with company-yasnippet))))Projectile
Functions
std::projectile::magit-status
(defun std::projectile::magit-status (&optional arg)
"Use projectile with Helm for running `magit-status'
With a prefix ARG invalidates the cache first."
(interactive "P")
(if (projectile-project-p)
(projectile-maybe-invalidate-cache arg))
(let ((helm-ff-transformer-show-only-basename nil)
(helm-boring-file-regexp-list nil))
(helm :prompt "Git status in project: "
:buffer "*helm projectile*"
:sources (helm-build-sync-source "Projectile Projects"
:candidates projectile-known-projects
:action #'magit-status
:filtered-candidate-transformer 'helm-fuzzy-highlight-matches))))Keybinds
(with-eval-after-load 'projectile
(spacemacs/set-leader-keys
"pg" nil
"pt" #'projectile-find-tag
"psa" #'helm-projectile-ag
"pgs" #'std::projectile::magit-status
"pC" #'projectile-cleanup-known-projects))Settings
(with-eval-after-load 'projectile
(setq projectile-switch-project-action #'project-find-file))Flycheck
Settings
(setq
flycheck-check-syntax-automatically '(mode-enabled save idle-change)
flycheck-idle-change-delay 10
flycheck-pos-tip-timeout 999)Keybinds
(with-eval-after-load "flycheck"
(evil-leader/set-key
"ee" #'flycheck-buffer
"e C-e" #'flycheck-mode)
(define-key evil-normal-state-map (kbd "C-.") #'spacemacs/next-error)
(define-key evil-normal-state-map (kbd "C-,") #'spacemacs/previous-error))Helm
Settings
(setq
helm-ag-base-command "ag -f -t --hidden --nocolor --nogroup --depth 999999 --smart-case --recurse"
helm-imenu-delimiter ": "
helm-move-to-line-cycle-in-source t
helm-swoop-use-line-number-face t)Keybinds
(with-eval-after-load "helm"
(evil-leader/set-key
"saa" #'helm-do-ag-this-file)
(define-key helm-map (kbd "M-j") #'helm-next-source)
(define-key helm-map (kbd "M-k") #'helm-previous-source))Version Control
Settings
(with-eval-after-load 'magit
(setq
git-commit-summary-max-length 120
magit-diff-highlight-hunk-region-functions '(magit-diff-highlight-hunk-region-dim-outside)))
(with-eval-after-load 'git-gutter
(setq git-gutter-fr:side 'left-fringe))Keybinds
(with-eval-after-load 'magit
(defvar std::magit-key-maps
(list
magit-mode-map
magit-status-mode-map
magit-log-mode-map
magit-diff-mode-map
magit-branch-section-map
magit-untracked-section-map
magit-file-section-map
magit-status-mode-map
magit-hunk-section-map
magit-stash-section-map
magit-stashes-section-map
magit-staged-section-map
magit-unstaged-section-map))
(std::def-key-for-maps (kbd "J") #'std::quick-forward std::magit-key-maps)
(std::def-key-for-maps (kbd "K") #'std::quick-backward std::magit-key-maps)
(std::def-key-for-maps (kbd "M-j") #'magit-section-forward-sibling std::magit-key-maps)
(std::def-key-for-maps (kbd "M-k") #'magit-section-backward-sibling std::magit-key-maps)
(std::def-key-for-maps (kbd ",u") #'magit-section-up std::magit-key-maps)
(std::def-key-for-maps (kbd ",1") #'magit-section-show-level-1-all std::magit-key-maps)
(std::def-key-for-maps (kbd ",2") #'magit-section-show-level-2-all std::magit-key-maps)
(std::def-key-for-maps (kbd ",3") #'magit-section-show-level-3-all std::magit-key-maps)
(std::def-key-for-maps (kbd ",4") #'magit-section-show-level-4-all std::magit-key-maps))Elm
Functions
(defun std::format-and-save-elm-buffer ()
"Format an elm buffer and then save it."
(interactive)
(elm-mode-format-buffer)
(save-buffer))Settings
(defun std::elm-mode-hook ()
(setq-local company-backends
'((company-elm company-dabbrev-code company-files :with company-yasnippet))))
(add-hook 'elm-mode-hook #'std::elm-mode-hook t)Keybinds
(with-eval-after-load 'elm-mode
(spacemacs/set-leader-keys-for-major-mode 'elm-mode
"R" nil
"h" nil
"=" nil
"em" #'elm-preview-main
"eb" #'elm-preview-buffer
"d" #'elm-oracle-doc-at-point
"t" #'elm-oracle-type-at-point
"==" #'elm-mode-format-buffer
"C-t" #'elm-mode-generate-tags)
(which-key-add-major-mode-key-based-replacements 'elm-mode
",e" "preview")
(spacemacs/set-leader-keys
"fs" #'std::format-and-save-elm-buffer)
(define-key elm-package-mode-map (kbd "J") #'std::quick-forward)
(define-key elm-package-mode-map (kbd "K") #'std::quick-backward)
(define-key elm-package-mode-map (kbd "q") #'kill-buffer-and-window)
(define-key elm-mode-map (kbd "C-x C-s") #'std::format-and-save-elm-buffer)
(define-key elm-mode-map (kbd "M-.") #'elm-mode-goto-tag-at-point))Git
Settings
(with-eval-after-load 'magit
(setq magit-repository-directories '(("~/Documents/git/" . 1))
magit-display-buffer-function 'magit-display-buffer-fullframe-status-v1))Ranger
Functions
std::deer-new-frame
(defun std::deer-new-frame ()
(interactive)
(let ((frame (make-frame-command)))
(select-frame frame)
(deer)
(delete-other-windows)))std::deer-kill-frame
(with-eval-after-load 'ranger
(defun std::deer-delete-frame ()
(interactive)
(ranger-close)
(when (> (cl-list-length (frame-list)) 1)
(delete-frame))))Settings
(with-eval-after-load 'ranger
(setq ranger-cleanup-eagerly t
ranger-cleanup-on-disable t
ranger-deer-show-details t
ranger-dont-show-binary t
ranger-hide-cursor t
ranger-listing-dir-first t
ranger-modify-header t
ranger-map-style 'dired
ranger-override-dired t
ranger-tabs-style 'normal
ranger-show-hidden t))Keybinds
(spacemacs/set-leader-keys
"ad" #'std::deer-new-frame)
(with-eval-after-load 'ranger
(evil-define-key 'motion ranger-mode-map (kbd "q") #'std::deer-delete-frame))Clojure
Settings
(setq clojure-enable-fancify-symbols t)Single Package Configurations
dired+
(with-eval-after-load 'dired
(require 'dired+))Eyebrowse
Switch desktops via SPC + num
(eyebrowse-mode t)
(dolist (num (number-sequence 0 9))
(let ((key (kbd (concat "SPC " (number-to-string num))))
(func (intern (concat "eyebrowse-switch-to-window-config-" (number-to-string num)))))
(spacemacs/set-leader-keys key func)))Shackle
Replace popwin
(shackle-mode t)
(setq helm-display-function 'pop-to-buffer)
(setq shackle-rules
'(("*helm-ag*" :select t :align right :size 0.5)
("*helm semantic/imenu*" :select t :align right :size 0.4)
("*helm org inbuffer*" :select t :align right :size 0.4)
(flycheck-error-list-mode :select nil :align below :size 0.25)
(ert-results-mode :select t :align below :size 0.5)
(calendar-mode :select t :align below :size 0.25)
(racer-help-mode :select t :align right :size 0.5)
(help-mode :select t :align right :size 0.5)
(helpful-mode :select t :align right :size 0.5)
(compilation-mode :select t :align right :size 0.5)
("*Org Select*" :select t :align below :size 0.33)
("*Org Note*" :select t :align below :size 0.33)
("*Org Links*" :select t :align below :size 0.2)
(" *Org todo*" :select t :align below :size 0.2)
("*Man.*" :select t :align below :size 0.5 :regexp t)
("*helm.*" :select t :align below :size 0.33 :regexp t)
("*Org Src.*" :select t :align below :size 0.5 :regexp t)))Yasnippet
Keybinds
(with-eval-after-load "yasnippet"
(define-key evil-insert-state-map (kbd "C-l") #'yas-expand))Settings
(with-eval-after-load 'yasnippet
(autoload #'f-join "f.el")
(setq-default yas-snippet-dirs (list (f-join (getenv "SPACEMACSDIR") "snippets"))))Enable Smartparens
Smartparens is disabled while yasnippet is expanding and editing a snippet. Whatever this was a workaround for I don’t seem affected, and I’d rather keep my electric pairs inside my snippets.
(unless (bound-and-true-p std::yasnippet::smartparens-restored)
(if (member #'spacemacs//smartparens-disable-before-expand-snippet yas-before-expand-snippet-hook)
(remove-hook 'yas-before-expand-snippet-hook #'spacemacs//smartparens-disable-before-expand-snippet)
(error "Smartparens no longer disabled before yasnippet starts."))
(if (member #'spacemacs//smartparens-restore-after-exit-snippet yas-after-exit-snippet-hook)
(remove-hook 'yas-after-exit-snippet-hook #'spacemacs//smartparens-restore-after-exit-snippet)
(error "Smartparens no longer restored after yasnippet ends.")))
(defvar std::yasnippet::smartparens-restored t)i3wm-config-mode
(require 'i3wm-config-mode)Writeroom mode
(spacemacs|add-toggle writeroom
:mode writeroom-mode
:documentation "Disable visual distractions."
:evil-leader "TW")
(with-eval-after-load 'writeroom-mode
(setq writeroom-width 120
writeroom-extra-line-spacing 0))Treemacs
Settings
(setq treemacs-be-evil t)
(with-eval-after-load 'treemacs
(setq treemacs-header-function #'treemacs--create-header-projectile
treemacs-follow-after-init t
treemacs-git-integration t)
(treemacs-follow-mode))Keybinds
(spacemacs/set-leader-keys
"ft" #'treemacs-init
"fT" #'treemacs-projectile-init)
(global-set-key (kbd "<f8>") #'treemacs-toggle)
(global-set-key (kbd "<C-M-tab>") #'treemacs-toggle)Vimish fold
A fallback in case evil’s own folding is not sufficient
(define-key evil-normal-state-map (kbd "zva") #'vimish-fold-avy)
(define-key evil-normal-state-map (kbd "zvd") #'vimish-fold-delete)
(define-key evil-normal-state-map (kbd "zvv") #'vimish-fold-toggle)
(define-key evil-normal-state-map (kbd "zvz") #'vimish-fold)Winum
Settings
(setq winum-scope 'frame-local)Persp
Settings
(setq
persp-add-buffer-on-after-change-major-mode nil
persp-add-buffer-on-find-file t
persp-auto-resume-time 0
persp-auto-save-opt 0
persp-auto-save-persps-to-their-file-before-kill nil
persp-autokill-buffer-on-remove nil)Layouts
(spacemacs|define-custom-layout "@OrgDir"
:binding "a"
:body
(-if-let (org-files (f-files org-directory))
(find-file-existing (first org-files))
(user-error "No org files ")))Evil Goggles
Settings
(evil-goggles-mode t)
(setq evil-goggles-duration 0.1
evil-goggles-pulse t
evil-goggles-enable-delete t
evil-goggles-enable-indent t
evil-goggles-enable-yank t
evil-goggles-enable-join t
evil-goggles-enable-fill-and-move t
evil-goggles-enable-paste t
evil-goggles-enable-shift t
evil-goggles-enable-surround t
evil-goggles-enable-commentary t
evil-goggles-enable-nerd-commenter t
evil-goggles-enable-replace-with-register t
evil-goggles-enable-set-marker t
evil-goggles-enable-undo t
evil-goggles-enable-redo t)Helpful
Keybinds
(global-set-key (kbd "C-x ß") #'helpful-at-point)Settings
(add-hook 'helpful-mode-hook #'evil-motion-state)Modeline
Turn off unwanted segments
(spacemacs/toggle-mode-line-minor-modes-off)
(spaceline-toggle-purpose-off)Don’t use Spacemacs’ evil state highlighter
(setq spaceline-highlight-face-func 'spaceline-highlight-face-evil-state)Fonts
Functions
std::downscale
(cl-defun std::downscale (font &key char start end)
(set-fontset-font "fontset-default" `(,(or start char) . ,(or end char))
(font-spec :size 12 :name font)))Scaled Characters
Some unicode characters are displayed taller than the default text. Scrolling through such characters will sometimes cause the cursor to be jumpy. To avoid that these unicode characters need to be scaled down.
First the entirety of Font Awesome
(std::downscale "Font Awesome" :start #xf000 :end #xf2e0)Then single characters, like those used for prettify-symbols
(std::downscale "Symbola" :char ?\⇛)
(std::downscale "Symbola" :char ?\⭢)
(std::downscale "Symbola" :char ?\⩵)
(std::downscale "Symbola" :char ?\⮕)
(std::downscale "Symbola" :char ?\⬅)
(std::downscale "Symbola" :char ?\◉)
(std::downscale "Symbola" :char ?\•)
(std::downscale "Symbola" :char ?\⏵)
(std::downscale "Symbola" :char ?\⏸)
(std::downscale "Symbola" :char ?\⏹)
(std::downscale "Symbola" :char ?\⏮)
(std::downscale "Symbola" :char ?\⏭)
(std::downscale "Symbola" :char ?\⏪)
(std::downscale "Symbola" :char ?\⏩)
(std::downscale "Symbola" :char ?\🔀)
(std::downscale "Symbola" :char ?\🔁)
(std::downscale "Symbola" :char ?\🔂)
(std::downscale "Symbola" :char ?\❯)
(std::downscale "Symbola" :char ?\✸)
(std::downscale "Symbola" :char ?\✿)
(std::downscale "Cantarell" :char ?\•)Misc. Settings
General Key Binds
Use visual lines
(std::def-key-for-maps
(kbd "j") #'evil-next-visual-line
(list evil-normal-state-map evil-visual-state-map evil-motion-state-map))
(std::def-key-for-maps
(kbd "k") #'evil-previous-visual-line
(list evil-normal-state-map evil-visual-state-map evil-motion-state-map))Quick line jumping
(defun std::quick-forward ()
(interactive) (evil-next-visual-line 5))
(defun std::quick-backward ()
(interactive) (evil-previous-visual-line 5))
(dolist (map (list evil-normal-state-map evil-visual-state-map evil-motion-state-map))
(define-key map (kbd "J") #'std::quick-forward))
(dolist (map (list evil-normal-state-map evil-visual-state-map evil-motion-state-map))
(define-key map (kbd "K") #'std::quick-backward))Emacs style line start/end jump
(dolist (map (list evil-motion-state-map evil-normal-state-map evil-visual-state-map evil-insert-state-map))
(define-key map (kbd "C-e") #'evil-end-of-visual-line))
(dolist (map (list evil-motion-state-map evil-normal-state-map evil-visual-state-map evil-insert-state-map))
(define-key map (kbd "C-a") #'evil-beginning-of-visual-line))Evil search on emacs’ buttons
(global-set-key (kbd "C-s") #'evil-search-forward)
(global-set-key (kbd "C-r") #'evil-search-backward)Splitting and joining lines
(define-key evil-normal-state-map (kbd "C-j") #'electric-newline-and-maybe-indent)
(evil-leader/set-key "C-j" #'evil-join)Dumb Refactoring
(defun std::defun-query-replace ()
(interactive)
(mark-defun)
(call-interactively 'anzu-query-replace))
(evil-leader/set-key
"üü" #'anzu-query-replace
"üf" #'std::defun-query-replace)Find definition
(global-set-key (kbd "M-.") #'xref-find-definitions)
(define-key evil-normal-state-map (kbd "M-.") #'xref-find-definitions)Quitting with q
(evil-define-key 'normal messages-buffer-mode-map (kbd "q") #'quit-window)
(define-key flycheck-error-list-mode-map (kbd "q") #'kill-buffer-and-window)
(with-eval-after-load 'Man-mode
(define-key Man-mode-map (kbd "q") #'kill-buffer-and-window))Killing a buffer alongside its window
(spacemacs/set-leader-keys "b C-d" #'kill-buffer-and-window)Same comment keybind as in eclipse
(global-set-key (kbd "C-7") #'evilnc-comment-operator)Smooth Scrolling
No more jumpy recenter
(setq
scroll-conservatively 20
scroll-margin 10
scroll-preserve-screen-position t)Minor modes
On/Off Switches
On
(global-subword-mode t)
(blink-cursor-mode t)
(mouse-avoidance-mode 'banish)
(desktop-save-mode t)Off
(ido-mode -1)
(global-hl-line-mode -1)Hooks
(add-hook 'prog-mode-hook #'rainbow-delimiters-mode-enable)
(add-hook 'snippet-mode-hook #'rainbow-delimiters-mode-disable)
(add-hook 'emacs-lisp-mode-hook #'rainbow-mode)
(add-hook 'conf-mode-hook #'rainbow-mode)
(add-hook 'help-mode-hook #'rainbow-mode)
(add-hook 'org-mode-hook #'smartparens-mode)Prettify Symbols
(setq-default
prettify-symbols-alist
`(("lambda" . "λ")
("!=" . "≠")
("==" . "⩵")
("<=" . "⇚")
("=>" . "⇛")
("<-" . "⬅")
("->" . "⮕")))
(add-hook 'prog-mode-hook #'prettify-symbols-mode)Single Settings
Better line numbers
(setq linum-format " %d ")Pos Tip colors
(with-eval-after-load "pos-tip"
(setq pos-tip-background-color "#2d2d2d"
pos-tip-foreground-color "#ccb18b"))Pack the custom settings away from the actual config to somewhere they can be easily gitignored.
(setq custom-file (concat (getenv "SPACEMACSDIR") "/custom-file.el"))Simple newlines
(setq next-line-add-newlines t)No more ugly line splitting
(setq-default truncate-lines t)I’ll never want to keep my current tags when switching projects
(setq tags-add-tables nil)No need for vi-tilde, emacs default looks better
(setq-default indicate-empty-lines t)Banish mouse to the bottom so as not to interfere with notifications
(setq-default mouse-avoidance-banish-position
'((frame-or-window . frame)
(side . right)
(side-pos . 3)
(top-or-bottom . bottom)
(top-or-bottom-pos . 0)))Don’t load outdated files
(setq load-prefer-newer t)1 tab = 4 spaces
(setq-default tab-width 4)No more asking to following symlinks
(setq vc-follow-symlinks t)Desktop Restoration
Settings
(setq desktop-restore-eager 2
desktop-restore-forces-onscreen nil
desktop-lazy-idle-delay 10)Restoration
The way spacemacs loads its config doesn’t seem to mesh with desktop-save-mode so it needs to be done manually - just once on boot and not every time the config is reloaded at runtime
(when (and (bound-and-true-p desktop-save-mode)
(not (boundp 'std::boot-finished)))
(desktop-read)
(defvar std::boot-finished t))This final text prevents that the END_SRC face bleeds into the collapsed heading.