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
(setq user-full-name "Ryan McGuire"
user-mail-address "ryan@enigmacurry.com")
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)
)
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)
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"))
(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)
(use-package monokai-theme
:if (window-system)
:ensure t
:init
(setq monokai-use-variable-pitch nil)
(switch-theme 'monokai)
)
(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)
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))
Start the client server
(use-package server
:config
(server-start))
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)))
(use-package company
:ensure t
:init
; use company-mode everywhere
(add-hook 'after-init-hook 'global-company-mode)
)
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))
(use-package avy
:ensure t
:init
(global-set-key (kbd "C-z") 'avy-goto-char-timer)
)
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)))
(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))
;; 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))
(use-package gist
:init
(setq gist-view-gist t) ; view gist in browser on create
:ensure t
:commands gist-list)
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))
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
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))
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)
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))))))
(use-package quickrun
:defer 10
:ensure t
:bind ("s-q" . quickrun))
(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
)
(use-package js2-refactor
:ensure t
:init
(add-hook 'js2-mode-hook #'js2-refactor-mode)
)
(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))))
)
(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)
)
(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))
)
(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))))
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))
Sublime text like miniature buffer sidebar
(use-package minimap
:ensure t
:init
;(minimap-mode)
)
(use-package yaml-mode
:ensure t
)
(use-package yasnippet
:ensure t
)
(use-package pug-mode
:ensure t
)
(use-package dired+
:ensure t
:config
; Don't open new buffers when visiting directories in dired
(diredp-toggle-find-file-reuse-dir 1)
)
(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
)
(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))
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)
(setq org-agenda-files
(delq nil
(mapcar (lambda (x) (and (file-exists-p x) x))
'("~/Dropbox/Agenda"))))
(bind-key "C-c c" 'org-capture)
(setq org-default-notes-file "~/Dropbox/Notes/notes.org")
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))
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-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)
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)
Pandoc converts between a huge number of different file formats.
(use-package ox-pandoc
:no-require t
:defer 10
:ensure t)
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"))
Make chromium my default browser:
(setq browse-url-browser-function 'browse-url-chromium)
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"))
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)))
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)