Skip to content

Latest commit

 

History

History
1039 lines (743 loc) · 25.3 KB

config.org

File metadata and controls

1039 lines (743 loc) · 25.3 KB

Emacs Configuration

Initialization

Package management

Use use-package for package management.

(setq package-archives
      '(("gnu"	      . "https://elpa.gnu.org/packages/")
        ("melpa-stable" . "https://stable.melpa.org/packages/")
        ("melpa"        . "https://melpa.org/packages/")
        ("org"          . "https://orgmode.org/elpa/")))

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(setq use-package-always-ensure t)

(use-package delight :ensure t)
(use-package diminish :ensure t)
(use-package use-package-ensure-system-package :ensure t)

Disable that annoying bell sound.

(setq ring-bell-function (lambda () (message "*beep*")))

Emacs

Better GC values.

(setq gc-cons-threshold 10000000)

(let ((normal-gc-cons-threshold (* 20 1024 1024))
      (init-gc-cons-threshold (* 128 1024 1024)))
  (setq gc-cons-threshold init-gc-cons-threshold)
  (add-hook 'after-init-hook
            (lambda ()
              (setq gc-cons-threshold normal-gc-cons-threshold))))

Better M-x menu.

(use-package smex)

Better buffer navigation and manipulation. Replace default buffer UI with ibuffer.

(use-package ibuffer
  :defer t
  :bind ("C-x C-b" . ibuffer)
  :custom
  (defalias 'list-buffers 'ibuffer))

Customizations

Avoid appending UI customizations to init.el.

(setq-default custom-file (expand-file-name "custom.el" user-emacs-directory))

(when (file-exists-p custom-file)
  (load custom-file t))

Base

General

I work in UTF-8.

