coldnew's emacs

Table of Contents

https://img.shields.io/badge/license-GPL_3-green.svg?dummy https://travis-ci.org/coldnew/coldnew-emacs.svg?branch=master

Introduction

This is my emacs configuration, you can find it on GitHub or read in HTML or init.el directly.

Install emacs

My emacs is running under Mac OSX and Gentoo Linux and I really like them, following are some record for how I installed my emacs.

Mac OSX

In Mac OSX, I use homebrew to mantain opensource packages, I always install latest version of emacs via following command

# change --HEAD to --devel for current development version
brew install emacs --HEAD --use-git-head --with-cocoa --with-gnutls --with-rsvg --with-imagemagick
brew linkapps

Gentoo Linux

Gentoo Linux is the best linux distrobution I ever used and it's really easy to install latest apps.

USE="X gtk3 inotify xft imagemagick" emerge app-editors/emacs

Install or testing this config

  • First use git to download whole repo

    git clone https://github.com/coldnew/coldnew-emacs.git
    
  • Then use git submodule to download the spacemacs

    git submodule init
    git submodule update
    
  • You also need to install Cask for package management

    curl -fsSL https://raw.githubusercontent.com/cask/cask/master/go | python
    
  • Then use the make command bootstrap this config

    make bootstrap
    
  • If you only want to generate the init.el, jut type

    make init.el
    
  • If you do not put this repo on ~/.emacs.d, you need to use following command to start emacs

    emacs -q -l ~/coldnew-emacs/init.el
    

Packages need to install in system (Optional)

Some extra packages need to be installed in the system manually. These packages are optional but can make this configuration work more nicely.

Mac OSX

brew install fasd
brew install aspell --with-lang-en
brew install the_silver_searcher
brew install doxymacs
brew install gpg
brew install mu  --with-emacs --HEAD
brew install offlineimap

Gentoo Linux

In Gentoo Linux, don't forget to enable USE=emacs to make gentoo auto install emacs-related packages.

emerge app-shells/fasd
emerge app-shells/aspell
emerge sys-apps/the_silver_searcher
emerge app-shells/doxymacs
emerge app-crypt/gnupg
USE="emacs" emerge net-mail/mu
emerge net-mail/offlineimap

Initialization Emacs

There are some configurations I need to put at the beginning of the emacs config. These configurations are derived from my original init.el file.

Use lexical binding

For some of my functions, and general coolness, lexical binding is a must. Without it, closures cannot be made for example.

This line needs to appear at the beginning of the file to work. Just to keep things looking nice I put it at the beginning of the file.

;; -*- lexical-binding: t -*-

Prevent load outdated .elc files

Since emacs 24.4, new option load-prefer-newer has been introduce, which make me never accidentally using outdated compiled files.

(setq load-prefer-newer t)

Setup user-emacs-directory variable

In this configuration, user-emacs-directory always refer to the emacs configuration's init.el parent directory.

;; We set `user-emacs-directory' here so we can use command-line
;; switch different emacs configuration like following:
;;
;;    emacs -q -l ~/coldnew-spacemacs/init.el
(defconst user-emacs-directory
  (file-name-directory (or load-file-name (buffer-file-name)))
  "My emacs config directory.")

Setup user-cache-directory variable

Setup the cache directory to store some cache content.

(defconst user-cache-directory
  (file-name-as-directory (concat user-emacs-directory ".cache"))
  "My emacs storage area for persistent files.")
;; create the `user-cache-directory' if not exists
(make-directory user-cache-directory t)

Setup user-ramdisk-directory variable

(defconst user-ramdisk-directory
    (let ((ramdisk "/Volumes/ramdisk/")
          (user-ramdisk                   ; ~/ramdisk/
           (concat (getenv "HOME") "/ramdisk/"))
          (tmp "/tmp/"))
      (if (eq system-type 'darwin)
          ramdisk
        ;; if ~/ramdisk/ exist, use it
        (if (file-exists-p user-ramdisk)
            user-ramdisk
          ;; fallcack to system default ramdisk dir
          temporary-file-directory)))
  "My ramdisk path in system.")

Method to load secret file

Some of my password stored in a secret file with gnupg encrypt, I add this function here so I can inject some emacs-command which hass password/account setting.

(defun my/load-secret ()
  "Load my secret setting include password... etc."
  (let ((secret "~/.secret.el.gpg"))
    (when (file-exists-p secret) (load-file secret))))

Package Management

The main package magement in my emacs is Cask, which is a really nice package like npm, cargo …etc.

Cask can also install packages according to your emacs version, so you don't be afraid to get version conflicts after upgrade emacs.

Take my emacs as example, after initialize Cask, all package install by package.el just save to .cask folder according to your emacs version.

coldnew@Sara ~/.emacs.d $ tree -L 1 .cask/
.cask/
├── 24.5.1
├── 25.0.50.1
└── 25.1.50.1

3 directories, 0 files

Initialize package.el

Before we start this section, we need to initialize package.el first.

;; This must come before configurations of installed packages.
;; Don't delete this line. If you don't want it, just comment it out by adding a
;; semicolon to the start of the line. You may delete these explanatory
;; comments.
(package-initialize)

Add melpa to package list.

(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/"))

Cask and Pallet

Pallet is a wonderful little tool built on Cask, a dependency management tool for Emacs packages. Pallet adds automatic updating of the Caskfile when packages are installed and deleted.

Installing Cask

Just run this command in your terminal of choice:

curl -fsSkL https://raw.github.com/cask/cask/master/go | python

then add ~/.cask/bin to your PATH so that you can use cask.

Creating a Caskfile

For now, we just need a minimal Cask to get Pallet set up. Mine looks like this:

(source gnu)
(source melpa)

(depends-on "f")
(depends-on "s")
(depends-on "dash")
(depends-on "noflet")
(depends-on "pallet")
(depends-on "async")
(depends-on "req-package")
(depends-on "paradox")
(depends-on "org")
(depends-on "htmlize")

Then run the following command in your .emacs.d directory to set up Pallet.

cask install

Since the Cask file is just emacs-lisp file, add it to mode-alist.

(add-to-list 'auto-mode-alist '("Cask$" . emacs-lisp-mode))

Initialize Cask

Finally, we add the following lines to our init file:

(require 'cask "~/.cask/cask.el")
(cask-initialize)

Initialize Pallet

Since we already install pallet via cask, we just need to use the following code to initialize pallet.

(require 'pallet)
(pallet-mode t)

use-package

The use-package macro allows you to isolate package configuration in your .emacs file in a way that is both performance-oriented and, well, tidy. I created it because I have over 80 packages that I use in Emacs, and things were getting difficult to manage. Yet with this utility my total load time is around 2 seconds, with no loss of functionality!

GitHub: https://github.com/jwiegley/use-package

(require 'use-package)                  ; Installed by Cask
;; Auto install non-installed packages.
;; (setq use-package-always-ensure t)

req-package

req-package is a wrapper on top of use-package, a package dependency management tool. The documentation for use-package is immensely helpful for figuring out how to describe package dependencies and settings. req-package adds the :require keyword which allows us to define dependencies between related packages.

GitHub: https://github.com/edvorg/req-package

Initialize req-package

With the preceding process complete, we just need to add the following line to our init file to begin using req-package:

(require 'req-package)

Start loading packages in right order

To start loading packages in right order, we need to added following in the last of emacs config.

(req-package-finish)

You can take a look at End of configuration section.

paradox

Project for modernizing Emacs' Package Menu. With improved appearance, mode-line information. Github integration, customizability, asynchronous upgrading, and more.

GitHub: https://github.com/Malabarba/paradox

(require 'paradox)                  ; Installed by Cask

Load Path

The variable load-path lists all the directories where Emacs should look for Elisp files.

Though I use Cask as package management in my emacs, some local packages like my own theme or others can't fetch by elpa need to add to load-path, this will help emacs find them.

Following are my method to add directories to load-path recursively, this function also create directory to prevent directory not exist.

If you don't have any local elisp and all packages is mantain by cask or elpa or spacemacs, you can skip following code.

;; Add directories to emacs's `load-path' recursively.
;; if path does not exist, create directory.
(let* ((lisp-dir '("local-lisp/" "themes/")))
  (dolist (lisp-path lisp-dir)
    (when (not (file-exists-p lisp-path))
      (make-directory (concat user-emacs-directory lisp-path) t))
    (let* ((load-dir (concat user-emacs-directory lisp-path))
           (default-directory load-dir))
      (setq load-path
            (append
             (let ((load-path (copy-sequence load-path)))
               (append
                (copy-sequence (normal-top-level-add-to-load-path '(".")))
                (normal-top-level-add-subdirs-to-load-path)))
             load-path)))))

Sometimes package manager will install some emacs-lisp file to system path, add them to my emacs's load-path.

;;;; add some system site-lisp to my load-path

;; Mac OSX
(when (equal system-type 'darwin)
  (let ((default-directory "/usr/local/share/emacs/site-lisp/"))
    (normal-top-level-add-subdirs-to-load-path)))

;; Linux
(when (equal system-type 'gnu/linux)
  (let ((default-directory "/usr/share/emacs/site-lisp/"))
    (normal-top-level-add-subdirs-to-load-path)))

I think I'll write some dynamic module extension, which will save to ~/.emacs.d/modules, use a helper script to help me load them.

;; load the `load-modules.el' file which help me load external modulept
(let ((script (concat user-emacs-directory "modules/load-modules.el")))
  (when (file-exists-p script)
    (load script)))

Basic setup

Some basic setup to disabe/enable default feature before we start. The configuration here only depends on valina emacs's buildin libraries.

Personal Information

Some information about myself.

(setq user-full-name "Yen-Chin, Lee")
(setq user-mail-address "coldnew.tw@gmail.com")

Startup emacs server

;; Only start server mode if I'm not root
(unless (string-equal "root" (getenv "USER"))
  (require 'server)
  (unless (server-running-p) (server-start)))

Under Mac OSX use Command key as ALT

Under Mac OSX, I always bind Caps lock as Control key, and make the Command key as ALT key like I done in Linux.

The Option key will be setup as Super.

I also disable some keys like ⌘-h bypass to system in emacs-mac port.

(setq mac-option-modifier 'super)
(setq mac-command-modifier 'meta)
(setq mac-pass-command-to-system nil)

Don't ask me when close emacs with process is running

When I type C-x C-c which means I want to quit emacs, don't stand in my way.

(require 'noflet)
(defadvice save-buffers-kill-emacs (around no-query-kill-emacs activate)
  "Prevent annoying \"Active processes exist\" query when you quit Emacs."
  (noflet ((process-list ())) ad-do-it))

Don't ask me when kill process buffer

(setq kill-buffer-query-functions
      (remq 'process-kill-buffer-query-function
            kill-buffer-query-functions))

Save custom-file as cache

Most of my config is written in this file, it's no need to tracking the emacs's custom-setting.

I move the file to cache-dir and make git ignore it.

(setq-default custom-file (concat user-cache-directory "custom.el"))
;; load custom-file only when file exist
(when (file-exists-p custom-file)
  (load-file custom-file))

Async rebuild init.el after save

(require 'async)   ; Installed by Cask
;; If I'm edit my init.org, async generate init.el when save.
(defun tangle-init ()
  "If the current buffer is 'init.org' the code-blocks are tangled."
  (let ((buffer-name "async-make-init.el"))
    (when (equal (buffer-file-name)
                 (expand-file-name (concat user-emacs-directory "init.org")))
      ;; If previous building buffer exist, discard it
      ;; (when (get-buffer (concat "*" buffer-name "*"))
      ;;   (kill-buffer (concat "*" buffer-name "*")))
      ;; build with `make init.el' command
      (async-start-process buffer-name "make"
                           '(lambda (result)
                              (message "Re-Generate init.el")) "init.el"))))
;; Add to hook
(add-hook 'after-save-hook 'tangle-init)

Setup auto-save directory

(setq auto-save-list-file-prefix
      (concat user-cache-directory "auto-save-list/.saves-"))

(setq auto-save-interval 100)
(setq auto-save-timeout  60)
(setq auto-save-visited-file-name nil)
(setq delete-auto-save-files t)

Setup backup files

By default Emacs saves BackupFiles under the original name with a tilde ~ appended. Example: Editing README will result in README and README~ in the same directory.

This is primitive and boring.

I save my backup files to ~/.emacs.d/.cache/backup and since is always ignore by version control system, it's a nice place to store backup files.

(let ((backup-dir (concat user-cache-directory "backup")))
  ;; Move backup file to `~/.emacs.d/.cache/backup'
  (setq backup-directory-alist `(("." . ,backup-dir)))
  ;; Makesure backup directory exist
  (when (not (file-exists-p backup-dir))
    (make-directory backup-dir t)))

Also setup some backup settings.

(setq delete-by-moving-to-trash nil)
(setq version-control t)
(setq kept-old-versions 10)
(setq kept-new-versions 20)
(setq delete-old-versions t)
(setq backup-by-copying t)

Disable some default stuff

Some emacs feature is not really useful

Turn-off menu bar

The menu bar is one of the UI elements which work best with mouses.

(when (featurep 'menu-bar) (menu-bar-mode -1))

Turn-off tool bar

I never use the tool bar, it's really no need.

(when (featurep 'tool-bar) (tool-bar-mode -1))

Turn-off blinking cursor

I hate the blinking cursor actually, it's really annoying.

(blink-cursor-mode -1)

Turn-off scroll bar

Actually when you familier with emacs, you don't need to use scroll-bar anymore.

(when (featurep 'scroll-bar) (scroll-bar-mode -1))

Turn-off startup screen

I don't want to enter the startup screen after initialize emacs.

(setq inhibit-startup-screen t)

Turn-off cursor blink

(blink-cursor-mode -1)

Turn-off Alarm Bell

(setq ring-bell-function #'ignore)

Clean scratch buffer messages

Leave me a clean scratch buffer and I'll be more happy :)

(setq initial-scratch-message "")

Use visible bell instead of buzzer

(setq visible-bell t)

Ask for y or n, not yes or no

Emacs starts out asking for you to type yes or no with most important questions. Just let me use y or n with no RET required an I'm quite happy.

(defalias 'yes-or-no-p 'y-or-n-p)

Languages and Encodings

Since current Emacs default run on UTF-8, it's no need to setup the encoding.

For language, though Traditional Chinese is my mothertone, I still prefer use en_US to display time info.

(prefer-coding-system 'utf-8)
(setq system-time-locale "en_US")

Buildin Packages

Some buildin packages need to some setup.

bookmark

(eval-after-load 'bookmark
  '(progn
     (setq bookmark-default-file
           (concat user-cache-directory "bookmarks"))))

idlwave

(eval-after-load 'dilwave
  '(progn
     (setq idlwave-config-directory
           (concat user-cache-directory "idlwave"))))

srecode

;; change srecode cache file path
(eval-after-load 'srecode
  '(progn
     (setq srecode-map-save-file
           (concat user-cache-directory "srecode-map.el"))))

request

(eval-after-load 'request
  '(progn
     (setq request-storage-directory
           (concat user-cache-directory "request"))))

nsm

(eval-after-load 'nsm
  '(progn
     (setq nsm-settings-file
           (concat user-cache-directory "network-security.data"))))

url

(eval-after-load 'url
  '(progn
     (setq url-configuration-directory
           (file-name-as-directory
            (concat user-cache-directory "url")))))

External Packages

Most of emacs packages do not need many configs or just provide commands/functions to use, I put them here.

ag

ag.el allows you to search using the_silver_searcher from inside Emacs. You can filter by file type, edit results inline, or find files.

GitHub: https://github.com/Wilfred/ag.el

(req-package ag
  :if (executable-find "ag"))

To use ag.el we also need to install the_silver_searcher in system.

For Mac OSX, just type

brew install the_silver_searcher

If you use Gentoo Linux, you can use following command to install this package

emerge sys-apps/the_silver_searcher

ascii

Ascii provides a way to display ASCII code on a window, that is, display in another window an ASCII table highlighting the current character code.

(req-package ascii
  :config
  (defun ascii-toggle ()
    "Toggle ascii-mode."
    (interactive)
    (if (not (ascii-off)) (ascii-on)))

  ;; alias ascii to ascii-toggle
  (defalias 'ascii 'ascii-toggle))

ascii-art-to-unicode

Convert simple ASCII art drawings (and org-tables) to beautiful Unicode.

(req-package ascii-art-to-unicode)

avy

avy is a GNU Emacs package for jumping to visible text using a char-based decision tree. See also ace-jump-mode and vim-easymotion - avy uses the same idea.

GitHub: https://github.com/abo-abo/avy

(req-package avy)

buffer-move

This file is for lazy people wanting to swap buffers without typing C-x b on each window. This is useful when you have :

              
    #emacs    
              
             
    #gnus    
             
                            
           .emacs           
                            

and you want to have :

              
    #gnus     
              
             
   .emacs    
             
                            
           #emacs           
                            

With buffer-move, just go in #gnus, do buf-move-left, go to #emacs (which now should be on top right) and do buf-move-down.

GitHub: https://github.com/lukhas/buffer-move

(req-package buffer-move)

bpr

This package provides logic for async process execution.

It's similar to async-shell-command, but:

  • bpr spawns processes asynchronously without displaying output buffers.
  • bpr shows progress messages for running processes in echo area.
  • bpr can display buffer with process output in case of errors.
  • bpr can use projectile for assigning process directory.
  • bpr can format process output (understands ansi escape codes).
  • it's possible to set different options for different processes.

bpr is very handy for running tests/builds, but you can run any processes with it.

GitHub: https://github.com/ilya-babanov/emacs-bpr

(req-package bpr)

calfw

Calfw - A calendar framework for Emacs.

GitHub: https://github.com/kiwanami/emacs-calfw

(req-package calfw)

cbm

Cycle by major - Cycle through buffers with the same major-mode.

GitHub: https://github.com/akermu/cbm.el

(req-package cbm)

crux

A Collection of Ridiculously Useful eXtensions for Emacs. crux bundles a few useful interactive commands to enhance your overall Emacs experience.

GitHub: https://github.com/bbatsov/crux

(req-package crux)

darkroom

Remove visual distractions and focus on writing.

GitHub: https://github.com/capitaomorte/darkroom

(req-package darkroom)

discover-my-major

discover-my-major make you discover key bindings and their meaning for the current Emacs major mode.

GitHub: https://github.com/steckerhalter/discover-my-major

(req-package discover-my-major)

doxymacs

Doxygen is a system for extracting documentation from source code. It supports a variety of programming languages, human languages and output formats. You can find it at http://www.doxygen.org.

doxymacs is emacs's wrapper for Doxygen.

(when (require 'doxymacs nil 'noerror)
  (add-hook 'prog-mode-hook '(lambda () (doxymacs-mode))))

To use doxymacs we also need to install it in system manually.

For Mac OSX, just type

brew install doxymacs

If you use Gentoo Linux, you can use following command to install this package

emerge app-shells/doxymacs

esup

Benchmark Emacs Startup time without ever leaving your Emacs.

GitHub: https://github.com/jschaf/esup

(req-package esup)

exec-path-from-shell

exec-path-from-shell is A GNU Emacs library to ensure environment variables inside Emacs look the same as in the user's shell.

Ever find that a command works in your shell, but not in Emacs?

This happens a lot on OS X, where an Emacs instance started from the GUI inherits a default set of environment variables.

This library works solves this problem by copying important environment variables from the user's shell: it works by asking your shell to print out the variables of interest, then copying them into the Emacs environment.

GitHub: https://github.com/purcell/exec-path-from-shell

(req-package exec-path-from-shell
  :config
  (when (memq window-system '(mac ns x))
    (exec-path-from-shell-initialize)))

expand-region

Expand region increases the selected region by semantic units. Just keep pressing the key until it selects what you want.

GitHub: https://github.com/magnars/expand-region.el

(req-package expand-region
  :bind (("M-v" . er/expand-region)))

fancy-narrow

Emacs package to immitate narrow-to-region with more eye-candy.

GitHub: https://github.com/Malabarba/fancy-narrow

(req-package fancy-narrow)

focus

Focus provides focus-mode that dims the text of surrounding sections, similar to iA Writer's Focus Mode.

GitHub: https://github.com/larstvei/Focus

(req-package focus)

google-translate

This package allows to translate the strings using Google Translate service directly from GNU Emacs.

GitHub: https://github.com/atykhonov/google-translate

(req-package google-translate)

howdoi

howdoi is a way to query Stack Overflow directly from the Emacs and get back the most upvoted answer to the first question that comes up for that query.

GitHub: https://github.com/atykhonov/emacs-howdoi

(req-package howdoi)

htmlize

(req-package htmlize)

hungry-delete

hungry-delete borrows hungry deletion from cc-mode, which will causes deletion to delete all whitespace in the direction you are deleting.

(req-package hungry-delete
  :config
  (global-hungry-delete-mode))

hydra

This is a package for GNU Emacs that can be used to tie related commands into a family of short bindings with a common prefix - a Hydra.

GitHub: https://github.com/abo-abo/hydra

(req-package hydra
  :config
  <<hydra-config>>)

Window Management

  (defhydra hydra-window ()
     "
  Movement^^        ^Split^         ^Switch^      ^Resize^
  ----------------------------------------------------------------
  _h_ ←         _v_ertical      _b_uffer        _q_ X←
  _j_ ↓         _x_ horizontal  _f_ind files    _w_ X↓
  _k_ ↑         _z_ undo        _a_ce 1     _e_ X↑
  _l_ →         _Z_ reset       _s_wap      _r_ X→
  _F_ollow        _D_lt Other     _S_ave      max_i_mize
  _SPC_ cancel    _o_nly this     _d_elete
  "
     ("h" windmove-left )
     ("j" windmove-down )
     ("k" windmove-up )
     ("l" windmove-right )
     ("q" hydra-move-splitter-left)
     ("w" hydra-move-splitter-down)
     ("e" hydra-move-splitter-up)
     ("r" hydra-move-splitter-right)
     ("b" helm-mini)
     ("f" helm-find-files)
     ("F" follow-mode)
     ("a" (lambda ()
            (interactive)
            (ace-window 1)
            (add-hook 'ace-window-end-once-hook
                      'hydra-window/body)))
     ("v" (lambda ()
            (interactive)
            (split-window-right)
            (windmove-right)))
     ("x" (lambda ()
            (interactive)
            (split-window-below)
            (windmove-down)))
     ("s" (lambda ()
            (interactive)
            (ace-window 4)
            (add-hook 'ace-window-end-once-hook
                      'hydra-window/body)))
     ("S" save-buffer)
     ("d" delete-window)
     ("D" (lambda ()
            (interactive)
            (ace-window 16)
            (add-hook 'ace-window-end-once-hook
                      'hydra-window/body)))
     ("o" delete-other-windows)
     ("i" ace-maximize-window)
     ("z" (progn
            (winner-undo)
            (setq this-command 'winner-undo)))
     ("Z" winner-redo)
     ("SPC" nil))

;;(global-set-key (kbd "C-x w") 'hydra-window/body)

Buffer Movement

(defhydra hydra-movement ()
  "
     ^Forward^          ^Backward^      ^Up^     ^Down^   ^Char^
    ^^^^^^^^---------------------------------------------------
                       _c_: char
    ^^^^^^^^
     _n_: scroll down  _p_: scroll up
    "
  ("c" avy-goto-char)
  ;; others
  ("n" evil-scroll-page-down)
  ("p" evil-scroll-page-up)
  )

;;(global-set-key (kbd "C-x m") 'hydra-movement/body)

Font Setup

(defhydra hydra-font-setup ()
  "
Font Size^^
----------------------------------------------------------------
_=_ ↑
_\-_ ↓
"
  ("=" text-scale-increase)
  ("-" text-scale-decrease))

☛ TODO NEED REVIEW

(defhydra ig-hydra-windows (:color pink
                                   :hint nil)
  "
      ^Move          ^^^^^Swap      ^^^Resize                  ^^^^^^Del
      _<up>_            ^^^_k_         ^^_K_      ^_r_: new ⮞     _d_: cur     _SPC_: quit
_<left>_   _<right>_    _h_   _l_     _H_   _L_    _n_: new ⮟     _x_: buf
     _<down>_           ^^^_j_         ^^_J_      ^_b_: bury buf  _o_: other
"
  ("<left>" windmove-left)
  ("<down>" windmove-down)
  ("<up>" windmove-up)
  ("<right>" windmove-right)
  ("h" buf-move-left)
  ("j" buf-move-down)
  ("k" buf-move-up)
  ("l" buf-move-right)
  ("H" hydra-move-splitter-left)
  ("J" hydra-move-splitter-down)
  ("K" hydra-move-splitter-up)
  ("L" hydra-move-splitter-right)
  ("r" (lambda () (interactive) (split-window-right)(windmove-right)) :color blue)
  ("n" (lambda () (interactive) (split-window-below)(windmove-down)) :color blue)
  ("d" delete-window :color blue)
  ("o" delete-other-windows :color blue)
  ("x" kill-this-buffer :color blue)
  ("b" bury-buffer :color blue)
  ("SPC" hydra-keyboard-quit :color blue))

(defhydra hydra-multiple-cursors (:hint nil)
  "
   ^Up^            ^Down^        ^Miscellaneous^
  ----------------------------------------------
  [_p_]   Next    [_n_]   Next    [_l_] Edit lines
  [_P_]   Skip    [_N_]   Skip    [_a_] Mark all
  [_M-p_] Unmark  [_M-n_] Unmark  [_q_] Quit"
  ("l" mc/edit-lines :exit t)
  ("a" mc/mark-all-like-this :exit t)
  ("n" mc/mark-next-like-this)
  ("N" mc/skip-to-next-like-this)
  ("M-n" mc/unmark-next-like-this)
  ("p" mc/mark-previous-like-this)
  ("P" mc/skip-to-previous-like-this)
  ("M-p" mc/unmark-previous-like-this)
  ("q" nil))

  (defhydra hydra-org (:color red :hint nil)
    "
  Navigation^
  ---------------------------------------------------------
  _j_ next heading
  _k_ prev heading
  _h_ next heading (same level)
  _l_ prev heading (same level)
  _u_p higher heading
  _g_o to
  "
    ("j" outline-next-visible-heading)
    ("k" outline-previous-visible-heading)
    ("h" org-forward-heading-same-level)
    ("l" org-backward-heading-same-level)
    ("u" outline-up-heading)
    ("g" org-goto :exit t))

(defhydra hydra-toggles-macro  (:color blue :hint nil )
     "macro commands
     "
     ("s" start-kbd-macro  "start macro" )
     ("e"   "end macro" )
     ("e" kmacro-end-and-call-macro  "use C-x e" )
     ("n" name-last-kbd-macro  "name macro" )
     ("i" insert-kbd-macro  "insert macro" )
     ("q" nil "cancel" nil)
)
  (defhydra hydra-goto (:color blue :hint nil)
    "
  Goto:
  ^Char^              ^Word^                ^org^                    ^search^
  ^^^^^^^^---------------------------------------------------------------------------
  _c_: 2 chars        _w_: word by char     _h_: headline in buffer  _o_: helm-occur
  _C_: char           _W_: some word        _a_: heading in agenda   _p_: helm-swiper
  _L_: char in line   _s_: subword by char  _q_: swoop org buffers   _f_: search forward
  ^  ^                _S_: some subword     ^ ^                      _b_: search backward
  -----------------------------------------------------------------------------------
  _B_: helm-buffers       _l_: avy-goto-line
  _m_: helm-mini          _i_: ace-window
  _R_: helm-recentf

  _n_: Navigate           _._: mark position _/_: jump to mark
  "
    ("c" avy-goto-char-2)
    ("C" avy-goto-char)
    ("L" avy-goto-char-in-line)
    ("w" avy-goto-word-1)
    ;; jump to beginning of some word
    ("W" avy-goto-word-0)
    ;; jump to subword starting with a char
    ("s" avy-goto-subword-1)
    ;; jump to some subword
    ("S" avy-goto-subword-0)

    ("l" avy-goto-line)
    ("i" ace-window)

    ("h" helm-org-headlines)
    ("a" helm-org-agenda-files-headings)
    ("q" helm-multi-swoop-org)

    ("o" helm-occur)
    ("p" swiper-helm)

    ("f" isearch-forward)
    ("b" isearch-backward)

    ("." org-mark-ring-push :color red)
    ("/" org-mark-ring-goto :color blue)
    ("B" helm-buffers-list)
    ("m" helm-mini)
    ("R" helm-recentf)
    ("n" hydra-navigate/body))
(global-set-key (kbd "M-g") 'hydra-goto/body)
  • Window/Buffer Management
    (defhydra hydra-window-buffer (:color red :hint nil)
    "
     ^Window^             ^Buffer^           ^Frame^
    ^^^^^^^^---------------------------------------------------
     ^hjkl^: move         _p_: previous      _u_: winner undo      ....../ \-.   .
     _s_: split below     _n_: next          _r_: winner redo   .-/     (    o\.//
     _v_: split right     _b_: switch        _w_: revert all     |  ...  \./\---'
     _c_: delete this     _;_: last          ^ ^                 |.||  |.||
     _o_: delete other    _K_: kill current  ^ ^
    ^^^^^^^^
    "
      ("w" revert-all-buffers :color blue)
    
      ("u" winner-undo)
      ("r" winner-redo)
    
      ("h" windmove-left)
      ("j" windmove-down)
      ("k" windmove-up)
      ("l" windmove-right)
    
      ("p" previous-buffer)
      ("n" next-buffer)
      ("b" ido-switch-buffer)
      (";" mode-line-other-buffer :color blue)
    
      ("s" split-window-below)
      ("v" split-window-right)
    
      ("K" kill-this-buffer)
    
      ("c" delete-window)
      ("o" delete-other-windows :color blue)
    
      ;; ("H" hydra-move-splitter-left)
      ;; ("J" hydra-move-splitter-down)
      ;; ("K" hydra-move-splitter-up)
      ;; ("L" hydra-move-splitter-right)
    
      ("q" nil))
      (global-set-key (kbd "C-x w") 'hydra-window-buffer/body)
    

iedit

iedit let you edit multiple regions in the same way simultaneously.

GitHub: https://github.com/victorhge/iedit

(req-package iedit
  :bind (("C-;" . iedit-mode)))

know-your-http-well

HTTP encodings, headers, media types, methods, relations and status codes, all summarized and linking to their specification.

GitHub: https://github.com/for-GET/know-your-http-well

(req-package know-your-http-well)

kurecolor

A collection of color tools aimed at those working with (normal 6 digit) hex color codes, useful for CSS, Emacs themes, etc. etc.

View the presentation at https://github.com/emacsfodder/kurecolor

GitHub: https://github.com/emacsfodder/kurecolor

(req-package kurecolor)

lentic

Lentic allows two buffers to share the same or similar content but otherwise operate independently. This can be used for several different purposes. Different buffers can be in the same mode, with different locations of point, even different text sizes – in effect, providing multiple persistent views.

GitHub: https://github.com/phillord/lentic

(req-package lentic)

link-hint

link-hint.el is inspired by the link hinting functionality in vim-like browsers and browser plugins such as pentadactyl. It provides commands for using avy to open or copy "links."

GitHub: https://github.com/noctuid/link-hint.el

(req-package link-hint)

manage-minor-mode

manage-minor-mode let you manage your minor-mode on the dedicated interface buffer.

(req-package manage-minor-mode)

mustache

A mustache templating library in Emacs Lisp.

GitHub: https://github.com/Wilfred/mustache.el

(req-package mustache)

mwim

This Emacs package provides commands for moving to the beginning/end of code or line.

GitHub: https://github.com/alezost/mwim.el

(req-package mwim
  :bind
  (("C-a" . mwim-beginning-of-code-or-line)
   ("C-e" . mwim-end-of-code-or-line)))

moedict

Look up (Tranditional) Chinese vocabulary with MOE dict (萌典) in Emacs.

GitHub: https://github.com/kuanyui/moedict.el

(req-package moedict)

noflet

noflet is dynamic, local, advice for Emacs-Lisp code.

noflet also has an Emacs indentation function for flet like macros.

It's great for test code when you need to mock another function.

This is useful for definining functions that overide a base definition in some way. You get access to the original (before you re-defined it) function through a different name.

GitHub: https://github.com/nicferrier/emacs-noflet

(req-package noflet)

nand2tetris

The aim of this package is to be best emacs tool to accompany you on your nand2tetris journey in coursearea, or the Official Website for it.

GitHub: https://github.com/CestDiego/nand2tetris.el

(req-package nand2tetris
  :require (company company-nand2tetris nand2tetris-assembler)
  :if (file-exists-p "~/Workspace/nand2tetris")
  :config
  (setq nand2tetris-core-base-dir "~/Workspace/nand2tetris"))

pangu-spacing

pangu-spcing is an minor-mode to auto add space between Chinese and English characters. Note that these white-space characters are not really added to the contents, it just like to do so.

(req-package pangu-spacing
  :config
  ;; start pangu-spacing globally
  (global-pangu-spacing-mode 1)
  ;; Always insert `real' space in org-mode.
  (add-hook 'org-mode-hook
            '(lambda ()
               (set (make-local-variable 'pangu-spacing-real-insert-separtor) t))))

password-generator

password-generator provides simple functions to create passwords and insert them inside buffer immediately.

GitHub: https://github.com/zargener/emacs-password-genarator

(req-package password-generator :defer t)

rainbow-mode

rainbow-mode s a minor mode for Emacs which displays strings representing colors with the color they represent as background.

(req-package rainbow-mode)

reveal-in-osx-finder

  • If M-x reveal-in-osx-finder is invoked in a file-associated buffer, it will open the folder enclosing the file in the OS X Finder. It will also highlight the file the buffer is associated with within the folder.
  • If M-x reveal-in-osx-finder is invoked in a dired buffer, it will open the current folder in the OS X Finder. It will also highlight the file at point if available.
  • If M-x reveal-in-osx-finder is invoked in a buffer not associated with a file, it will open the folder defined in the default-directory variable.

GitHub: https://github.com/kaz-yos/reveal-in-osx-finder

(req-package reveal-in-osx-finder
  :when (eq system-type 'darwin))

smartparens

Smartparens is a minor mode for dealing with pairs in Emacs.

GitHub: https://github.com/Fuco1/smartparens

(req-package smartparens
  :require smartparens-config
  :config
  (smartparens-mode 1))

spray

A speed reading mode for Emacs.

GitHub: https://github.com/ian-kelling/spray

(req-package spray)

sicp

Reading sicp in emacs.

(req-package sicp)

string-inflection

underscore -> UPCASE -> CamelCase conversion of names.

GitHub: https://github.com/akicho8/string-inflection

(req-package string-inflection)

sx

SX is a full featured Stack Exchange mode for GNU Emacs 24+. Using the official API, it provides a versatile experience for the Stack Exchange network within Emacs itself.

(req-package sx :require sx-load)

tldr

tldr is a collection of simplified and community-driven man pages.

GitHub: https://github.com/kuanyui/tldr.el

(req-package tldr
  :init
  (setq tldr-directory-path (concat user-cache-directory "tldr/"))
  (setq tldr-saved-zip-path (concat user-cache-directory "tldr-source.zip")))

travis

An Emacs client for TravisCI.

GitHub: https://github.com/nlamirault/emacs-travis

(req-package travis)

Befor execute M-x travis-show-projects you must setup your github token

export TRAVIS_TOKEN=XXXXXXX

url-shortener

This package can convert long url to tiny url and expand tiny url to long url ,support:

  • bit.ly
  • goo.gl
  • dwz.cn
  • 126.am

GitHub: https://github.com/yuyang0/url-shortener

(req-package url-shortener)

verify-url

verify-url is a little tool that used to find out invalid urls in the buffer or region.

Use M-x verify-url to find invalid urls in current buffer.

After executed command, you can use verify-url/next-invalid-url to goto next invalid-url or verify-url/previous-invalid-url to goto previous one.

GitHub: https://github.com/lujun9972/verify-url

(req-package verify-url)

which-key

which-key is a minor mode for Emacs that displays the key bindings following your currently entered incomplete command (a prefix) in a popup. For example, after enabling the minor mode if you enter C-x and wait for the default of 1 second the minibuffer will expand with all of the available key bindings that follow C-x (or as many as space allows given your settings). This includes prefixes like C-x 8 which are shown in a different face. Screenshots of what the popup will look like are included below. which-key started as a rewrite of gude-key-mode, but the feature sets have diverged to a certain extent.

GitHub: https://github.com/justbur/emacs-which-key

(req-package which-key
  :config
  ;; enable globally
  (which-key-mode)
  ;; Hide/Modify some function prefix in which-key show menu
  (setq which-key-description-replacement-alist
        '(("Prefix Command" . "prefix")
          ("which-key-show-next-page" . "wk next pg")
          ("\\`calc-" . "") ; Hide "calc-" prefixes when listing M-x calc keys
          ("/body\\'" . "") ; Remove display the "/body" portion of hydra fn names
          ("modi/" . "m/") ; The car is intentionally not "\\`modi/" to cover
                                        ; cases like `hydra-toggle/modi/..'.
          ("\\`hydra-" . "+h/")
          ("\\`org-babel-" . "ob/")
          ("\\`my/" . ""))))

xkcd

Read xkcd from Emacs.

GitHub: https://github.com/vibhavp/emacs-xkcd

(req-package xkcd
  :init
  (setq xkcd-cache-dir (concat user-cache-directory "xkcd/"))
  (when (not (file-directory-p xkcd-cache-dir))
    (make-directory xkcd-cache-dir :parents)))

zzz-to-char

This package provides two new commands: zzz-to-char and zzz-up-to-char which work like built-ins zap-to-char and zap-up-to-char, but allow you quickly select exact character you want to “zzz” to.

The commands are minimalistic and often work like built-in ones when there is only one occurrence of target character (except they automatically work in backward direction too). You can also specify how many characters to scan from each side of point, see zzz-to-char-reach.

This package uses avy as backend.

GitHub: https://github.com/mrkkrp/zzz-to-char

(req-package zzz-to-char
  :bind (("M-z" . zzz-to-char)))

Interactive Commands

In emacs, we can use M-x to execute interactive commands, I implement some of them to make my emacs more easy to use.

Buffers

Kill all buffers except scratch buffer

Sometimes I just want to kill all buffers, this command will kill all of them and make *scratch* buffer alone.

(defun nuke-all-buffers ()
  "Kill all buffers, leaving *scratch* only."
  (interactive)
  (mapcar (lambda (x) (kill-buffer x)) (buffer-list))
  (delete-other-windows))

Make emacs can always save buffers (even if file is not modified)

The default command save-buffer will not really save file when it untouched, use this command can let me force save file even if file is not modified.

(defun my/save-buffer-always ()
  "Save the buffer even if it is not modified."
  (interactive)
  (set-buffer-modified-p t)
  (save-buffer))

Abort minibuffer recursive edit

(defun minibuffer-keyboard-quit ()
  "Abort recursive edit.
In Delete Selection mode, if the mark is active, just deactivate it;
then it takes a second \\[keyboard-quit] to abort the minibuffer."
  (interactive)
  (if (and delete-selection-mode transient-mark-mode mark-active)
      (setq deactivate-mark t)
    (when (get-buffer "*Completions*") (delete-windows-on "*Completions*"))
    (abort-recursive-edit)))

Make buffer untabify

(defun untabify-buffer ()
  (interactive)
  (save-excursion
    (untabify (point-min) (point-max))))

Indent whole buffer

(defun indent-whole-buffer ()
  "Indent whole buffer."
  (interactive)
  (save-excursion
    (indent-region (point-min) (point-max))))

Remove buffers trailing whitespace and untabify

(defun cleanup-buffer ()
  "Perform a bunch of operations on the whitespace content of a buffer."
  (interactive)
  (save-excursion
    (delete-trailing-whitespace)
    (indent-region (point-min) (point-max))
    (untabify (point-min) (point-max))))

Replace the preceding sexp with its value

(defun eval-and-replace ()
  "Replace the preceding sexp with its value."
  (interactive)
  (backward-kill-sexp)
  (condition-case nil
      (prin1 (eval (read (current-kill 0)))
             (current-buffer))
    (error (message "Invalid expression")
           (insert (current-kill 0)))))

Quick folding source block

(defun quick-folding-source ()
  "Use emacs buildin easy to folding code."
  (interactive)
  (set-selective-display
   (if selective-display nil 1)))

Narrowing to code more wisely

ref: http://endlessparentheses.com/emacs-narrow-or-widen-dwim.html

(defun my/narrow-or-widen-dwim (p)
  "Widen if buffer is narrowed, narrow-dwim otherwise.
Dwim means: region, org-src-block, org-subtree, or defun,
whichever applies first. Narrowing to org-src-block actually
calls `org-edit-src-code'.

With prefix P, don't widen, just narrow even if buffer is
already narrowed."
  (interactive "P")
  (declare (interactive-only))
  (cond ((and (buffer-narrowed-p) (not p)) (widen))
        ((region-active-p)
         (narrow-to-region (region-beginning) (region-end)))
        ;; org-mode
        ((derived-mode-p 'org-mode)
         ;; `org-edit-src-code' is not a real narrowing
         ;; command. Remove this first conditional if you
         ;; don't want it.
         (cond ((ignore-errors (org-edit-src-code))
                (delete-other-windows))
               ((ignore-errors (org-narrow-to-block) t))
               (t (org-narrow-to-subtree))))
        ;; latex-mode
        ((derived-mode-p 'latex-mode)
         (LaTeX-narrow-to-environment))
        (t (narrow-to-defun))))

Edit (Insert/Remove)

Insert U200B char

<U200B> character is a zero width space character which is nice to use under org-mode.

For more info, please see: suggestion for org-emphasis-regexp-components: *U*nited *N*ations

(defun insert-U200B-char ()
  "Insert <U200B> char, this character is nice use in org-mode."
  (interactive)
  (insert "\ufeff"))

Insert empty line after current line

(defun insert-empty-line ()
  "Insert an empty line after current line and position cursor on newline."
  (interactive)
  (move-end-of-line nil)
  (open-line 1)
  (next-line 1))

Insert lorem ipsum

(defun insert-lorem ()
  "Insert a lorem ipsum."
  (interactive)
  (insert "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
          "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim"
          "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
          "aliquip ex ea commodo consequat. Duis aute irure dolor in "
          "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "
          "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in "
          "culpa qui officia deserunt mollit anim id est laborum."))

Delete word

(defun delete-word (arg)
  "Delete characters forward until encountering the end of a word.
With argument, do this that many times."
  (interactive "p")
  (delete-region (point) (progn (forward-word arg) (point))))

Backward delete word

(defun backward-delete-word (arg)
  "Delete characters backward until encountering the end of a word.
With argument, do this that many times."
  (interactive "p")
  (delete-word (- arg)))

Set mark or expand region

(defun set-mark-mode/rectangle-mark-mode ()
  "toggle between set-mark-command or rectangle-mark-mode"
  (interactive)
  (if (not mark-active)
     (call-interactively 'set-mark-command)
    (call-interactively 'rectangle-mark-mode)))

Indent region/buffer and cleanup

(defun indent-region-or-buffer-and-cleanup ()
  "Indents a region if selected, otherwise the whole buffer."
  (interactive)
  (cl-flet ((format-fn (BEG END) (indent-region BEG END) (untabify BEG END)))
    (save-excursion
      (if (region-active-p)
          (progn
            (delete-trailing-whitespace (region-beginning) (region-end))
            (format-fn (region-beginning) (region-end))
            (message "Indented selected region and clear whitespace and untabify."))
        (progn
          (delete-trailing-whitespace)
          (format-fn (point-min) (point-max))
          (message "Indented whole buffer and clear whitespace and untabify."))))))

Copy and comments

(defun my/copy-and-comment ()
  "Copy region and comment it."
  (interactive)
  (kill-ring-save (region-beginning) (region-end))
  (comment-dwim nil))

File Handle

Reopen file as root

(defun file-reopen-as-root ()
  (interactive)
  (when buffer-file-name
    (find-alternate-file
     (concat "/sudo:root@localhost:"
             buffer-file-name))))

Delete current buffer file

(defun delete-current-buffer-file ()
  "Removes file connected to current buffer and kills buffer."
  (interactive)
  (let ((filename (buffer-file-name))
        (buffer (current-buffer))
        (name (buffer-name)))
    (if (not (and filename (file-exists-p filename)))
        (ido-kill-buffer)
      (when (yes-or-no-p "Are you sure you want to remove this file? ")
        (delete-file filename)
        (kill-buffer buffer)
        (message "File '%s' successfully removed" filename)))))

Rename current Buffer and file

(defun rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let ((name (buffer-name))
        (filename (buffer-file-name)))
    (if (not (and filename (file-exists-p filename)))
        (error "Buffer '%s' is not visiting a file!" name)
      (let ((new-name (read-file-name "New name: " filename)))
        (if (get-buffer new-name)
            (error "A buffer named '%s' already exists!" new-name)
          (rename-file filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil)
          (message "File '%s' successfully renamed to '%s'"
                   name (file-name-nondirectory new-name)))))))

Add executable attribute to file

Actually this command is the same as chmod +x but it doesn't use any shell command, it use emacs's logior function to change file attribute.

I only make owener can has executable permission, not change it for gourp or others user.

(defun set-file-executable()
  "Add executable permissions on current file."
  (interactive)
  (when (buffer-file-name)
    (set-file-modes buffer-file-name
                    (logior (file-modes buffer-file-name) #o100))
    (message (concat "Made " buffer-file-name " executable"))))

Clone current file to new one

(defun clone-file-and-open (filename)
  "Clone the current buffer writing it into FILENAME and open it"
  (interactive "FClone to file: ")
  (save-restriction
    (widen)
    (write-region (point-min) (point-max) filename nil nil nil 'confirm))
  (find-file filename))

Show current buffer-file information

(defun my/file-info ()
  "Show current buffer information."
  (interactive)
  (if (buffer-file-name (current-buffer))
      (progn
        (let* ((file-name (buffer-file-name (current-buffer)))
               (f-attr (file-attributes file-name))
               (f-size (nth 7 f-attr))  ; ファイルサイズ
               (f-mode (nth 8 f-attr))  ; ファイル属性
               (mes1 (format "file path: %s\n" file-name))
               (mes2 (format "file size: %s byte\n" f-size))
               (mes3 (format "file type: %s" f-mode))
               (mess (concat mes1 mes2 mes3)))
          (message "%s" mess)))
    nil))

Debug

Eval emacs buffer until error

A really nice command help me to find error on elisp buffer.

(defun eval-buffer-until-error ()
  "Evaluate emacs buffer until error occured."
  (interactive)
  (goto-char (point-min))
  (while t (eval (read (current-buffer)))))

Display face found at the current point

(defun what-face (pos)
  "Display face found at the current point."
  (interactive "d")
  (let ((face (or (get-char-property (point) 'read-face-name)
                  (get-char-property (point) 'face))))
    (if face (message "Face: %s" face) (message "No face at %d" pos))))

Reload emacs init config

(defun my/reload-init ()
  "Reload init.el file"
  (interactive)
  (load-file user-init-file))

Window

Switch to other window or split it

If other window does not exist, split it, else switch to it.

(defun my/other-window-or-split ()
  "Switch to other window or split it."
  (interactive)
  (when (one-window-p)
    (split-window-horizontally))
  (other-window 1))

Theme

I always want to customize everything on my own, so I build another emacs theme called coldnew-theme-night and coldnew-theme-day, you can find them at theme/coldnew-theme.el.

Before use emacs's load-theme function, I advise it to it fully unload previous theme before loading a new one.

;; Make `load-theme' fully unload previous theme before loading a new one.
(defadvice load-theme
    (before theme-dont-propagate activate)
  (mapc #'disable-theme custom-enabled-themes))

;; My light theme
(req-package coldnew-theme-day-theme
  :require (powerline powerline-evil))

;; My night them (default)
(req-package coldnew-theme-night-theme
  :config (coldnew-theme-night))

;;(req-package coldnew-modeline-config
;;  :require (powerline powerline-evil))
;; TODO:
(req-package spaceline
  :config
  (require 'spaceline-config)
  (spaceline-spacemacs-theme))

Minibuffer

(req-package minibuffer                  ; buildin
  :config
  <<minibuffer-config>>)

Make cursor in minibufer use bar shape

;; only use `bar' type of cursor shape
(add-hook 'minibuffer-setup-hook '(lambda () (setq cursor-type 'bar)))

Some helper function to let me insert quick in minibuffer

;; define some helper function to insert to minibuffer quickly
(defun my/minibuffer-insert (p)
  (kill-line 0) (insert p))

(defun my/minibuffer-switch-to-ramdisk ()
  "Insert ramdisk path according to system type"
  (interactive)
  (my/minibuffer-insert user-ramdisk-directory))

(defun my/minibuffer-switch-to-home ()
  "Insert $HOME path."
  (interactive)
  (my/minibuffer-insert (file-name-as-directory (getenv "HOME"))))

(defun my/minibuffer-switch-to-rootdir ()
  "Insert / path."
  (interactive)
  (my/minibuffer-insert "/"))

(defun my/minibuffer-switch-to-tramp ()
  "Insert /ssh:."
  (interactive)
  (my/minibuffer-insert "/ssh:"))

Save history of minibuffer :tangle no :noweb-ref minibuffer-config

When Savehist mode is enabled, minibuffer history is saved periodically and when exiting Emacs. When Savehist mode is enabled for the first time in an Emacs session, it loads the previous minibuffer history from ‘savehist-file’.

(req-package savehist
  :config
  (setq savehist-file (concat user-cache-directory "savehist.dat"))
  (savehist-mode 1))

Increase Garbage Collector Value in minibuffer

By binding this temporarily to a large number, you can effectively prevent garbage collection during a part of the program. I increase the value when enter minibuffer, this will help to improve minibuffer speed with large package like helm, flx.

ref: http://bling.github.io/blog/2016/01/18/why-are-you-changing-gc-cons-threshold/

(eval-after-load 'minibuffer
  '(progn
     (lexical-let ((default-threshold gc-cons-threshold))
       (defun my/minibuffer-gc-setup-hook ()
         (setq gc-cons-threshold most-positive-fixnum))
       (add-hook 'minibuffer-setup-hook #'my/minibuffer-gc-setup-hook)
       ;; When exit, set back to default threshold
       (defun my/minibuffer-gc-exit-hook ()
         (setq gc-cons-threshold default-threshold))
       (add-hook 'minibuffer-exit-hook #'my/minibuffer-gc-exit-hook))))

Setup Keybindings

(bind-keys :map minibuffer-local-map
           ("C-w" . backward-kill-word)
           ("M-p" . previous-history-element)
           ("M-n" . next-history-element)
           ("C-g" . minibuffer-keyboard-quit)
           ("M-t" . my/minibuffer-switch-to-ramdisk)
           ("M-h" . my/minibuffer-switch-to-home)
           ("M-/" . my/minibuffer-switch-to-rootdir)
           ("M-s" . my/minibuffer-switch-to-tramp))

Org

(use-package org
  :pin gnu                              ; fetch fron `gnu'
  :mode (("\\.org\\'" . org-mode)
         ("\\.org_archive\\'" . org-mode))
  :config
  <<org-config>>)

Basic setup

;; fontify source code
(setq org-src-fontify-natively t)
;; Use current window when switch to source block
(setq org-src-window-setup 'current-window)
;; Disable prompting to evaluate babel blocks
(setq org-confirm-babel-evaluate nil)
;; Disable add validation link when export to HTML
(setq org-html-validation-link nil)

Indention setup

;; Always enable auto indent mode
(use-package org-indent
  :config
  (setq org-indent-mode t))

Pretty Bullets

Show org-mode bullets as UTF-8 characters.

GitHub: https://github.com/sabof/org-bullets

(req-package org-bullets
  :config
  (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))

Fancy Todo States

(setq org-todo-keywords '((sequence "☛ TODO(t)" "|" "✔ DONE(d)")
                          (sequence "⚑ WAITING(w)" "|")
                          (sequence "|" "✘ CANCELED(c)")))

Enable word-wrap

Call visual-line-mode to have soft-wrap.

(add-hook 'org-mode-hook #'visual-line-mode)

Extend org-mode's easy templates

org-mode make it easy to insert blocks by typing <s[TAB] …etc. I defined some extra easy-templates I need to use here.

(add-to-list 'org-structure-template-alist
             '("E" "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC"))
(add-to-list 'org-structure-template-alist
             '("S" "#+BEGIN_SRC sh\n?\n#+END_SRC"))
(add-to-list 'org-structure-template-alist
             '("p" "#+BEGIN_SRC plantuml :file uml.png \n?\n#+END_SRC"))

Extend babel support languages

(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (C . t)
   (ditaa . t)
   (dot . t)
   (js . t)
   (latex . t)
   (perl . t)
   (python . t)
   (ruby . t)
   (sh . t)
   (plantuml . t)
   (clojure . t)))
;; make dot work as graphviz-dot
(add-to-list 'org-src-lang-modes '("dot" . graphviz-dot))

Setup link abbreviations

Link abbreviations

An abbreviated link looks like

[[linkword:tag][description]]
(setq org-link-abbrev-alist
      '(("google" . "http://www.google.com/search?q=")
        ("google-map" . "http://maps.google.com/maps?q=%s")
        ))

Capture and Agenda

;; make agenda show on current window
(setq org-agenda-window-setup 'current-window)
;; highlight current in agenda
(add-hook 'org-agenda-mode-hook 'hl-line-mode)
;; Setup files for agenda
(setq org-agenda-files (list "~/Org/task/Office.org" "~/Org/task/Personal.org"))
;;
(setq org-directory "~/Org")
(setq org-default-notes-file (f-join org-directory "task" "Office.org"))

;; Always use `C-g' to exit agenda
(add-hook 'org-agenda-mode-hook
          '(lambda ()
             (local-set-key (kbd "C-g") 'org-agenda-exit)))

Make spell-checking tool ignore some org-mode section

see: http://emacs.stackexchange.com/questions/450/intelligent-spell-checking-in-org-mode

(eval-after-load 'ispell
  '(progn
     (add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:"))
     (add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC"))
     ))

Crypt contents in org-mode

(use-package org-crypt
  :config
  ;; Auto encrypt when save file
  (org-crypt-use-before-save-magic)
  ;; Encrypt with tagname: `secret'
  (setq org-crypt-tag-matcher "secret")
  ;; Prevent the `secret' tag inherit by child
  ;; (The child item still will be encrypt)
  (setq org-tags-exclude-from-inheritance (quote ("secret")))
  ;; Use my own password to encrypt
  (setq org-crypt-key nil))

Integrate with redmine

GitHub: https://github.com/gongo/org-redmine

(use-package org-redmine
  :ensure t
  :config
  ;; NOTE: in personal private setting
  (setq org-redmine-uri nil)
  (setq org-redmine-auth-api-key nil)
  (setq org-redmine-auth-password nil)
                                        ;
  ;; Advice org-remine function so it will load my private config
  (defadvice org-redmine-get-issue (before load-password activate)
    (my/load-secret))
  (defadvice org-redmine-anything-show-issue-all (before load-password activate)
    (my/load-secret)))

Exporter Setup

Latex Export

(setq org-format-latex-options
      '(:forground "black" :background "white"
                   :scale 1.5
                   :html-foreground "Black" :html-background "Transparent"
                   :html-scale 1.0
                   :matchers ("begin" "$1" "$" "$$" "\\(" "\\[")))

Textile

An Org Mode Exporter Backend For Textile.

GitHub: https://github.com/yashi/org-textile

(use-package ox-textile
  :ensure t)

Setup Org Keybindings

(bind-keys :map org-mode-map
           ("M-p"   . org-previous-visible-heading)
           ("M-n"   . org-next-visible-heading)
           ("C-c a" . org-agenda)
           ("C-c c" . org-capture)
           ("C-c l" . org-stored-links)
           ("C-c b" . org-metaleft)
           ("C-c f" . org-metaright)
           ("C-c p" . org-metaup)
           ("C-c n" . org-metadown)
           ("C-c i" . org-insert-link)
           ("C-c I" . org-toggle-inline-images))
(bind-keys :map org-src-mode-map
           ("C-c C-c" . org-edit-src-exit))

Editors

Why emacs config has an editor section, doesn't means emacs is not an editor ? Yes, Emacs is an OS :)

I put some editor/IDE relative functions and packages here.

Create minor-mode to controll all keybindings

(defvar coldnew-editor-map (make-keymap))

(define-minor-mode coldnew-editor-mode
  "coldnew's editor minor mode."
  :init-value t
  :keymap coldnew-editor-map)

(define-globalized-minor-mode global-coldnew-editor-mode
  coldnew-editor-mode (lambda ()
                        (if (not (minibufferp (current-buffer)))
                            (coldnew-editor-mode 1))))

;; Gloabal enable
(global-coldnew-editor-mode t)

Line Numbers

In most case, I'll make line numers display globally by linum.

(req-package linum :init (global-linum-mode 1))

Disable line number in some mode, for example, since org-mode can has many lines, it's not recommand to enable linum-mode.

I use linum-off to disable some mode.

(req-package linum-off
  :config
    (setq linum-disabled-mode-list
          '(eshell-mode shell-mode term-mode erc-mode compilation-mode
                        woman-mode w3m-mode calendar-mode org-mode)))

Keeping files in sync

By default, Emacs will not update the contents of open buffers when a file changes on disk. This is inconvenient when switching branches in Git - as you’d risk editing stale buffers.

This problem can be solved by:

(global-auto-revert-mode 1)
(setq global-auto-revert-non-file-buffers t)
(setq auto-revert-verbose nil)
(setq revert-without-query '(".*")) ;; disable revert query

Colorfy delimters

rainbow-delimiters is a "rainbow parentheses"-like mode which highlights delimiters such as parentheses, brackets or braces according to their depth. Each successive level is highlighted in a different color. This makes it easy to spot matching delimiters, orient yourself in the code, and tell which statements are at a given depth.

(req-package rainbow-delimiters
  :config
  (add-hook 'prog-mode-hook #'rainbow-delimiters-mode))

Add support for editorconfig

EditorConfig helps developers define and maintain consistent coding styles between different editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.

see: http://editorconfig.org/

(req-package 'editorconfig
  :if (executable-find "editorconfig")
  :mode ("\\.editorconfig\\'" . conf-unix-mode))

Adapt to foreign indentation offsets

An Emacs minor mode that guesses the indentation offset originally used for creating source code files and transparently adjusts the corresponding settings in Emacs, making it more convenient to edit foreign files.

GitHub: https://github.com/jscheid/dtrt-indent

(req-package dtrt-indent
  :config
  ;; enable dtrt-indent-mode globally
  (dtrt-indent-mode 1))

En/Decrypt files by EasyPG

(req-package epa-file
  :config
  (epa-file-enable)
  ;; Control whether or not to pop up the key selection dialog.
  (setq epa-file-select-keys 0)
  ;; Cache passphrase for symmetric encryption.
  (setq epa-file-cache-passphrase-for-symmetric-encryption t))

Install gnupg to system

For Mac OSX, just type

brew install gpg

Most Linux already shipped with gnupg, if you use Gentoo Linux, you can use following command to install it

emerge app-crypt/gnupg

Remote file editing

(req-package tramp
  :init
  (setq tramp-persistency-file-name (concat user-cache-directory "tramp"))
  :config
  (setq tramp-default-method "rsync"))

Intelligently call whitespace-cleanup on save

This Emacs library minor mode will intelligently call whitespace-cleanup before buffers are saved.

whitespace-cleanup is a handy function, but putting it in before-save-hook for every buffer is overkill, and causes messy diffs when editing third-party code that did not initially have clean whitespace.

Additionally, whitespace preferences are often project-specific, and it's inconvenient to set up before-save-hook in a .dir-locals.el file.

whitespace-cleanup-mode is a minor mode which calls whitespace-cleanup before saving the current buffer, but only if the whitespace in the buffer was initially clean. It determines this by quickly checking to see if whitespace-cleanup would have any effect on the buffer.

GitHub: https://github.com/purcell/whitespace-cleanup-mode

(req-package whitespace-cleanup-mode
  :config
  (add-hook 'prog-mode-hook 'whitespace-cleanup-mode))

Save recent file info

(req-package recentf
  :init
  (setq recentf-save-file (expand-file-name "recentf" user-cache-directory))
  :config
  (recentf-mode 1))

Highlight numbers

highlight-numbers is an Emacs minor mode that highlights numeric literals in source code.

GitHub: https://github.com/Fanael/highlight-numbers

(req-package highlight-numbers
  :config
  ;; json-mode has it's own highlight numbers method
  (add-hook 'prog-mode-hook '(lambda()
                               (if (not (derived-mode-p 'json-mode))
                                   (highlight-numbers-mode)))))

Highlight escape charset

GitHub: https://github.com/dgutov/highlight-escape-sequences

(req-package highlight-escape-sequences
  :config
  ;; Make face the same as builtin face
  (put 'font-lock-regexp-grouping-backslash 'face-alias 'font-lock-builtin-face)
  ;; Enable globally
  (hes-mode 1))

Highlight FIXME, TODO

(defun font-lock-comment-annotations ()
  "Highlight a bunch of well known comment annotations.
This functions should be added to the hooks of major modes for programming."
  (font-lock-add-keywords
   nil
   '(("\\<\\(FIX\\(ME\\)?\\|BUG\\|HACK\\):" 1 font-lock-warning-face t)
     ("\\<\\(NOTE\\):" 1 'org-level-2 t)
     ("\\<\\(TODO\\):" 1 'org-todo t)
     ("\\<\\(DONE\\):" 1 'org-done t))
   ))

(add-hook 'prog-mode-hook 'font-lock-comment-annotations)

Use undo-tree for undo/redo

Standard Emacs undo is kind of confusing. undo-tree replaces this with a simpler tree structure. It also allows us to visualize the tree directly.

(req-package undo-tree
  :config
  ;; Persistent undo-tree history across emacs sessions
  (let ((dir
         (file-name-as-directory (concat user-cache-directory "undo-tree"))))
    (setq undo-tree-history-directory-alist `(("." . ,dir))))
  (setq undo-tree-auto-save-history t)
  ;; global enable undo-tree
  (global-undo-tree-mode))

Track Emacs commands frequency

Use keyfreq-show to see how many times you used a command.

GitHub: https://github.com/dacap/keyfreq

(req-package keyfreq
  :config
  ;; setup cache file
  (setq keyfreq-file (concat user-cache-directory "keyfreq"))
  (setq keyfreq-file-lock (concat keyfreq-file ".lock"))
  ;; enable globally
  (keyfreq-mode 1)
  (keyfreq-autosave-mode 1))

Takes care of trailing whitespaces (removal, highlighting)

The definitive emacs customizations for people who are OCD about whitespace .

GitHub: https://github.com/glasserc/ethan-wspace

(req-package ethan-wspace
  :config
  ;; Turn off `mode-require-final-newline' since ethan-wspace
  ;; supersedes `require-final-newline'.
  (setq mode-require-final-newline nil)

  ;; Enable ethan-wspace globally
  (global-ethan-wspace-mode 1)

  ;; Prevent etha-wspace touch my TAB on makefile mode
  (add-hook 'makefile-mode-hook
            '(lambda()
               (setq ethan-wspace-errors (remove 'tabs ethan-wspace-errors))))

  ;; Not use in diff-mode since it breaking my syntax-highlight
  (add-hook 'diff-mode-hook
            '(lambda()
               (ethan-wspace-mode -1)))

  ;; Ignore no trailing newline error
  (setq-default ethan-wspace-errors (remove 'no-nl-eof ethan-wspace-errors)))

Show vertical lines to guide indentation

GitHub: https://github.com/zk-phi/indent-guide

(req-package indent-guide
  :config
  ;; Only show indent-guide in idle-time.
  (setq indent-guide-delay 0.1))

Visualization of matching parens

(show-paren-mode 1)
(setq show-paren-delay 0)               ; no delay

Setup TABS

(setq tab-always-indent 'complete)

Use god-mode for entering commands withoud modifier keys

This is a global minor mode for entering Emacs commands without modifier keys. It's similar to Vim's separation of commands and insertion mode.

GitHub: https://github.com/chrisdone/god-mode

(req-package god-mode
  :bind
  ("M-o" . god-local-mode)
  :config
  (bind-keys :map god-local-mode-map
             ("z" . repeat)
             ("i" . god-local-mode)))

Displays tildes in the fringe on empty lines a la Vi

GitHub: https://github.com/syohex/vi-tilde-fringe

(req-package vi-tilde-fringe
  :if window-system
  :config
  (global-vi-tilde-fringe-mode))

Vim Emulation

Though I am really familier with emacs, I still like some vim command.

(req-package evil
  :require (undo-tree)
  :config
  ;; enable evil-mode globally
  (evil-mode t)
  ;; some configs setup later
  <<evil-config>>
  ;; extra keybindings defined in `Keybinding' section
  <<evil-keybindings>>
  <<evil-ex-commands>>)

Setup default state to insert-state

;; default state set to insert-state
(setq evil-default-state 'insert)

Make insert-state the same as emacs-state

To me, vim's insert state is useless, so I mapping all my emacs keybinding to insert-state.

First, bind all emacs-state key to insert state

(setcdr evil-insert-state-map nil)
(define-key evil-insert-state-map
  (read-kbd-macro evil-toggle-key) 'evil-emacs-state)

Make sure ESC key in insert-state will call evil-normal-state.

(define-key evil-insert-state-map [escape] 'evil-normal-state)

We also need to make all emacs-state buffer become to insert-state.

(dolist (m evil-emacs-state-modes)
  (add-to-list 'evil-insert-state-modes m))

evil-leader

Evil Leader provides the <leader> feature from Vim that provides an easy way to bind keys under a variable prefix key. For an experienced Emacs User it is nothing more than a convoluted key map, but for a Evil user coming from Vim it means an easier start.

GitHub: https://github.com/cofi/evil-leader

(req-package evil-leader
  :config
  ;; enable evil-leader globally
  (global-evil-leader-mode)
  ;; extra keybindings defined in `Keybinding' section
  <<evil-leader-keybindings>>)

evil-surround

This package emulates surround.vim by Tim Pope. The functionality is wrapped into a minor mode.

GitHub: https://github.com/timcharper/evil-surround

(req-package evil-surround
  :config
  (global-evil-surround-mode 1))

IDE Features

emacs has some IDE feature, add here.

projectile

Projectile is a project interaction library for Emacs. Its goal is to provide a nice set of features operating on a project level without introducing external dependencies(when feasible). For instance - finding project files has a portable implementation written in pure Emacs Lisp without the use of GNU find (but for performance sake an indexing mechanism backed by external commands exists as well).

GitHub: https://github.com/bbatsov/projectile

(req-package projectile
  :config
  (projectile-global-mode)
  ;; save projectile-known-projects-file in cache folder
  (setq projectile-known-projects-file
        (concat user-cache-directory "projectile-bookmarks.eld"))
  (setq projectile-cache-file
        (concat user-cache-directory "projectile.cache"))
  ;; Enable projectile globally
  (projectile-global-mode))

semantic

(req-package semantic
  :config
  (setq semanticdb-default-save-directory
        (concat user-cache-directory "semanticdb/"))

  (global-semanticdb-minor-mode 1)
  (global-semantic-idle-scheduler-mode 1)

  (semantic-mode 1))

GDB

(req-package gdb
  :config
  ;; Use many window in gdb
  (setq gdb-many-windows t)
  ;; Display source file containing the main routine at startup.
  ;; Also display the main routine in the disassembly buffer if present.
  (setq gdb-show-main t))

realgud

A modular GNU Emacs front-end for interacting with external debuggers.

See https://github.com/rocky/emacs-dbgr/wiki/Debuggers-Supported for a list of debuggers supported.

A debugger can be run out of a comint process buffer, or you can use a M-x realgud-track-mode inside an existing shell, or eshell buffer.

GitHub: https://github.com/rocky/emacs-dbgr

(req-package realgud)

cscope

(req-package xcscope
  :config
  ;; Use gtas's cscope command
  (setq cscope-program "gtags-cscope")
  ;; basic setup
  (cscope-setup))

flycheck

(req-package flycheck
  :config
  ;; enable globally
  (global-flycheck-mode))

Helm

(req-package helm
  :require helm-config
  :config
  ;; enable helm globally
  (helm-mode 1)
  ;; extra helm configs
  <<helm-config>>)

Use fuzzy match in helm

;; Use fuzzy match in helm
(setq helm-M-x-fuzzy-match t)
(setq helm-buffers-fuzzy-matching t)
(setq helm-recentf-fuzzy-match t)

Make helm can select anything even not match

;; make helm can select anything even not match
(setq helm-move-to-line-cycle-in-source nil)
(setq helm-ff-search-library-in-sexp t)
(setq helm-ff-file-name-history-use-recentf t)

Integrate helm with projectile

GitHub: https://github.com/bbatsov/helm-projectile

(req-package helm-projectile
  :require (helm projectile)
  :config
  ;; make projectile use helm as completion system
  (setq projectile-completion-system 'helm)
  ;; start helm-projectile
  (helm-projectile-on))

Integrate helm with gtags

helm-gtags.el is GNU GLOBAL helm interface.

GitHub: https://github.com/syohex/emacs-helm-gtags

(req-package helm-gtags
  :config
  (setq helm-gtags-ignore-case t)
  (setq helm-gtags-auto-update t)
  (setq helm-gtags-use-input-at-cursor t)
  (setq helm-gtags-pulse-at-cursor t)
  ;; add to following modes
  (add-hook 'c-mode-hook #'helm-gtags-mode)
  (add-hook 'c++-mode-hook #'helm-gtags-mode))

Integrate helm with bm.el

GitHub: https://github.com/yasuyk/helm-bm

(req-package helm-bm)

Integrate helm with yasnippet

GitHub: https://github.com/emacs-jp/helm-c-yasnippet

(req-package helm-yasnippet
  :require (helm yasnippet)
  :config
  (setq helm-yas-space-match-any-greedy t))

Integrate with cscope

helm-cscope.el is a helm interface for xcscope.el. You can search cscope database and narrow selection using helm interface.

Helm-cscope shares most functions with xcscope.el. It just provide M-x helm-cscope-find-* commands as helm version alternatives for M-x cscope-find-*

GitHub: https://github.com/alpha22jp/helm-cscope.el

(req-package helm-cscope
  :config
  (add-hook 'c-mode-common-hook 'helm-cscope-mode))

Insert fontawesome with helm interface

Emacs fontawesome utility.

GitHub: https://github.com/syohex/emacs-fontawesome

(req-package fontawesome)

Efficiently hopping squeezed lines powered by Emacs helm interface

List match lines to another buffer, which is able to squeeze by any words you input. At the same time, the original buffer's cursor is jumping line to line according to moving up and down the line list.

GitHub: https://github.com/ShingoFukuyama/helm-swoop

(req-package helm-swoop)

Browse Dash docsets inside emacs

This package uses Dash docsets inside emacs to browse documentation. Here's an article explaining the basic usage of it.

It doesn't require Dash app.

GitHub: https://github.com/areina/helm-dash

(req-package helm-dash
  :require helm)

Setup keybindings

(bind-keys :map helm-map
           ("TAB"   . helm-execute-persistent-action)
           ("<tab>" . helm-execute-persistent-action)
           ("C-w"   . backward-kill-word)
           ("M-t" . my/minibuffer-switch-to-ramdisk)
           ("M-h" . my/minibuffer-switch-to-home)
           ("M-/" . my/minibuffer-switch-to-rootdir)
           ("M-s" . my/minibuffer-switch-to-tramp))

Completion

Company is a text completion framework for Emacs. The name stands for "complete anything". It uses pluggable back-ends and front-ends to retrieve and display completion candidates.

GitHub: https://github.com/company-mode/company-mode

(req-package company
  :config
  ;; enable globally
  (global-company-mode 1)
  ;; some configuration add here by noweb
  <<company-config>> )

Do not show company menu until I trigger it

(setq company-idle-delay nil)

Completion C/C++ headers

(req-package company-c-headers
  :require company
  :config
  (add-to-list 'company-backends 'company-c-headers))

Fuzzy matching for company

(req-package company-flx
  :require company
  :config
  (company-flx-mode +1))

Sort completion candidates by previous completion choices

Company-statistics is a global minor mode built on top of the in-buffer completion system company-mode. The idea is to keep a log of a certain number of completions you choose, along with some context information, and use that to rank candidates the next time you have to choose — hopefully showing you likelier candidates at the top of the list.

GitHub: https://github.com/company-mode/company-statistics

(req-package company-statistics
  :config
  ;; save cache file to `user-cache-directory'
  (setq company-statistics-file (concat user-cache-directory
                                        "company-statistics-cache.el"))
  ;; start company-statictics-mode after init
  (add-hook 'after-init-hook 'company-statistics-mode))

Setup keybindings

(bind-keys :map company-active-map
           ("C-g" . company-abort)
           ("C-n" . company-select-next)
           ("C-s" . company-filter-candidates)
           ("C-p" . company-select-previouse)
           ("TAB" . company-complete-selction)
           ("<tab>" . company-complete-selction))

(bind-keys :map company-search-map
           ("C-n" . company-select-next)
           ("C-p" . company-select-previous))

Snippets

(req-package yasnippet
  :mode ("emacs.+/snippets/" . snippet-mode)
  :config
  ;; enable yasnippet globally
  (yas-global-mode 1)
  ;; extra yasnipet configs
  <<yasnippet-config>>)

Setup yasnippet prompt method

(setq yas/prompt-functions '(yas-dropdown-prompt
                             yas-completing-prompt
                             yas-ido-prompt))

Setup yasnippet snippet dirs

(setq yas/snippet-dirs (concat user-emacs-directory "snippets"))

Prevent yasnippet conflict with term-mode

(add-hook 'term-mode-hook (lambda() (yas-minor-mode -1)))

Implement org-mode's easy-template like function

I really like org-mode's easy-template function, so I implement one called major-mode-expand which will let you use easy-template like function in any major-mode.

(defadvice yas-expand (around major-mode-expand activate)
  "Try to complete a structure template before point like org-mode does.
This looks for strings like \"<e\" on an otherwise empty line and
expands them.
Before use this function, you must setup `major-mode-name'-expand-alist variable.

Take emacs-lisp-mode as example, if you wand to use <r to expand your snippet `require'
in yasnippet, you muse setup the emacs-lisp-mode-expand-alist variable.

 (setq emacs-lisp-expand-alist '((\"r\" . \"require\")))"
  (let* ((l (buffer-substring (point-at-bol) (point)))
         (expand-symbol (intern (concat (symbol-name major-mode) "-expand-alist")))
         (expand-alist (if (boundp expand-symbol) (symbol-value expand-symbol) nil))
         a)
    (when (and (looking-at "[ \t]*$")
               (string-match "^[ \t]*<\\([a-zA-Z]+\\)$" l)
               (setq a (assoc (match-string 1 l) expand-alist)))
      (backward-delete-char (1+ (length (car-safe a))))
      (if (symbolp (cdr-safe a))
          (funcall (cdr-safe a))
        (insert (cdr-safe a)))
      t)
    ad-do-it))

Take emacs-lisp-mode as example, if I want to use <r and press TAB then yasnippet will expand the command, just add following code:

(setq emacs-lisp-mode-expand-alist '(("r" . "require")))

For c-mode, just do the same but change the relative major-mode-expand-alist like following

(setq c-mode-expand-alist '(("i" . "include")))

Programming Languages

arduino

(req-package arduino-mode
  :mode ("\\.pde\\'" "\\.ino\\'"))

android

(req-package android-mode
  :config
  (setq android-mode-sdk-dir (getenv "ANDROID_HOME")))

Integrate logcat with emacs

logcat interface for emacs based on android-mode.

GitHub: https://github.com/youngker/elogcat.el

(req-package elogcat)

bash

(req-package flymake-shell
  :require (flymake shell)
  :config (add-hook 'sh-set-shell-hook 'flymake-shell-load))

bison

(req-package bison-mode
  :mode ("\\.y\\'" "\\.l\\'" "\\.jison\\'"))

bitbake

(req-package bitbake
  :mode ("\\.bb\\'" "\\.bbappend\\'"))

brainfuck

(req-package brainfuck-mode
  :mode "\\.bf\\'")

crontab

(req-package crontab-mode
  :mode "\\.?cron\\(tab\\)?\\'")

cmake

(req-package cmake-mode
  :mode ("CMakeLists\\.txt\\'" "\\.cmake\\'"))

docker

(req-package dockerfile-mode
  :mode "Dockerfile\\'")

dts

(req-package dts-mode
  :mode ("\\.dts\\'" "\\.dtsi\\'"))

elixir

(req-package elixir-mode)
(req-package alchemist)

gnuplot

A major mode for Emacs for interacting with Gnuplot

GitHub: https://github.com/bruceravel/gnuplot-mode

(req-package gnuplot
  :commands gnuplot-mode
  :mode "\\.gp$")

graphviz dot

(req-package graphviz-dot-mode
  :mode "\\.dot\\'"
  :config
  ;; alias `dot-mode' to graphviz-dot-mode
  (defalias 'dot-mode 'graphviz-dot-mode))

glsl

(req-package glsl-mode
  :mode (("\\.vs\\'" . glsl-mode)
         ("\\.fs\\'" . glsl-mode)
         ("\\.gs\\'" . glsl-mode))
  :config
  (setq glsl-other-file-alist '(("\\.fs$" (".vs")) ("\\.vs$" (".fs")))))

javascript

(req-package js2-mode
  :mode "\\.js\\'")
(req-package js2-refactor)
(req-package jsx-mode
  :mode "\\.jsx\\'")

Simplify importing JS modules

import-js is a tool to automatically import dependencies in your JavaScript project. Use it in Vim or Emacs by placing your cursor on a variable and hit <leader>j (Vim), or (M-x) import-js-import (Emacs).

GitHub: https://github.com/trotzig/import-js

(req-package import-js)

json

(req-package json-mode
  :mode "\\.json\\'")
(req-package json-reformat :commands json-reformat-region)
(req-package flymake-json
  :require flymake
  :config
  (add-hook 'json-mode-hook (lambda () (flymake-json-load))))

lua

(req-package lua-mode
  :mode "\\.lua$")

markdown

(req-package markdown-mode
  :mode "\\.\\(md\\|markdown\\)\\'")

po

(req-package po-mode
  :mode "\\.po\\'\\|\\.po\\."
  :config

  ;; To use the right coding system automatically under Emacs 20 or newer,
  ;; also add:
  (when (require 'po nil 'noerror)
    (modify-coding-system-alist 'file "\\.po\\'\\|\\.po\\."
                                'po-find-file-coding-system))
  )

php

(req-package php-mode
  :mode "\\.php\\'")

python

(req-package python
  :mode (("\\.py\\'" . python-mode)
         ("SConstruct\\'" . python-mode)
         ("SConscript\\'" . python-mode)))

qml

(req-package qml-mode
  :mode "\\.qml$")

ruby

(req-package ruby-mode
  :mode (("Gemfile\\'"  . ruby-mode)
         ("Kirkfile\\'" . ruby-mode)
         ("Rakefile\\'" . ruby-mode)
         ("Vagrantfile\\'" . ruby-mode)
         ("\\.builder\\'"  . ruby-mode)
         ("\\.gemspec\\'"  . ruby-mode)
         ("\\.irbrc\\'" . ruby-mode)
         ("\\.pryrc\\'" . ruby-mode)
         ("\\.rake\\'"  . ruby-mode)
         ("\\.rjs\\'"   . ruby-mode)
         ("\\.ru\\'"    . ruby-mode)
         ("\\.rxml\\'"  . ruby-mode))
  :config
  ;; We never want to edit Rubinius bytecode
  (add-to-list 'completion-ignored-extensions ".rbc"))

rust

rust-mode is a major emacs-mode for editing Rust source code.

(req-package rust-mode
  :mode "\\.rs\\'")

llvm

(req-package llvm-mode)

lua

(req-package lua-mode
  :mode "\\.lua$")

Haskell

(req-package haskell-mode
  :mode "\\.hs\\'"
  :config
  <<haskell-config>>)

Setup Haskell Keybinding

(bind-keys :map haskell-mode-map
           ("C-c '" . my/narrow-or-widen-dwim))

scala

(req-package scala-mode2
  :mode "\\.scala$")
(req-package sbt-mode
  :mode "\\.sbt$")

ssh config

(req-package ssh-config-mode
  :mode ((".ssh/config\\'"       . ssh-config-mode)
         ("sshd?_config\\'"      . ssh-config-mode)
         ("known_hosts\\'"       . ssh-known-hosts-mode)
         ("authorized_keys2?\\'" . ssh-authorized-keys-mode)))

swift

(req-package swift-mode)

systemd

(req-package systemd)

toml

(req-package toml-mode
  :mode "\\.toml$")

nxml

(use-package nxml-mode
  :mode (("\\.plist\\'" . nxml-mode)
         ("\\.rss\\'"   . nxml-mode)
         ("\\.svg\\'"   . nxml-mode)
         ("\\.xml\\'"   . nxml-mode)
         ("\\.xsd\\'"   . nxml-mode)
         ("\\.xslt\\'"  . nxml-mode)
         ("\\.pom$"     . nxml-mode))
  :config
  ;; Any file start with xml will be treat as nxml-mode
  (add-to-list 'magic-mode-alist '("<\\?xml" . nxml-mode))
  ;; Use nxml-mode instead of sgml, xml or html mode.
  (mapc
   (lambda (pair)
     (if (or (eq (cdr pair) 'xml-mode)
             (eq (cdr pair) 'sgml-mode))
         (setcdr pair 'nxml-mode)))
   auto-mode-alist))

yaml

(req-package yaml-mode)

C / C++ Development

(use-package cc-mode
  :mode
  (("\\.h\\'" . c-mode)
   ("\\.c\\'" . c-mode)
   ("\\.hpp\\'" . c++-mode)
   ("\\.cpp\\'" . c++-mode))
  :config
  <<cc-mode-config>>)

Use regexp to find header is C++ header or not

(add-to-list 'magic-mode-alist
             `(,(lambda ()
                  (and (string= (file-name-extension (or (buffer-file-name) "")) "h")
                       (or (re-search-forward "#include <\\w+>"
                                              magic-mode-regexp-match-limit t)
                           (re-search-forward "\\W\\(class\\|template\\namespace\\)\\W"
                                              magic-mode-regexp-match-limit t)
                           (re-search-forward "std::"
                                              magic-mode-regexp-match-limit t))))
               . c++-mode))

Use dummy-h-mode to help detect header's major mode

dummy-h-mode is an major-mode to help switch major mode to c/c++/objc-mode on .h file.

GitHub: https://github.com/yascentur/dummy-h-mode-el

(req-package dummy-h-mode
  :require cc-mode
  :mode "\\.h$"
  :config
  (add-hook 'dummy-h-mode-hook
            (lambda ()
              ;; use c-mode by default
              (setq dummy-h-mode-default-major-mode 'c-mode)
              ;; setup search limit
              (setq dummy-h-mode-search-limit 60000))))

Add eldoc support for C/C++

(req-package c-eldoc
  :require eldoc
  :config
  (add-hook 'c-mode-common-hook
            '(lambda ()
               (setq c-eldoc-includes "`pkg-config --cflags --libs` -I./ -I../")
               (c-turn-on-eldoc-mode))))

Highlight a few dangerous types in C/C++

cwarn-mode is a minor mode that ca highlight a few dangerous types in C/C++.

By default it highlights:

  • Semicolons right after conditions and loops (e.g. if (x == y);)
  • Assignments in tests (e.g. if (x = y) {)
  • Functions with reference parameters (e.g. void funct(string &p) {)
(req-package cwarn
  :config
  (add-hook 'c-mode-common-hook '(lambda () (cwarn-mode 1))))

Comment #if 0 #endif region

(defun my/cc-mode/highlight-if-0 ()
  "highlight c/c++ #if 0 #endif macros"
  (setq cpp-known-face 'default)
  (setq cpp-unknown-face 'default)
  (setq cpp-known-writable 't)
  (setq cpp-unknown-writable 't)
  (setq cpp-edit-list '(("0" '(foreground-color . "gray")  default both)
                        ("1" default font-lock-comment-face both)))
  (cpp-highlight-buffer t))

;; Add to c/c++ mode
(defun my/cc-mode/highlight-if-0-hook ()
  (when (or (eq major-mode 'c++-mode) (eq major-mode 'c-mode))
    (my/cc-mode/highlight-if-0)))
(add-hook 'after-save-hook #'my/cc-mode/highlight-if-0-hook)

Extra highlight keywords for C/C++

Extra hightlight for stdint.h

(dolist (m '(c-mode c++-mode))
  (font-lock-add-keywords
   m
   '(("\\<\\(int8_t\\|int16_t\\|int32_t\\|int64_t\\|uint8_t\\|uint16_t\\|uint32_t\\|uint64_t\\)\\>" . font-lock-keyword-face))))

Syntax check and code-completion with CMake project

cpputils-cmake is a nice tool for cmake project.

GitHub: https://github.com/redguardtoo/cpputils-cmake

(req-package cpputils-cmake
  :require (flymake flycheck)
  :config
  (add-hook 'c-mode-common-hook
            (lambda ()
              (when (derived-mode-p 'c-mode 'c++-mode)
                (cppcm-reload-all)))))

Quick switch between header and source file in C/C++

This extension allows to quickly switch between header and a source file with the same name located in the directory tree or repository. It is an alternatife to ff-find-other-file.

GitHub: https://github.com/fourier/cff

(use-package cff :ensure t)

Use subword-mode for C/C++ project

In most C/C++ project, we naming variable in camelCase, subword-mode can help us treat helloWorld as two words.

;; subword-mode, e.g., someThing is treated as two words
(add-hook 'c-mode-common-hook '(lambda () (subword-mode 1)))

Auto pair parentheses with electric-pair

(add-hook 'c-mode-common-hook 'electric-pair-mode)

Add refactor function support

Semantic Refactor is a C/C++ refactoring tool based on Semantic parser framework.

GitHub: https://github.com/tuhdo/semantic-refactor

(use-package srefactor
  :ensure t)

Coding Styles (C)

General C Coding Style

I always use linux coding style for c language by default.

(add-hook 'c-mode-hook
          '(lambda ()
             (c-set-style "linux")
             (setq c-basic-offset 8)
             ;; Make TAB equivilent to 8 spaces
             (setq tab-width 8)))

Linux Kernel C Coding Style

As part of Linux Kernel developer, I add linux-kernel coding style rule, which use tabs as indent and follow linux kernel development rules. Use following code to make emacs switch to linux-kernel style automatically when enter linux kernel directories.

This coding style is document in https://www.kernel.org/doc/Documentation/CodingStyle.

(defun c-lineup-arglist-tabs-only (ignored)
  "Line up argument lists by tabs, not spaces"
  (let* ((anchor (c-langelem-pos c-syntactic-element))
         (column (c-langelem-2nd-pos c-syntactic-element))
         (offset (- (1+ column) anchor))
         (steps (floor offset c-basic-offset)))
    (* (max steps 1)
       c-basic-offset)))

;; Add Linux kernel style
(add-hook 'c-mode-common-hook
          (lambda ()
            (c-add-style "linux-kernel"
                         '("linux" (c-offsets-alist
                                    (arglist-cont-nonempty
                                     c-lineup-gcc-asm-reg
                                     c-lineup-arglist-tabs-only))))))

(defun linux-kernel-development-setup ()
  (let ((filename (buffer-file-name)))
    ;; Enable kernel mode for the appropriate files
    (when (and filename
               (or (locate-dominating-file filename "Kbuild")
                   (locate-dominating-file filename "Kconfig")
                   (save-excursion (goto-char 0)
                                   (search-forward-regexp "^#include <linux/\\(module\\|kernel\\)\\.h>$" nil t))))
      ;; (setq indent-tabs-mode t)
      ;; (setq show-trailing-whitespace t)
      (c-set-style "linux-kernel")
      (message "Setting up indentation for the linux kernel"))))

(add-hook 'c-mode-hook 'linux-kernel-development-setup)

Coding Styles (C++)

Use my C++ coding style.

(add-hook 'c++-mode-hook
          '(lambda ()

             ;; Use stroustrup style
             (c-set-style "stroustrup")

             ;; Setting indentation lvel
             (setq c-basic-offset 4)

             ;; Make TAB equivilent to 4 spaces
             (setq tab-width 4)

             ;; Use spaces to indent instead of tabs.
             (setq indent-tabs-mode nil)

             ;; Indent the continuation by 2
             (setq c-continued-statement-offset 2)

             ;; Brackets should be at same indentation level as the statements they open
             ;; for example:
             ;;                 if (0)        becomes        if (0)
             ;;                     {                        {
             ;;                        ;                         ;
             ;;                     }                        }
             (c-set-offset 'substatement-open 0)

             ;; make open-braces after a case
             (c-set-offset 'case-label '+)

             ;; Not indent code inside a namespace
             ;; for example:
             ;;                namespace A {
             ;;
             ;;                int namespace_global_variable;
             ;;
             ;;                class Class {
             ;;
             ;;                Class();
             ;;                //...
             ;;                };
             ;;
             ;;                }
             (c-set-offset 'innamespace 0)
             ))

Setup C/C++ Keybinding

(bind-keys :map c-mode-base-map
           ("C-c '" . my/narrow-or-widen-dwim)
           ("C-c C-c" . compile)
           ("C-c C-g" . gdb)
           ("C-c C-o" . cff-find-other-file))

;; Some keys may override global map add here
(bind-keys :map c-mode-base-map
           ("M-." . helm-gtags-dwim)
           ("M-," . helm-gtags-pop-stack))

LISP Development

Though LISP has many dialet, it still is the best programming language I ever met.

Plugins

Common setup for LISP development.

lispy

This package reimagines Paredit - a popular method to navigate and edit LISP code in Emacs.

GitHub: https://github.com/abo-abo/lispy

For more info to control lispy, please refer: http://oremacs.com/lispy/

(req-package lispy
  :require (hungry-delete projectile)
  :config
  ;; My special hack for lispy-mode
  (defun my/lispy-mode ()
    (lispy-mode 1)
    ;; `M-m' is preserved for mode setting
    (define-key lispy-mode-map (kbd "M-m") nil)
    ;; `M-s' is for my search command, rebind to `C-c s'
    (define-key lispy-mode-map (kbd "M-s") nil)
    (define-key lispy-mode-map (kbd "C-c s") 'lispy-splice)
    ;; `[' and `]' just insert them
    (define-key lispy-mode-map (kbd "[") 'lispy-open-square)
    (define-key lispy-mode-map (kbd "]") 'lispy-close-square))

  ;; Use projectile to find file
  (setq lispy-visit-method 'projectile)

  (add-hook 'emacs-lisp-mode-hook #'my/lispy-mode)
  (add-hook 'lisp-interaction-mode-hook #'my/lispy-mode)
  (add-hook 'clojure-mode-hook #'my/lispy-mode)
  (add-hook 'scheme-mode-hook #'my/lispy-mode)
  (add-hook 'lisp-mode-hook #'my/lispy-mode))

indent-guide

(use-package indent-guide
  :ensure t
  :config
  (add-hook 'emacs-lisp-mode-hook #'indent-guide-mode)
  (add-hook 'lisp-interaction-mode-hook #'indent-guide-mode)
  (add-hook 'clojure-mode-hook #'indent-guide-mode)
  (add-hook 'scheme-mode-hook #'indent-guide-mode)
  (add-hook 'lisp-mode-hook #'indent-guide-mode))

Prettify symbols

Show lambda as λ.

(global-prettify-symbols-mode 1)

Emacs Lisp

(req-package emacs-lisp-mode
  :config
  <<emacs-lisp-mode-config>>)

Plugins

  • Additional flavour to emacs-lisp programming

    el-spice is a minor mode that provides additional configuration to make programming in Emacs Lisp more enjoyable.

    GitHub: https://github.com/vedang/el-spice

    (req-package el-spice)
    
  • Interactive macro-expander for Emacs

    macrostep is an Emacs minor mode for interactively stepping through the expansion of macros in Emacs Lisp source code. It lets you see exactly what happens at each step of the expansion process by pretty-printing the expanded forms inline in the source buffer, which is temporarily read-only while macro expansions are visible. You can expand and collapse macro forms one step at a time, and evaluate or instrument the expansions for debugging with Edebug as normal (but see “Bugs and known limitations”, below). Single-stepping through the expansion is particularly useful for debugging macros that expand into another macro form. These can be difficult to debug with Emacs’ built-in macroexpand, which continues expansion until the top-level form is no longer a macro call.

    GitHub: https://github.com/joddie/macrostep

    (use-package macrostep)
    

Add eldoc support

(req-package eldoc
  :config
  (add-hook 'emacs-lisp-mode-hook
            '(lambda ()
               ;; enable eldoc
               (turn-on-eldoc-mode)
               ;; fix for paredit if exist
               (eval-after-load 'paredit
                 '(progn
                    (eldoc-add-command 'paredit-backward-delete
                                       'paredit-close-round))))))

On-the-fly evaluation/substitution of emacs lisp code

litable keeps a list of pure functions as a safeguard for unwanted evaluations. A function must first be accepted into this list (using M-x litable-accept-as-pure) before it can be evaluated on-the-fly.

You should take care of what function you accept as pure to avoid any unfortunate accidents. Also, note that the pure functions list persists across sessions.

GitHub: https://github.com/Fuco1/litable

(req-package litable
  :config
  ;; Save cache file to `user-cache-direcotry'
  (setq litable-list-file (concat user-cache-directory ".litable-lists.el"))
  ;; Enable litable-mode globally
  (litable-mode))

Syntax highlighting for Emacs' cl-lib

This library adds all of the familiar highlighting to cl-lib macros (cl-defun, cl-loop, etc.) that were originally provided for cl.

It's not simply throwing in all the symbols as keywords. They're being added using the same regular expressions that cl gets, so function names get highlighted with cl-defun, type names get highlighted with cl-defstruct, etc.

GitHub: https://github.com/skeeto/cl-lib-highlight

(req-package cl-lib-highlight
  :config
  (cl-lib-highlight-initialize))

Display ^L glyphs as horizontal lines

This Emacs library provides a global mode which displays ugly form feed characters as tidy horizontal rules.

GitHub: https://github.com/purcell/page-break-lines

(req-package page-break-lines
  :config
  ;; enable globally
  (global-page-break-lines-mode 1))

Remove *.elc when save

(defun remove-elc-on-save ()
  "If you're saving an elisp file, likely the .elc is no longer valid."
  (make-local-variable 'after-save-hook)
  (add-hook 'after-save-hook
            (lambda ()
              (if (file-exists-p (concat buffer-file-name "c"))
                  (delete-file (concat buffer-file-name "c"))))))

(add-hook 'emacs-lisp-mode-hook 'remove-elc-on-save)

Shows keyboard macros or latest interactive commands as emacs lisp.

GitHub: https://github.com/Silex/elmacro

(req-package elmacro
  :config
  (elmacro-mode))

Setup Emacs-Lisp Keybinfons

(bind-keys :map emacs-lisp-mode-map
           ("C-c '" . my/narrow-or-widen-dwim))

Clojure

(req-package clojure-mode
  :require (clojure-mode-extra-font-locking flycheck-clojure lispy)
  :mode "\\.\\(clj\\|boot\\|cljx\\|edn\\|cljs\\|cljs.hl\\)\\'"
  :config
  <<clojure-config>>)

Add refactor function support

GitHub: https://github.com/clojure-emacs/clj-refactor.el

(req-package clj-refactor
  :require (helm cljr-helm)
  :config
  ;; Add clj-refactor to clojure-mode
  (add-hook 'clojure-mode-hook '(lambda () (clj-refactor-mode 1)))
  ;; Use `C-c C-x' as prefix
  (cljr-add-keybindings-with-prefix "M-m"))

Use cider for interactive development

cider is a Clojure Interactive Development Environment that Rocks for Emacs

(req-package cider
  :require (cider-decompile cider-eval-sexp-fu eldoc projectile)
  :config

  ;; Enable eldoc in Clojure buffers
  (add-hook 'cider-mode-hook 'cider-turn-on-eldoc-mode)

  ;; Hide `*nrepl-connection*' and `*nrepl-server*' buffers from appearing
  ;; in some buffer switching commands like switch-to-buffer
  (setq nrepl-hide-special-buffers t)

  ;; Enabling CamelCase support for editing commands(like forward-word,
  ;; backward-word, etc) in the REPL is quite useful since we often have
  ;; to deal with Java class and method names. The built-in Emacs minor
  ;; mode subword-mode provides such functionality
  (add-hook 'cider-repl-mode-hook #'subword-mode)

  ;; The use of paredit when editing Clojure (or any other Lisp) code is
  ;; highly recommended. You're probably using it already in your
  ;; clojure-mode buffers (if you're not you probably should). You might
  ;; also want to enable paredit in the REPL buffer as well.
  ;; (add-hook 'cider-repl-mode-hook #'paredit-mode)

  ;; Auto-select the error buffer when it's displayed:
  (setq cider-auto-select-error-buffer t)

  ;; Controls whether to pop to the REPL buffer on connect.
  (setq cider-repl-pop-to-buffer-on-connect nil)

  ;; Controls whether to auto-select the error popup buffer.
  (setq cider-auto-select-error-buffer t)

  ;; T to wrap history around when the end is reached.
  (setq cider-repl-wrap-history t)

  ;; Log protocol messages to the `nrepl-message-buffer-name' buffer.
  (setq nrepl-log-messages t))

Search on Clojars more easily

This Emacs extension allows you to search for projects on clojars.org and copies your selection to the kill ring in a format suitable for your project.clj.

GitHub: https://github.com/joshuamiller/clojars.el

(req-package clojars)

Search Clojure Cheatsheet

GitHub: https://github.com/clojure-emacs/clojure-cheatsheet

(req-package clojure-cheatsheet)

Interactive Commands

Some interactive commands for clojure-mode.

  • Send S-Expression and evaluate it there
    (defun my/cider-send-and-evaluate-sexp ()
      "Sends the s-expression located before the point or the active
      region to the REPL and evaluates it. Then the Clojure buffer is
      activated as if nothing happened."
      (interactive)
      (if (not (region-active-p))
          (cider-insert-last-sexp-in-repl)
        (cider-insert-in-repl
         (buffer-substring (region-beginning) (region-end)) nil))
      (cider-switch-to-repl-buffer)
      (cider-repl-closing-return)
      (cider-switch-to-last-clojure-buffer)
      (message ""))
    

Setup Clojure Keybinding

(bind-keys :map clojure-mode-map
           ;; M-m     . refactor command
           ("C-c C-f" . projectile-find-file)
           ("C-c M-c" . cider-connect)
           ("C-c M-j" . cider-jack-in)
           ("C-c '"   . my/narrow-or-widen-dwim)
           ("C-c h"   . clojure-cheatsheet)
           ("C-c C-k" . cider-load-buffer)
           ("C-x C-e" . cider-eval-last-sexp)
           ("C-c C-v" . my/cider-send-and-evaluate-sexp)
           ("C-c C-t" . projectile-toggle-between-implementation-and-test))

Scheme

(use-package scheme
  :mode ("\\.scm\\'" . scheme-mode)
  :config
  <<scheme-config>>)
(use-package racket-mode
  :ensure t
  :mode "\\.rkt[dl]?\\'")

Use geiser to interaction wich scheme

(use-package geiser
  :ensure t
  :init
  ;; On opening a scheme file, Geiser will try to guess its Scheme,
  ;; defaulting to the first in the list. Use `C-c C-s' to select the
  ;; implementation by hand (on a per file basis).
  (setq geiser-active-implementations '(guile chicken)))

Setup Scheme Keybinding

(bind-keys :map scheme-mode-map
           ("C-c '" . my/narrow-or-widen-dwim))

Common Lisp

(req-package lisp-mode
  :mode "\\.lisp\\'"
  :config
  <<common-lisp-config>>)

Setup Common Lisp Keybinding

(bind-keys :map lisp-mode-map
           ("C-c '" . my/narrow-or-widen-dwim))

newlisp

(req-package newlisp-mode)

Web Development

(req-package web-mode
  :mode (("\\.html?\\'" . web-mode)
         ("\\.ejs?\\'" . web-mode)))

CSS

(req-package css-mode :mode "\\.css\\'")

Add support for eldoc

(req-package css-eldoc
  :config
  (progn
    (add-hook 'css-mode-hook 'turn-on-css-eldoc)
    (add-hook 'scss-mode-hook 'turn-on-css-eldoc)
    (add-hook 'less-css-mode-hook 'turn-on-css-eldoc)))

Less

(req-package less-css-mode
  :init (add-to-list 'auto-mode-alist '("\\.less$" . less-css-mode))
  :mode "\\.less$")

SCSS

(req-package scss-mode
  :mode "\\.scss\\'"
  :config
  (progn
    ;; dont' build scss to css after save file
    (setq scss-compile-at-save nil)))

mustache

Sometimes we will use mustache as template system, mustache-mode is a nice helper.

GitHub: https://github.com/mustache/emacs

(req-package mustache-mode :mode "\\.mustache$")

Use emmet-mode to add Zen Coding support

emmet-mode is a fork of zencoding-mode which add minor mode providing support for Zen Coding by producing HTML from CSS-like selectors.

GitHub: https://github.com/smihica/emmet-mode

(req-package emmet-mode
  :config
  (progn
    ;; Following mode support emmet-mode
    (add-hook 'html-mode-hook 'emmet-mode)
    (add-hook 'sgml-mode-hook 'emmet-mode)
    (add-hook 'nxml-mode-hook 'emmet-mode)
    (add-hook 'css-mode-hook  'emmet-mode)

    ;; Move cursor between quotes after expand
    (add-hook 'emmt-mode-hook
              '(lambda()
                 (setq emmet-move-cursor-between-quotes t)))

    ;; Make tab can also expand emmt instead of use yasnippet directly
    (define-key emmt-mode-keymap (kbd "TAB") 'emmt-expand-yas)
    (define-key emmt-mode-keymap (kbd "<tab>") 'emmt-expand-yas)))

Buffer

Create scratch automatically

Sometimes I'll clean the *scratch* buffer by kill it, add following function to let emacs re-create it automatically.

;; Create *scratch* automatically
(run-with-idle-timer 1 t
                     '(lambda ()
                        (unless (get-buffer "*scratch*")
                          (with-current-buffer (get-buffer-create "*scratch*")
                            (lisp-interaction-mode)))))

Make buffer names unique

The library uniquify overrides Emacs' default mechanism for making buffer names unique (using suffixes like <2>, <3> etc.) with a more sensible behaviour which use parts of the file names to make the buffer names distinguishable.

For instance, buffers visiting /u/mernst/tmp/Makefile and /usr/projects/zaphod/Makefile would be named Makefile|tmp and Makefile|zaphod, respectively (instead of Makefile and Makefile<2>).

(req-package uniquify
  :config
  ;; starting separator for buffer name components
  (setq uniquify-separator " • ")
  ;; rerationalize buffer names after a buffer has been killed.
  (setq uniquify-after-kill-buffer-p t)
  ;; ignore non file buffers
  (setq uniquify-ignore-buffers-re "^\\*"))

Version Control

Git

Magit is an interface to the version control system Git, implemented as an Emacs package. Magit aspires to be a complete Git porcelain. While we cannot (yet) claim that Magit wraps and improves upon each and every Git command, it is complete enough to allow even experienced Git users to perform almost all of their daily version control tasks directly from within Emacs. While many fine Git clients exist, only Magit and Git itself deserve to be called porcelains.

GitHub: https://github.com/magit/magit

(req-package magit
  :config
  <<magit-config>>)

Setup default commit arguments

(setq magit-commit-arguments '("--verbose" "--signoff"))

Add support for git configuration files

(req-package gitconfig-mode
  :require flyspell
  :mode (("/\\.?git/?config\\'" . gitconfig-mode)
         ("/\\.gitmodules\\'" . gitconfig-mode)
         ("/_gitconfig\\'" . gitconfig-mode))
  :config
  (add-hook 'gitconfig-mode-hook 'flyspell-mode))

Add support for gitignore files

(req-package gitignore-mode
  :mode (("/\\.gitignore\\'" . gitignore-mode)
         ("/\\.git/info/exclude\\'" . gitignore-mode)
         ("/git/ignore\\'" . gitignore-mode)))

Add GitGutter on fringe

GitHub: https://github.com/syohex/emacs-git-gutter-fringe

(req-package git-gutter-fringe
  :if window-system                     ; git-gutter-fringe only work on GUI
  :require fringe-helper
  :config
  ;; enable globally
  (git-gutter-mode))

Terminal Emulator

ansi-term

Close ansi-term buffer after exit

After the ansi-term process ends it should leaves a buffer.

(defadvice term-handle-exit (after kill-buffer-after-exit activate)
  "Kill the term buffer if the process finished."
  (kill-buffer (current-buffer)))

Sane Term

Ansi Term with sane options and the ability to cycle/create terms.

GitHub: https://github.com/adamrt/sane-term

(req-package sane-term
  :config
  ;; shell to use for sane-term
  (setq sane-term-shell-command "/bin/bash")
  ;; sane-term will create first term if none exist
  (setq sane-term-initial-create t)
  ;; `C-d' or `exit' will kill the term buffer.
  (setq sane-term-kill-on-exit t)
  ;; After killing a term buffer, not cycle to another.
  (setq sane-term-next-on-kill nil))

Eshell

eshell is not really a system shell, it's written in pure lisp. What I like is it fully integrated with emacs.

(req-package eshell
  :config
  ;; extra eshell configs
  <<eshell-config>>)

Setup eshell file to cache directory

;; move eshell cache dir to ~/.emacs.d/.cache
(setq eshell-directory-name (concat user-cache-directory "eshell"))

Use bash like prompt with color

;; Make eshell prompt look likes default bash prompt
(setq eshell-prompt-function
      '(lambda ()
         (concat
          user-login-name "@" system-name " "
          (if (search (directory-file-name (expand-file-name (getenv "HOME"))) (eshell/pwd))
              (replace-regexp-in-string (expand-file-name (getenv "HOME")) "~" (eshell/pwd))
            (eshell/pwd))
          (if (= (user-uid) 0) " # " " $ "))))
;; Add color for eshell prompt like Gentoo does
(defun colorfy-eshell-prompt ()
  (let* ((mpoint)
         (user-string-regexp (concat "^" user-login-name "@" system-name)))
    (save-excursion
      (goto-char (point-min))
      (while (re-search-forward (concat user-string-regexp ".*[$#]") (point-max) t)
        (setq mpoint (point))
        (overlay-put (make-overlay (point-at-bol) mpoint) 'face '(:foreground "dodger blue")))
      (goto-char (point-min))
      (while (re-search-forward user-string-regexp (point-max) t)
        (setq mpoint (point))
        (overlay-put (make-overlay (point-at-bol) mpoint) 'face '(:foreground "green3"))))))
;; Make eshell prompt more colorful
(add-hook 'eshell-output-filter-functions 'colorfy-eshell-prompt)

Use ansi-term to render visual commands

(setq eshell-visual-commands
      '("less" "tmux" "htop" "top" "bash" "zsh" "fish" "ssh" "tail"))

(setq eshell-visual-subcommands
      '(("git" "log" "diff" "show")))

Support for multi-eshell instance

(req-package multi-eshell
  :require eshell
  :config
  (setq multi-eshell-shell-function '(eshell))
  (setq multi-eshell-name "*eshell*"))

Add autojump command

Eshell Autojump is an autojump like command written in pure elisp, which add a j command to let you jump to folder you has been access.

GitHub: https://github.com/coldnew/eshell-autojump

(req-package eshell-autojump :require eshell)

Eshell commands setup

  • ..
    (defun eshell/.. (&optional level)
      "Go up LEVEL directories"
      (interactive)
      (let ((level (or level 1)))
        (eshell/cd (make-string (1+ level) ?.))
        (eshell/ls)))
    
  • clear
    (defun eshell/clear ()
      "Clears the shell buffer ala Unix's clear or DOS' cls"
      ;; the shell prompts are read-only, so clear that for the duration
      (let ((inhibit-read-only t))
        ;; simply delete the region
        (delete-region (point-min) (point-max))))
    
  • emacs
    (defun eshell/emacs (&rest args)
      "Open a file in emacs. Some habits die hard."
      (if (null args)
          ;; If I just ran "emacs", I probably expect to be launching
          ;; Emacs, which is rather silly since I'm already in Emacs.
          ;; So just pretend to do what I ask.
          (bury-buffer)
        ;; We have to expand the file names or else naming a directory in an
        ;; argument causes later arguments to be looked for in that directory,
        ;; not the starting directory
        (mapc #'find-file (mapcar #'expand-file-name (eshell-flatten-list (reverse args))))))
    
    (defalias 'eshell/e 'eshell/emacs)
    
  • unpack
    (defun eshell/unpack (file)
      (let ((command (some (lambda (x)
                             (if (string-match-p (car x) file)
                                 (cadr x)))
                           '((".*\.tar.bz2" "tar xjf")
                             (".*\.tar.gz" "tar xzf")
                             (".*\.bz2" "bunzip2")
                             (".*\.rar" "unrar x")
                             (".*\.gz" "gunzip")
                             (".*\.tar" "tar xf")
                             (".*\.tbz2" "tar xjf")
                             (".*\.tgz" "tar xzf")
                             (".*\.zip" "unzip")
                             (".*\.Z" "uncompress")
                             (".*" "echo 'Could not unpack the file:'")))))
        (eshell-command-result (concat command " " file))))
    

Window Management

Maximized window after emacs start

(modify-all-frames-parameters '((fullscreen . maximized)))

winner-mode

(req-package winner
  :config
  ;; I use my own keymap for winner-mode
  (setq winner-dont-bind-my-keys t)
  ;; Start winner-mode globally
  (winner-mode t))

eyebrowse

eyebrowse is a global minor mode for Emacs that allows you to manage your window configurations in a simple manner, just like tiling window managers like i3wm with their workspaces do. It displays their current state in the modeline by default. The behaviour is modeled after ranger, a file manager written in Python.

GitHub: https://github.com/wasamasa/eyebrowse

(req-package eyebrowse
  :config
  ;; enable eyebrowse globally
  (eyebrowse-mode t))

window-numbering

Numbered window shortcuts for Emacs.

Enable window-numbering-mode and use M-1 through M-0 to navigate.

If you want to affect the numbers, use window-numbering-before-hook or window-numbering-assign-func. For instance, to always assign the calculator window the number 9, add the following to your .emacs:

(setq window-numbering-assign-func
      (lambda () (when (equal (buffer-name) "*Calculator*") 9)))

GitHub: https://github.com/nschum/window-numbering.el

(req-package window-numbering)

Web Browser

Firefox

In firefox-controller, we have two different modes:

  • firefox-controller-remote-mode

    This is based on the original moz-controller, but the number of available commands increases from 11 to more than 30, and simpler key bindings and a better UI are also provided.

  • firefox-controller-direct-mode

    In this mode, you can send the keys directly to firefox.

GitHub: https://github.com/cute-jumper/emacs-firefox-controller

(req-package firefox-controller)

Email

bbdb

(req-package bbdb
  :init
  (setq bbdb-file (concat user-cache-directory "bbdb"))
  :config
  (bbdb-initialize))

mu4e

mu is really nice tool to help me read and search email in emacs.

GitHub: https://github.com/djcb/mu

;; setup loadpath later
<<mu4e-load-path>>

(req-package mu4e
  :config
  <<mu4e-config>>)

Install mu4e to system

Since mu can't install via pacakge.el, you must install manually.

For Mac OSX, just type

brew install mu  --with-emacs --HEAD

An don't forget to add mu4e to your emacs load-path

(when (eq system-type 'darwin)
  (add-to-list 'load-path "/usr/local/Cellar/mu/HEAD/share/emacs/site-lisp/mu4e"))

If you use Gentoo Linux, you can use following command to install this package

USE="emacs" emerge net-mail/mu

Install offlinimap

I use offlineimap to help me fetch the email, we need to install it in system.

For Mac OSX, just type

brew install offlineimap

If you use Gentoo Linux, you can use following command to install this package

emerge net-mail/offlineimap
  • Make offlineimap get password from emacs

    My email password is saved in ~/.authinfo.gpg, which is encrypted by gnupg, since I prefer make prompt for password dialog show on my emacs, I let offlineimap get the emacs password via my emacs.

    To achive this, you need add following conifg in ~/.offlineimaprc

    pythonfile = ~/.offlineimap.py
    

    Then create a file named ~/.offlineimap.py with following code

    #!/usr/bin/env python
    
    import subprocess
    
    def get_output(cmd):
        # Bunch of boilerplate to catch the output of a command:
        pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        (output, errout) = pipe.communicate()
        assert pipe.returncode == 0 and not errout
        return output
    
    def get_password_emacs(host, port):
        cmd = "emacsclient --eval '(offlineimap-get-password \"%s\" \"%s\")'" % (host,port)
        return get_output(cmd).strip().lstrip('"').rstrip('"')
    

    From ~/offlineimap.py, we can see I use emacsclient call eslip function to get the password, so you also need to add offlineimap-get-password function in your ~/.emacs

    (defun offlineimap-get-password (host port)
      (require 'netrc)
      (let* ((netrc (netrc-parse (expand-file-name "~/.authinfo.gpg")))
             (hostentry (netrc-machine netrc host port port)))
        (when hostentry (netrc-get hostentry "password"))))
    

    After all is done, add following line in ~/.offlineimaprc and we can get password by emacs.

    remotepasseval = get_password_emacs("imap.gmail.com")
    

Basic mu4e setup

;; Use mu4e as default mail agent
(setq mail-user-agent 'mu4e-user-agent)
;; Mail folder set to ~/Maildir
(setq mu4e-maildir "~/Maildir")
;; Fetch mail by offlineimap
(setq mu4e-get-mail-command "offlineimap")
;; Fetch mail in 60 sec interval
(setq mu4e-update-interval 60)
;; Setup default mu4e search result mails list, if I want to see
;; more, use M-x `mu4e-headers-toggle-full-search' to make mi4e show all mails
(setq mu4e-headers-results-limit 1000)
;; Make mu4e does not show the "Indexing..." message
(setq mu4e-hide-index-messages t)

Use eww for html file render

(req-package mu4e-contrib
  :config
  (setq mu4e-html2text-command 'mu4e-shr2text)
  ;; try to emulate some of the eww key-bindings
  (add-hook 'mu4e-view-mode-hook
            (lambda ()
              (local-set-key (kbd "<tab>") 'shr-next-link)
              (local-set-key (kbd "<backtab>") 'shr-previous-link))))

Setup send mail method

;; SMTP setup
(setq message-send-mail-function 'smtpmail-send-it
      smtpmail-stream-type 'starttls
      starttls-use-gnutls t)
;; don't save messages to Sent Messages, Gmail/IMAP takes care of this
(setq mu4e-sent-messages-behavior 'delete)

Setup my email acount list

(setq coldnew/mu4e-account-alist
      '(("Gmail"
         (mu4e-sent-folder "/Gmail/Sent")
         (mu4e-drafts-folder "/Gmail/Drafts")
         (mu4e-trash-folder "/Gmail/Trash")
         (user-mail-address "coldnew.tw@gmail.com")
         (smtpmail-smtp-server "smtp.gmail.com")
         (smtpmail-smtp-service 587)
         (smtpmail-smtp-user "coldnew.tw@gmail.com")
         (user-full-name "Yen-Chin, Lee")
         (mu4e-compose-signature ""))))

Since I use list to store my account info, add foollowing function to setup default account.

(defun coldnew/mu4e-set-default-account (account)
  "Setup the default account based on coldnew/mu4e-account-alist."
  (let* ((account (cdr (assoc account coldnew/mu4e-account-alist))))
    (when account (mapc #'(lambda (a)
                            (set (car a) (if (stringp (cadr a)) (cadr a) (eval (cadr a))))) account))))

;; set Gmail to default
(coldnew/mu4e-set-default-account "Gmail")

Select my email account when sending email.

(defun coldnew/mu4e-set-account ()
  "Set the account for composing a message."
  (interactive)
  (let* ((account
          (if mu4e-compose-parent-message
              (let ((maildir (mu4e-msg-field mu4e-compose-parent-message :maildir)))
                (string-match "/\\(.*?\\)/" maildir)
                (match-string 1 maildir))
            (completing-read (format "Compose with account: (%s) "
                                     (mapconcat #'(lambda (var) (car var)) coldnew/mu4e-account-alist "/"))
                             (mapcar #'(lambda (var) (car var)) coldnew/mu4e-account-alist)
                             nil t nil nil (caar coldnew/mu4e-account-alist))))
         (account-vars (cdr (assoc account coldnew/mu4e-account-alist))))
    (if account-vars
        (mapc #'(lambda (var)
                  (set (car var) (cadr var)))
              account-vars))))

(add-hook 'mu4e-compose-pre-hook 'coldnew/mu4e-set-account)

Let mu4e fontify diff contents

I always use mu4e to read maliing-list, it's really nice to fontify diff contents.

(defun mu4e~view-fontify-diff ()
  "Colorize diff message."
  (interactive)
  (let ((inhibit-read-only t))
    (save-excursion
      (goto-char (point-min))
      ;; consider only lines that heuristically look like a citation line...
      (while (re-search-forward "^\\(\\(\\+\\)[^+]\\|\\(-\\)[^-]\\)" nil t)
        (let ((cur-point (or (match-beginning 2) (match-beginning 3)))
              (color (if (match-beginning 2)
                         "green"
                       "deep pink")))
          (end-of-line)
          (add-text-properties cur-point (point)
                               `(face ((foreground-color . ,color))))))
      (goto-char (point-min))
      (while (re-search-forward "^\\(\\+\\+\\+\\|---\\)" nil t)
        (let ((cur-point (match-beginning 1)))
          (end-of-line)
          (add-text-properties cur-point (point)
                               '(face ((weight . bold)))))))))

(add-hook 'mu4e-view-mode-hook 'mu4e~view-fontify-diff)

Setup Keybinfings

(bind-keys :map mu4e-view-mode-map
           ("C-f" . evil-scroll-page-down)
           ("C-b" . evil-scroll-page-up))

IRC

I always use ERC as my irc client, which is bundle with emacs.

(req-package erc
  :require (erc-notify)
  :config
  (progn
    ;; set prompt to ->>
    (setq erc-prompt "->> ")
    ;; Encoding with utf-8
    (setq erc-server-coding-system '(utf-8 . utf-8))
    ;; column with is 100
    (setq erc-fill-column 100)
    ;; Auto join irc server when erc start
    (erc-autojoin-mode t)
    ;; truncate too long line
    (erc-truncate-mode +1)
    ;; Interpret mIRC-style color commands in IRC chats
    (setq erc-interpret-mirc-color t)
    ;; Kill buffers for channels after /part
    (setq erc-kill-buffer-on-part t)
    ;; Kill buffers for private queries after quitting the server
    (setq erc-kill-queries-on-quit t)
    ;; Kill buffers for server messages after quitting the server
    (setq erc-kill-server-buffer-on-quit t)
    ;; open query buffers in the current window
    (setq erc-query-display 'buffer)
    (setq erc-save-buffer-on-part t)))

Setup default irc room I want to join

(setq erc-autojoin-channels-alist
      '(
        ;; english channel
        (".*\\.freenode.net" "#clojure" "#wayland" "#libhybris" "#webos-ports")
        (".*\\.mozilla.org" "#b2g")
        ;; Chinese channel
        (".*\\.freenode.net" "#emacs.tw" "#cschat.tw" "#clojure.tw" "#lisp.tw")))

Hide some sort of message

(setq erc-hide-list
      '(;; notices
        "JOIN" "PART" "QUIT" "LEFT" "NICK"
        ;; robot
        "^j[a-z]*bot!" "^fussbot!"))

Add timestamp for messages

(erc-timestamp-mode 1)
(setq erc-insert-timestamp-function 'erc-insert-timestamp-left)

Coloify user's nickname

(req-package erc-hl-nicks)

Enable track-mode for erc

(eval-after-load 'erc
  '(progn
     ;; enable track-mode
     (erc-track-mode t)
     ;; do not track some type of message
     (setq erc-track-exclude-types '("JOIN" "NICK" "PART" "QUIT" "MODE"
                                     "324" "329" "332" "333" "353" "477"))))

Enable spell checking

(req-package erc-spelling
  :config
  (progn
    (erc-spelling-mode 0)))

Autoaway setup

(req-package erc-autoaway
  :config
  (progn
    (setq erc-auto-discard-away t)
    (setq erc-autoaway-idle-seconds 600)
    (setq erc-autoaway-use-emacs-idle t)))

Quick start/switch erc with one command

(defun erc-start-or-switch ()
  "Connect to IRC, if already connected, switch to active irc buffer."
  (interactive)
  (let ((irc-active-p (and (fboundp 'erc-buffer-list)
                           (erc-buffer-list))))
    ;; we track irc.freenode.net to make sure erc is already active
    (if irc-active-p
        (erc-track-switch-buffer 1)
      (progn
        ;; connect to irc server
        (erc-tls :server "irc.freenode.net" :port 6697 :nick erc-nick)
        (erc-tls :server "irc.debian.org" :port 6697 :nick erc-nick)
        (erc-tls :server "irc.mozilla.org" :port 6697 :nick erc-nick)))))

Keybindings

Global Keybinding

(bind-keys :map global-map
           ("C-x C-s" . my/save-buffer-always)
           ("M-g" . avy-goto-char-2))
(bind-keys :map global-map
           ("C-=" . hydra-font-setup/body))

Window Selection

(bind-keys :map global-map
           ("M-1" . select-window-1)
           ("M-2" . select-window-2)
           ("M-3" . select-window-3)
           ("M-4" . select-window-4)
           ("M-5" . select-window-5)
           ("M-6" . select-window-6)
           ("M-7" . select-window-7)
           ("M-8" . select-window-8)
           ("M-9" . select-window-9)
           ("M-0" . select-window-0))

Disable All mouse input to force me familier with keyboard

We should not use mouse when play with emacs.

(global-unset-key (kbd "<down-mouse-1>"))
(global-unset-key (kbd "<mouse-1>"))
(global-unset-key (kbd "<down-mouse-3>"))
(global-unset-key (kbd "<mouse-3>"))

Normal State

(evil-define-key 'normal coldnew-editor-map
    (kbd "C-x C-f") 'helm-find-files
    (kbd "C-x C-q") 'read-only-mode
    (kbd "C-x M-1") 'deft-or-close
    (kbd "C-x M-2") 'multi-eshell
    (kbd "C-x M-3") 'mu4e
    (kbd "C-x M-4") 'erc-start-or-switch
    (kbd "C-x vl") 'magit-log
    (kbd "C-x vp") 'magit-push
    (kbd "C-x vs") 'magit-status
    (kbd "C-x b") 'helm-buffers-list
    (kbd "M-[") 'winner-undo
    (kbd "M-]") 'winner-redo
    (kbd "M-x") 'helm-M-x
    (kbd "M-s") 'helm-occur
    (kbd "C-x C-o") 'other-frame
    (kbd "M-o") 'other-window)

Insert State

(evil-define-key 'insert coldnew-editor-map
  (kbd "<delete>") 'hungry-delete-backward
 ;; (kbd "TAB") 'yas/expand
  (kbd "C-;") 'iedit-mode
  (kbd "C-d") 'hungry-delete-forward
  (kbd "C-l") 'hungry-delete-backward
  (kbd "C-n") 'evil-next-line
  (kbd "M-z")   'zzz-to-char
  (kbd "C-o") 'evil-execute-in-normal-state
  (kbd "C-p") 'evil-previous-line
  (kbd "C-w") 'backward-kill-word
  (kbd "C-x C-f") 'helm-find-files
  (kbd "C-x C-n") 'company-complete
  (kbd "C-x C-q") 'read-only-mode
  (kbd "C-x M-1") 'deft-or-close
  (kbd "C-x M-2") 'multi-eshell
  (kbd "C-x M-3") 'mu4e
  (kbd "C-x M-4") 'erc-start-or-switch
  (kbd "C-x vl") 'magit-log
  (kbd "C-x vp") 'magit-push
  (kbd "C-x vs") 'magit-status
  (kbd "C-x b") 'helm-buffers-list
  (kbd "M-<SPC>") 'insert-U200B-char
  (kbd "M-[") 'winner-undo
  (kbd "M-]") 'winner-redo
  (kbd "M-s") 'helm-occur
  (kbd "s-<RET>") 'insert-empty-line
  (kbd "s-<SPC>") 'insert-U200B-char
  (kbd "C-v") 'set-mark-mode/rectangle-mark-mode
  (kbd "C-x C-i") 'indent-region-or-buffer-and-cleanup
  (kbd "M-v") 'er/expand-region
  (kbd "M-x") 'helm-M-x
  (kbd "M-y") 'helm-show-kill-ring
  ;; (kbd "M-o") 'other-window
  (kbd "C-x C-o") 'other-frame
  (kbd "C-x t") 'sane-term
  (kbd "C-x T") 'sane-term
  (kbd "M-y") 'helm-show-kill-ring
  )

Space State

For space state, I use evil-leader to achive this goal.

(evil-leader/set-leader "<SPC>")
(evil-leader/set-key
  "1" 'select-window-1
  "2" 'select-window-2
  "3" 'select-window-3
  "4" 'select-window-4
  "5" 'select-window-5
  "6" 'select-window-6
  "7" 'select-window-7
  "8" 'select-window-8
  "9" 'select-window-9
  "0" 'select-window-0)

Ex Command

(evil-ex-define-cmd "ag" 'helm-ag)
(evil-ex-define-cmd "agp[roject]" 'helm-projectile-ag)
(evil-ex-define-cmd "agi[nteractive]" 'helm-do-ag)
(evil-ex-define-cmd "google" 'helm-google)
(evil-ex-define-cmd "google-suggest" 'helm-google-suggest)
(evil-ex-define-cmd "gtag" 'ggtags-create-tags)
(evil-ex-define-cmd "howdoi" 'howdoi-query)

End of configuration

Oh YA!! We finish loading emacs configuration :)

However, since we use req-package for loading and installing packages, be sure to execute following line to send req-package on its merry way.

(req-package-finish)

In the end of configuration, I'll load my private config from ~/.personal.el, which contains something like password or account settings.

(let ((secret "~/.personal.el"))
  (when (file-exists-p secret) (load-file secret)))

Reference

Author: Yen-Chin, Lee <coldnew>

Created: 2016-02-05 Fri 09:37