Skip to content

Latest commit

 

History

History
958 lines (713 loc) · 26 KB

config.org

File metadata and controls

958 lines (713 loc) · 26 KB

Helpers

There are a number of helper functions that we’ll need through the rest of this. We’ll just define them up here.

load-if-exists

This is just a nice function to load a file if it exists, but just print a message rather than an error if it doesn’t. This is handy for things like loading specific local config that you don’t want to go into github or be shared such as erc nicks, passwords, blog rolls, etc.

(defun load-if-exists (file)
  (if (file-exists-p file)
      (progn
        (load file)
        (message (format "Loading file: %s" file)))
    (message (format "No %s file. So not loading one." file))))

Globals

Update PATH

(setenv "PATH" (concat (getenv "PATH") ":/usr/local/bin"))
(setq exec-path (append exec-path '("/usr/local/bin")))

Temporarily set text quoting style to grave

git-gutter has a bug - “=” in its docstrings is not escaped properly and compiler in Emacs 29.x shows a bunch of warnings. This sets the quoting style to the old-style.

(setq text-quoting-style 'grave)

Company mode

(use-package company
   :ensure t
   :diminish company-mode
   :config
   (global-company-mode))
;;(add-hook 'after-init-hook 'global-company-mode)

Hippie Expand

HippieExpand looks at the word before point and tries to expand it in various ways including expanding from a fixed list, expanding from matching text found in a buffer or expanding in ways defind by your own functions.

(global-set-key (kbd "M-RET") 'hippie-expand)
(setq hippie-expand-try-functions-list
  '(yas-hippie-try-expand
    try-expand-dabbrev
    try-expand-dabbrev-all-buffers
    try-expand-dabbrev-from-kill
    try-complete-file-name-partially
    try-complete-file-name
    try-expand-all-abbrevs
    try-expand-list
    try-expand-line
    try-complete-lisp-symbol-partially
    try-complete-lisp-symbol))

diminish

Stops minor modes from making a mess of the modeline.

(use-package diminish
  :ensure t)

Tabs

Let’s not used tabs for identation.

(setq-default indent-tabs-mode nil)

uniquify

When several buffers visit identically-named files, Emacs must give the buffers distinct names. There are several different styles for constructing such names. Post-forward puts the dricetory names in forward order after the file name.

(require 'uniquify)
(setq uniquify-buffer-name-style 'post-forward)

Multiple Cursors

(use-package multiple-cursors)
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)

Discover

Allows to discover more of Emacs using context menus.

(use-package discover)
(global-discover-mode 1)

Disable beep

Disable the beep sound when trying to move the cursor beyond the beginning or end of a document.

(defun my-bell-function ()
  (unless (memq this-command
    '(isearch-abort abort-recursive-edit exit-minibuffer
          keyboard-quit mwheel-scroll down up next-line previous-line
          backward-char forward-char))
        (ding)))
 (setq ring-bell-function 'my-bell-function)

Better moving between windows

Rebind the default C-x o to M-o as it’s such a common binding to use.

(global-set-key (kbd "M-o") 'other-window)

Save Emacs sessions

(desktop-save-mode 1)

Save Cider history

(setq cider-repl-history-file "~/.emacs.d/cache/cider-history")

Remove cider banner

(setq cider-repl-display-help-banner nil)

Load dev alias when jackin-in

(setq cider-clojure-cli-global-options "-A:dev")

Auto-save in the visited file

(setq auto-save-visited-file-name t)

Delete trailing whitespace

(add-hook 'before-save-hook
             (lambda nil
              (delete-trailing-whitespace)))

Mouse mode in iTerm 2

(unless window-system
  (require 'mouse)
  (xterm-mouse-mode t)
  (global-set-key [mouse-4] '(lambda ()
                             (interactive)
                             (scroll-down 1)))
  (global-set-key [mouse-5] '(lambda ()
                             (interactive)
                             (scroll-up 1)))
  (defun track-mouse (e))
  (setq mouse-sel-mode t))

Pragma block

(defun insert-pragma-block ()
  (interactive)
  (insert ";;-------------------------------------------------------------------------------
;; ## Pragma-block-name"))

(global-set-key (kbd "<f5> p") 'insert-pragma-block)

Don’t split windows automatically

(setq split-height-threshold nil
      split-width-threshold nil)

non-elpa

(add-to-list 'load-path (concat user-emacs-directory "non-elpa/"))

OSX Specific Setup

$PATH is broken

If you don’t run emacs in a terminal on Mac OS X then it can be really awkward to get the stuff you want in your path. This is the best way I’ve found so far to sort this out and get things like ~/bin and /usr/loca/bin in a $PATH that emacs can access. I quite like running emacs from outside the terminal.

Thanks to the lovely and helpful Tom O’Brien I’ve got a better way of doing this and now my emacs environment will be in sync with my shell. You can out more at the github page for exec-path-from-shell.

(use-package exec-path-from-shell)
(when (memq window-system '(mac ns))
  (exec-path-from-shell-initialize))

Control speed of the mouse scroll

Who uses a mouse when they’re in Emacs, right? Well, I do. And MacOS Sierra default scroll is way too fast.

(setq mouse-wheel-scroll-amount '(1 ((shift) . 1) ((control) . nil)))
(setq ring-bell-function 'ignore)

Pretty Emacs is pretty

color themes

custom-theme-directory

Themes seem to be quite picky about where they live. They require custom-theme-directory to be set. By default this is the same as user-emacs-directory, which is usually ~/.emacs.d. I’d like to keep them separate if possible. I learned this one by reading some of Neale Swinnerton’s dotfiles.

(setq custom-theme-directory (concat user-emacs-directory "themes"))

cyberpunk

Back to the roots

(use-package cyberpunk-theme)
(load-theme 'cyberpunk t)

grandshell

I’ve been finding lots of interesting things from steckerhalter and this grandshell theme looks pretty good. I’m going to try it for a while.

;; (use-package grandshell-theme)

fonts

Ah, the joys of playing with different monospaced fonts on emacs. I’m using Fira Code now. But Menlo is a good alternative when you don’t want to code in a char grid and aren’t that crazy about ligatures.

(when (memq window-system '(mac ns))
  (set-frame-font  "-apple-Menlo-medium-normal-normal-*-14-*-*-*-m-0-iso10646-1" nil t))

bars, menus and numbers

I like no scroll bars, no toolbars and line and column numbers in the mode-line. I like having the menus, unless I”m in a terminal as I sometimes discover keybindings or functions I wasn’t aware of before.

(tool-bar-mode -1)
(size-indication-mode 1)
(scroll-bar-mode -1)
(line-number-mode 1)
(column-number-mode 1)
;; no horizontal scroll bar
(when (boundp 'horizontal-scroll-bar-mode)
  (horizontal-scroll-bar-mode -1))

Startup Screen

I’d also like to ski the startup screen and go straight to the scratch buffer.

(setq inhibit-startup-screen t)

alpha alpha alpha

I don’t use this all the time, but sometimes, when I’m hacking only on my diddy 13” laptop I like to have a window tailing a file in the background while I’m writing something in the foreground. This let’s us toggle transparency. Who wouldn’t like that? I’m pretty sure I got this from Anthony Grimes.

(defun toggle-transparency ()
  (interactive)
  (let ((param (cadr (frame-parameter nil 'alpha))))
    (if (and param (/= param 100))
        (set-frame-parameter nil 'alpha '(100 100))
      (set-frame-parameter nil 'alpha '(85 50)))))
(global-set-key (kbd "C-c t") 'toggle-transparency)

directories, navigation, searching, movement

dired

dired can do lots of things. I’m pretty basic in my use. I do like to have the file listings use human friendly numbers though.

(setq dired-listing-switches "-alh")

helm-mode

helm-mode is the succesor to anything.el. I don’t really have my head around it all yet, but I’m already pretty impressed with it so I’ll include it here and add more to it as I understand what is going on.

My helm-mode guru is Kris Jenkins.

(use-package helm)
(customize-set-variable 'helm-ff-lynx-style-map t)
(global-set-key (kbd "C-x C-f") 'helm-find-files)
(global-set-key (kbd "M-x")     'helm-M-x)
(helm-mode 1)
(set-face-attribute 'helm-selection nil
  :background "purple"
  :foreground "black")
(set-face-attribute 'helm-ff-directory nil
  :background "grey17"
  :foreground "OrangeRed3")

We can diminish how much room helm-mode takes up on the command line.

(diminish 'helm-mode)

git

magit

magit is a fantastic mode for dealing with git.

(use-package magit)

I use magit-status a lot. So let’s bind it to C-x g.

(global-set-key (kbd "C-x g") 'magit-status)

git-gutter-mode+

It is really nice having +/= in the gutter.

(use-package git-gutter)
(global-git-gutter-mode t)

It is also quite nice to be able to navigate a file by he git hunks. It makes it a bit easier to see what has changed since the last time in the context of the whole file.

(global-set-key (kbd "s-n") 'git-gutter-next-hunk)
(global-set-key (kbd "s-p") 'git-gutter-previous-hunk)

We can diminish the size of GitGutter in the mode-line

(diminish 'git-gutter-mode)

Git links

(use-package git-link
   :ensure t)

Git time machine

(use-package git-timemachine
  :ensure t)

ace-jump-mode

Move quickly anywhere in the buffer in 3 keystrokes. We can move there with C-c j and back to where we started with C-c k.

(use-package ace-jump-mode)
(global-set-key (kbd "C-c j") 'ace-jump-mode)
(global-set-key (kbd "C-c k") 'ace-jump-mode-pop-mark)

window and buffer tweaking

window movement

Use Shift+arrow_keys to move cursor around split panes

(windmove-default-keybindings)

buffer movement

Sometimes the problem isn’t that you want to move the cursor to a particular window, but you want to move a buffer. buffer-move lets you do that.

(use-package buffer-move)
(global-set-key (kbd "<s-up>")     'buf-move-up)
(global-set-key (kbd "<s-down>")   'buf-move-down)
(global-set-key (kbd "<s-left>")   'buf-move-left)
(global-set-key (kbd "<s-right>")  'buf-move-right)

shrink and enlarge windows

On large screens where there are lots of windows in a frame we’ll often want to shrink or grow individual windows. It would be handy to have easier keys for this.

(global-set-key (kbd "s-=") 'shrink-window)
(global-set-key (kbd "s-+") 'enlarge-window)

backup directories

I’m fed up of having to put *~ into my .gitignore everywhere and I shouldn’t really leave emacs only things in there anyway. Let’s just move all the backup files to one directory.

(setq
 backup-by-copying t      ; don't clobber symlinks
 backup-directory-alist
 '(("." . "~/.saves"))    ; don't litter my fs tree
 delete-old-versions t
 kept-new-versions 6
 kept-old-versions 2
 version-control t)       ; use versioned backups

ibuffer

I’ve never used ibuffer much before, but many people swear by it (rather than at it). I’ve tried it now and it looks good. So let’s rebind C-x C-b.

(global-set-key (kbd "C-x C-b") 'ibuffer)

projectile

projectile from Bozhidar Batsov constrains and helps things like searches so that they happen within a git repo or leiningen project.

(use-package projectile)
(projectile-global-mode)

But we don’t need to see that projectile mode is running everywhere so let’s diminish it.

(diminish 'projectile-mode)

key bindings

(defun backward-kill-line (arg)
  "Kill ARG lines backward."
  (interactive "p")
  (kill-line (- 1 arg)))
(global-set-key "\C-cu" 'backward-kill-line) ;; `C-c u'

Programming Modes

prog-mode

Parentheses

Show Parens

(show-paren-mode +1)

paredit-mode

(use-package paredit)
(diminish 'paredit-mode "()")
(add-hook 'prog-mode-hook 'paredit-mode)

rainbow-delimiters

(use-package rainbow-delimiters)
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode)

rainbow mode

(use-package rainbow-mode)
(add-hook 'prog-mode-hook 'rainbow-mode)
(diminish 'rainbow-mode)

highlight-symbol

(use-package highlight-symbol)
(add-hook 'prog-mode-hook 'highlight-symbol-mode)

yasnippet

Tempate system for Emacs. It allows you to type an abbreviation and automatically expand it into function templates.

(use-package yasnippet
 :ensure t
 :defer t
 :diminish yas-minor-mode
 :config (yas-global-mode 1))

Snippets

Let’s get the snippets installed

(setq yas-snippet-dirs
 '("~/.emacs.d/snippets"))

Let’s automatically load them when we create new file

 ;; (defun yas--expand-by-uuid (mode uuid)
  ;;   "Exapnd snippet template in MODE by its UUID"
  ;;   (yas-expand-snippet
  ;;     (yas--template-content
 ;;        (yas--get-template-by-uuid mode uuid))))

   ;; Yasnippet templates used in auto-insert mode
;;   (use-package autoinsert)
;;   (auto-insert-mode)
;;   (setq auto-insert-query nil)
  ;;    (define-auto-insert "\.R"
 ;;        '(lambda () (yas--expand-by-uuid 'clojure-mode "ns")))

smartscan

A suggestion from Effective Editing in Mastering Emacs.

(use-package smartscan)
(add-hook 'prog-mode-hook
          '(lambda () (smartscan-mode 1)))

lisp modes

lisp hooks

(setq lisp-hooks (lambda ()
                   (eldoc-mode +1)
                   (diminish 'eldoc-mode)
                   (define-key paredit-mode-map
                     (kbd "{") 'paredit-open-curly)
                   (define-key paredit-mode-map
                     (kbd "}") 'paredit-close-curly)))

emacs-lisp

lisp-mode-hook

(add-hook 'emacs-lisp-mode-hook lisp-hooks)

Pop Up Help in Emacs Lisp

(require 'popup)

(defun describe-thing-in-popup ()
  (interactive)
  (let* ((thing (symbol-at-point))
         (help-xref-following t)
         (description (with-temp-buffer
                        (help-mode)
                        (help-xref-interned thing)
                        (buffer-string))))
    (popup-tip description
               :point (point)
               :around t
               :height 30
               :scroll-bar t
               :margin t)))
The usual help keybinding

Let’s use C-c C-d for describing functions at point as this is the binding in cider/nrepl that I’m used to. We’ll probably do this in other modes as well so we’ll make it a local keybinding and then it will more or less dwim.

(add-hook 'emacs-lisp-mode-hook
          (lambda () (local-set-key (kbd "C-c C-d") 'describe-thing-in-popup)))

clojure

clojure-mode is must-have.

(use-package clojure-mode)

Add clj-refactor to keep things tidy

;; (use-package clj-refactor)

cider

install

You can get most of the clojure support by just elpa installing cider.

(use-package cider)
don’t print too much
(setq cider-repl-print-length 100)
clojure-mode-hook
(add-hook 'clojure-mode-hook lisp-hooks)
Save cider history
(setq cider-history-file (concat user-emacs-directory "cider-history"))
Pop up Documentation

Docs go in a popup rather than another window.

(define-key cider-mode-map (kbd "C-c C-d") 'ac-nrepl-popup-doc)
Don’t pop up errors
(setq cider-show-error-buffer nil)
cider-test-report diff hook
(defun cider-ediff-hack ()
 (interactive)
 (let ((expected (get-text-property (point) 'actual))
  (tmp-buffer (generate-new-buffer " *tmp*"))
  (expected-buffer (generate-new-buffer " *expected*"))
  (actual-buffer   (generate-new-buffer " *actual*")))
 (with-current-buffer tmp-buffer
  (insert expected)
  (goto-char (point-min))
  (re-search-forward "= ")
  (let ((opoint (point)))
    (forward-sexp 1)
    (let* ((tpoint (point))
           (our-exp (buffer-substring-no-properties opoint (point)))
           (_ (forward-sexp 1))
           (our-act (buffer-substring-no-properties tpoint (point) )))
      (with-current-buffer expected-buffer
        (insert our-exp)
        (delete-trailing-whitespace))
      (with-current-buffer actual-buffer
        (insert our-act)
        (delete-trailing-whitespace))
      (apply 'ediff-buffers
             (setq cider-test-ediff-buffers
                   (list (buffer-name expected-buffer)
                         (buffer-name actual-buffer)))))))))

helm and clojure

(use-package helm-cider)

javascript

(use-package js2-mode)
(add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
(add-to-list 'interpreter-mode-alist '("node" . js2-mode))

Text Modes

Check spelling

(setq ispell-program-name "aspell"
      ispell-dictionary "english")

org-mode

I also use org-mode on its own and would like to use it more. I used to be a complete planner-mode addict. I’ve never really gotten into org-mode in the same way. Having a way to sync to trello and link to my email, magit and everything else keeps making me want to try though.

fontify

This is all written in org-mode. It would be good if the source code examples were fonitfies according to their major mode.

(setq org-src-fontify-natively t)

spelling

On a Mac we need to tell org-mode to use aspell, which we installed using homebrew.

(setq ispell-program-name (executable-find "aspell"))

org-headlines

Just like in helm and clojure we’d like to be able to look at the headlines in org-mode too.

(add-hook 'org-mode-hook
          (lambda () (local-set-key (kbd "s-h") 'helm-org-headlines)))

html, sgml, xml

css

I should probably look at adding more sugar to this.

paredit

(add-hook 'css-mode-hook 'paredit-mode)

rainbow mode

(add-hook 'css-mode-hook 'rainbow-mode)

markdown

(use-package markdown-mode)

Github Flavouring

I pretty much always want to do github flavoured markdown, so let’s just change that auto-mode-alist.

(add-to-list 'auto-mode-alist '(".md$" . gfm-mode))

Github Flavoured Preview

We also need to change the preview as the standard preview doesn’t render github flavoured markdown correctly. I’ve installed markdown Preview+ as a Chrome Extension and associated .md files with Chrome on Mac OS X.

This is all a bit broken really, but will work for now. I’m sorry that it is like this and I’m sure some day I’ll fix it. This also means that you use markdown-open rather than markdown-preview.

(setq markdown-open-command "open")

helm markdown headlines

I want super-h to work and give me headlines just like in org-mode. I feel this could perhaps be a bit better, but this will do for now.

(defun helm-markdown-headlines ()
  "Display headlines for the current Clojure file."
  (interactive)
  (helm :sources '(((name . "Markdown Headlines")
                    (volatile)
                    (headline "^[#]")))))

(add-hook 'markdown-mode-hook
          (lambda () (local-set-key (kbd "s-h") 'helm-markdown-headlines)))

Syntax checking

Flycheck

(use-package flycheck
  :ensure t
  :hook ((sh-mode clojure-mode) . flycheck-mode))

(use-package flycheck-color-mode-line)
(global-flycheck-mode)

Joker

Clojure syntax checker \o/

(use-package flycheck-joker)

clj-kondo

(use-package flycheck-clj-kondo)

Use multiple checkers

(dolist (checker '(clojure-joker clj-kondo-clj clj-kondo-cljs clj-kondo-edn))
  (setq flycheck-checkers (cons checker (delq checker flycheck-checkers))))

(dolist (checkers '((clojure-joker . clj-kondo-clj)
                    (clj-kondo-cljs . clojurescript-joker)
                    (clj-kondo-cljc . clojure-joker)
                    (clj-kondo-edn . edn-joker)))
        (flycheck-add-next-checker (car checkers) (cons 'error (cdr checkers))))

Diffing

Let’s make diffing of cider test output a tiny bit better

(setq-default ediff-ignore-similar-regions t)
;; used when calling ediff-show-diff-output from ediff session
;; (bound to D). Not interactive.
(setq ediff-custom-diff-options "--suppress-common-lines")

Social media

IRC

Let’s use IRC in Emacs because why not.

Disabling it for now - don’t like it when there are distractions in my Emacs

;; (use-package erc)
;; (setq erc-hide-list '("JOIN" "PART" "QUIT"))
;; (setq erc-autojoin-channels-alist
;;    '(("freenode.net" "#clojure")))
;; (erc :server "irc.freenode.net" :port 6667 :nick "annapawlicka")