Skip to content

Instantly share code, notes, and snippets.

@yaodong
Last active November 1, 2022 13:55
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yaodong/532e5b31781724ea2566503edcc498c3 to your computer and use it in GitHub Desktop.
Save yaodong/532e5b31781724ea2566503edcc498c3 to your computer and use it in GitHub Desktop.
title date tags categories
How to get started to build your own Spacemacs
2018-10-12 12:59
emacs
Tools

I have been a Vim user for quite a while. I love it, so the very first thing when I set up a new server is installing VIM. I heard a lot about Emacs and tried it. It's better at almost everything except text editing. So I stayed with Vim until Spacemacs was released. The Vim key bindings of Spacemacs is so excellent that I switched.

However, Spacemacs has its problem: boots up slowly and crashes frequently. Upgrading packages became very challenging. Finally, I have to use the develop branch because the master branch is not working anymore. People began to complain and requested to speed up the release from the master branch. Considering its dependencies and numerous open issues, I have no hope for this.

screenshot of spacemacs on Github

Screenshot taken on Oct. 31, 2018, Spacemacs has 2008 open issues and the last update of master branch is Mar 3, 2018.

I decided to build my Spacemacs.

The features of Spacemacs I rely on most are the evil layer and the convenient key bindings. Other features such as navigating, window management, and programming language support can be added later. Then I did it and found that It's much easier than I thought.

Assuming you are a proficient Emacs user. If not, start from here or pick one starter-kit.

The first step is managing the packages with macro use-package. For this step, you need to

  1. Installation of use-package
  2. learn how to use it

Then, we need three packages:

  1. evil
  2. which-key
  3. general

If any package of the above is new to you, stop reading and Google it.

(use-package evil
  :ensure t
  :config
  (progn
    (evil-mode 1)
    (require 'evil-leader)
    (setq evil-default-cursor t)))

(use-package general
  :ensure t)

(use-package which-key
  :ensure t
  :config
  (progn
    (setq which-key-idle-delay 0.5)
    (which-key-mode +1)))

That's all you need to get started. Pretty easy, isn't it?

I used the global leader key SPC and major mode leader key , a lot in Specemacs. Let's define two key sequences for demonstration.

  • SPC w / which can split the selected window into two windows, positioned side by side.
  • , h s which can insert a subheading when and only when the major mode is org-mode.

To define a global key sequence with general, using general-define-key:

(general-define-key
   :state 'normal
   :prefix "SPC"
   "w/" 'split-window-right)

Now pressing SPC w / can call the function split-window-right, but if you pause typing after typed SPC you will see a hint: w +prefix. That's because Emacs doesn't know what's SPC w means. To fix this, we need to provide a clue for which-key.

(which-key-add-key-based-replacements
   "SPC w"
   "windows")

Now, pressing SPC w you can see w +windows instead of w +prefix.

The configuration of major mode leader key is similar:

(general-define-key
   :prefix ","
   :states 'normal
   :keymaps 'org-mode-map
   "hs" 'org-insert-subheading)

(which-key-add-major-mode-key-based-replacements
   'org-mode
   ",h"
   "headings")

But writing multiple key bindings is still not convenient, so I wrote some helpers:

(setq-default
  leader-key "SPC"
  leader-for-major-mode ",")

(defun set-keys-for-major-mode (maps key def &rest bindings)
  (while key
    (general-define-key 
      :prefix "," 
      :states 'normal 
      :keymaps maps 
      key def)
    (setq key (pop bindings) def (pop bindings))))

(defun set-keys (key def &rest bindings)
  (while key
    (general-define-key 
      :states 'normal
      :prefix user/leader-key
      key def)
    (setq key (pop bindings) def (pop bindings))))

(defun declare-prefixes (prefix name &rest bindings)
  (while prefix
    (which-key-add-key-based-replacements (concat leader-key " " prefix) name)
    (setq prefix (pop bindings) name (pop bindings))))

(defun declare-prefixes-for-major-mode (mode key def &rest bindings)
  (while key
    (which-key-add-major-mode-key-based-replacements mode (concat leader-for-major-mode key) def)
    (setq key (pop bindings) def (pop bindings))))

With these helpers, defining multiple prefixes can be rewritten to:

(declare-prefixes 
  "a"   "applications"
  "b"   "buffers"
  "e"   "errors"
  "f"   "files"
  ;; omitted
  "w"   "windows")

(set-keys
  "SPC" 'helm-M-x
  "!"   'shell-command
  "v"   'er/expand-region
  "ac"  'calc-dispatch
  "aP"  'proced
  ;; omitted
  "au"  'undo-tree-visualize)

The define of multiple major mode key bindings can be:

(declare-prefixes-for-major-mode 
 'org-mode
 "e"  "export"
 "x"  "text"
 "h"  "headings"
 "i"  "insert"
 "t"  "tables"
 ;; omitted
 "tt" "toggle")

(set-keys-for-major-mode 'org-mode-map 
 "'" 'org-edit-special
 "c" 'org-capture
 "d" 'org-deadline
 ;; omitted
 "b" 'org-tree-to-indirect-buffer
 "A" 'org-archive-subtre)

The above steps may take you one or two hours. Then you will be able to start to build yourself a tremendous Spacemacs-like experience and don't need to wait for one of the thousands issues to be fixed.

By the way, here is my emacs.d. Free feel to use it.

@michael-nhat
Copy link

Very helpfull for some Spacemacs users, if he want customize emacs more flexiblely!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment