Skip to content

Latest commit

 

History

History
852 lines (723 loc) · 22.5 KB

config.org

File metadata and controls

852 lines (723 loc) · 22.5 KB

Emacs Configuration

Declaring Emacs bankruptcy (again) and starting a new literate config using Org mode.

All packages are configured with use-package

Much of this adapted from danelmai’s config

Personal Information

(setq user-full-name "Ryan McGuire"
      user-mail-address "ryan@enigmacurry.com")

Global keybindings

Let’s use key chords for easy non-modal movement keys.

(use-package key-chord
  :ensure t
  :init
  (key-chord-mode 1)
  (key-chord-define-global "ji" 'backward-char)
  (key-chord-define-global "ko" 'forward-char)
  (key-chord-define-global "io" 'previous-line)
  (key-chord-define-global "ui" 'previous-line)
  (key-chord-define-global "jk" 'next-line)
  (key-chord-define-global "kl" 'next-line)
  )

Customize settings

Set up the customize file to its own separate file, instead of saving customize settings in init.el.

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

Sane defaults

Let’s start with some sane defaults, shall we?

Sources for this section include Magnars Sveen and Sacha Chua.

;; These functions are useful. Activate them.
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'dired-find-alternate-file 'disabled nil)

;; Answering just 'y' or 'n' will do
(defalias 'yes-or-no-p 'y-or-n-p)

;; Keep all backup and auto-save files in one directory
(setq backup-directory-alist '(("." . "~/.emacs.d/backups")))
(setq auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-save-list/" t)))

;; UTF-8 please
(setq locale-coding-system 'utf-8) ; pretty
(set-terminal-coding-system 'utf-8) ; pretty
(set-keyboard-coding-system 'utf-8) ; pretty
(set-selection-coding-system 'utf-8) ; please
(prefer-coding-system 'utf-8) ; with sugar on top
(setq-default indent-tabs-mode nil)

;; Turn off the blinking cursor
(blink-cursor-mode -1)

(setq-default indent-tabs-mode nil)
(setq-default indicate-empty-lines t)

;; Don't count two spaces after a period as the end of a sentence.
;; Just one space is needed.
(setq sentence-end-double-space nil)

;; delete the region when typing, just like as we expect nowadays.
(delete-selection-mode t)

(show-paren-mode t)

(column-number-mode t)

(global-visual-line-mode)
(diminish 'visual-line-mode)

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

;; -i gets alias definitions from .bash_profile
(setq shell-command-switch "-ic")

;; Visible bell:
;(setq visible-bell t)
;; Turn off bell completely:
(setq visible-bell nil)
(setq ring-bell-function 'ignore)

The following function for occur-dwim is taken from Oleh Krehel from his blog post at (or emacs. It takes the current region or the symbol at point as the default value for occur.

(defun occur-dwim ()
  "Call `occur' with a sane default."
  (interactive)
  (push (if (region-active-p)
            (buffer-substring-no-properties
             (region-beginning)
             (region-end))
          (thing-at-point 'symbol))
        regexp-history)
  (call-interactively 'occur))

(bind-key "M-s o" 'occur-dwim)

Here we make page-break characters look pretty, instead of appearing as ^L in Emacs. Here’s an informative article called “Using Page-Breaks in GNU Emacs” by Eric J. M. Ritz.

(use-package page-break-lines
  :ensure t)

Who uses suspend?

(global-unset-key (kbd "C-z"))

Themes

Theme functions

(defun switch-theme (theme)
  "Disables any currently active themes and loads THEME."
  ;; This interactive call is taken from `load-theme'
  (interactive
   (list
    (intern (completing-read "Load custom theme: "
                             (mapc 'symbol-name
                                   (custom-available-themes))))))
  (let ((enabled-themes custom-enabled-themes))
    (mapc #'disable-theme custom-enabled-themes)
    (load-theme theme t)))

(defun disable-active-themes ()
  "Disables any currently active themes listed in `custom-enabled-themes'."
  (interactive)
  (mapc #'disable-theme custom-enabled-themes))

(bind-key "s-<f12>" 'switch-theme)
(bind-key "s-<f11>" 'disable-active-themes)

Monokai theme

(use-package monokai-theme
  :if (window-system)
  :ensure t
  :init
  (setq monokai-use-variable-pitch nil)
  (switch-theme 'monokai)
)

Transparent Background

 (set-frame-parameter (selected-frame) 'alpha '(85 . 50))
 (add-to-list 'default-frame-alist '(alpha . (85 . 50)))
 (defun transparency-toggle ()
   (interactive)
   (let ((alpha (frame-parameter nil 'alpha)))
     (set-frame-parameter
      nil 'alpha
      (if (eql (cond ((numberp alpha) alpha)
                     ((numberp (cdr alpha)) (cdr alpha))
                     ;; Also handle undocumented (<active> <inactive>) form.
                     ((numberp (cadr alpha)) (cadr alpha)))
               100)
          '(85 . 50) '(100 . 100)))))
(transparency-toggle)

Font

Default font:

(add-to-list 'default-frame-alist
             '(font . "Ubuntu Mono-24"))

Display emojis. Source of system-specific fonts is in the README for the emacs-ac-emoji package.

(let ((font (if (= emacs-major-version 25)
                "Symbola"
              (cond ((string-equal system-type "darwin")    "Apple Color Emoji")
                    ((string-equal system-type "gnu/linux") "Symbola")))))
  (set-fontset-font t 'unicode font nil 'prepend))

Emacsclient

Start the client server

(use-package server
  :config
  (server-start))

Ido

Ido makes finding files/buffers/etc much easier

(use-package ido
  :init
  (setq ido-enable-flex-matching t)
  (setq ido-everywhere t)
  (ido-mode t)
  (use-package ido-vertical-mode
    :ensure t
    :defer t
    :init 
    ; Use more space in the mini buffer
    (ido-vertical-mode 1)
    ;remember buffers opened in previous sessions
    (setq ido-use-virtual-buffers t)
    (setq ido-vertical-define-keys 'C-n-and-C-p-only)))

ELPA packages

Company

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

Whichkey

Whichkey is awesome, it teaches you keyboard shortcuts as you type them. Let’s do that gloablly:

(use-package which-key
  :ensure t
  :init
  (which-key-mode))

Avy

(use-package avy
  :ensure t
  :init
  (global-set-key (kbd "C-z") 'avy-goto-char-timer)
  )

Ace Window

I think avy is superior, but sometimes you simply want to “go to the other window” (not caring where exactly, because avy could do that better), but that starts to get tediously complex when you have more than two windows open. ace-window solves that nicely with numeric jump points.

Rebind C-x o to ace-window:

(use-package ace-window
  :ensure t
  :init
  (progn
    (global-set-key [remap other-window] 'ace-window)))

Magit

(use-package magit
  :ensure t
  :defer t
  :bind ("C-c g" . magit-status)
  :config
  (define-key magit-status-mode-map (kbd "q") 'magit-quit-session)
  (define-key magit-status-mode-map (kbd "q") 'magit-quit-session))

Fullscreen magit

;; full screen magit-status

(defadvice magit-status (around magit-fullscreen activate)
  (window-configuration-to-register :magit-fullscreen)
  ad-do-it
  (delete-other-windows))

(defun magit-quit-session ()
  "Restores the previous window configuration and kills the magit buffer"
  (interactive)
  (kill-buffer)
  (jump-to-register :magit-fullscreen))

Gists

(use-package gist
  :init
  (setq gist-view-gist t) ; view gist in browser on create
  :ensure t
  :commands gist-list)

Rainbow mode

This minor mode sets background color to strings that match color names, e.g. #0000ff is displayed in white with a blue background.

(use-package rainbow-mode
  :ensure t
  :config
  ;(add-hook 'html-mode-hook 'rainbow-mode)
  (add-hook 'css-mode-hook 'rainbow-mode))

Emmet

According to their website, “Emmet — the essential toolkit for web-developers.”

(use-package emmet-mode
  :ensure t
  :commands emmet-mode
  :config
  (add-hook 'html-mode-hook 'emmet-mode)
  (add-hook 'css-mode-hook 'emmet-mode))

Zoom-frm

zoom-frm is a nice package that allows you to resize the text of entire Emacs frames (this includes text in the buffer, mode line, and minibuffer). The zoom-in/out command acts similar to the text-scale-adjust command—you can chain zooming in, out, or resetting to the default size once the command has been initially called.

Changing the frame-zoom-font-difference essentially enables a “presentation mode” when calling toggle-zoom-frame.

(use-package zoom-frm
  :ensure t
  :bind (("C-M-=" . zoom-in/out)
         ("H-z"   . toggle-zoom-frame)
         ("s-<f1>" . toggle-zoom-frame))
  :config
  (setq frame-zoom-font-difference 15))

Scratch

Convenient package to create *scratch* buffers that are based on the current buffer’s major mode. This is more convienent than manually creating a buffer to do some scratch work or reusing the initial *scratch* buffer.

(use-package scratch
  :ensure t
  :commands scratch)

Shell pop

Quickly open and close a shell

(use-package shell-pop
  :ensure t
  :bind ("C-c t" . shell-pop)
  :init
  (setq shell-pop-shell-type (quote ("ansi-term" "*ansi-term*" (lambda nil (ansi-term shell-pop-term-shell))))))

Quickrun

(use-package quickrun
  :defer 10
  :ensure t
  :bind ("s-q" . quickrun))

Javascript

Venerable JS2 mode

(use-package js2-mode
  :ensure t
  :init
  (add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
  (add-to-list 'interpreter-mode-alist '("node" . js2-mode))
  (add-to-list 'auto-mode-alist '("\\.jsx\\'" . js2-jsx-mode))
  :config
  (setq js2-basic-offset 2) ; Use two spaces for indentation
  (setq js2-strict-missing-semi-warning nil); Don't enforce semicolons
)

js2-refactor

(use-package js2-refactor
  :ensure t
  :init
  (add-hook 'js2-mode-hook #'js2-refactor-mode)
)

Flycheck enabled eslint:

(use-package eslint-fix
  :ensure t
  :init
  (eval-after-load 'js2-mode
    '(add-hook 'js2-mode-hook 
               (lambda () 
                 (add-hook 'after-save-hook 
                           (lambda ()
                             (eslint-fix)
                             ;(revert-buffer nil t)
                             ))
                 (flycheck-mode))))
)

Tern.js code introspection and completion:

Web mode

(use-package web-mode
  :ensure t
  :init
  (require 'web-mode)
  (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.tsx\\'" . web-mode))
  (add-hook 'web-mode-hook
            (lambda ()
              (when (string-equal "tsx" (file-name-extension buffer-file-name))
                (setup-tide-mode))))
  (setq web-mode-enable-auto-quoting nil)
  (setq web-mode-code-indent-offset 2)
  (setq web-mode-markup-indent-offset 2)
  (setq web-mode-css-indent-offset 2)
  )

Typescript

(defun setup-tide-mode ()
  (interactive)
  (tide-setup)
  (flycheck-mode +1)
  (setq flycheck-check-syntax-automatically '(save mode-enabled))
  (eldoc-mode +1)
  (tide-hl-identifier-mode +1)
  ;; company is an optional dependency. You have to
  ;; install it separately via package-install
  ;; `M-x package-install [ret] company`
  (company-mode +1))
(use-package tide
  :ensure t
  :config
  ;; aligns annotation to the right hand side
  (setq company-tooltip-align-annotations t)
  ;; formats the buffer before saving
  (add-hook 'before-save-hook 'tide-format-before-save)
  (add-hook 'typescript-mode-hook #'setup-tide-mode)
  ;; format options
  (setq tide-format-options '(:insertSpaceAfterFunctionKeywordForAnonymousFunctions t :placeOpenBraceOnNewLineForFunctions nil))
  )

Markdown mode

(use-package markdown-mode
  :ensure t
  :mode (("\\.markdown\\'" . markdown-mode)
         ("\\.md\\'"       . markdown-mode)
         ("\\.markdown\\'" . orgtbl-mode)
         ("\\.md\\'"       . orgtbl-mode))
)

;; Convert Org-mode table to Github Flavored Markdown
;; https://gist.github.com/yryozo/5807243
;; http://stackoverflow.com/questions/14275122/editing-markdown-pipe-tables-in-emacs#20912535
;;  
;; <!-- 
;; #+ORGTBL: SEND $1 orgtbl-to-gfm
;; | $0 | 
;; -->

(defun orgtbl-to-gfm (table params)
  "Convert the Orgtbl mode TABLE to GitHub Flavored Markdown."
  (let* ((alignment (mapconcat (lambda (x) (if x "|--:" "|---"))
                               org-table-last-alignment ""))
         (params2
          (list
           :splice t
	   :hline (concat alignment "|")
           :lstart "| " :lend " |" :sep " | ")))
    (orgtbl-to-generic table (org-combine-plists params2 params))))

Projectile mode

Work on project directories

(use-package projectile
  :ensure t
  :diminish projectile-mode
  :commands (projectile-mode projectile-switch-project)
  :bind ("C-c p p" . projectile-switch-project)
  :config
  (projectile-global-mode t)
  (setq projectile-enable-caching t)
  (setq projectile-switch-project-action 'projectile-dired))

Minimap

Sublime text like miniature buffer sidebar

(use-package minimap
  :ensure t
  :init
  ;(minimap-mode)
)

YAML mode

(use-package yaml-mode
  :ensure t
)

Yasnippet

(use-package yasnippet
  :ensure t
  )

Pug

(use-package pug-mode
  :ensure t
  )

Dired+

(use-package dired+
  :ensure t
  :config
  ; Don't open new buffers when visiting directories in dired
  (diredp-toggle-find-file-reuse-dir 1)
  )

Neotree

(use-package neotree
  :ensure t
  :config
  (global-set-key [f8] 'neotree-toggle)
  (setq neo-theme 'nerd)
  )
(use-package all-the-icons
  ;used for the icons theme
  ;but make sure to install the TTFs from the repo:
  ; https://github.com/domtronn/all-the-icons.el/tree/master/fonts
  :ensure t
)

Python

(use-package python-mode
  :defer t
  :ensure t
  :init
  ;; Configure flymake for Python
  (when (load "flymake" t)
    (defun flymake-pylint-init ()
      (let* ((temp-file (flymake-init-create-temp-buffer-copy
                         'flymake-create-temp-inplace))
             (local-file (file-relative-name
                          temp-file
                          (file-name-directory buffer-file-name))))
        (list "epylint" (list local-file))))
    (add-to-list 'flymake-allowed-file-name-masks
                 '("\\.py\\'" flymake-pylint-init)))
  ;; Set as a minor mode for Python
  (add-hook 'python-mode-hook '(lambda () (flymake-mode)))
  ;; To avoid having to mouse hover for the error message, 
  ;; these functions make flymake error messages appear in the minibuffer
  (defun show-fly-err-at-point ()
    "If the cursor is sitting on a flymake error, display the message in the minibuffer"
    (require 'cl)
    (interactive)
    (let ((line-no (line-number-at-pos)))
      (dolist (elem flymake-err-info)
        (if (eq (car elem) line-no)
            (let ((err (car (second elem))))
              (message "%s" (flymake-ler-text err))))))))

(add-hook 'post-command-hook 'show-fly-err-at-point)
(use-package jedi
  :ensure t
  :init
  (add-hook 'python-mode-hook 'jedi:setup)
  (setq jedi:complete-on-dot t))

Org mode

Org activation bindings

Set up some global key bindings that integrate with Org Mode features.

(bind-key "C-c l" 'org-store-link)
(bind-key "C-c c" 'org-capture)
(bind-key "C-c a" 'org-agenda)

Org agenda

(setq org-agenda-files
      (delq nil
            (mapcar (lambda (x) (and (file-exists-p x) x))
                    '("~/Dropbox/Agenda"))))

Org capture

(bind-key "C-c c" 'org-capture)
(setq org-default-notes-file "~/Dropbox/Notes/notes.org")

Org setup

Speed commands are a nice and quick way to perform certain actions while at the beginning of a heading. It’s not activated by default.

See the doc for speed keys by checking out the documentation for speed keys in Org mode.

(setq org-use-speed-commands t)
(setq org-image-actual-width 550)
(setq org-highlight-latex-and-related '(latex script entities))

Org tags

The default value is -77, which is weird for smaller width windows. I’d rather have the tags align horizontally with the header. 45 is a good column number to do that.

(setq org-tags-column 45)

Org babel languages

(org-babel-do-load-languages
 'org-babel-load-languages
 '((python . t)
   (C . t)
   (calc . t)
   (latex . t)
   (java . t)
   (ruby . t)
   (lisp . t)
   (scheme . t)
   (shell . t)
   (sqlite . t)
   (js . t)))

(defun my-org-confirm-babel-evaluate (lang body)
  "Do not confirm evaluation for these languages."
  (not (or (string= lang "C")
           (string= lang "java")
           (string= lang "python")
           (string= lang "emacs-lisp")
           (string= lang "sqlite"))))
(setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate)

Org babel/source blocks

I like to have source blocks properly syntax highlighted and with the editing popup window staying within the same window so all the windows don’t jump around. Also, having the top and bottom trailing lines in the block is a waste of space, so we can remove them.

I noticed that fontification doesn’t work with markdown mode when the block is indented after editing it in the org src buffer—the leading #s for headers don’t get fontified properly because they appear as Org comments. Setting org-src-preserve-indentation makes things consistent as it doesn’t pad source blocks with leading spaces.

(setq org-src-fontify-natively t
      org-src-window-setup 'current-window
      org-src-strip-leading-and-trailing-blank-lines t
      org-src-preserve-indentation t
      org-src-tab-acts-natively t)

Org exporting

Pandoc exporter

Pandoc converts between a huge number of different file formats.

(use-package ox-pandoc
  :no-require t
  :defer 10
  :ensure t)

LaTeX exporting

I’ve had issues with getting BiBTeX to work correctly with the LaTeX exporter for PDF exporting. By changing the command to `latexmk` references appear in the PDF output like they should. Source: http://tex.stackexchange.com/a/161619.

(setq org-latex-pdf-process (list "latexmk -pdf %f"))

Browser

Make chromium my default browser:

(setq browse-url-browser-function 'browse-url-chromium)

Sound effects

Let’s define some sound effects to use audible alerts:

(defun play-mp3 (mp3file)
  (let ((default-directory (expand-file-name "~/.emacs.d/audio")))
    (start-process-shell-command "play-mp3" nil (format "mpg123 %s" mp3file))))

;; CC-0 sounds from http://freesound.org/people/soneproject/packs/15057/
(defun beep-1 nil
  (play-mp3 "244356__soneproject__digital-life-1.mp3"))
(defun beep-2 nil
  (play-mp3 "255102__soneproject__jingle3.mp3"))
(defun beep-error-1 nil
  (play-mp3 "260084__soneproject__sfx15.mp3"))

;; Try-finally wrapper with sounds:
(defmacro audible-success (fn &rest finally)
  `(unwind-protect
       (let (retval)
         (condition-case ex
             (setq retval (progn ,fn))
           ('error 
            (setq retval (cons 'exception (list ex)))
            (beep-error-1)
            (error "%s" retval)))
         (beep-1)
         retval)
     ,@finally))
;; test:
;;(audible-success (message "k") (message "done"))
;;(audible-success (error "nope") (message "done"))

Blog

All my blog config is in the rymcg.tech repository, which tangles to rymcg.tech.el. Bootstrap it by loading that file if it exists:

;; Load rymcg.tech.el which is tangled from rymcg.tech/README.org
(let ((rymcg/init (expand-file-name "~/.emacs.d/rymcg.tech.el")))
  (if (file-exists-p rymcg/init)
    (load-file rymcg/init)))

Smart TAB completion

This is giving me some problems so this is left unbound for now.

(defun check-expansion ()
  (save-excursion
    (if (looking-at "\\_>") t
      (backward-char 1)
      (if (looking-at "\\.") t
        (backward-char 1)
        (if (looking-at "->") t nil)))))

(defun do-yas-expand ()
  (let ((yas/fallback-behavior 'return-nil))
      (yas/expand)))

(defun tab-indent-or-complete ()
  (interactive)
  (if (minibufferp)
      (minibuffer-complete)
    (if (or (not yas/minor-mode)
            (null (do-yas-expand)))
        (if (check-expansion)
            (company-complete-common)
          (indent-for-tab-command)))))

;(global-set-key [tab] 'tab-indent-or-complete)