(defvar my-config-el-start-time (current-time) "Time when config.el was started")
(setenv "PATH" (concat (getenv "PATH") ":/Users/islinger/bin"))
;(profiler-start 'cpu);; test startup performance - create report with M-x profiler-report
Use use-package
as much as possible so just bootstrap that to get other packages.
(require 'package)
(setq package-enable-at-startup nil)
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/"))
(package-initialize)
;; Bootstrap `use-package'
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(eval-when-compile
(require 'use-package))
(setq use-package-always-ensure t)
;; The default setting is too low for lsp-mode's needs due to the fact that client/server communication generates a lot of memory/garbage.
(setq gc-cons-threshold (* 100 1000 1000))
;; Again the emacs default is too low 4k considering that the some of the language server responses are in 800k - 3M range.
(setq read-process-output-max (* 2 1024 1024)) ;; 2mb
;; Nice theme
(use-package monokai-theme
:config
(load-theme 'monokai t))
;; Nice modeline from spacemacs
(use-package spaceline
:demand t
:init
(setq powerline-default-separator 'arrow-fade)
:config
(require 'spaceline-config)
;; (spaceline-spacemacs-theme)
(spaceline-emacs-theme)
(spaceline-toggle-buffer-size-off))
;; Only do auto save in buffers where it is not likely to screw up a live site somewhere over tramp
(use-package real-auto-save
:ensure t
:config
(add-hook 'org-mode-hook 'real-auto-save-mode)
(setq real-auto-save-interval 7))
;; Try company mode again to get nice completion in clojure buffers
(use-package company
:ensure t
:diminish company-mode
:init
(add-hook 'cider-repl-mode-hook #'company-mode)
(add-hook 'cider-mode-hook #'company-mode)
:bind
("M-/" . company-complete-common)
:config
(setq company-idle-delay nil) ;; only trigger when asked?
(global-set-key (kbd "TAB") #'company-indent-or-complete-common))
;; nice utf-8 bullets in org mode
(use-package org-bullets
:ensure t
:config
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))
; nice but REALLY slows down editing
;(use-package smartparens
; :defer t
; :ensure t
; :diminish smartparens-mode
; :init
; (setq sp-override-key-bindings
; '(("C-k" . sp-kill-sexp)
; ("M-s" . sp-splice-exp)))
; :config
; (require 'smartparens-config)
; (sp-use-smartparens-bindings)
; (sp--update-override-key-bindings)
; (show-smartparens-global-mode t)
; (add-hook 'minibuffer-setup-hook 'turn-on-smartparens-strict-mode)
; :commands (smartparens-mode show-smartparens-mode))
;(use-package aggressive-indent
; :diminish aggressive-indent-mode
; :config
; (global-aggressive-indent-mode 1))
;; key bindings and code colorization for Clojure
(use-package clojure-mode
:ensure t
:defer t
:mode (("\\.clj\\'" . clojure-mode)
("\\.edn\\'" . clojure-mode)
("\\.cljs\\'" . clojurescript-mode))
:init
(add-hook 'clojure-mode-hook #'yas-minor-mode)
(remove-hook 'clojure-mode-hook #'subword-mode)
;;(add-hook 'clojure-mode-hook #'smartparens-mode)
(add-hook 'clojure-mode-hook #'rainbow-delimiters-mode)
(add-hook 'clojure-mode-hook #'eldoc-mode)
(add-hook 'cider-mode-hook #'paredit-mode)
(global-set-key (kbd "<f5>") 'cider-eval-defun-at-point)
:config
;; _ and - are part of a word
(modify-syntax-entry ?_ "w" clojure-mode-syntax-table)
(modify-syntax-entry ?- "w" clojure-mode-syntax-table))
;; M-x kibit to check for style in clojure
;(use-package kibit-helper)
;; integration with a Clojure REPL
(use-package cider
:ensure t
:defer t
; :init
:diminish subword-mode
:config
(setq nrepl-log-messages t
;;cider-repl-display-in-current-window t
cider-repl-use-clojure-font-lock t
cider-prompt-save-file-on-load 'always-save
cider-font-lock-dynamically '(macro core function var)
nrepl-hide-special-buffers t
cider-overlays-use-font-lock t)
(setq cider-cljs-lein-repl
"(do (require 'figwheel-sidecar.repl-api)
(figwheel-sidecar.repl-api/start-figwheel!)
(figwheel-sidecar.repl-api/cljs-repl))"))
(use-package paredit
:diminish paredit-mode
:init
(add-hook 'clojure-mode-hook 'enable-paredit-mode)
(add-hook 'cider-repl-mode-hook 'enable-paredit-mode)
(add-hook 'lisp-mode-hook 'enable-paredit-mode)
(add-hook 'emacs-lisp-mode-hook 'enable-paredit-mode)
(add-hook 'lisp-interaction-mode-hook 'enable-paredit-mode)
(add-hook 'ielm-mode-hook 'enable-paredit-mode)
(add-hook 'json-mode-hook 'enable-paredit-mode))
;; Project management
;; (use-package projectile
;; :diminish projectile-mode
;; :init
;; (projectile-global-mode))
;; colorful parenthesis matching
(use-package rainbow-delimiters
:ensure
:init
(progn
(add-hook 'emacs-lisp-mode-hook (lambda()
(rainbow-delimiters-mode t)))))
;; edit html tags like sexps
(use-package tagedit
:defer)
(use-package web-mode
:diminish web-mode
:config
(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode)))
;; git integration
(use-package magit
:defer
:config
(setq magit-auto-revert-mode nil))
;;; this fails on load
;;; (diminish 'auto-revert-mode)
;; On OS X, an Emacs instance started from the graphical user
;; interface will have a different environment than a shell in a
;; terminal window, because OS X does not run a shell during the
;; login. Obviously this will lead to unexpected results when
;; calling external utilities like make from Emacs.
;; This library works around this problem by copying important
;; environment variables from the user's shell.
;; https://github.com/purcell/exec-path-from-shell
;; THIS IS REALLY SLOW TO START UP! DO WE NEED IT?
;; (use-package exec-path-from-shell
;; :ensure t
;; :config (when (memq window-system '(mac ns))
;; (exec-path-from-shell-initialize)
;; (exec-path-from-shell-copy-envs '("PATH"))))
(use-package visual-regexp-steroids
:diminish isearch-mode
:ensure
:demand
:bind (("C-M-r" . vr/isearch-backward)
("C-M-s" . vr/isearch-forward)
("M-%" . vr/query-replace)))
(use-package yaml-mode
:mode ("\\.\\(e?ya?\\|ra\\)ml\\'" . yaml-mode))
(use-package markdown-mode
:ensure t
:commands (markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:config (setq markdown-command "multimarkdown"
markdown-header-scaling 1))
(use-package git-gutter
:ensure t
:init
(when (display-graphic-p)
(use-package git-gutter-fringe
:ensure t))
(global-git-gutter-mode))
(use-package editorconfig
:ensure t
:config
(editorconfig-mode 1))
(use-package jinja2-mode
)
;; optional if you want which-key integration
(use-package which-key
:config
(which-key-mode))
(use-package lsp-mode
:init
;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
(setq lsp-keymap-prefix "M-z")
:hook (;; replace XXX-mode with concrete major-mode(e. g. python-mode)
(python-mode . lsp-deferred))
:commands (lsp lsp-deferred))
(setq lsp-headerline-breadcrumb-enable nil)
;; optionally
;;(use-package lsp-ui :commands lsp-ui-mode)
;; if you are helm user
(use-package helm-lsp :commands helm-lsp-workspace-symbol)
;; if you are ivy user
;;(use-package lsp-ivy :commands lsp-ivy-workspace-symbol)
;;(use-package lsp-treemacs :commands lsp-treemacs-errors-list)
;; optionally if you want to use debugger
;;(use-package dap-mode)
;; (use-package dap-LANGUAGE) to load the dap adapter for your language
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-package helm
:bind (("M-x" . helm-M-x)
("M-<f5>" . helm-find-files)
("C-x C-b" . helm-buffers-list)
([S-f10] . helm-recentf)
("C-x C-f" . helm-find-files))
:init
(progn
(setq helm-buffers-fuzzy-matching t
helm-buffer-max-length nil)))
(use-package helm-swoop)
;; (use-package helm-projectile
;; :bind (("C-x C-b" . helm-projectile-switch-to-buffer))
;; :init
;; (helm-projectile-on))
;; allow helm to rifle through org buffers
(use-package helm-org-rifle)
;; Highlight and replace symbols
(use-package highlight-symbol
:init
(global-set-key [(control f3)] 'highlight-symbol)
(global-set-key [f3] 'highlight-symbol-next)
(global-set-key [(shift f3)] 'highlight-symbol-prev)
(global-set-key [(meta f3)] 'highlight-symbol-query-replace))
(setq org-return-follows-link 1)
(setq org-hide-leading-stars t)
(setq org-startup-indented t)
;; Don't let M-Ret split lines - why would you?
(setq org-M-RET-may-split-line '((item . nil)))
;; Syntax highlighting in org code blocks
(setq org-src-fontify-natively t)
;; Hide /italic/ *bold* markers
(setq org-hide-emphasis-markers t)
;; This is useful for working with camel-case tokens, like names of
;; Java classes (e.g. JavaClassName)
(add-hook 'clojure-mode-hook 'subword-mode)
;; A little more syntax highlighting
(use-package clojure-mode-extra-font-locking)
;;;;;;;;
;; Cider
;;;;;;;;
;; provides minibuffer documentation for the code you're typing into the repl
;;(add-hook 'cider-mode-hook 'eldoc-mode)
;; go right to the REPL buffer when it's finished connecting
;;etq cider-repl-pop-to-buffer-on-connect t)
;; ;; When there's a cider error, show its buffer and switch to it
;; (setq cider-show-error-buffer t)
;; (setq cider-auto-select-error-buffer t)
;; ;; Where to store the cider history.
;; (setq cider-repl-history-file "~/.emacs.d/cider-history")
;; Wrap when navigating history.
(setq cider-repl-wrap-history t)
;; ;; Use clojure mode for other extensions
(add-to-list 'auto-mode-alist '("\\.edn$" . clojure-mode))
(add-to-list 'auto-mode-alist '("\\.boot$" . clojure-mode))
(add-to-list 'auto-mode-alist '("\\.cljs.*$" . clojure-mode))
(add-to-list 'auto-mode-alist '("lein-env" . enh-ruby-mode))
(add-to-list 'exec-path "/usr/local/bin")
(add-to-list 'exec-path "~/bin")
;; "When several buffers visit identically-named files,
;; Emacs must give the buffers distinct names. The usual method
;; for making buffer names unique adds ‘<2>’, ‘<3>’, etc. to the end
;; of the buffer names (all but one of them).
;; The forward naming method includes part of the file's directory
;; name at the beginning of the buffer name
;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Uniquify.html
(use-package uniquify
:ensure nil
:config
(setq uniquify-buffer-name-style 'forward))
;; Highlights matching parenthesis
(show-paren-mode 1)
;; DON'T Highlight current line except in GUI mode (later)
(global-hl-line-mode -1)
;; When you visit a file, point goes to the last place where it
;; was when you previously visited the same file.
;; http://www.emacswiki.org/emacs/SavePlace
(use-package saveplace
:config
(setq-default save-place t)
;; keep track of saved places in ~/.emacs.d/places
(setq save-place-file (concat user-emacs-directory "places")))
;; use 2 spaces for tabs
(defun kill-tabs ()
(interactive)
(set-variable 'tab-width 2)
(mark-whole-buffer)
(untabify (region-beginning) (region-end))
(keyboard-quit))
(setq electric-indent-mode nil)
;; Something overrides macro start - restore it
(global-set-key (quote [f3]) (quote start-kbd-macro))
Some stuff only applies in GUI mode anyway, and other stuff is because we want to keep the startup short in terminal
(if (not (display-graphic-p))
(message "Skipping GUI stuff in non GUI environment...")
;; Different size heading levels
(let* ((variable-tuple (cond ((x-list-fonts "Source Sans Pro") '(:font "Source Sans Pro"))
((x-list-fonts "Lucida Grande") '(:font "Lucida Grande"))
((x-list-fonts "Verdana") '(:font "Verdana"))
((x-family-fonts "Sans Serif") '(:family "Sans Serif"))
(nil (warn "Cannot find a Sans Serif Font. Install Source Sans Pro."))))
(base-font-color (face-foreground 'default nil 'default))
(headline `(:inherit default )))
(custom-theme-set-faces 'user
`(org-level-8 ((t (,@headline ,@variable-tuple))))
`(org-level-7 ((t (,@headline ,@variable-tuple))))
`(org-level-6 ((t (,@headline ,@variable-tuple))))
`(org-level-5 ((t (,@headline ,@variable-tuple))))
`(org-level-4 ((t (,@headline ,@variable-tuple :height 1.05))))
`(org-level-3 ((t (,@headline ,@variable-tuple :height 1.1))))
`(org-level-2 ((t (,@headline ,@variable-tuple :height 1.2))))
`(org-level-1 ((t (,@headline ,@variable-tuple :height 1.2))))
`(org-document-title ((t (,@headline ,@variable-tuple :height 1.5 :underline nil))))))
;; Strike through for DONE items
(setq org-fontify-done-headline t)
(custom-set-faces
'(org-done ((t (:foreground "PaleGreen"
:weight normal
:strike-through t))))
'(org-headline-done
((((class color) (min-colors 16) (background dark))
(:foreground "LightSalmon" :strike-through t)))))
;; Remove the graphical toolbar at the top.
(when (fboundp 'tool-bar-mode)
(tool-bar-mode -1))
;; Don't show native OS scroll bars for buffers because they're redundant
(when (fboundp 'scroll-bar-mode)
(scroll-bar-mode -1))
;; Color Themes
;; Read http://batsov.com/articles/2012/02/19/color-theming-in-emacs-reloaded/
;; for a great explanation of emacs color themes.
;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Custom-Themes.html
;; for a more technical explanation.
(add-to-list 'custom-theme-load-path "~/.emacs.d/themes")
(add-to-list 'load-path "~/.emacs.d/themes")
;; (load-theme 'zenburn t)
(load-theme 'wombat t) ;; Even nicer
;; Highlight whole expression on paren match, not just other bracket
(setq show-paren-style 'mixed)
;;;; doesn't work in emacs 26
;;;; (set-face-background 'show-paren-match-face "#996666")
;; These settings relate to how emacs interacts with your operating system
(setq ;; makes killing/yanking interact with the clipboard
x-select-enable-clipboard t
;; I'm actually not sure what this does but it's recommended?
x-select-enable-primary t
;; Save clipboard strings into kill ring before replacing them.
;; When one selects something in another program to paste it into Emacs,
;; but kills something in Emacs before actually pasting it,
;; this selection is gone unless this variable is non-nil
save-interprogram-paste-before-kill t
;; Shows all options when running apropos. For more info,
;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Apropos.html
apropos-do-all t
;; Mouse yank commands yank at point instead of at click.
mouse-yank-at-point t
;; no bell
ring-bell-function 'ignore)
;; No cursor blinking, it's distracting
(blink-cursor-mode 0)
;; full path in title bar
(setq-default frame-title-format "%b (%f)")
;; don't pop up font menu
(global-set-key (kbd "s-t") '(lambda () (interactive)))
;; Only do this in graphics mode - random command line edits don't need it.
;; Keeps asking to save, clashes with main invocation of emacs
(desktop-save-mode 1)
;; don't exit in GUI mode in case I did C-x C-c by mistake
(setq confirm-kill-emacs 'y-or-n-p)
;; Nicer cursor
(setq-default cursor-type 'bar)
(setq default-frame-alist
'((cursor-color . "white")))
;; Copy on select
(setq mouse-drag-copy-region t)
;; Sane mouse scroll wheel
(setq mouse-wheel-scroll-amount '(3))
(setq mouse-wheel-progressive-speed nil)
;; highlight line is reasonably subtle in gui
(global-hl-line-mode t)
;; Neo tree
(use-package all-the-icons)
(use-package neotree
:bind
("<f8>" . neotree-toggle)
:config
;; needs package all-the-icons
(setq neo-theme (if (display-graphic-p) 'icons 'arrow))
(setq neo-window-fixed-size nil)
;; Disable line-numbers minor mode for neotree
(add-hook 'neo-after-create-hook
(lambda (&optional dummy) (display-line-numbers-mode -1)))
;; Every time when the neotree window is opened, let it find current
;; file and jump to node.
(setq neo-smart-open t)
;; track ‘projectile-switch-project’ (C-c p p),
(setq projectile-switch-project-action 'neotree-projectile-action))
;; Pretty face
(set-face-attribute 'default nil :height 140)
;; increase font size for better readability
(set-face-attribute 'default nil :height 160))
;; Nicer font on OSX
(set-face-attribute 'default nil :family "Monospace" :weight 'Light :height 120)
(setq-default cursor-type 'box)
;; Set selection colour to something actually visible in this theme
(set-face-attribute 'region nil :background "#6666")
My preferences for a comfortable environment.
;; Use plists for deserialization in lsp-mode
(setq lsp-use-plists 1)
;; Auto save is ok in org mode
(setq auto-save-default nil) ;; disable by default
(setq auto-save-timeout 5)
(add-hook 'org-mode-hook #'auto-save-mode) ;; enable in org-mode
;; Set remote user to root by default
(setq tramp-default-user "root")
;(setq cider-repl-use-pretty-printing t)
;; Set up cider for clojurescript dev
;(setq cider-cljs-lein-repl
; "(do (require 'figwheel-sidecar.repl-api)
; (figwheel-sidecar.repl-api/start-figwheel!)
; (figwheel-sidecar.repl-api/cljs-repl))")
;; Mmmmmm hoopy symbols like λ in lisp
(global-prettify-symbols-mode +1)
;; Restore/undo last window config with C-c left and C-c right
(winner-mode 1)
(global-set-key (kbd "C-c <C-left>") 'winner-undo)
(global-set-key (kbd "C-c <C-right>") 'winner-redo)
;; New comment key in 25.1. M-; toggles comments sensibly
(global-set-key [remap comment-dwim] #'comment-line)
; Turn off elpy vertical bars. Yuk.
(add-hook 'elpy-mode-hook (lambda () (highlight-indentation-mode -1)))
(global-set-key (kbd "<f8>") 'other-window)
(message "→★ finished loading config.org in %.2fs" (float-time (time-subtract (current-time) my-config-el-start-time)))