Emacs from scratch

Spacemacs is the first Emacs version I used, so I’m kind of attached to the evil-mode and SPC mnemonic key binding.

But I always have a feeling that something is not right, Spacemacs hides a lot of things under the hood, and it loads a lot of stuff that I do not need during the startup. This would be a huge waste, and I need to have a fresh setup that I can control every single thing in my editor.

So I created my own Emacs configuration, it’s surprisingly easier than as I thought.

custom-emacs.png

In this post, I’ll go through the steps I built a minimal Spacemacs-like version, with some basic key binding:

General:
  SPC /     : ripgrep
  SPC TAB   : previous buffer
  SPC SPC   : Open M-x

Files:
  SPC p f   : find files

Buffers:
  SPC b b   : buffers list

Window:
  SPC w l   : move right
  SPC w h   : move left 
  SPC w j   : move down
  SPC w k   : move up
  SPC w /   : split right
  SPC w -   : split bottom
  SPC w x   : close window

Other:
  SPC a t   : open terminal in current buffer

Configuration file

First, we need to create a init.el file:

$ mkdir -p ~/.emacs.d
$ touch ~/.emacs.d/init.el

Now, Emacs will start with the ugly tools bar and status bar, just like any editor that I would uninstall right away. Let’s change this.

Minimal UI

Now, we need to disable all the ugly stuff and make Emacs just as clean and clear as Vim or Sublime, Atom,… or whatever modern editor today has.

Put these to the beginning of your init.el:

;; Minimal UI
(scroll-bar-mode -1)
(tool-bar-mode   -1)
(tooltip-mode    -1)
(menu-bar-mode   -1)

Font and Frame Size

By default, Emacs will starts with a default monospace font and squared size window. We can change this by adding these settings:

(add-to-list 'default-frame-alist '(font . "mononoki-12"))
(add-to-list 'default-frame-alist '(height . 24))
(add-to-list 'default-frame-alist '(width . 80))

In the above config, we set the default font face to mononoki and font size is 12. We also set the frame dimension into 80x24, just like any default terminal emulator size.

Next, we’ll add a package manager to start installing themes/packages.

Package Manager

By default, Emacs is configured to use ELPA package archive, we’ll need to add more repository such as GNU ELPA, MELPA,…

Put this to the beginning of your init.el:

;; Package configs
(require 'package)
(setq package-enable-at-startup nil)
(setq package-archives '(("org"   . "http://orgmode.org/elpa/")
                         ("gnu"   . "http://elpa.gnu.org/packages/")
                         ("melpa" . "https://melpa.org/packages/")))
(package-initialize)

Next, we’ll use use-package to configure our packages better, in case you don’t know, this package provides a macro to allow you to easily install packages and isolate package configuration in a way that is both performance-oriented and tidy.

