Skip to content

Latest commit

 

History

History
3110 lines (2427 loc) · 97.7 KB

init-old.org

File metadata and controls

3110 lines (2427 loc) · 97.7 KB

coldnew’s emacs config

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

About

This is another emacs config of mine, which is a totally rewritten version based on top of spacemacs and coldnew-emacs with literate programming in org-mode, but it uses English to write this config instead.

Feel free to use it :).

Install or testing this config

  • First use git to download whole repo
    git clone https://github.com/coldnew/coldnew-spacemacs.git
        
  • Then use git submodule to download the spacemacs
    git submodule init
    git submodule update
        
  • Before trying to start emacs, you need to bootstrap it with Cask
    cask install
        
  • Then use the make command to generate an init.el file
    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-spacemacs/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 spacemacs config work much more nicely.

  • Mac OSX
    brew install the_silver_searcher \
         fasd \
         doxymacs \
         aspell --with-lang-en
    
    brew install mu --with-emacs --HEAD
        
  • Gentoo Linux
    USE="emacs" emerge sys-apps/the_silver_searcher \
       app-shells/fasd \
       net-mail/mu \
       app-emacs/doxymacs \
       aspell
        

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.

load prefer newer

;; 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)

Change the user-emacs-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
(setq user-emacs-directory
      (file-name-directory (or load-file-name (buffer-file-name))))

Define user-cache-directory variable

(defconst user-cache-directory
  (file-name-as-directory (concat user-emacs-directory ".cache"))
  "My emacs storage area for persistent files.")

Package Management with 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 "evil")
(depends-on "f")
(depends-on "s")
(depends-on "dash")
(depends-on "pallet")
(depends-on "req-package")

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

cask install

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)

Dependency Management with 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.

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.

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/" "theme/")))
  (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)))))

Spacemacs

Spacemacs is an emacs starterkit focus on Evil, which emulate vim keymap on Emacs.

I make my emacs on top of spacemacs since I also use vim keymap.

In my config file, the original ~/.spacemacs file has move to spacemacs.el under user-emacs-directory folder, I also advice spacemacs funtion to prevent orphan packages deleted by spacemacs.

After all spacemacs init done, switch back to *scratch* buffer.

Load basic spacemacs configuration file

(setenv "SPACEMACSDIR" (concat user-emacs-directory "spacemacs.d"))

Overwrite spacemacs function to let it not remove my packages

;; Make spacemacs not remove my orphan packages.
(defadvice configuration-layer/delete-orphan-packages (around null-func activate)
  "Overwrite the spacemacs's `configuration-layer/delete-orphan-packages'
  to make it not remove any orphan packages.")

(defadvice spacemacs/check-for-new-version (around null-func activate)
  "Overwrite the spacemacs's `spacemacs/check-for-new-version' to
  makt it useless since I use git submodule to bundle spacemacs with my emacs.")

Load spacemacs

The original spacemacs is suggest to clone it to ~/.emacs.d, I really not like this. Instead, I move it to ~/.emacs.d/spacemacs so I can use org-mode with literature writing, I also change ~/.spacemacs to ~/.emacs.d/spacemacs.el which make all of my config track by git.

;; Use `~/.emacs.d/spacemacs.el' instead of `~/.spacemacs'
(defconst dotspacemacs-filepath
  (concat user-emacs-directory "spacemacs.el"))

;; Make a fake entry point for spacemacs, also modify the
;; `user-emacs-directory' temporary to mislead spacemacs real emacs
;; directory.
(let* ((spacemacs-dir
        (directory-file-name (concat user-emacs-directory "spacemacs")))
       (spacemacs-init
        (concat (file-name-as-directory spacemacs-dir) "init.el"))
       (user-emacs-directory (file-name-directory spacemacs-init))
       ;; move `~/.spacemacs' to `~/.emacs.d/spacemacs.el'
       ;;(dotspacemacs-filepath (concat user-emacs-directory "spacemacs.el"))
       (dotspacemacs-filepath dotspacemacs-filepath))

  ;; Initial spacemacs, our emacs run on top of it
  (load spacemacs-init))

