Inspired by larstvei’s setup.
Check out EmacsCast, my podcast about Emacs. I talk about my config in Episode 2.
I think it’ll be better not to clone and use this as is, but rather build your config using mine as a starting point. But if you really want to try it, then follow these steps:
Clone the repo:
git clone https://github.com/freetonik/emacs-dotfiles
Make a backup of your old .emacs.d
:
mv ~/.emacs.d ~/.emacs.d-bak
Rename cloned directory:
mv dot-emacs ~/.emacs.d
On the first run Emacs will install some packages. It’s best to restart Emacs after that process is done for the first time.
When this configuration is loaded for the first time, the init.el
is
the file that is loaded. It looks like this:
;; This file replaces itself with the actual configuration at first run.
;; We can't tangle without org!
(require 'org)
;; Open the configuration
(find-file (concat user-emacs-directory "init.org"))
;; tangle it
(org-babel-tangle)
;; load it
(load-file (concat user-emacs-directory "init.el"))
;; finally byte-compile it
(byte-compile-file (concat user-emacs-directory "init.el"))
Lexical scoping for the init-file is needed, it can be specified in the header. This is the first line of the actual configuration:
;;; -*- lexical-binding: t -*-
Tangle and compile this file on save automatically:
(defun tangle-init ()
"If the current buffer is 'init.org' the code-blocks are
tangled, and the tangled file is compiled."
(when (equal (buffer-file-name)
(expand-file-name (concat user-emacs-directory "init.org")))
;; Avoid running hooks when tangling.
(let ((prog-mode-hook nil))
(org-babel-tangle)
(byte-compile-file (concat user-emacs-directory "init.el")))))
(add-hook 'after-save-hook 'tangle-init)
I like the default Menlo font, but 12 is too small for me. Also, remove the cruft and make the initial size bigger.
(set-frame-font "Menlo 15")
(load-theme 'tsdh-light)
(setq initial-frame-alist '((top . 50) (left . 100) (width . 145) (height . 50)))
(tool-bar-mode -1)
(display-time-mode 1)
Highlight parens without delay.
(setq show-paren-delay 0)
(show-paren-mode 1)
Wrap lines always.
(global-visual-line-mode 1)
Let all the file backups go to one global location instead of corresponding paths:
(setq backup-directory-alist '(("." . "~/.emacs.d/backups")))
Don’t show the startup message or screen, show keystrokes right away, don’t show the message in the scratch buffer, org-mode by default, sentences end with a single space, time in 24h format, wrap lines, disable the scroll bar and delete text when typing over selection.
(setq
inhibit-startup-message t
inhibit-startup-screen t
echo-keystrokes 0.1
initial-scratch-message nil
initial-major-mode 'org-mode
sentence-end-double-space nil
display-time-24hr-format t)
(visual-line-mode 1)
(scroll-bar-mode -1)
(delete-selection-mode 1)
I’m still not sure which way to go with the keys on macOS… The only truly comfortable CTRL position in the left command, but this will breaks muscle memory for some useful, but not-Emacsy things like CMD+c/v/x/z, CMD+s and CMD+a.
I’ll try this setup for now.
(setq mac-command-modifier 'control)
(setq mac-right-command-modifier 'control)
(setq mac-option-modifier 'meta)
(setq mac-control-modifier 'super)
With that in mind, Cmd+z becomes an annoying minimize into dock feature. So, C-z can be undo!
(global-set-key (kbd "C-z") 'undo)
Muscle memory is strong. Very often I press Cmd+v to paste, but it scrolls down. I rarely need to scroll one page, haven’t use scroll up/down since switching to Mac, so I’d rather unbind C-v completely. Scrolling pages is always disorienting anyways, I’d rather move by lines, paragraphs or i-search.
(global-unset-key (kbd "C-v"))
Nicer scrolling behaviour. Thanks to https://zeekat.nl/articles/making-emacs-work-for-me.html
(setq scroll-margin 1
scroll-step 1
scroll-conservatively 10000
scroll-preserve-screen-position 1)
(setq mouse-wheel-follow-mouse 't)
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1)))
Initialize package and add Melpa source
(require 'package)
(let* ((no-ssl (and (memq system-type '(windows-nt ms-dos))
(not (gnutls-available-p))))
(proto (if no-ssl "http" "https")))
;; Comment/uncomment these two lines to enable/disable MELPA and MELPA Stable as desired
(add-to-list 'package-archives (cons "melpa" (concat proto "://melpa.org/packages/")) t)
;;(add-to-list 'package-archives (cons "melpa-stable" (concat proto "://stable.melpa.org/packages/")) t)
(when (< emacs-major-version 24)
;; For important compatibility libraries like cl-lib
(add-to-list 'package-archives '("gnu" . (concat proto "://elpa.gnu.org/packages/")))))
(package-initialize)
Install use-package
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
Install try to try packages
(use-package try
:ensure t)
Nyan mode is essential
(use-package nyan-mode
:ensure t
:config
(nyan-mode))
Pass system shell environment to Emacs. This is important primarily for shell inside Emacs, but also things like Org mode export to Tex PDF don’t work, since it relies on running external command pdflatex
, which is loaded from PATH
.
(use-package exec-path-from-shell
:ensure t)
(when (memq window-system '(mac ns x))
(exec-path-from-shell-initialize))
Enable IDO mode
(setq ido-enable-flex-matching t)
(ido-mode 1)
(setq ido-everywhere t)
Store all my org files in ~/org
.
(setq org-directory "~/org")
And all of those files should be in included agenda.
(setq org-agenda-files '("~/org"))
Allow shift selection with arrows. This will not interfere with some built-in shift+arrow functionality in Org.
(setq org-support-shift-select t)
While writing this configuration file in Org mode, I have to write code blocks all the time. Org has templates, so doing <s TAB
creates a source code block. Here I create a custom template for emacs-lisp specifically. So, <el TAB
creates the Emacs lisp code block and puts the cursor inside.
(eval-after-load 'org
'(progn
(add-to-list 'org-structure-template-alist '("el" "#+BEGIN_SRC emacs-lisp \n?\n#+END_SRC"))))
There is a warning I haven’t dealt with yet:
:Warning: the following functions might not be defined at runtime: nyan-mode, exec-path-from-shell-initialize
It doesn’t seem to affect anything for now. I’ll fix it later.