;; Bootstrap `use-package`
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))
(require 'use-package)

Vim key binding with Evil Mode

Now that you have package manager setted up, let’s install our first package: evil-mode, this package allows you to use Vim-like key binding in Emacs.

;; Vim mode
(use-package evil
  :ensure t
  :config
  (evil-mode 1))

I personally prefer using jk for escape key, so I’ll install evil-escape and have this setting:

(use-package evil-escape
  :ensure t
  :init
  (setq-default evil-escape-key-sequence "jk")
  :config
  (evil-escape-mode 1))

That’s it! Now restart your Emacs, you’ll see the mode line displaying the current Vim mode, and you’ll be able to navigate with hjkl.

Installing Theme

One of the best theme for Emacs I could found is doom-themes package, that has a lot of cool themes. The following code will install this package and load its flagship theme doom-one:

;; Theme
(use-package doom-themes
  :ensure t
  :config
  (load-theme 'doom-one t))

Installing Helm

Helm is a framework for incremental completions and narrowing selections in Emacs. Many people prefer ivy because it’s much lighter, for me, it’s doesn’t matter. I find helm is easier to use and config.

The following snippet will install helm and configure fuzzy matching:

;; Helm
(use-package helm
  :ensure t
  :init
  (setq helm-M-x-fuzzy-match t
  helm-mode-fuzzy-match t
  helm-buffers-fuzzy-matching t
  helm-recentf-fuzzy-match t
  helm-locate-fuzzy-match t
  helm-semantic-fuzzy-match t
  helm-imenu-fuzzy-match t
  helm-completion-in-region-fuzzy-match t
  helm-candidate-number-list 150
  helm-split-window-in-side-p t
  helm-move-to-line-cycle-in-source t
  helm-echo-input-in-header-line t
  helm-autoresize-max-height 0
  helm-autoresize-min-height 20)
  :config
  (helm-mode 1))

Installing Which Key

In Spacemacs, when you press SPC or any other key sequence, a small buffer will be popped up to show the list of features you can do next, installing which-key will give you this.

;; Which Key
(use-package which-key
  :ensure t
  :init
  (setq which-key-separator " ")
  (setq which-key-prefix-prefix "+")
  :config
  (which-key-mode 1))

Custom Key Binding

Finally, you can start config your custom key binding with general package, this is my config, the prefix is SPC just like in Spacemacs:

;; Custom keybinding
(use-package general
  :ensure t
  :config (general-define-key
  :states '(normal visual insert emacs)
  :prefix "SPC"
  :non-normal-prefix "M-SPC"
  ;; "/"   '(counsel-rg :which-key "ripgrep") ; You'll need counsel package for this
  "TAB" '(switch-to-prev-buffer :which-key "previous buffer")
  "SPC" '(helm-M-x :which-key "M-x")
  "pf"  '(helm-find-files :which-key "find files")
  ;; Buffers
  "bb"  '(helm-buffers-list :which-key "buffers list")
  ;; Window
  "wl"  '(windmove-right :which-key "move right")
  "wh"  '(windmove-left :which-key "move left")
  "wk"  '(windmove-up :which-key "move up")
  "wj"  '(windmove-down :which-key "move bottom")
  "w/"  '(split-window-right :which-key "split right")
  "w-"  '(split-window-below :which-key "split bottom")
  "wx"  '(delete-window :which-key "delete window")
  ;; Others
  "at"  '(ansi-term :which-key "open terminal")
))

Matching Titlebar color on MacOS

If you’re using Emacs on macOS, you can add this to have your titlebar color changed and matching your color theme:

;; Fancy titlebar for MacOS
(add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))
(add-to-list 'default-frame-alist '(ns-appearance . dark))
(setq ns-use-proxy-icon  nil)
(setq frame-title-format nil)

Project Management

One of the most important thing to install at first is projectile, for manage projects in Emacs. In my configuration, I also unset the projectile-require-project-root option to have projectile recognize any folder as a project, not just ones with project files.

;; Projectile
(use-package projectile
  :ensure t
  :init
  (setq projectile-require-project-root nil)
  :config
  (projectile-mode 1))

Optional: NeoTree and Icons

One thing that nice to have is neotree, which will display the folder tree. In this configuration, I also installed all-the-icons so neotree can be displayed with some nice graphical icons:

;; All The Icons
(use-package all-the-icons :ensure t)

;; NeoTree
(use-package neotree
  :ensure t
  :init
  (setq neo-theme (if (display-graphic-p) 'icons 'arrow)))

Just don’t forget to run M-x all-the-icons-install-fonts after start your Emacs for the first time.

Optional: Matching Parentheses

This is a very helpful built-in feature of Emacs, by enable this, it will highlight any matching parentheses that the cursor is on.

;; Show matching parens
(setq show-paren-delay 0)
(show-paren-mode 1)

Optional: Disable backup files

I find it really annoying when Emacs automatically create a backup file for every buffer you opened, so I disabled it, you might not want to do this:

;; Disable backup files
(setq make-backup-files nil) ; stop creating backup~ files
(setq auto-save-default nil) ; stop creating #autosave# files

Optional: Problem with environment variables

If you got problem with environment variables or commands, for example, Emacs could not recognize `brew` or something, you might need to load your .bashrc or .bash_profile manually:

(let ((path (shell-command-to-string ". ~/.bashrc; echo -n $PATH")))
  (setenv "PATH" path)
  (setq exec-path 
        (append
         (split-string-and-unquote path ":")
         exec-path)))

From here, you can continue customizing Emacs as you need, for example, add more language supports, customize your mode line,…

I hope you’ll find this post helpful and will be able to build your own Emacs configuration. Also, you can check my customized configuration here.

The best To-Do List System

Let me tell you about the best To-Do List System I’m using, the only one you need that could replace every single app on your mobile or your desktop. You are not gonna need bullet journals, google keep, org-mode or evernote for to-do list anymore.

A timeless method for to-do list:

./img/todo-list-method.jpg

What the fuck? You may asked.

I found it’s better to use a real to-do list, which you can just put it right under your nose, rather than an electronic one that hidden somewhere in your browser, or buried somewhere as an org-mode file, and required some efforts to open it up.

The paper list doesn’t go anywhere, you can quickly glance at it, take the pen and write it down immediately when something is coming up, you can’t forget it, and it will make you feel more responsibility with the tasks you wrote down.

This is what you need:

For an on-going task, draw a circle following by a description:

./img/on-going-task.jpg

The description should be clear, with the definition of done, do not put something generic or unclear without the goal, you won’t make it without a goal.

If you need a deadline, put it on the right side:

./img/on-going-with-deadline.jpg

You can even update the deadline:

./img/deadline-changed.jpg

When you done with it, just fill the circle, and scratch the whole line out:

./img/finished-task.jpg

That’s it. The to-do list need to be in short term only, for me, it’s just in a day. Any longer schedule should be on a calendar. At the end of the day, I just tear off the page, and throw it away. Carry over the to-do list will ruin your productivity, so don’t do that.

If you need to store the lists to keep track of your productivity, you can use Scannable app to scan and store it into your Evernote. It would be useful because Evernote can search for your handwritten text directly.

./img/evernote-search-handwritten.png

Update: After trying out Evernote OCR feature for a while, I decided to move to OneNote, the Office Lens + OneNote is a better OCR solution, because, you can see, it can recognize my dirty handwriting very well…

./img/onenote-ocr.png

Some might prefer bullet journals, it’s a good method as well, as long as you try to focus on the note-taking, don’t be that guy who trying to keep his notes tidy and clean and beautiful just to upload them to Instagram, some even draw some fancy stuff, that’s unneccessary and waste of time.

I doubt any of those guys who posted fancy to-do lists ever use a to-do list.

Create your website with WordPress.com
Get started