Some function should execute after loading spacemacs-init.

spacemacs is really awesome, but there’s something I don’t like.

;; Disable global highlight by default (which is set by spacemacs.)
(global-hl-line-mode -1)

;; After spacemacs loading finished, switch back to `*scratch*' buffer
;; and make sure it's in `lisp-interaction-mode'
(switch-to-buffer "*scratch*")
(with-current-buffer (get-buffer-create "*scratch*")
  (lisp-interaction-mode))

I really hate spacemacs default echo the helm input in header line, it’s really annoying.

(setq helm-echo-input-in-header-line nil)
(remove-hook 'helm-minibuffer-set-up-hook 'helm-hide-minibuffer-maybe)

Disable ido-mode if spacemacs enable it.

(ido-mode -1)

Basic setup

Most setup I want to use is done by spacemacs, but I still keep some basic setup here, some are not set or just keep for backward compability.

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.

We 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

(defadvice save-buffers-kill-emacs (around no-query-kill-emacs activate)
  "Prevent annoying \"Active processes exist\" query when you quit Emacs."
  (flet ((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))

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" )

Packages

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

4clojure

4clojure.el let you open and evaluate 4clojure questions.

(req-package 4clojure)

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
  :init
  (progn
    ;; ascii-toggle
    (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)

iedit

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

(req-package iedit)

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
  :init
  (progn
    ;; 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)))))

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)

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
  :init (global-hungry-delete-mode))

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)

doxymacs

(req-package doxymacs
  :config
  (add-hook 'prog-mode-hook '(lambda () (doxymacs-mode))))

deft

deft

(req-package deft
  :config
  (progn
    ;; default extension set to .org
    (setq deft-extension "org")

    ;; setup an minor-mode to quickly kill all deft buffers
    (define-minor-mode deft-note-mode "Deft notes" nil " Deft-Notes" nil)
    (setq deft-text-mode 'deft-note-mode)

    ;; My notes set to ~/Org
    (setq deft-directory "~/Org/")

    ;; Use filename as title
    (setq deft-use-filename-as-title t)

    ;; Do not make deft automatically save file
    (setq deft-auto-save-interval 0)

    ;; Quickly kill deft buffers
    (defun kill-all-deft-notes ()
      (interactive)
      (save-excursion
        (let ((count 0))
          (dolist (buffer (buffer-list))
            (set-buffer buffer)
            (when (not (eq nil deft-note-mode))
              (setq count (1+ count))
              (kill-buffer buffer))))))

    ;; Enable/Disable defts
    (defun deft-or-close ()
      (interactive)
      (if (or (eq major-mode 'deft-mode) (not (eq nil deft-note-mode)))
          (progn (kill-all-deft-notes) (kill-buffer "*Deft*"))
        (deft)))))

async

(req-package async
  :config
  (progn
    ;; 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" 'ignore "init.el"))))

    (add-hook 'after-save-hook 'tangle-init)
    ))

password-generator

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

(req-package password-generator)

skeletor

Skeletor provides project templates for Emacs. It also automates the mundane parts of setting up a new project like version control, licenses and tooling.

Skeletor comes with a number of predefined templates and allows you to easily create your own.

(req-package skeletor)

discover-my-major

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

(req-package discover-my-major)

google-translate

(req-package google-translate
  :config
  (progn
    ;; defaylt language for translation
    (setq google-translate-default-source-language "en")
    (setq google-translate-default-target-language "zh_TW")
    ))

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.

(req-package howdoi)

org-download

(req-package org-download)

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.

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

htmlize

(req-package htmlize)

manage-minor-mode

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

(req-package manage-minor-mode)

rpn-calc

rpn-calc is an quick RPN calculator for emacs.

(req-package rpn-calc)

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 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)))

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."))))))

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))

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)))))

Theme

I always use dark theme for coding, moe-theme is a good start point, it’s bright and has good default faces for most modes. It also has dark and light versions, which is convenient.

However, I always want to customize everything on my own, so I rebuild another emacs theme called coldnew-theme-night and coldnew-theme-day which are based on moe-theme, 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))

