Journey of me writing modern(?) day .emacs.d using:
use-packagegeneral.elevil-modewhich-key
These problems are getting bigger and my Spacemacs config are getting
messier. So I decided to write my own .emacs.d. After writing some
code I really feel like that everyone should write their own Emacs
configuration, here is why:
- Different people emphasize on different tech stack, you don’t need EVERYTHING
- Some prefer emacs key bindings while others prefer vim key bindings
- There EXIST people who use keyboard layout other than QWERTY
- The problem with large configuration like spacemacs is the same
with any complex enough IDE:
- Their is a learning curve before you can be productive.
- Even you think you are productive, you still just use, like 10% of what it offers.
- Configuration generally separates into two parts, the default part, or core if you prefer, and more flexible part, or module. And to be honest, I find it difficult to distinguish them. Because you still need to change the configuration if you want to tweak it no matter which part it from. Code is code.
I know that my problem is unique that not everybody is using emacs with evil-mode on a dvorak keyboard. But after writing some lisp myself. I find it quite satisfying and enjoyable:
- Emacs Lisp is extremely well documented.
C-h kdocumentation for a key strokeC-h fdocumentation for a functionC-h vdocumentation for a variableC-h blist of all keybindings available in current bufferC-h Ssearch symbol in Emacs manual
- Emacs ecosystem has advanced a lot since version 22/23. With proper
tools one can easily replicated what minimal spacemacs offers.
use-packagekeep your code tidy and fastgeneral.eldrop-in replacement for various keybinding methods for both stock emacs an evil-modeevil-modeuse Vim inside Emacswhich-keydisplay key bindings following your currently entered incomplete command in a popup window
- There are a lot of great tutorials and source codes out there that helps you write anything you want.
I also read a lot Doom, Prelude and Spacemacs source code. I
learned a lot even just by copy-pasting their code. I check every
variable and every function I see with C-h so that I know what they
do.
Actually, Spacemacs internally use use-package and which-key. I
think with this approach the ideal configuration should look something
like this:
Just bunch of use-package forms.
That being said, there are some minor issues:
use-packagedoesn’t offer a convenient way to write code dependent on multiple packages, here is an issue that describes it.Spacemacssolves it by create it’s own layer loading mechanism. but it’s excessive as long as you aren’t writing that much code. You can just use our old friendwith-eval-after-load. Or don’t use anything, just make sure your packages are load in correct order.- Need quite some time to figure out how to glue these five packages
together. I haven’t found one single
.emacs.don github that uses all five package, let alone one with DVORAK keybindings support (I can’t type on QWERTY). - Need to RTFM. Like, a LOT. And some of them are confusing, like buffers and windows.
Once having a basic setup, one can extend it with ease and efficiency. By saying basic setup, I meant to write Emacs Lisp comfortably:
- basic theme/font/ui setup that doesn’t give me eyesore
- a package manager that doesn’t suck, e.g.
straight.el,el-get,quelpa… - an autocomplete framework, e.g.
company,auto-complete - a completion framework, e.g.
ivy,helm - a lisp Structural Editing framework, e.g.
smartparens,paredit - a lisp Structural Editing framework that works with
evil-mode, e.g.evil-cleverparen
Then, just extend Emacs with bunch of use-package forms.
Anyway, here I am trying to achieve this. My configuration is
optimized for DVORAK keyboard. You may not be using DVORAK, but apart
from that it’s still a good reference to get started hacking Emacs.
It’s using “htns” instead of “hjkl” to move around. It also tries to
remap possible “C-j” “C-k” “C-n” “C-p” to “C-t” “C-n”. And it works
with evil-mode. It has a fast startup time, but I usually use emacs
daemon (see scripts directory). Check the tasks list for what I’ve
been doing and what will be implemented in the future.
Hope you find my experience helpful.
I guess not everybody is gonna read all the code (not too much TBH), so I’ll describe what my typical workflow looks like (keep in mind that this is entry level stuff, don’t laugh at me):
- Run
ecin terminal to fire up Emacs server and connect to it (export PATH=”$PATH:$HOME/.emacs.d/scripts/). - Switch to a project using
SPC p p, orSPC f fto navigate to a file in a new project. - Use
SPC p fto find file in a project. - In case of
projectilecouldn’t find a newly created file or still showing deleted file, runSPC p I - File related keybindings are in
SPC f, e.g.SPC f fget a list of files in current directory to open withSPC f Ddelete current file and its bufferSPC f Rrename current file and its buffer
but I usually find myself using
rangerto manage file (press-) - Buffer related keybindings are in
SPC b, e.g.SPC b bget a list of buffers to switch toSPC b dkill current buffer, but its window is still thereSPC b xkill current buffer and its windowSPC b Dget a list of buffers and choose one to killSPC b tnext bufferSPC b nprevious buffer
- Window related keybindings are in
SPC w, e.g.SPC w 2split window verticallySPC w 3split window horizontallySPC w h/t/n/smove to the left/down/up/right windowSPC 1/2.../9switch to a window by numberSPC w ddelete current window
- While editing a file
C-sto search text in current bufferSPC /to search text in current project (usingrg):%s/from/to/gto find and replace text in current buffer
- After editing some file, I fire up magit:
SPC g sgugo to the unstaged changess ystage all the changesc cwrite my commit message and “C-c C-c”P ppush to originqquit magit
C-x C-corSPC e qto exit Emacs
Some editing notes:
- Parentheses are paired using
smartparens, andevil-cleverparensto provide evil integration. Some keybindings I use most:M-(wrap an expression in parenthesesM-ainsert at end of an expressionM-iinsert at beginning of an expressionM-rraise an expressionM-ssplice an expression<and>to slurp expression_move to the first non opening characterddwill not break parenthesis and keep our s-expression correct
evil-commentaryadd comment operator, e.g.gcapto comment current paragraph
evil-surroundcan emulates surround.vim, e.g.ysW"to wrap to word with"csW"(change surrounding of a word from"to(
evil-lionadd align text operator, e.g.glap'to align current paragraph using'
expand-regionis integrated with evil. For example, in the string (hello “foo| oo”):- double press
vit will select “foo” - then “"foo"”
- then “hello "foooo"”
- then the whole expression with the parenthesis.
- double press
- If you’ve seen emacsrocks episode1, you may wonder how to do this
in evil-mode
- in normal state press
C-vwhich callsevil-visual-block - move to the space before
lhowever you want (avy isearch swiper) - press
R, now anything typed will only show up on the first line, but when one returns to normal state, by pressing ESC, then the typed characters will appear on each line of the block/rectangle.
- in normal state press
- ivy is integrated with wgrep, so you can edit your search result:
- while searching with counsel-rg/swiper, press
C-c C-oto runivy-occur, it’ll bring up a new buffer with all search result. - then press
wto enter editable state if you want to edit it, at last pressC-c C-cto save orC-c C-kto abort.
- while searching with counsel-rg/swiper, press
- [X] company (? seems hard to manage all the backends, need to investigate more)
- [ ] imenu
- custom imenu regular expressions with different languages
- imenu-list
- imenu-everywhere
- counsel-imenu (? counsel-org-goto)
- [ ] text folding with evil (? evil-vimish-fold and hideshow)
- [ ] ediff (? magit)
- [ ] snippet
- [ ] custom dashboard (? maybe)
- [ ] org-mode
- [X] popup management)
- [ ] workspace management (? but how)
- [ ] terminal (? is emacs really suitable for terminal usage)
- [ ] flycheck
- [ ] email client (? notmuch / mu4e)
- [-] various programming languages (? do we use language server)
- [X] Emacs-Lisp
- [X] Clojure
- [X] Ocaml
- [ ] …
- [X] basic emacs setup (speed up hacks, basic ui tweaks)
- [X] use-package
- [X] general.el
- [X] which-key
- [X] basic evil setup
- [X] basic build-in libraries (hideshow parens hl-line recentf saveplace …)
- [X] basic theme support
- [X] smartparens
- [X] evil-cleverparen
- [X] fira code ligature
- [X] basic evil setup with dvorak keybindings
- [X] expand-region with evil
- [X] avy
- [X] basic ivy
- [X] ivy-occur with evil
- [X] basic buffer management
- [X] basic counsel
- [X] projectile
- [X] counsel-projectile
- [X] macrostep with evil
- [X] page break (ui)
- [X] magit and evil-magit
- [X] ranger with evil
- [X] edebug with evil
- [X] expand-region with evil
- [X] esup with evil
- [X] indent guide
- [X] whitespace cleanup
- [X] aggressive-indent (? any better auto indent options out there)
- [X] xref with evil
- [X] multiple-cursor (evil-multiedit)
- [X] window management
- [X] winum
- [X] evil-window-map
- [X] ace-window
- [X] auto-compile (? don’t bother to compile our .emacs.d)
- [X] mode-line ui (doom-modeline seems decent enough)
- [X] leetcode module (solve leetcode problem without leaving emacs)
I’m using Emacs version 26, so I can’t guarantee it’ll be working on lower version.
mv ~/.emacs.d ~/.emacs.d.backup
git clone https://github.com/ACEMerlin/lain-emacs.git ~/.emacs.d
cp ~/.emacs.d/personal/lain.el.example ~/.emacs.d/personal/lain.elCustomize lain.el to your needs. (“SPC e I” to open it)
Also any lisp files inside personal directory will be loaded.
To use fancy icons M-x all-the-icons-install-fonts
Emacs will initialize tool-bar/menu-bar even if you have disabled them in your configuration, to avoid this:
cp ~/.emacs.d/.Xresources.example ~/.Xresources
xrdb ~/.XresourcesYou may want to put last line in your zshrc or bashrc.
You are gonna use your pinky a lot, and this will result in RSI if not handled properly. To avoid this, first I recommend reading xah’s blog “How to Avoid Emacs Pinky”.
Now here are some additional methods which are not mentioned in the blog post:
- If you’re using a thinkpad as I do, remap the two keys above touchpad and below spacebar to the keys you like.
- Use spacebar as control: Pressing and releasing results in space
as normal, but if held while pressing other keys it acts like
control. You can achieve this by using xcape if you’re on linux and
karabiner if on OSX. Both provide additonal features like generate
the
Escapekey whenLeft Controlis pressed and released on its own, it plays nicely with evil-mode(Vim). Also I’m on WSL, it works fine with X server.
If these two doesn’t suit you, I think at least you should swap keys around, or use sticky keys....
Good luck my fellow Emacsers.
To use my config, you’ll also need these.
I’m on debian so…
curl -LO https://github.com/BurntSushi/ripgrep/releases/download/0.10.0/ripgrep_0.10.0_amd64.deb
sudo dpkg -i ripgrep_0.10.0_amd64.debcurl -LO https://github.com/tonsky/FiraCode/files/412440/FiraCode-Regular-Symbol.zip
curl -LO https://github.com/tonsky/FiraCode/releases/download/1.206/FiraCode_1.206.zipcurl -LO https://github.com/sharkdp/fd/releases/download/v7.2.0/fd_7.2.0_amd64.debopam install utop ocamlformat ocp-indent dune merlinHappy hacking!