(setq locale-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(prefer-coding-system 'utf-8)

Default settings for Emacs.

(setq
 ad-redefinition-action 'accept                   ; Silence warnings for redefinition
 cursor-in-non-selected-windows t                 ; Hide the cursor in inactive windows
 display-time-default-load-average nil            ; Don't display load average
 fill-column 80                                   ; Set width for automatic line breaks
 help-window-select t                             ; Focus new help windows when opened
 inhibit-startup-screen t                         ; Disable start-up screen
 initial-scratch-message ""                       ; Empty the initial *scratch* buffer
 load-prefer-newer t                              ; Prefers the newest version of a file
 scroll-margin 8                                  ;  smooth scroll
 redisplay-dont-pause t
 scroll-preserve-screen-position 1
 scroll-conservatively 1000
 scroll-step 1
 select-enable-clipboard t                        ; Merge system's and Emacs' clipboard
 tab-width 4                                      ; Set width for tabs
 use-package-always-ensure t                      ; Avoid the :ensure keyword for each package
 user-full-name "chris etheridge"                 ; Set the full name of the current user
 user-mail-address "[email protected]"    ; Set the email address of the current user
 ffap-machine-p-known  'reject                    ; don't try ping domains
 delete-by-moving-to-trash t                        ; delete by moving to trash
 show-trailing-whitespace t                       ; always show trailing whitespace
 vc-follow-symlinks t
 disabled-command-function nil
 indent-tabs-mode nil
 tab-always-indent 'complete)                            ; Always follow the symlinks
(cd "~/")                                         ; Move to the user directory
(column-number-mode 1)                            ; Show the column number
(global-linum-mode 1)                             ; Enable line numbers
(display-time-mode 1)                             ; Enable time in the mode-line
(fset 'yes-or-no-p 'y-or-n-p)                     ; Replace yes/no prompts with y/n
(show-paren-mode 1)                               ; Show the parent
(delete-selection-mode 1)                           ; Replace selection on paste
(global-subword-mode 1) ; Move through camel case words
(electric-pair-mode 1) ; match parenthesis
(global-auto-revert-mode 1) ; refresh buffers

Disable that annoying bell sound.

(setq ring-bell-function (lambda () (message "*beep*")))

Always :ensure packages.

(setq use-package-always-ensure t)

Saving / backups

Use saveplace to save place in file after closing.

(use-package saveplace
  :config
  (setq save-place-file (concat user-emacs-directory "places")))

Clean whitespace upon saving, and disable backups, change autosave file location.

(setq-default backup-inhibited t)
(add-hook 'before-save-hook 'delete-trailing-whitespace)

(setq auto-save-file-name-transforms
      `((".*" "~/.emacs-saves/" t)))

Environment

(setenv "PATH" (concat "/usr/local/bin:" (getenv "PATH")))
(add-to-list 'exec-path "/usr/local/bin")

Make Emacs read vars from the environment.

(use-package exec-path-from-shell
  :config
  (exec-path-from-shell-initialize))

Emacs

Better M-x menu.

(use-package smex)

Better buffer navigation and manipulation. Replace default buffer UI with ibuffer.

(use-package ibuffer
  :defer t
  :bind ("C-x C-b" . ibuffer)
  :custom
  (defalias 'list-buffers 'ibuffer))

Track key frequency.

(use-package keyfreq
  :bind ("M-f" . keyfreq-show)
  :custom
  (keyfreq-mode 1)
  (keyfreq-autosave-mode 1))

Git

Magit for git management.

(use-package magit
  :defer t
  :bind ("C-c g" . magit-status)
  :delight
  (magit-autro-revert-mode)
  (auto-revert-mode))

Show Git changes in the fringe of Emacs. https://github.com/syohex/emacs-git-gutter-fringe

(use-package git-gutter-fringe
  :defer t
  :custom
  (git-gutter-mode))

Show historical git versions of files.

(use-package git-timemachine
  :config
  (setq git-timemachine-abbreviation-length 6))

(use-package evil-leader)
(use-package evil-magit)

Customizations

Avoid appending UI customizations to init.el.

(setq-default custom-file (expand-file-name "custom.el" user-emacs-directory))
(when (file-exists-p custom-file)
  (load custom-file t))

UI customizations

Look and feel

Font and theme

(load-theme 'poet-monochrome t)

(set-frame-font "Hack 12" nil t)

;; override poet theme font settings
(set-face-attribute 'default nil :family "Hack" :height 120)
(set-face-attribute 'fixed-pitch nil :family "Hack")
(set-face-attribute 'variable-pitch nil :family "Hack")

Modeline

Add line, column, and file size to modeline.

(line-number-mode t)
(column-number-mode t)
(size-indication-mode t)

Use telephone line for the modeline.

(use-package doom-modeline
  :ensure t
  :defer t
  :hook (after-init . doom-modeline-init)
  :config
  ;; How tall the mode-line should be (only respected in GUI Emacs).
  (setq doom-modeline-height 30)

  ;; How wide the mode-line bar should be (only respected in GUI Emacs).
  (setq doom-modeline-bar-width 3)

  ;; Whether show `all-the-icons' or not (if nil nothing will be showed).
  ;; The icons may not be showed correctly on Windows. Disable to make it work.
  (setq doom-modeline-icon nil)

  ;; Determines the style used by `doom-modeline-buffer-file-name'.
  ;;
  ;; Given ~/Projects/FOSS/emacs/lisp/comint.el
  ;;   truncate-upto-project => ~/P/F/emacs/lisp/comint.el
  ;;   truncate-from-project => ~/Projects/FOSS/emacs/l/comint.el
  ;;   truncate-with-project => emacs/l/comint.el
  ;;   truncate-except-project => ~/P/F/emacs/l/comint.el
  ;;   truncate-upto-root => ~/P/F/e/lisp/comint.el
  ;;   truncate-all => ~/P/F/e/l/comint.el
  ;;   relative-from-project => emacs/lisp/comint.el
  ;;   relative-to-project => lisp/comint.el
  ;;   file-name => comint.el
  ;;   buffer-name => comint.el<2> (uniquify buffer name)
  ;;
  ;; If you are expereicing the laggy issue, especially while editing remote files
  ;; with tramp, please try `file-name' style.
  ;; Please refer to https://github.com/bbatsov/projectile/issues/657.
  (setq doom-modeline-buffer-file-name-style 'truncate-upto-root)

  ;; Whether show the icon for major mode. It should respect `doom-modeline-icon'.
  (setq doom-modeline-major-mode-icon nil)

  ;; Whether display minor modes or not. Non-nil to display in mode-line.
  (setq doom-modeline-minor-modes nil))

Highlight

(use-package hl-todo
  :ensure t
  :hook (prog-mode . hl-todo-mode))

Miscellaneous

Turn off GUI elements.

(when window-system
  (menu-bar-mode -1)                              ; Disable the menu bar
  (scroll-bar-mode -1)                            ; Disable the scroll bar
  (tool-bar-mode -1)                              ; Disable the tool bar
  (tooltip-mode -1))                              ; Disable the tooltips

Smooth scrolling.

(use-package smooth-scrolling
  :config
  (smooth-scrolling-mode 1)
  (setq smooth-scroll-margin 18))

Heads up

Ivy, Swiper, and Counsel for command completion UI (like Helm) https://github.com/abo-abo/swiper

(use-package counsel
  :after ivy
  :diminish
  :config (counsel-mode)
  :bind (("s-g" . counsel-ag)))

(use-package ivy
  :defer 0.1
  :diminish
  :bind (("C-c C-r" . ivy-resume)
         ("C-x B" . ivy-switch-buffer-other-window))
  :custom
  (ivy-count-format "(%d/%d) ")
  (ivy-use-virtual-buffers t)
  :config (ivy-mode)
  (setq ivy-initial-inputs-alist nil))

(use-package ivy-pass
  :after ivy
  :commands ivy-pass)

(use-package ivy-rich
  :after ivy
  :custom
  (ivy-virtual-abbreviate 'full
                          ivy-rich-switch-buffer-align-virtual-buffer t
                          ivy-rich-path-style 'abbrev))

(use-package swiper
  :after ivy
  :bind (("C-s" . swiper)))

Start page

Use a dashboard-like start page. https://github.com/rakanalh/emacs-dashboard

(use-package dashboard
  :preface
  (defun my/dashboard-banner ()
    "Set a dashboard banner including information on package initialization
     time and garbage collections."
    (setq dashboard-banner-logo-title
          (format "ready in %.2f sec with %d gc"
                  (float-time (time-subtract after-init-time before-init-time)) gcs-done)))
  :init
  (add-hook 'after-init-hook 'dashboard-refresh-buffer)
  (add-hook 'dashboard-mode-hook 'my/dashboard-banner)
  :custom
  (dashboard-startup-banner 'logo)
  :config
  (setq dashboard-items '((recents  . 5)
                          (bookmarks . 5)
                          (projects . 5)
                          (agenda . 5)
                          (registers . 5)))
  (dashboard-setup-startup-hook))

Window management

Use winner to move around windows.

(use-package winner
  :ensure t
  :init (winner-mode 1))

Development

General

Editing

Cursors

Use iedit for multiple cursor editing.

(use-package iedit)

Undo

Undo tree

(use-package undo-tree
  :diminish
  :bind
  ("C--" . undo-tree-redo)
  :init
  (progn
    (global-undo-tree-mode 1)
    (defalias 'redo 'undo-tree-redo)

    (global-set-key (kbd "s-z") 'undo)
    (global-set-key (kbd "s-Z") 'redo))
  :custom
  (undo-tree-visualizer-timestamps t)
  (undo-tree-visualizer-diff t))

Keybindings

Which key to show keybindings

(use-package which-key
  :diminish
  :config (which-key-mode))

Rings

Visually browse the kill ring.

(use-package browse-kill-ring
  :bind
  ("C-c C-k" . browse-kill-ring))

Text

Highlight color values as their color

(use-package rainbow-mode
  :defer 2
  :hook (prog-mode))

Highlight the same symbols.

(use-package highlight-symbol
  :custom
  (highlight-symbol-mode))

Auto complete

Use company for auto completion.

(use-package company
  :defer 2
  :diminish
  :config
  (setq company-global-modes '(not term-mode))
  (setq company-minimum-prefix-length 2
        company-selection-wrap-around t
        company-show-numbers t
        company-tooltip-align-annotations t
        company-require-match nil
        company-dabbrev-downcase nil
        company-dabbrev-ignore-case nil)
  (setq company-transformers '(company-sort-by-occurrence))

  (use-package company-quickhelp
    :config
    (setq company-quickhelp-delay nil)
    (company-quickhelp-mode 1))

  :custom
  (company-begin-commands '(self-insert-command))
  (company-idle-delay .1)
  (company-minimum-prefix-length 2)
  (company-show-numbers t)
  (company-tooltip-align-annotations 't)
  (global-company-mode t))

Project management

Use Projectile for project management.

(use-package ag)

(use-package projectile
  :defer 1
  :init
  (setq projectile-keymap-prefix (kbd "C-c p"))
  :custom
  (projectile-cache-file (expand-file-name ".projectile-cache" user-emacs-directory))
  (projectile-completion-system 'ivy)
  (projectile-enable-caching t)
  (projectile-known-projects-file (expand-file-name
                                   ".projectile-bookmarks" user-emacs-directory))
  (projectile-mode-line '(:eval (projectile-project-name)))
  :config
  (setq projectile-globally-ignored-directories
        (cl-union projectile-globally-ignored-directories
                  '(".git"
                    ".cljs_rhino_repl"
                    ".svn"
                    "out"
                    "node_modules"
                    "resources/public/js/compiled")))
  (setq projectile-globally-ignored-files
        (cl-union projectile-globally-ignored-files
                  '(".DS_Store"
                    ".lein-repl-history"
                    "*.gz"
                    "*.pyc"
                    "*.png"
                    "*.jpg"
                    "*.jar"
                    "*.retry"
                    "*.svg"
                    "*.tar.gz"
                    "*.tgz"
                    "*.zip")))
  (setq projectile-mode-line '(:eval (format " [%s] " (projectile-project-name))))
  (projectile-global-mode)
  :bind)

Use perspective for different project contexts.

(use-package perspective
  :ensure t
  :bind ("C-x x x" . persp-switch-last)
  :init (persp-mode +1)

  (use-package persp-projectile
    :ensure t
    :bind ("C-x x P" . projectile-persp-switch-project))

  :config
  (setq persp-interactive-completion-function #'ido-completing-read)
  (persp-turn-off-modestring))

Linting

(use-package flycheck
  :defer 2
  :diminish
  :init (global-flycheck-mode))

Fly spell for spelling.

(use-package flyspell
  :defer 1
  :custom
  (flyspell-abbrev-p t)
  (flyspell-issue-message-flag nil)
  (flyspell-issue-welcome-flag nil)
  (flyspell-mode 1))

(use-package flyspell-correct-ivy
  :after flyspell
  :bind (:map flyspell-mode-map
              ("C-;" . flyspell-correct-word-generic))
  :custom (flyspell-correct-interface 'flyspell-correct-ivy))

(use-package ispell
  :custom
  (ispell-silently-savep t))

Set aspell path.

(setq ispell-program-name "/usr/local/bin/aspell")

Emacs

Package management

(use-package paradox
  :defer 2
  :custom
  (paradox-column-width-package 27)
  (paradox-column-width-version 13)
  (paradox-execute-asynchronously t)
  (paradox-hide-wiki-packages t)
  :config
  (paradox-enable)
  (remove-hook 'paradox-after-execute-functions #'paradox--report-buffer-print))

Snippets

(use-package yasnippet
  :ensure t
  :config (progn (setq yas-snippet-dirs '("~/.emacs.d/snippets"))
                 (add-hook 'term-mode-hook (lambda() (setq yas-dont-activate t)))
                 (yas-global-mode 1)))

(use-package yasnippet-snippets
  :after yasnippet
  :config (yasnippet-snippets-initialize))

(use-package ivy-yasnippet :after yasnippet)

Languages

Lisps

Paredit and paxedit for sexp editing.

(use-package paxedit
  :delight
  :hook
  ((org-mode
    emacs-lisp-mode
    clojure-mode
    cider-repl-mode) . paxedit-mode)
  :bind (:map paxedit-mode-map
              ("M-t" . 'paxedit-transpose-forward)
              ("C-M-t" . 'paxedit-transpose-backward)))


(use-package paredit
  :delight
  :hook ((org-mode
          emacs-lisp-mode
          clojure-mode
          cider-repl-mode
          racket-mode) . paredit-mode)
  :bind (:map paredit-mode-map
              ("M-[" . paredit-wrap-square)
              ("M-{" . paredit-wrap-curly)))

Show different colors between delimiter levels.

(use-package rainbow-delimiters
  :defer 1
  :hook (prog-mode . rainbow-delimiters-mode))

Emacs lisp

(use-package elisp-mode
  :ensure nil
  :delight emacs-lisp-mode "ξ")

Clojure

(use-package clojure-mode
  :config
  (require 'flycheck-clj-kondo)
  (setq clojure-align-forms-automatically t)
  (define-clojure-indent
    ;; Compojure
    (GET 'defun)
    (POST 'defun)
    (context 'defun)
    (tufte/p 'defun)
    (tufte/profile 'defun)
    (cj/GET 'defun)
    (cj/POST 'defun )
    (cj/context 'defun))
  :bind
  ("C-c C-q" . cider-quit))

Add an IDE-like exeperience to Emacs, primarily interaction a Clojure REPL. https://github.com/clojure-emacs/cider

(use-package cider
  :custom
  (cider-auto-test-mode 1)
  (global-set-key (kbd "C-c r") 'cider-repl-reset)
  :bind
  (("C-c M-s" . cider-connect-clojurescript)
   ("C-x C-r" . cider-inspect-last-result)
   ("C-x C-s" . cider-inspect-last-sexp))
  :hook
  (cider-mode-hook . eldoc-mode)
  :config
  (setq
   nrepl-log-messges t
   cider-use-fringe-indicators nil                   ;
   cider-prompt-for-symbol nil                       ; Don't prompt for symbol for cider doc
   cider-repl-pop-to-buffer-on-connect nil
   cider-repl-display-in-current-window t  ; open repl buffer in current window
   cider-show-error-buffer t           ; don't show error buffer automatically
   cider-auto-select-error-buffer nil      ; don't switch to error buffer on error
   cider-save-file-on-load t               ; save file on prompt when evaling
   cider-repl-history-file (concat user-emacs-directory "cider-history")
   cider-repl-use-clojure-font-lock t      ; nicer repl output
   cider-font-lock-dynamically t           ; font-lock as much as possible

   cider-font-lock-reader-conditionals nil           ; Disable font-locking for symbols in cljc files
   cider-repl-wrap-history t
   cider-repl-history-size 3000
   ))

(use-package cider-eval-sexp-fu)

Refactor Clojure code. https://github.com/clojure-emacs/clj-refactor.el

(use-package clj-refactor
  :after (clojure-mode yasnippet)
  :config
  (cljr-add-keybindings-with-prefix "C-c C-r")
  :hook
  (clj-refactor-mode . yas-minor-mode)
  (clojure-mode . clj-refactor-mode))

Use flycheck-joker for linting.

;; (use-package flycheck-joker)

(use-package flycheck-clj-kondo
:ensure t)

Css / html

(use-package css-mode
  :custom (css-indent-offset 2))

(use-package emmet-mode
  :defer 6
  :hook (sgml-mode css-mode web-mode))

(use-package less-css-mode
  :mode "\\.less\\'"
  :interpreter ("less" . less-css-mode))

(use-package scss-mode :mode "\\.scss\\'")

Markdown

(use-package markdown-mode
  :delight markdown-mode "μ"
  :mode ("INSTALL\\'"
         "CONTRIBUTORS\\'"
         "LICENSE\\'"
         "README\\'"
         "\\.markdown\\'"
         "\\.md\\'"))

Meta

General

Config file

(defun find-config ()
  "Edit config.org"
  (interactive)
  (find-file "~/.emacs.d/config.org"))

(global-set-key (kbd "C-c I") 'find-config)

Compile on change

Define a function that asynchrously compiles the config.org file, into the config file that Emacs uses. Copied from from: https://raw.githubusercontent.com/rememberYou/.emacs.d/e96fec91103524761b9e6bd66811121106db1639/config.org

(use-package async)

(defvar *config-file* (expand-file-name "config.org" user-emacs-directory)
  "The configuration file.")

(defvar *config-last-change* (nth 5 (file-attributes *config-file*))
  "Last modification time of the configuration file.")

(defvar *show-async-tangle-results* nil
  "Keeps *emacs* async buffers around for later inspection.")

(defun my/config-updated ()
  "Checks if the configuration file has been updated since the last time."
  (time-less-p *config-last-change*
               (nth 5 (file-attributes *config-file*))))

(defun my/config-tangle ()
  "Tangles the org file asynchronously."
  (when (my/config-updated)
    (setq *config-last-change*
          (nth 5 (file-attributes *config-file*)))
    (my/async-babel-tangle *config-file*)))

    (my/config-tangle)

(defun my/async-babel-tangle (org-file)
  "Tangles the org file asynchronously."
  (let ((init-tangle-start-time (current-time))
        (file (buffer-file-name))
        (async-quiet-switch "-q"))
    (async-start
     `(lambda ()
        (require 'org)
        (org-babel-tangle-file ,org-file)))
    (unless *show-async-tangle-results*
      `(lambda (result)
         (if result
             (message "SUCCESS: %s successfully tangled (%.2fs)."
                      ,org-file
                      (float-time (time-subtract (current-time)
                                                 ',init-tangle-start-time)))
           (message "ERROR: %s as tangle failed." ,org-file))))))

Org setup

(use-package org
  :init
  (add-hook 'org-mode-hook 'visual-line-mode)
  (add-hook 'org-mode-hook 'org-indent-mode)
  (add-hook 'org-mode-hook 'flyspell-mode)
  :diminish visual-line-mode
  :diminish org-indent-mode
  :ensure org-plus-contrib
  :hook
  ((before-save . (lambda ()
                    (interactive)
                    (org-table-recalculate-buffer-tables)))
   (after-save . my/config-tangle))
  :config
  (setq
   org-src-fontify-natively t
   org-src-tab-acts-natively t
   org-confirm-babel-evaluate nil
   org-ellipsis " ... "
   org-startup-truncated nil
   org-export-with-smart-quotes nil
   org-replace-disputed-keys t)
  (add-to-list 'org-structure-template-alist
               '("el" "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC"))

  (use-package org-bullets
    :defer t
    :init
    (add-hook 'org-mode-hook
              (lambda ()
                (org-bullets-mode t)))))

(use-package org-indent :after org :ensure nil :diminish)