;; use coldnew-theme-night by default
(req-package coldnew-theme
  :require (powerline powerline-evil)
  :config (coldnew-theme-night))

Minibuffers

(req-package minibuffer
  :config
  (progn

    ;; Make cursor in minibufer use bar shape
    (add-hook 'minibuffer-setup-hook '(lambda () (setq cursor-type 'bar)))

    (define-key minibuffer-local-map (kbd "C-w") 'backward-kill-word)
    (define-key minibuffer-local-map (kbd "M-p") 'previous-history-element)
    (define-key minibuffer-local-map (kbd "M-n") 'next-history-element)
    (define-key minibuffer-local-map (kbd "C-g") 'minibuffer-keyboard-quit)

    (defun coldnew/minibuffer-switch-dir (path) (kill-line 0) (insert path))

    ;; switch to tmp dir
    (define-key minibuffer-local-map (kbd "M-t") '(lambda()
                                                    (interactive)
                                                    (let ((dir (if (eq system-type 'darwin)
                                                                   "/Volumes/ramdisk/" "/tmp/")))
                                                      (coldnew/minibuffer-switch-dir dir))))
    ;; switch to home dir
    (define-key minibuffer-local-map (kbd "M-h") '(lambda()
                                                    (interactive)
                                                    (coldnew/minibuffer-switch-dir (file-name-as-directory (getenv "HOME")))))

    ;; other with C-x prefix to prevent conflict with helm
    (define-key minibuffer-local-map (kbd "C-x r") '(lambda()
                                                    (interactive)
                                                    (coldnew/minibuffer-switch-dir "/")))

    (define-key minibuffer-local-map (kbd "C-x s") '(lambda()
                                                    (interactive)
                                                    (coldnew/minibuffer-switch-dir "/ssh:")))
    ))

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.

Setup tab width

(setq tab-width 8)
(setq indent-tabs-mode nil)

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
  (progn
    (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

(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))

Highlight numbers

highlight-numbers

(req-package highlight-numbers
  :init
  ;; 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

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

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

    ;; Add extra modes
    (add-to-list 'hes-simple-modes 'c-mode)
    (add-to-list 'hes-simple-modes 'c++-mode)

    ;; 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)

Highlight indentation

TODO: only dupport python

(req-package highlight-indentation)

Blocking syntax highlight

FIXME: buggy, can’t really use

(req-package rainbow-blocks
  :init (global-rainbow-blocks-mode t))

Takes care of trailing whitespaces (removal, highlighting)

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

(req-package ethan-wspace
  :config
  (progn
    ;; 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))))

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.

(req-package editorconfig)

Vim Emulation

(req-package evil
  :require (undo-tree)
  :ensure evil
  :init
  (progn
    ;; Default state set to `'insert-state'
    ;;(setq evil-default-state 'insert)
    (evil-mode t))
  :config
  (progn
    ;; 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' in insert-state will call `evil-normal-state'
    (define-key evil-insert-state-map [escape] 'evil-normal-state)

    ;; Make all emacs-state buffer become to insert-state
    (dolist (m evil-emacs-state-modes)
      (add-to-list 'evil-insert-state-modes m))
    ))
(req-package evil-terminal-cursor-changer)
(req-package vim-empty-lines-mode
  :config (progn
            (add-hook 'diff-mode-hook (lambda () (vim-empty-lines-mode -1)))))

En/Decrypt files by EasyPG

(req-package epa-file
  :init (epa-file-enable)
  :config
  (progn
    ;; 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)))

Remote file editing

(req-package tramp
  :config
  (progn
    (setq tramp-default-method "scp")))

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)))))

Project management with projectile

(req-package projectile
  :interpreter ("projectile" . projectil-mode))

Completion with Company mode

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.

(req-package company
  :init (global-company-mode 1)
  :config (setq company-idle-delay nil))

Completion C/C++ headers

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

Add quickhelp in company-mode

(req-package company-quickhelp
  :require company
  :init (company-quickhelp-mode 1))

Key Bindings

KeyCommanddescription
C-gcompany-abortabort company completion
C-ncompany-select-nextselect next completion
C-pcompany-select-previousselect previous completion
TABcompany-complete-selectionUse TAB to select current completion
<tab>company-complete-selectionUse TAB to select current completion
(add-hook 'company-mode-hook '(lambda()
          <<define-keys(map="company-active-map", keys=company-active-keys)>> ))

Completion with Bit Bang

bbyac is another emacs completion framework, which will let you type a little bit, and bang! You can complete it into a much longer string.

Say you have a very-very-long-emacs-lisp-variable-name, you need only type vvn and press a shortcut key (M-s <return>), it will be completed into that long name. Or you can type vln if you like that better.

You can type the bit that you like better, or is easier to remember, or is easier to type.

(req-package bbyac
  :init (bbyac-global-mode 1)
  :config
  (eval-after-load 'yasnippet
    '(progn
 ;;      (defadvice yas-expand (around bbyac activate) (bbyac-expand-symbols) ad-do-it)
       )))

Snippet handle by yasnippet

(req-package yasnippet
  :init (yas-global-mode 1)
  :mode ("emacs.+/snippets/" . snippet-mode)
  :config
  (progn
    (setq yas/prompt-functions '(yas-dropdown-prompt
                                 yas-completing-prompt
                                 yas-ido-prompt))

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

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.

(eval-after-load 'yasnippet
  '(progn
     (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")))

Helm

(req-package helm
  :require helm-config
  :init (helm-mode 1)
  :config
  (progn
    ;; Use fuzzy match in helm
    (setq  helm-M-x-fuzzy-match t
           helm-buffers-fuzzy-matching t
           helm-recentf-fuzzy-match    t
           ;; make helm can select anything even not match
           helm-move-to-line-cycle-in-source nil
           helm-ff-search-library-in-sexp t
           helm-ff-file-name-history-use-recentf t)

    (bind-key "TAB" 'helm-execute-persistent-action helm-map)
    (bind-key "<tab>" 'helm-execute-persistent-action helm-map)
    ))

TODO: take from https://github.com/edvorg/emacs-configs/blob/master/init.d/init-helm.el

;; helm proc

;;(req-package helm-proc
;;  :require helm)

;; helm company

(req-package helm-company
  :require company
  :commands helm-company
  :config (progn (define-key company-mode-map (kbd "C-:") 'helm-company)
                 (define-key company-active-map (kbd "C-:") 'helm-company)))

;; helm helm commands

(req-package helm-helm-commands
  :require helm)

;; helm swoop

(req-package helm-swoop
  :require
  helm
  :config
  (define-key isearch-mode-map (kbd "M-i") 'helm-swoop-from-isearch))

;; helm desc binds

(req-package helm-descbinds :require helm)

;; helm open github

(req-package helm-open-github
  :require helm
  :commands (helm-open-github-from-commit
             helm-open-github-from-file
             helm-open-github-from-issues
             helm-open-github-from-pull-requests)
  :bind (("C-c o f" . helm-open-github-from-file)
         ("C-c o c" . helm-open-github-from-commit)
         ("C-c o i" . helm-open-github-from-issues)
         ("C-c o p" . helm-open-github-from-pull-requests)))

;; helm package

(req-package helm-package
  :require
  helm)

;; helm flymake

(req-package helm-flymake
  :require
  (helm flymake))

;; helm make

(req-package helm-make
  :require
  (helm makefile-runner)
  :config
  (global-set-key (kbd "s-B")
                  (lambda () (interactive) (helm-make (makefile-runner--find-makefile)))))

;; helm wgrep

(req-package wgrep-helm
  :require
  (helm wgrep grep))

;; helm github stars

Browse GitHub starred repositories in Emacs

helm-github-stars provides capabilities to fetch your starred repositories from github and select one for browsing.

(req-package helm-github-stars
  :require helm
  :config
  (progn
    ;; setup user
    (setq helm-github-stars-username (getenv "USER"))
    ;; setup cache path
    (setq helm-github-stars-cache-file (concat spacemacs-cache-directory "helm-github-stars.cache"))))

helm-backup

helm-backup aims to create a backup system for emacs using both power of git to store changes and power of helm to fetch backups easily.

  (req-package helm-backup
    :require (helm)
    :config (progn (setq helm-backup-path (concat spacemacs-cache-directory "helm-backup"))
    (add-hook 'after-save-hook 'helm-backup-versioning)
))

Add silver searcher support

(req-package helm-ag
  :require (helm helm-projectile)
  :config
  (progn

    (defun helm-projectile-ag ()
      (interactive)
      (helm-ag (projectile-project-root)))
    ))

Add Google search support

https://github.com/steckerhalter/helm-google

(req-package helm-google
  :require (helm)
  :init (setq helm-google-use-regexp-parsing t))

Key Bindings

KeyCommanddescription
C-wbackward-delete-word
<delete>hungry-delete-backwardbackward delete with hungru-mode
C-c fhelm-ff-file-name-historySearch recent files
(add-hook 'helm-mode-hook '(lambda()
          <<define-keys(map="helm-map", keys=helm-keys)>> ))

TAGS

Add GTAGS support

ggtags is an Emacs frontend to GNU Global source code tagging system.

(req-package ggtags
  :init
  (add-hook 'c-mode-common-hook
            (lambda ()
              (when (derived-mode-p 'c-mode 'c++-mode 'java-mode)
                (ggtags-mode 1)))))

Cedet

(req-package cedet
  :config
  (progn
    (setq ede-project-placeholder-cache-file (concat user-cache-directory "ede-projects.el"))
    (setq semanticdb-default-save-directory (concat user-cache-directory "semanticdb"))
    (setq srecode-map-save-file (concat user-cache-directory "srecode-map.el"))
    ))

GDB

(req-package gdb-mi
  :require cc-mode
  :config
  (progn (setq gdb-many-windows t)
         (setq gdb-show-main t)))

Terminal Emulator

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
  :init
  ;; move eshell cache dir to ~/.emacs.d/.cache
  (setq eshell-directory-name (concat user-cache-directory "eshell")))

Use bash like prompt with color

(eval-after-load 'eshell
  '(progn
     ;; 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

(eval-after-load 'eshell
  '(progn
    (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
  (progn
    (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.

(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 emac start

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

winner-mode

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

Org

(req-package org
  :require (org-crypt org-mac-link org-magit)
  :mode (("\\.org\\'" . org-mode)
         ("\\.org_archive\\'" . org-mode))
:config
(progn
  ;; Always enable auto indent mode
  (setq org-indent-mode t)
  ;; 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)
  ))

Capture and Agenda

(eval-after-load 'org
  '(progn
     ;; 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)))
     ))

Extend org-mode’s easy templates

(eval-after-load 'org
  '(progn
    (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

  (eval-after-load 'org
    '(progn
       (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)
          ))
       (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")
        ))

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"))
     ))

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" "$" "$$" "\\(" "\\[")))

Key Bindings

KeyCommanddescription
C-c borg-metaleft
C-c forg-metaright
C-c porg-metaup
C-c norg-metadown
C-c iorg-insert-link
C-c Iorg-toggle-inline-imagesToggle display inline image
(add-hook 'org-mode-hook '(lambda()
          <<define-keys(map="org-mode-map", keys=org-mode-keys)>> ))

Programming Languages

Android

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

Assembly

(req-package nasm-mode
    :mode (("\\.asm$" . nasm-mode)
           ("\\.nasm$" . nasm-mode)))

Bash

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

Batch

(req-package batch-mode :mode "\\.bat\\'")

Emacs Lisp

(req-package lisp-mode
  :init
  (progn
    (add-to-list 'auto-mode-alist '("\\.el$" . emacs-lisp-mode))
    (add-to-list 'auto-mode-alist '("Cask" . emacs-lisp-mode))
    ))
(req-package eldoc
  :init
  (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.

(req-package litable :init (litable-mode))

Highlight defined symbols

(req-package hl-defined
  :config
  (add-hook 'emacs-lisp-mode-hook 'hdefd-highlight-mode)
  (add-hook 'lisp-interaction-mode-hook 'hdefd-highlight-mode))

Highlight functions or macros belone to cl.el

(req-package highlight-cl
  :init
  (add-hook 'emacs-lisp-mode-hook
            '(lambda ()
               (highlight-cl-add-font-lock-keywords))))

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)

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))
  :init (add-hook 'ssh-config-mode-hook 'turn-on-font-lock))

CMake

(req-package cmake-font-lock
  :require (cmake-mode)
  :init (add-hook 'cmake-mode-hook 'cmake-font-lock-activate))

Rust

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

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

Go

(req-package go-mode
  :mode "\\.go$"
  :config
  (progn
    ;; Use gofmt to format code before save
    (add-hook 'before-save-hook 'gofmt-before-save)))

C/C++

(req-package cc-mode
  :mode
  (("\\.h\\'" . c-mode)
   ("\\.c\\'" . c-mode)
   ("\\.hpp\\'" . c++-mode)
   ("\\.cpp\\'" . c++-mode))
  :config
  (progn
    ;; use regexp to check if it's C++ header
    (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))
    ))
(req-package clang-format
  :commands clang-format-region)

Guess indent setup automatically

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

(req-package dtrt-indent
  :config
  (add-hook 'c-mode-common-hook
            (lambda()
              (dtrt-indent-mode t))))

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
  :init (add-hook 'c-mode-common-hook '(lambda () (cwarn-mode 1))))

Add eldoc support for C/C++

(req-package c-eldoc
  :config
  (progn
    (add-hook 'c-mode-common-hook
              '(lambda ()
                 (setq c-eldoc-includes "`pkg-config gtk+-3.0 --cflags --libs` -I./ -I../")
                 (c-turn-on-eldoc-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.

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

Syntax check and code-completion with CMake project

cpputils-cmake is a nice tool for cmake project.

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

C language 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)))

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)

C++ language coding style

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)
             ))

Extra highlight keywords for C/C++

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))))

Key Bindings

KeyCommanddescription
C-c C-off-find-other-fileFind header/source in C/C++ file
(add-hook 'c-mode-hook '(lambda()
          <<define-keys(map="c-mode-map", keys=c-c++-mode-keys)>> ))
(add-hook 'c++-mode-hook '(lambda()
          <<define-keys(map="c++-mode-map", keys=c-c++-mode-keys)>> ))

Graphviz

(req-package graphviz-dot-mode
  :init (defalias 'dot-mode 'graphviz-dot-mode))

Clojure

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

Add refactor function support

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

(req-package clj-refactor
  :config
  (progn
    ;; 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 "C-c C-x")))

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)
  :config
  (progn

    ;; Enable eldoc in Clojure buffers
    (eval-after-load 'eldoc
      '(progn
         (add-hook 'cider-mode-hook #'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)

    ;; Toggle between test and implementation, instead of showing test report buffer.
    ;;(define-key cider-mode-map (kbd "C-c C-t") 'projectile-toggle-between-implementation-and-test)

    ;; (defun piggiepack-repl ()
    ;;   (interactive)
    ;;   ;; (cider-jack-in)
    ;;   (cider-interactive-eval
    ;;    "(require 'cljs.repl.browser)
    ;;     (cemerick.piggieback/cljs-repl :repl-env (cljs.repl.browser/repl-env :port 9000))"))

    ;; (defun node-repl ()
    ;;   (interactive)
    ;;   (cider-interactive-eval
    ;;    "(require '[cljs.repl.node :as node])
    ;;     (node/run-node-nrepl)"))

    ))

Insert libraries in project more easily

latest-clojure-libraries helps to looks up the latest version of clojure libraries on clojars/maven and automatically populates the buffer with the appropriate dependency vector. Optionally uses pomegranate to load the dependency directly into your running nrepl.

To use this plugin, you need to edit your ~/.lein/profiles.clj :plugins vector to include [lein-ancient "0.5.1"] and optionally add [com.cemerick/pomegranate "0.2.0"] to your :dependencies vector if you want the feature which automatically adds the library to your classpath without restarting the repl.

After all step done, use M-x latest-clojure-libraries-insert-dependency to insert latest clojure libraries to your project.

(req-package latest-clojure-libraries)

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
  :init (setq js2-highlight-level 3)
  :mode "\\.js$")

Json

(req-package json-reformat :commands json-reformat-region)

(req-package flymake-json :require flymake)

(req-package json-mode
  :require flymake-json
  :mode ("\\.json$" . json-mode)
  :init (add-hook 'json-mode-hook (lambda () (flymake-json-load))))

Python

(req-package jinja2-mode)

Java

(req-package malabar-mode
  :mode "\\.java$")

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

Markdown

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

Ruby

(req-package ruby-mode
  :mode (("Rakefile\\'" . ruby-mode)
         ("\\.rake$" . ruby-mode)
         ("\\.gemspec$" . ruby-mode)
         ("\\.rb$'" . ruby-mode)
         ("\\.ru$" . ruby-mode)
         ("Gemfile$" . ruby-mode)
         ("Guardfile$" . ruby-mode))
  :config
  (progn
    ;; We never want to edit Rubinius bytecode
    (add-to-list 'completion-ignored-extensions ".rbc")
    ))

(req-package rake)

QML

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

XML

(req-package nxml-mode
  :mode (("\\.pom$" . nxml-mode))
  :config
  (progn
    ;; 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)
    ))

SCSS

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

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$")

YAML

(req-package yaml-mode
  :mode "\\.yml$")

Device Tree

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

scala

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

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

newlisp

(req-package newlisp :mode "\\.lsp$")

Vala

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

BitBake

(req-package bitbake
  :mode "\\.bbclass$"
  :config
  (progn
    ;; For .inc file if locate under meta-*/ dir, make it use bitbake-mode
    (add-to-list 'magic-mode-alist
                 `(,(lambda ()
                      (and (string= (file-name-extension (or (buffer-file-name) "")) "inc")
                           (string-match "meta-" (buffer-file-name))))
                      . bitbake-mode))
    ))

diff

 (eval-after-load 'vim-empty-lines-mode
   '(progn
           (add-hook 'diff-mode-hook (lambda () (vim-empty-lines-mode -1)))
           (add-hook 'diff-mode-hook (lambda () (whitespace-mode -1)))
      ))

(remove-hook 'diff-mode-hook 'whitespace-mode t)

ebnf

(req-package ebnf-mode
  :mode (("\\.bnf$" . bnf-mode)
         ("\\.ebnf$" . ebnf-mode)))

Web Development

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

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.

(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)))

Version Control

Git

Add suport for git configuration files

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

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

Use git-wip to view your WIP commit

https://github.com/itsjeyd/git-wip-timemachine

(req-package git-wip-timemachine)

Key Bindings

KeyCommanddescription
C-gmagit-mode-quit-windowExit magit mode window
(add-hook 'magit-mode-hook '(lambda()
          <<define-keys(map="magit-mode-map", keys=magit-mode-keys)>> ))

Email

I use mu4e.

install in osx

brew install mu --with-emacs --HEAD

install in gentoo

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

(req-package mu4e
  :require w3m
  :config
  (progn
    ;; 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)
    ;; Use 'w3m' to read html email
    (setq mu4e-html2text-command "w3m -dump -T text/html")
    ;; Show mail's image
    (setq mu4e-view-show-images t)
    ;; 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 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 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")

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 "[email protected]")
         (smtpmail-smtp-server "smtp.gmail.com")
         (smtpmail-smtp-service 587)
         (smtpmail-smtp-user "[email protected]")
         (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)

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")
        (".*\\.oftc.net" "#dot")))

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)))))

Keybinding

Create my minor-mode to control 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)

Generate keymap from org-mode table

org-mode is really nice for literature programmering, I can use it to generate keybing via table, just use following functions:

(require 's)
(mapcar (lambda (l)
          (let* ((key (nth 0 l))
                 (command (nth 1 l)))
            ;; make sure key and command not nil
            (if (not (or (s-blank? key) (s-blank? command)))
                (princ (format "(%s %s %s %s '%s)\n"
                               fn
                               (if (string= state "") "" (concat "'" state))
                               map
                               (if (s-equals? fn "evil-ex-define-cmd")
                                   (format "\"%s\"" key)
                                 (format "(kbd \"%s\")" key))
                               command)))))
        ;; remove all `hline' tag
        (remove 'hline keys))

Spacemacs Map

spacemacs reserve the SPC-o for user setup theirs own keymap, I think I should add something here :(

Normal State

KeyCommanddescription
C-x C-fhelm-find-filesfind-file by helm
C-x C-qread-only-modetoggle read-only-mode
C-x C-ssave-buffer-alwaysAlways save buffer even not modified
C-x M-1deft-or-closeUse deft open my note
C-x M-2multi-eshellShow eshell window
C-x M-3mu4eUse mu4e to read mail
C-x M-4erc-start-or-switchSwitch to erc budder
C-x vlmagit-log
C-x vpmagit-push
C-x vsmagit-status
C-x bhelm-buffers-listSiwtch to another buffer by helm
M-[winner-undoswitch back to earlier window layout
M-]winner-redorestore resent window layout
M-xhelm-M-xUse heml for interactive commands (M-x)
M-shelm-occurSearch in current buffer
C-x C-oother-frameSwitch to other frame
M-oother-windowSwitch to other window
C–text-scale-decreaseDecrease text scale
C-=text-scale-increaseIncrease text scale
<<define-keys(fn="evil-define-key", state="normal", map="coldnew-editor-map", keys=global-evil-normal)>>

Insert State

KeyCommanddescription
<delete>hungry-delete-backwardbackward delete with hungry-mode
C-;iedit-modeQuicklly modify all same words
C-dhungry-delete-forwardforward delete with hungry-mode
C-lhungry-delete-backwardbackward delete with hungru-mode
C-nevil-next-linenext-line
C-oevil-execute-in-normal-stateTemporary switch to Normal sate
C-pevil-previous-lineprevious-line
C-wbackward-kill-wordBackward delete word
C-x C-fhelm-find-filesfind-file by helm
C-x C-ncompany-completeComplete with company-mode
C-x C-qread-only-modetoggle read-only-mode
C-x C-ssave-buffer-alwaysAlways save buffer even not modified
C-x M-1deft-or-closeUse deft open my note
C-x M-2multi-eshellShow eshell window
C-x M-3mu4eUse mu4e to read mail
C-x M-4erc-start-or-switchSwitch to erc budder
C-x vlmagit-log
C-x vpmagit-push
C-x vsmagit-status
C-x bhelm-buffers-listSiwtch to another buffer by helm
M-<SPC>insert-U200B-charInsert <U200B> character
M-[winner-undoswitch back to earlier window layout
M-]winner-redorestore resent window layout
M-shelm-occurSearch in current buffer
s-<RET>insert-empty-lineInsert empty line after current line
s-<SPC>insert-U200B-charInsert <U200B> character
C-vset-mark-mode/rectangle-mark-mode
C-x C-iindent-region-or-buffer-and-cleanupIntent region/buffer and clean up
M-ver/expand-region
M-xhelm-M-xUse heml for interactive commands (M-x)
M-yhelm-show-kill-ringShow kill-ring by helm
M-oother-windowSwitch to other window
C-x C-oother-frameSwitch to other frame
C–text-scale-decreaseDecrease text scale
C-=text-scale-increaseIncrease text scale
<<define-keys(fn="evil-define-key", state="insert", map="coldnew-editor-map", keys=global-evil-insert)>>

Ex Command

KeyCommanddescription
aghelm-agSearch with silver searcher
agp[roject]helm-projectile-agSearch project with silver searcher
agi[nteractive]helm-do-agInteractive execute ag command
googlehelm-googleSearch with google
google-suggesthelm-google-suggestSearch with google-suggest
gtagggtags-create-tagsCreate gtags
howdoihowdoi-queryShow coding answers in another buffer
<<define-keys(fn="evil-ex-define-cmd", keys=global-evil-ex)>>

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

Following link is refrence for my emac config.

[1] https://github.com/r0man/.emacs.d/blob/master/init.el.org

[2] https://github.com/bodil/emacs.d

[3] https://github.com/mgalgs/.emacs.d