diff --git a/.gitignore b/.gitignore index b9e908f..52bc2f9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,19 @@ -custom.el -elpa -games -recentf -eshell -projectile* -.DS_Store -auto-save* -helm-adaptive-history -url -.last-package-update-day -smex-items -tramp -.mc-lists.el -/company-statistics-cache.el -/elpa25 -ac-comphist.dat -bookmarks -places +custom.el +elpa +games +recentf +eshell +projectile* +.DS_Store +auto-save* +helm-adaptive-history +url +.last-package-update-day +smex-items +tramp +.mc-lists.el +/company-statistics-cache.el +/elpa25 +ac-comphist.dat +bookmarks +places diff --git a/init.el b/init.el index 9706733..3fd5a09 100644 --- a/init.el +++ b/init.el @@ -1,858 +1,704 @@ -;; init.el -- Patrick Thomson's emacs config. -*- lexical-binding: t; -*- - -;;; Commentary: -;; This file is in the public domain. -;; -;; If you want to give this file a try, you can just drop it into -;; ~/.emacs.d: it downloads everything it needs. It is also relatively -;; fast to start up (once it's downloaded all the required packages), -;; as it endeavours to load packages lazily when possible. -;; -;; A general note on keybindings: the custom keybindings applicable to -;; all major modes appear with the C-c prefix, as is standard. -;; Per-language commands appear with the C-c a prefix. The most -;; important keybinding, C-;, provides counsel-M-x, which lets you -;; fuzzy-find through the space of available functions. Exploring -;; counsel-M-x is the best way to become familiar with the space of -;; extensible functions, which is a sine qua non for being comfortable -;; with Emacs. - -;;; Code: - -;; To start, we adjust the garbage collection param - -(setq gc-cons-threshold 32000000 ;; 32 MB - garbage-collection-messages t) ;; indicator of thrashing - -;; Bump up the recursion limit. -(setq max-lisp-eval-depth 2000) - -;; Package-initialization preamble, adding melpa and melpa-stable. - -(require 'package) - -(defmacro append-to-list (target suffix) - "Append SUFFIX to TARGET in place." - `(setq ,target (append ,target ,suffix))) - -(append-to-list package-archives - '(("melpa" . "http://melpa.org/packages/") - ("melpa-stable" . "http://stable.melpa.org/packages/") - ("org-elpa" . "https://orgmode.org/elpa/"))) - -(package-initialize) - -;; Ensure use-package is present. From here on out, all packages are loaded -;; with use-package. - -(unless (package-installed-p 'use-package) - (package-refresh-contents) - (package-install 'use-package)) - -;; Allow navigation between use-package stanzas with iMenu. -(setq-default use-package-enable-imenu-support t) - -(require 'use-package) - -(setq - use-package-always-ensure t - use-package-verbose t) - -;; Set the zenburn theme -;; TODO - -(use-package solarized-theme - :config - (load-theme 'solarized-light t) - (let ((line (face-attribute 'mode-line :underline))) - (set-face-attribute 'mode-line nil :overline line) - (set-face-attribute 'mode-line-inactive nil :overline line) - (set-face-attribute 'mode-line-inactive nil :underline line) - (set-face-attribute 'mode-line nil :box nil) - (set-face-attribute 'mode-line-inactive nil :box nil) - (set-face-attribute 'mode-line-inactive nil :background "#f9f2d9"))) - - -;; Use moody modeline -(use-package moody - :config - (setq x-underline-at-descent-line t) - (moody-replace-mode-line-buffer-identification) - (moody-replace-vc-mode)) - -;; Minions to add a menu with minor modes to the modeline -(use-package minions - :config (minions-mode 1)) - -;; -(use-package undo-tree - :init - global-undo-tree-mode) - -;; UTF-8 everywhere, please. -(prefer-coding-system 'utf-8) - -(set-face-attribute 'default nil - :family "Hack" - :height 110 - :weight 'normal - :width 'normal) - -;; Any Customize-based settings should live in custom.el, not here. - -(setq custom-file "~/.emacs.d/custom.el") -(load custom-file 'noerror) - -;; Always prefer newer files. - -(setq load-prefer-newer t) - -;; Disable otiose GUI settings: they just waste space. -;; fringe-mode is especially ruinous performance-wise. - -(when (window-system) - (tool-bar-mode -1) - (scroll-bar-mode -1) - (tooltip-mode -1) - (fringe-mode -1)) - -;; Haven't figured out how to diminish eldoc-mode outside of -;; requiring this explicitly and doing it manually. -(use-package diminish - :ensure t) - -(diminish 'eldoc-mode) - -(use-package all-the-icons) - -;; Ensure that items in the PATH are made available to Emacs. This should -;; probably just come with the main distribution. - -;; Recentf comes with Emacs but it should always be enabled. - -(use-package recentf - :init (recentf-mode t) - :config - (add-to-list 'recentf-exclude "\\.emacs.d") - (add-to-list 'recentf-exclude ".+tmp......\\.org")) - -;; Ivy makes most minibuffer prompts sortable and filterable. I used -;; to use helm, but it was too slow. Unfortunately org-ref depends on -;; it, but I never load it, so we good. - -(use-package ivy - :ensure t - :init - (ivy-mode 1) - (unbind-key "S-SPC" ivy-minibuffer-map) - (setq ivy-height 30 - ivy-use-virtual-buffers t - ivy-use-selectable-prompt t) - (defun swiper-at-point () - (interactive) - (swiper (thing-at-point 'word))) - :bind (("C-x b" . ivy-switch-buffer) - ("C-c C-r" . ivy-resume) - ("C-c s" . swiper-at-point) - ("C-s" . swiper)) - :diminish) - -;; ivy-rich makes Ivy look a little bit more like Helm. - -(use-package ivy-rich - :after counsel - :custom - (ivy-virtual-abbreviate 'full - ivy-rich-switch-buffer-align-virtual-buffer t - ivy-rich-path-style 'abbrev) - :init - (ivy-rich-mode)) - -(use-package ivy-hydra) - -;; Slurp environment variables from the shell. - -(use-package exec-path-from-shell - :config - (exec-path-from-shell-initialize)) - -(use-package fish-mode) - -(use-package gnu-elpa-keyring-update) - -;; Counsel applies Ivy-like behavior to other builtin features of -;; emacs, e.g. search. - -(use-package counsel - :ensure t - :after ivy - :init - (counsel-mode 1) - - :bind (("C-c ;" . counsel-M-x) - ("C-c U" . counsel-unicode-char) - ("C-c i" . counsel-imenu) - ("C-x f" . counsel-find-file) - ("C-c y" . counsel-yank-pop) - ("C-c r" . counsel-recentf) - :map ivy-minibuffer-map - ("C-r" . counsel-minibuffer-history)) - :diminish) - -;; Deadgrep is amazing. - -(use-package deadgrep - :bind (("C-c h" . deadgrep))) - -;; projectile comes with Emacs these days, but we want to enable -;; caching, since I work on big projects. - -(use-package projectile - :bind (("C-c f" . projectile-find-file)) - :config - (setq projectile-enable-caching t - projectile-completion-system 'ivy) - :diminish) - -;; Counsel and projectile should work together. - -(use-package counsel-projectile - :bind (("C-c f" . counsel-projectile)) - :init - (counsel-projectile-mode)) - -;; Sort commands by recency in ivy windows. - -(use-package smex) - -;; Keychain stuff. Note to self: if you keep having to enter your -;; keychain password on OS X, make sure that you have the following in .ssh/config: -;; Host * -;; UseKeychain yes - -(use-package keychain-environment - :config - (keychain-refresh-environment)) - -;; Elm stuff. - -(use-package elm-mode - :disabled) - -;; Company is the best Emacs completion system. - -(use-package company - :bind (("C-." . company-complete)) - :diminish company-mode - :custom - (company-dabbrev-downcase nil "Don't downcase returned candidates.") - (company-show-numbers t "Numbers are helpful.") - (company-tooltip-limit 20 "The more the merrier.") - (company-abort-manual-when-too-short t "Be less enthusiastic about completion.") - :config - (global-company-mode) - - ;; use numbers 0-9 to select company completion candidates - (let ((map company-active-map)) - (mapc (lambda (x) (define-key map (format "%d" x) - `(lambda () (interactive) (company-complete-number ,x)))) - (number-sequence 0 9)))) - -;; Textmate-style tap-to-expand-into-the-current-delimiter. - -(use-package expand-region - :bind (("C-c n" . er/expand-region))) - -;; Magit is one of the best pieces of OSS I have ever used. It is truly esssential. - -(use-package magit - :bind (("C-c g" . magit-status)) - :diminish magit-auto-revert-mode - :diminish auto-revert-mode - :custom - (magit-remote-set-if-missing t) - (magit-diff-refine-hunk t) - :config - (magit-auto-revert-mode t) - - ;; Magit, and Emacs in general, has a nasty habit of prompting to save buffers - ;; that are identical to those on disk. This is an attempt at remedying that, - ;; one that I should probably attach to other functions like save-buffers-kill-emacs. - (advice-add 'magit-refresh :before #'maybe-unset-buffer-modified) - (advice-add 'magit-commit :before #'maybe-unset-buffer-modified) - (setq magit-completing-read-function 'ivy-completing-read) - (add-to-list 'magit-no-confirm 'stage-all-changes)) - -;; Unclear whether this does anything at the moment. - -(use-package libgit - :disabled - :after magit) - -;; Since I grew up on Textmate, I'm more-or-less reliant on snippets. - -(use-package yasnippet - :config - (yas-global-mode 1) - (setq yas-prompt-functions '(yas-completing-prompt)) - :diminish yas-minor-mode) - -;; I usually don't edit very large files, but saveplace is nice on the occasions I do. - -(use-package saveplace - :disabled - :config (setq-default save-place t)) - -;; Haskell and Elisp are made a lot easier when delimiters are nicely color-coded. - -(use-package rainbow-delimiters - :disabled - :hook (prog-mode . rainbow-delimiters-mode)) - -;; multiple-cursors is better than cua-selection-mode. -;; TODO: learn ace-mc - -(use-package multiple-cursors - :bind (("C-c M" . mc/edit-lines))) - -;; Common Haskell snippets. These take a while to load, so no need to block on startup. - -(use-package haskell-snippets - :defer yasnippet) - -;; The beauty of undo-tree is that it means that, once you've typed something into -;; a buffer, you'll always be able to get it back. That is crucial. - -(use-package undo-tree - :bind (("C-c _" . undo-tree-visualize)) - :config - (global-undo-tree-mode +1) - (unbind-key "M-_" undo-tree-map) - :diminish) - -;; Trying undo-propose, which seems to offer a better experience, as -;; undo tree is prone to losing data. - -(use-package undo-propose - :disabled - :bind (("C-c _" . undo-propose) - :map undo-propose-mode-map - ("" . undo-only))) - -;; (use-package ansi-color -;; :config -;; (add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)) - -;; C stuff. - -(use-package cc-mode - :disabled) - -;; I do all of my writing in either org-mode or markdown-mode. - -(use-package markdown-mode - :mode ("\\.md$" . gfm-mode) - :config - (when (executable-find "pandoc") - (setq markdown-command "pandoc -f markdown -t html"))) - -;; Avy is better than ace-jump. -(use-package avy - :defer ivy - :bind (("C-c l l" . avy-goto-line) - ("C-c l c" . avy-goto-char-timer) - ("C-c l w" . avy-goto-word-1) - ("C-'" . ivy-avy))) - -(use-package yaml-mode - :bind (("C-c a c" . haskell-cabal-visit-file))) - -;; Quickly duplicate whatever's under the cursor. I'm shocked this requires a -;; third-party package; it should be standard. - -(use-package duplicate-thing - :bind (("C-c u" . duplicate-thing))) - -;; I can never remember the hierarchies of certain bindings, like C-x v for version control -;; stuff. Guide-key helps there. (TODO: figure out other places it'll help.) - -(use-package guide-key - :diminish guide-key-mode - :config - (guide-key-mode t) - (setq guide-key/guide-key-sequence '("C-x v" ;; version control - "C-c a" ;; my mode-specific bindings - "C-c l" ;; line-jumping - "C-c o" - ))) - -;; Since the in-emacs Dash browser doesn't work on OS X, we have to settle for dash-at-point. - -(use-package dash-at-point - :bind ("C-c d" . dash-at-point)) - -;; Need to remember to use this more, though I have my issues with the UI. - -(use-package dumb-jump - :disabled - :bind (("C-c j" . dumb-jump-go-prompt)) - :config (setq dumb-jump-selector 'ivy)) - -(use-package elec-pair - :config - (add-to-list 'electric-pair-pairs '(?` . ?`)) ; electric-quote backticks - (add-to-list 'electric-pair-pairs '(?“ . ?”))) ; and curlies - -;; OCaml is loaded not through melpa, but through OPAM itself. - -(ignore-errors - (autoload (expand-file-name "~/.opam/system/share/emacs/site-lisp/tuareg-site-file"))) - -(defun em-dash () - "Insert an em-dash." - (interactive) - (insert "—")) - -(defun ellipsis () - "Insert an ellipsis." - (interactive) - (insert "…")) - -(defun lambduh () - "Insert a lowercase lambda." - (interactive) - (insert "λ")) - -(defun open-semantic-notes () - "Open my notes file." - (interactive) - (find-file "~/Seafile/Notes/Org/semantic.org")) - -(use-package org - ;; Always get this from the GNU archive. - :pin gnu - - :diminish org-indent-mode - - ;; Global functions that drop me into org-mode-related modes - ;; are prefixed under C-c o. - :bind (("C-c o c" . org-capture) - ("C-c o n" . open-semantic-notes) - ("C-c o s" . org-store-link) - ("C-c o a" . org-agenda) - :map org-mode-map - ("M-s-" . org-insert-todo-heading) - ("M--" . em-dash) - ("M-;" . ellipsis) - ("C-c c" . org-mode-insert-code) - ("C-c a s" . org-emphasize) - ("C-c a r" . org-ref) - ("C-c a e" . outline-show-all) - ("C-c a l" . lambduh) - ("C-c a t" . unindent-by-four)) - - :hook (org-mode . visual-line-mode) - - :config - - ;; TODO: build a real indentation solution - - (defun unindent-by-four () - (interactive) - (indent-rigidly (region-beginning) (region-end) -4)) - - ;; Org-mode conflicts with a lot of stuff I take for granted. - (unbind-key "C-c ;" org-mode-map) - (unbind-key "C-," org-mode-map) - (unbind-key "M-" org-mode-map) - (unbind-key "M-" org-mode-map) - - (let ((todo-path (expand-file-name "~/Seafile/Notes/Org/todo.org"))) - (when (file-exists-p todo-path) - (setq org-agenda-files (list todo-path) - org-default-notes-file todo-path))) - - (setq org-footnote-section "" - org-startup-with-inline-images t - org-pretty-entities t - org-ellipsis "…" - org-startup-folded nil - org-footnote-section nil - org-hide-leading-stars nil - ) - - ;; This allegedly gets better behavior for delineating org-mode - ;; emphasis. But (Monique voice) I would like to see it. - (setcar (nthcdr 4 org-emphasis-regexp-components) 4) - - (defun org-mode-insert-code () - (interactive) - (org-emphasize ?~))) - -;; Autocomplete for org tags. -(use-package org-ac :after org) - -;; Sometimes useful for putting the right piece of punctuation in there. -(use-package typo) - -;; Reference management disabled for org-ref until I figure out what its deal is. -(use-package org-ref - :disabled - :defer - :config - (ignore-errors (load-private-settings))) - -(use-package go-mode - :init - (defun my-go-mode-hook () - (add-hook 'before-save-hook #'gofmt-before-save)) - - :hook (go-mode . my-go-mode-hook)) - -;; Flycheck mode is usually useful. -(use-package flycheck - :hook (org-mode . flycheck-mode) - :config - (setq-default flycheck-ghc-args - '( "-XDataKinds" - "-XDeriveFoldable" - "-XDeriveFunctor" - "-XDeriveGeneric" - "-XDeriveTraversable" - "-XFlexibleContexts" - "-XFlexibleInstances" - "-XMonadFailDesugaring" - "-XMultiParamTypeClasses" - "-XOverloadedStrings" - "-XRecordWildCards" - "-XStandaloneDeriving" - "-XTypeApplications" - )) - - - (global-flycheck-mode) - (add-to-list 'flycheck-checkers 'proselint)) - -;; For Hammerspoon. -(use-package lua-mode) - -;; Haskell is my programming language of choice. -(use-package haskell-mode - :config - - (defun my-haskell-mode-hook () - "Make sure the compile command is right." - (setq-local compile-command "stack build --fast")) - - (unbind-key "C-c C-s" haskell-mode-map) - - ;; I don't go overboard with the symbols but they can be nice. - (setq haskell-font-lock-symbols 't - haskell-font-lock-symbols-alist - '(("\\" . "λ") - ("<=" . "≤") - (">=" . "≥") - ("==" . "≡") - ("<>" . "♢") - ("/=" . "≢") - ("*" . "★") - ("<=<" . "<=<") -;; ("::" . "∷") - ("<+>" . "⍚") - ("undefined" . "⊥") - ("forall" . "∀") - ("." "∘" haskell-font-lock-dot-is-not-composition) ; or '◦' - )) - - ;; Unfortunately haskell-mode doesn't quite track the latest and - ;; greatest in Haskell extensions, so we have to give the font-lock - ;; system a couple of hints. - - (append-to-list haskell-ghc-supported-extensions - '("DerivingVia" "BlockArguments" "DerivingStrategies")) - - (append-to-list haskell-font-lock-keywords '("capi" "via" "stock" "anyclass")) - - (append-to-list haskell-language-extensions - '("-XDataKinds" - "-XDeriveFoldable" - "-XDeriveFunctor" - "-XDeriveGeneric" - "-XDeriveTraversable" - "-XFlexibleContexts" - "-XFlexibleInstances" - "-XMonadFailDesugaring" - "-XMultiParamTypeClasses" - "-XOverloadedStrings" - "-XRecordWildCards" - "-XStandaloneDeriving" - "-XStrictData" - "-XTypeApplications")) - - :mode ("\\.hs$" . haskell-mode) - :hook (haskell-mode . my-haskell-mode-hook) - - :bind (:map haskell-mode-map - ("C-c a c" . haskell-cabal-visit-file) - ("C-c a b" . haskell-mode-stylish-buffer) - ("C-c a i" . haskell-navigate-imports) - ("C-c a a" . haskell-mode-toggle-scc-at-point) - ("C-c a w" . stack-watch))) - -;; Intero… well, it sort-of works. It generally chokes on large projects, -;; but for sandboxes and small projects it's the best thing out there -;; (though I need to try dante-mode, or so joshvera tells me). -(use-package intero - :disabled - :after haskell-mode - :bind (:map haskell-mode-map - ("C-c a r" . intero-repl) - ("C-c a j" . intero-goto-definition) - ("C-c a n" . intero-info) - ("C-c a t" . intero-type-at) - ("C-c a u" . intero-uses-at) - ("C-c a s" . intero-apply-suggestions))) - -(use-package attrap - :bind (("C-c q" . attrap-attrap))) - -(use-package dante - :after haskell-mode - :bind (:map haskell-mode-map - ("C-c a t" . dante-type-at) - ("C-c a n" . dante-info) - ("C-c a s" . attrap-attrap) - )) - -;; Someday I'm going to start using Idris again. -(use-package idris-mode - :disabled - :bind (("C-c C-v" . idris-case-split))) - -(use-package typescript-mode :defer) - -(use-package protobuf-mode) - -(use-package dtrace-script-mode) - -(use-package rust-mode) - -(defun my-elisp-mode-hook () - "My elisp customizations." - (electric-pair-mode 1) - (add-hook 'before-save-hook 'check-parens nil t) - (auto-composition-mode nil)) - -(add-hook 'emacs-lisp-mode-hook 'my-elisp-mode-hook) - -(defun open-init-file () - "Open this very file." - (interactive) - (find-file user-init-file)) - -(defun kill-all-buffers () - "Close all buffers." - (interactive) - (maybe-unset-buffer-modified) - (save-some-buffers) - (mapc 'kill-buffer-with-prejudice (buffer-list))) - -(defun split-right-and-enter () - "Split the window to the right and enter it." - (interactive) - (split-window-right) - (other-window 1)) - -(defun switch-to-previous-buffer () - "Switch to previously open buffer. Repeated invocations toggle between the two most recently open buffers." - (interactive) - (switch-to-buffer (other-buffer (current-buffer) 1))) - -(defun display-startup-echo-area-message () - "Overrides the normally tedious error message." - (message "Welcome back.")) - -(defun eol-then-newline () - "Go to end of line then return." - (interactive) - (move-end-of-line nil) - (newline) - (indent-for-tab-command)) - -;; There is an extant bug where magit-refresh prompts to save files that haven't -;; been modified. We work around this with some defadvice over maybe-unset-buffer-modified. SO: -;; https://emacs.stackexchange.com/questions/24011/make-emacs-diff-files-before-asking-to-save - -(autoload 'diff-no-select "diff") - -(defun current-buffer-matches-file-p () - "Return t if the current buffer is identical to its associated file." - (when (and buffer-file-name (buffer-modified-p)) - (diff-no-select buffer-file-name (current-buffer) nil 'noasync) - (with-current-buffer "*Diff*" - (and (search-forward-regexp "^Diff finished \(no differences\)\." (point-max) 'noerror) t)))) - -(defun maybe-unset-buffer-modified (&optional _) - "Clear modified bit on all unmodified buffers." - (interactive) - (dolist (buf (buffer-list)) - (with-current-buffer buf - (when (and buffer-file-name (buffer-modified-p) (current-buffer-matches-file-p)) - (set-buffer-modified-p nil))))) - -;; Don't prompt to save unmodified buffers on exit. -(advice-add 'save-buffers-kill-emacs :before #'maybe-unset-buffer-modified) - -(defun kill-buffer-with-prejudice (&optional _) - "Kill a buffer, eliding the save dialogue if there are no diffs." - (interactive) - (when (current-buffer-matches-file-p) (set-buffer-modified-p nil)) - (kill-buffer)) - -(bind-key "C-x k" 'kill-buffer-with-prejudice) -(bind-key "C-c e" 'open-init-file) -(bind-key "C-c k" 'kill-all-buffers) -(bind-key "s-" 'eol-then-newline) -(bind-key "C-c 5" 'query-replace-regexp) ;; stupid vestigial binding -(bind-key "M-/" 'hippie-expand) -(bind-key "C-c '" 'switch-to-previous-buffer) -(bind-key "C-c \\" 'align-regexp) -(bind-key "C-c m" 'compile) -(bind-key "C-c 3" 'split-right-and-enter) -(bind-key "C-c /" 'comment-or-uncomment-region) -(bind-key "C-c x" 'ESC-prefix) -(bind-key "C-," 'other-window) -(bind-key "M-," 'other-window) -(bind-key "M-i" 'delete-indentation) - -;; When tracking down slowness, opening ivy to start these functions -;; throws off the traces. -;; (bind-key "C-c a p" 'profiler-start) -;; (bind-key "C-c a P" 'profiler-report) - -;; macOS-style bindings, too (no cua-mode, it's nasty) -(bind-key "s-+" 'text-scale-increase) -(bind-key "s-_" 'text-scale-decrease) -(bind-key "s-s" 'save-buffer) -(bind-key "s-c" 'kill-ring-save) -(bind-key "s-v" 'yank) -(bind-key "s-z" 'undo) -(bind-key "s-a" 'mark-whole-buffer) -(bind-key "s-<" 'beginning-of-buffer) -(bind-key "s-x" 'kill-region) -(bind-key "" 'beginning-of-buffer) -(bind-key "" 'end-of-buffer) -(bind-key "s->" 'end-of-buffer) -(bind-key "M-_" 'em-dash) -(bind-key "M-;" 'ellipsis) -(bind-key "C-=" 'next-error) -(bind-key "s-{" 'previous-buffer) -(bind-key "s-}" 'next-buffer) - -(unbind-key "C-z") ;; I never want to suspend the frame -(unbind-key "C-") ;; prevent switching to tab mode randomly -(unbind-key "C-h n") ;; I have never wanted to see emacs news ever -(unbind-key "C-h C-n") ;; why on earth is it bound to two keybindings?? -(unbind-key "C-x C-d") ;; list-directory is utterly useless given the existence of dired -(unbind-key "M-o") ;; facemenu mode is useless -(unbind-key "C-x C-r") ;; as is find-file-read-only - - -;; I'm not made of time, I can't type "yes" for every choice -(defalias 'yes-or-no-p 'y-or-n-p) - -(global-hl-line-mode t) ; Always highlight the current line. -(show-paren-mode t) ; And point out matching parentheses. -(delete-selection-mode t) ; Behave like any other sensible text editor would. -(save-place-mode) ; Remember where I was - -;; Make sure that ligatures from fonts that offer them are enabled. -;; This isn't present on GNU Emacs and requires a tremendous amount -;; of munging of 'prettify-symbols-alist'. -;; (ignore-errors (mac-auto-operator-composition-mode)) - -(setq - compilation-always-kill t ; Never prompt to kill a compilation session. - compilation-scroll-output 'first-error ; Always scroll to the bottom. - make-backup-files nil ; No backups, thanks. - auto-save-default nil ; Or autosaves. What's the difference between autosaves and backups? - create-lockfiles nil ; Emacs sure loves to put lockfiles everywhere. - default-directory "~/src/" ; My code lives here. - inhibit-startup-screen t ; No need to see GNU agitprop. - kill-whole-line t ; Lets C-k delete the whole line - mac-command-modifier 'super ; I'm not sure this is the right toggle, but whatever. - require-final-newline t ; Auto-insert trailing newlines. - ring-bell-function 'ignore ; Do not ding. Ever. - use-dialog-box nil ; Dialogues always go in the modeline. - frame-title-format "emacs – %b" ; Put something useful in the status bar. - initial-scratch-message nil ; SHUT UP SHUT UP SHUT UP - mac-option-modifier 'meta ; why isn't this the default - save-interprogram-paste-before-kill t ; preserve paste to system ring - enable-recursive-minibuffers t ; don't fucking freak out if I use the minibuffer twice - sentence-end-double-space nil ; are you fucking kidding me with this shit - confirm-kill-processes nil ; don't whine at me when I'm quitting. - mac-mouse-wheel-smooth-scroll nil ; no smooth scrolling - mac-drawing-use-gcd t ; and you can do it on other frames - mark-even-if-inactive nil ; prevent really unintuitive undo behavior - user-full-name "Patrick Thomson" ; it me - ) - -;; dired whines at you on macOS unless you do this. -(when (eq system-type 'darwin) - (setq dired-use-ls-dired nil)) - -(setq-default - cursor-type 'bar - indent-tabs-mode nil - cursor-in-non-selected-windows nil) - - -(set-fill-column 95) - -;; Always trim trailing whitespace. - -(add-hook 'before-save-hook 'delete-trailing-whitespace) - -;; (setq debug-on-error nil) - -;; Show file full path in title bar -(setq-default frame-title-format - (list '((buffer-file-name " %f" - (dired-directory - dired-directory - (revert-buffer-function " %b" - ("%b - Dir: " default-directory))))))) - -(require 'org-bullets) -(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))) - -;; Make check lists in org-mode pretty -(add-hook 'org-mode-hook (lambda () - "Beautify Org Checkbox Symbol" - (push '("[ ]" . "☐") prettify-symbols-alist) - (push '("[X]" . "☑" ) prettify-symbols-alist) - (push '("[-]" . "❍" ) prettify-symbols-alist) - (prettify-symbols-mode))) - -(defface org-checkbox-done-text - '((t (:foreground "#71696A" :strike-through t))) - "Face for the text part of a checked org-mode checkbox.") - -(font-lock-add-keywords - 'org-mode - `(("^[ \t]*\\(?:[-+*]\\|[0-9]+[).]\\)[ \t]+\\(\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\[\\(?:X\\|\\([0-9]+\\)/\\2\\)\\][^\n]*\n\\)" - 1 'org-checkbox-done-text prepend)) - 'append) - -;; Configure backup files to be in a dedicated directory -(setq backup-directory-alist `(("." . "~/.emacs-backup"))) -(setq backup-by-copying t) -(setq delete-old-versions t - kept-new-versions 6 - kept-old-versions 2 - version-control t) - -;; goodbye, thanks for reading - -(provide 'init) -;;; init.el ends here +;; init.el -- Patrick Thomson's emacs config. -*- lexical-binding: t; -*- + +;;; Commentary: +;; This file is in the public domain. +;; +;; If you want to give this file a try, you can just drop it into +;; ~/.emacs.d: it downloads everything it needs. It is also relatively +;; fast to start up (once it's downloaded all the required packages), +;; as it endeavours to load packages lazily when possible. +;; +;; A general note on keybindings: the custom keybindings applicable to +;; all major modes appear with the C-c prefix, as is standard. +;; Per-language commands appear with the C-c a prefix. The most +;; important keybinding, C-;, provides counsel-M-x, which lets you +;; fuzzy-find through the space of available functions. Exploring +;; counsel-M-x is the best way to become familiar with the space of +;; extensible functions, which is a sine qua non for being comfortable +;; with Emacs. + +;;; Code: + +;; To start, we adjust the garbage collection param + +(setq gc-cons-threshold 32000000 ;; 32 MB + garbage-collection-messages t) ;; indicator of thrashing + +;; Bump up the recursion limit. +(setq max-lisp-eval-depth 2000) + +;; Package-initialization preamble, adding melpa and melpa-stable. + +(require 'package) + +(defmacro append-to-list (target suffix) + "Append SUFFIX to TARGET in place." + `(setq ,target (append ,target ,suffix))) + +(append-to-list package-archives + '(("melpa" . "http://melpa.org/packages/") + ("melpa-stable" . "http://stable.melpa.org/packages/") + ("org-elpa" . "https://orgmode.org/elpa/"))) + +(package-initialize) + +;; Ensure use-package is present. From here on out, all packages are loaded +;; with use-package. + +(unless (package-installed-p 'use-package) + (package-refresh-contents) + (package-install 'use-package)) + +;; Allow navigation between use-package stanzas with iMenu. +(setq-default use-package-enable-imenu-support t) + +(require 'use-package) + +(setq + use-package-always-ensure t + use-package-verbose t) + +;; Set the zenburn theme +;; TODO + +(use-package solarized-theme + :config + (load-theme 'solarized-light t) + (let ((line (face-attribute 'mode-line :underline))) + (set-face-attribute 'mode-line nil :overline line) + (set-face-attribute 'mode-line-inactive nil :overline line) + (set-face-attribute 'mode-line-inactive nil :underline line) + (set-face-attribute 'mode-line nil :box nil) + (set-face-attribute 'mode-line-inactive nil :box nil) + (set-face-attribute 'mode-line-inactive nil :background "#f9f2d9"))) + + +;; Use moody modeline +(use-package moody + :config + (setq x-underline-at-descent-line t) + (moody-replace-mode-line-buffer-identification) + (moody-replace-vc-mode)) + +;; Minions to add a menu with minor modes to the modeline +(use-package minions + :config (minions-mode 1)) + +;; UTF-8 everywhere, please. +(prefer-coding-system 'utf-8) + +(set-face-attribute 'default nil + :family "Hack" + :height 110 + :weight 'normal + :width 'normal) + +;; Any Customize-based settings should live in custom.el, not here. + +(setq custom-file "~/.emacs.d/custom.el") +(load custom-file 'noerror) + +;; Always prefer newer files. +(setq load-prefer-newer t) + +;; Disable otiose GUI settings: they just waste space. +;; fringe-mode is especially ruinous performance-wise. +(when (window-system) + (tool-bar-mode -1) + (scroll-bar-mode -1) + (tooltip-mode -1) + (fringe-mode -1)) + +;; Haven't figured out how to diminish eldoc-mode outside of +;; requiring this explicitly and doing it manually. +(use-package diminish + :ensure t) + +(diminish 'eldoc-mode) + +(use-package all-the-icons) + +;; Ensure that items in the PATH are made available to Emacs. This should +;; probably just come with the main distribution. + +;; Recentf comes with Emacs but it should always be enabled. +(use-package recentf + :init (recentf-mode t) + :config + (add-to-list 'recentf-exclude "\\.emacs.d") + (add-to-list 'recentf-exclude ".+tmp......\\.org")) + +;; Ivy makes most minibuffer prompts sortable and filterable. I used +;; to use helm, but it was too slow. Unfortunately org-ref depends on +;; it, but I never load it, so we good. +(use-package ivy + :ensure t + :init + (ivy-mode 1) + (unbind-key "S-SPC" ivy-minibuffer-map) + (setq ivy-height 30 + ivy-use-virtual-buffers t + ivy-use-selectable-prompt t) + (defun swiper-at-point () + (interactive) + (swiper (thing-at-point 'word))) + :bind (("C-x b" . ivy-switch-buffer) + ("C-c C-r" . ivy-resume) + ("C-c s" . swiper-at-point) + ("C-s" . swiper)) + :diminish) + +;; ivy-rich makes Ivy look a little bit more like Helm. +(use-package ivy-rich + :after counsel + :custom + (ivy-virtual-abbreviate 'full + ivy-rich-switch-buffer-align-virtual-buffer t + ivy-rich-path-style 'abbrev) + :init + (ivy-rich-mode)) + +(use-package ivy-hydra) + +;; Slurp environment variables from the shell. +(use-package exec-path-from-shell + :config + (exec-path-from-shell-initialize)) + +(use-package fish-mode) + +(use-package gnu-elpa-keyring-update) + +;; Counsel applies Ivy-like behavior to other builtin features of +;; emacs, e.g. search. +(use-package counsel + :ensure t + :after ivy + :init + (counsel-mode 1) + + :bind (("C-c ;" . counsel-M-x) + ("C-c U" . counsel-unicode-char) + ("C-c i" . counsel-imenu) + ("C-x f" . counsel-find-file) + ("C-c y" . counsel-yank-pop) + ("C-c r" . counsel-recentf) + :map ivy-minibuffer-map + ("C-r" . counsel-minibuffer-history)) + :diminish) + +;; Deadgrep is amazing. +(use-package deadgrep + :bind (("C-c h" . deadgrep))) + +;; projectile comes with Emacs these days, but we want to enable +;; caching, since I work on big projects. +(use-package projectile + :bind (("C-c f" . projectile-find-file)) + :config + (setq projectile-enable-caching t + projectile-completion-system 'ivy) + :diminish) + +;; Counsel and projectile should work together. +(use-package counsel-projectile + :bind (("C-c f" . counsel-projectile)) + :init + (counsel-projectile-mode)) + +;; Sort commands by recency in ivy windows. +(use-package smex) + +;; Keychain stuff. Note to self: if you keep having to enter your +;; keychain password on OS X, make sure that you have the following in .ssh/config: +;; Host * +;; UseKeychain yes +(use-package keychain-environment + :config + (keychain-refresh-environment)) + +;; Elm stuff. +(use-package elm-mode + :disabled) + +;; Company is the best Emacs completion system. +(use-package company + :bind (("C-." . company-complete)) + :diminish company-mode + :custom + (company-dabbrev-downcase nil "Don't downcase returned candidates.") + (company-show-numbers t "Numbers are helpful.") + (company-tooltip-limit 20 "The more the merrier.") + (company-abort-manual-when-too-short t "Be less enthusiastic about completion.") + :config + (global-company-mode) + + ;; use numbers 0-9 to select company completion candidates + (let ((map company-active-map)) + (mapc (lambda (x) (define-key map (format "%d" x) + `(lambda () (interactive) (company-complete-number ,x)))) + (number-sequence 0 9)))) + +;; Textmate-style tap-to-expand-into-the-current-delimiter. + +(use-package expand-region + :bind (("C-c n" . er/expand-region))) + +;; Magit is one of the best pieces of OSS I have ever used. It is truly esssential. + +(use-package magit + :bind (("C-c g" . magit-status)) + :diminish magit-auto-revert-mode + :diminish auto-revert-mode + :custom + (magit-remote-set-if-missing t) + (magit-diff-refine-hunk t) + :config + (magit-auto-revert-mode t) + + ;; Magit, and Emacs in general, has a nasty habit of prompting to save buffers + ;; that are identical to those on disk. This is an attempt at remedying that, + ;; one that I should probably attach to other functions like save-buffers-kill-emacs. + (advice-add 'magit-refresh :before #'maybe-unset-buffer-modified) + (advice-add 'magit-commit :before #'maybe-unset-buffer-modified) + (setq magit-completing-read-function 'ivy-completing-read) + (add-to-list 'magit-no-confirm 'stage-all-changes)) + +;; Unclear whether this does anything at the moment. +(use-package libgit + :disabled + :after magit) + +;; Since I grew up on Textmate, I'm more-or-less reliant on snippets +(use-package yasnippet + :config + (yas-global-mode 1) + (setq yas-prompt-functions '(yas-completing-prompt)) + :diminish yas-minor-mode) + +;; I usually don't edit very large files, but saveplace is nice on the occasions I do. +(use-package saveplace + :disabled + :config (setq-default save-place t)) + +;; Haskell and Elisp are made a lot easier when delimiters are nicely color-coded. +(use-package rainbow-delimiters + :disabled + :hook (prog-mode . rainbow-delimiters-mode)) + +;; multiple-cursors is better than cua-selection-mode. +;; TODO: learn ace-mc +(use-package multiple-cursors + :bind (("C-c M" . mc/edit-lines))) + +;; The beauty of undo-tree is that it means that, once you've typed something into +;; a buffer, you'll always be able to get it back. That is crucial. +(use-package undo-tree + :bind (("C-x u" . undo-tree-visualize)) + :config + (global-undo-tree-mode +1) + (unbind-key "M-_" undo-tree-map) + :diminish) + +;; Trying undo-propose, which seems to offer a better experience, as +;; undo tree is prone to losing data. +(use-package undo-propose + :disabled + :bind (("C-c _" . undo-propose) + :map undo-propose-mode-map + ("" . undo-only))) + +;; (use-package ansi-color +;; :config +;; (add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)) + +;; C stuff. +(use-package cc-mode + :disabled) + +;; I do all of my writing in either org-mode or markdown-mode. +(use-package markdown-mode + :mode ("\\.md$" . gfm-mode) + :config + (when (executable-find "pandoc") + (setq markdown-command "pandoc -f markdown -t html"))) + +;; Avy is better than ace-jump. +(use-package avy + :defer ivy + :bind (("C-c l l" . avy-goto-line) + ("C-c l c" . avy-goto-char-timer) + ("C-c l w" . avy-goto-word-1) + ("C-'" . ivy-avy))) + +;; Quickly duplicate whatever's under the cursor. I'm shocked this requires a +;; third-party package; it should be standard. +(use-package duplicate-thing + :bind (("C-c u" . duplicate-thing))) + +;; I can never remember the hierarchies of certain bindings, like C-x v for version control +;; stuff. Guide-key helps there. (TODO: figure out other places it'll help.) +(use-package guide-key + :diminish guide-key-mode + :config + (guide-key-mode t) + (setq guide-key/guide-key-sequence '("C-x v" ;; version control + "C-c a" ;; my mode-specific bindings + "C-c l" ;; line-jumping + "C-c o" + ))) + +(use-package elec-pair + :config + (add-to-list 'electric-pair-pairs '(?` . ?`)) ; electric-quote backticks + (add-to-list 'electric-pair-pairs '(?“ . ?”))) ; and curlies + +;; OCaml is loaded not through melpa, but through OPAM itself. +(ignore-errors + (autoload (expand-file-name "~/.opam/system/share/emacs/site-lisp/tuareg-site-file"))) + +(defun em-dash () + "Insert an em-dash." + (interactive) + (insert "—")) + +(defun ellipsis () + "Insert an ellipsis." + (interactive) + (insert "…")) + +(defun lambduh () + "Insert a lowercase lambda." + (interactive) + (insert "λ")) + +(defun open-semantic-notes () + "Open my notes file." + (interactive) + (find-file "~/Seafile/Notes/Org/semantic.org")) + +(use-package org + ;; Always get this from the GNU archive. + :pin gnu + + :diminish org-indent-mode + + ;; Global functions that drop me into org-mode-related modes + ;; are prefixed under C-c o. + :bind (("C-c o c" . org-capture) + ("C-c o n" . open-semantic-notes) + ("C-c o s" . org-store-link) + ("C-c o a" . org-agenda) + :map org-mode-map + ("M-s-" . org-insert-todo-heading) + ("M--" . em-dash) + ("M-;" . ellipsis) + ("C-c c" . org-mode-insert-code) + ("C-c a s" . org-emphasize) + ("C-c a r" . org-ref) + ("C-c a e" . outline-show-all) + ("C-c a l" . lambduh) + ("C-c a t" . unindent-by-four)) + + :hook (org-mode . visual-line-mode) + + :config + + ;; TODO: build a real indentation solution + (defun unindent-by-four () + (interactive) + (indent-rigidly (region-beginning) (region-end) -4)) + + ;; Org-mode conflicts with a lot of stuff I take for granted. + (unbind-key "C-c ;" org-mode-map) + (unbind-key "C-," org-mode-map) + (unbind-key "M-" org-mode-map) + (unbind-key "M-" org-mode-map) + + (let ((todo-path (expand-file-name "~/Seafile/Notes/Org/todo.org"))) + (when (file-exists-p todo-path) + (setq org-agenda-files (list todo-path) + org-default-notes-file todo-path))) + + (setq org-footnote-section "" + org-startup-with-inline-images t + org-pretty-entities t + org-ellipsis "…" + org-startup-folded nil + org-footnote-section nil + org-hide-leading-stars nil + ) + + ;; This allegedly gets better behavior for delineating org-mode + ;; emphasis. But (Monique voice) I would like to see it. + (setcar (nthcdr 4 org-emphasis-regexp-components) 4) + + (defun org-mode-insert-code () + (interactive) + (org-emphasize ?~))) + +;; Autocomplete for org tags. +(use-package org-ac :after org) + +;; Sometimes useful for putting the right piece of punctuation in there. +(use-package typo) + +;; Reference management disabled for org-ref until I figure out what its deal is. +(use-package org-ref + :disabled + :defer + :config + (ignore-errors (load-private-settings))) + +(use-package go-mode + :init + (defun my-go-mode-hook () + (add-hook 'before-save-hook #'gofmt-before-save)) + + :hook (go-mode . my-go-mode-hook)) + +;; Flycheck mode is usually useful. +(use-package flycheck + :hook (org-mode . flycheck-mode) + :config + (setq-default flycheck-ghc-args + '( "-XDataKinds" + "-XDeriveFoldable" + "-XDeriveFunctor" + "-XDeriveGeneric" + "-XDeriveTraversable" + "-XFlexibleContexts" + "-XFlexibleInstances" + "-XMonadFailDesugaring" + "-XMultiParamTypeClasses" + "-XOverloadedStrings" + "-XRecordWildCards" + "-XStandaloneDeriving" + "-XTypeApplications" + )) + + + (global-flycheck-mode) + (add-to-list 'flycheck-checkers 'proselint)) + +;; For Hammerspoon. +(use-package lua-mode) + +(use-package typescript-mode :defer) + +(use-package protobuf-mode) + +(use-package dtrace-script-mode) + +(use-package rust-mode) + +(defun my-elisp-mode-hook () + "My elisp customizations." + (electric-pair-mode 1) + (add-hook 'before-save-hook 'check-parens nil t) + (auto-composition-mode nil)) + +(add-hook 'emacs-lisp-mode-hook 'my-elisp-mode-hook) + +(defun open-init-file () + "Open this very file." + (interactive) + (find-file user-init-file)) + +(defun kill-all-buffers () + "Close all buffers." + (interactive) + (maybe-unset-buffer-modified) + (save-some-buffers) + (mapc 'kill-buffer-with-prejudice (buffer-list))) + +(defun split-right-and-enter () + "Split the window to the right and enter it." + (interactive) + (split-window-right) + (other-window 1)) + +(defun switch-to-previous-buffer () + "Switch to previously open buffer. Repeated invocations toggle between the two most recently open buffers." + (interactive) + (switch-to-buffer (other-buffer (current-buffer) 1))) + +(defun display-startup-echo-area-message () + "Overrides the normally tedious error message." + (message "Welcome back.")) + +(defun eol-then-newline () + "Go to end of line then return." + (interactive) + (move-end-of-line nil) + (newline) + (indent-for-tab-command)) + +;; There is an extant bug where magit-refresh prompts to save files that haven't +;; been modified. We work around this with some defadvice over maybe-unset-buffer-modified. SO: +;; https://emacs.stackexchange.com/questions/24011/make-emacs-diff-files-before-asking-to-save + +(autoload 'diff-no-select "diff") + +(defun current-buffer-matches-file-p () + "Return t if the current buffer is identical to its associated file." + (when (and buffer-file-name (buffer-modified-p)) + (diff-no-select buffer-file-name (current-buffer) nil 'noasync) + (with-current-buffer "*Diff*" + (and (search-forward-regexp "^Diff finished \(no differences\)\." (point-max) 'noerror) t)))) + +(defun maybe-unset-buffer-modified (&optional _) + "Clear modified bit on all unmodified buffers." + (interactive) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when (and buffer-file-name (buffer-modified-p) (current-buffer-matches-file-p)) + (set-buffer-modified-p nil))))) + +;; Don't prompt to save unmodified buffers on exit. +(advice-add 'save-buffers-kill-emacs :before #'maybe-unset-buffer-modified) + +(defun kill-buffer-with-prejudice (&optional _) + "Kill a buffer, eliding the save dialogue if there are no diffs." + (interactive) + (when (current-buffer-matches-file-p) (set-buffer-modified-p nil)) + (kill-buffer)) + +(bind-key "C-x k" 'kill-buffer-with-prejudice) +(bind-key "C-c e" 'open-init-file) +(bind-key "C-c k" 'kill-all-buffers) +(bind-key "s-" 'eol-then-newline) +(bind-key "C-c 5" 'query-replace-regexp) ;; stupid vestigial binding +(bind-key "M-/" 'hippie-expand) +(bind-key "C-c '" 'switch-to-previous-buffer) +(bind-key "C-c \\" 'align-regexp) +(bind-key "C-c m" 'compile) +(bind-key "C-c 3" 'split-right-and-enter) +(bind-key "C-c /" 'comment-or-uncomment-region) +(bind-key "C-c x" 'ESC-prefix) +(bind-key "C-," 'other-window) +(bind-key "M-," 'other-window) +(bind-key "M-i" 'delete-indentation) + +;; When tracking down slowness, opening ivy to start these functions +;; throws off the traces. +;; (bind-key "C-c a p" 'profiler-start) +;; (bind-key "C-c a P" 'profiler-report) + +;; macOS-style bindings, too (no cua-mode, it's nasty) +(bind-key "s-+" 'text-scale-increase) +(bind-key "s-_" 'text-scale-decrease) +(bind-key "s-s" 'save-buffer) +(bind-key "s-c" 'kill-ring-save) +(bind-key "s-v" 'yank) +(bind-key "s-z" 'undo) +(bind-key "s-a" 'mark-whole-buffer) +(bind-key "s-<" 'beginning-of-buffer) +(bind-key "s-x" 'kill-region) +(bind-key "" 'beginning-of-buffer) +(bind-key "" 'end-of-buffer) +(bind-key "s->" 'end-of-buffer) +(bind-key "M-_" 'em-dash) +(bind-key "M-;" 'ellipsis) +(bind-key "C-=" 'next-error) +(bind-key "s-{" 'previous-buffer) +(bind-key "s-}" 'next-buffer) + +(unbind-key "C-z") ;; I never want to suspend the frame +(unbind-key "C-") ;; prevent switching to tab mode randomly +(unbind-key "C-h n") ;; I have never wanted to see emacs news ever +(unbind-key "C-h C-n") ;; why on earth is it bound to two keybindings?? +(unbind-key "C-x C-d") ;; list-directory is utterly useless given the existence of dired +(unbind-key "M-o") ;; facemenu mode is useless +(unbind-key "C-x C-r") ;; as is find-file-read-only + + +;; I'm not made of time, I can't type "yes" for every choice +(defalias 'yes-or-no-p 'y-or-n-p) + +(global-hl-line-mode t) ; Always highlight the current line. +(show-paren-mode t) ; And point out matching parentheses. +(delete-selection-mode t) ; Behave like any other sensible text editor would. +(save-place-mode) ; Remember where I was + +;; Make sure that ligatures from fonts that offer them are enabled. +;; This isn't present on GNU Emacs and requires a tremendous amount +;; of munging of 'prettify-symbols-alist'. +;; (ignore-errors (mac-auto-operator-composition-mode)) + +(setq + compilation-always-kill t ; Never prompt to kill a compilation session. + compilation-scroll-output 'first-error ; Always scroll to the bottom. + make-backup-files nil ; No backups, thanks. + auto-save-default nil ; Or autosaves. What's the difference between autosaves and backups? + create-lockfiles nil ; Emacs sure loves to put lockfiles everywhere. + default-directory "~/Notes/" ; All my Notes are here. + inhibit-startup-screen t ; No need to see GNU agitprop. + kill-whole-line t ; Lets C-k delete the whole line + require-final-newline t ; Auto-insert trailing newlines. + ring-bell-function 'ignore ; Do not ding. Ever. + use-dialog-box nil ; Dialogues always go in the modeline. + frame-title-format "emacs – %b" ; Put something useful in the status bar. + initial-scratch-message nil ; SHUT UP SHUT UP SHUT UP + save-interprogram-paste-before-kill t ; preserve paste to system ring + enable-recursive-minibuffers t ; don't fucking freak out if I use the minibuffer twice + sentence-end-double-space nil ; are you fucking kidding me with this shit + confirm-kill-processes nil ; don't whine at me when I'm quitting. + mark-even-if-inactive nil ; prevent really unintuitive undo behavior + user-full-name "Marcel Fries" ; it me + ) + +(setq-default + cursor-type 'bar + indent-tabs-mode nil + cursor-in-non-selected-windows nil) + + +(set-fill-column 95) + +;; Always trim trailing whitespace. +(add-hook 'before-save-hook 'delete-trailing-whitespace) + +;; (setq debug-on-error nil) + +;; Show file full path in title bar +(setq-default frame-title-format + (list '((buffer-file-name " %f" + (dired-directory + dired-directory + (revert-buffer-function " %b" + ("%b - Dir: " default-directory))))))) + +;; Make org-mode look pretty +(use-package org-bullets + :init (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))) + +(add-hook 'org-mode-hook (lambda () + "Beautify Org Checkbox Symbol" + (push '("[ ]" . "☐") prettify-symbols-alist) + (push '("[X]" . "☑" ) prettify-symbols-alist) + (push '("[-]" . "❍" ) prettify-symbols-alist) + (prettify-symbols-mode))) + +(defface org-checkbox-done-text + '((t (:foreground "#71696A" :strike-through t))) + "Face for the text part of a checked org-mode checkbox.") + +(font-lock-add-keywords + 'org-mode + `(("^[ \t]*\\(?:[-+*]\\|[0-9]+[).]\\)[ \t]+\\(\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\[\\(?:X\\|\\([0-9]+\\)/\\2\\)\\][^\n]*\n\\)" + 1 'org-checkbox-done-text prepend)) + 'append) + +;; Configure backup files to be in a dedicated directory +(setq backup-directory-alist `(("." . "~/.emacs-backup"))) +(setq backup-by-copying t) +(setq delete-old-versions t + kept-new-versions 6 + kept-old-versions 2 + version-control t) + +;; goodbye, thanks for reading + +(provide 'init) +;;; init.el ends here