日常工作使用Emacs

Table of Contents

Gernal packages configurations

当前分类下,列出支持的包的配置信息。

Auto complete using company-mode

自动完成功能的配置,可以基于它针对不同的语言进行配置自动提示功能;

;; Turn on auto complete.
;; (require 'auto-complete-config)
;;(ac-config-default)
(use-package company
:defer t
:config (add-hook 'prog-mode-hook 'company-mode))

Manage the dash package

此包用于在macbook上调用dash应用的功能,其它操作系统可以不用;

(use-package dash
:defer t)

Config the backups

配置自动备份;

;;(setq backup-directory-alist '(("." . "~/.emacs.d/backups")))
(setq backup-directory-alist '(("." . (expand-file-name "backups" user-emacs-directory))))

Save files

Emacs中的自动保存功能,单独存储在另一个文件夹中。

(setq delete-old-versions -1)
(setq version-control t)
(setq vc-make-backup-files t)
(setq auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-save-list/" t)))
;;(setq auto-save-file-name-transforms '((".*" (expand-file-name "auto-save-list" user-emacs-directory) t)))

Save history

保存历史记录 From http://www.wisdomandwonder.com/wordpress/wp-content/uploads/2014/03/C3F.html

;;(setq savehist-file "~/.emacs.d/savehist")
(setq savehist-file (expand-file-name "savehist" user-emacs-directory))
(savehist-mode 1)
(setq history-length t)
(setq history-delete-duplicates t)
(setq savehist-save-minibuffer-history 1)
(setq savehist-additional-variables
'(kill-ring
search-ring
regexp-search-ring))

Macros

Key bindings configuration for Macros

Key bindings for Macros

Table 1:

Org-mode快捷键

C-x (

开始录制宏

C-x )

结束录制宏

C-x e

使用宏

C-u

重复使用宏,C-u 100 C-x e重复100次

M-x name-last-kbd-macro

保存宏,可以在其它地方通过M-x调用此保存好的宏

Tramp

Configuration

;; setting for tramp
(setq tramp-default-method "ssh")
;; config for caching password for 36000s
(setq password-cache-expiry 36000)

DONE Winner mode - undo and redo window configuration

  • State "DONE" from "" [2016-05-29 Sun 07:02]</span>

winner-mode lets you use C-c <left> and C-c <right> to switch between window configurations. This is handy when something has popped up a buffer that you want to look at briefly before returning to whatever you were working on. When you're done, press C-c <left>.

(use-package winner
:defer t)

DONE Mode line format

  • State "DONE" from "" [2016-05-29 Sun 07:02]</span>

Display a more compact mode line

(use-package smart-mode-line
:defer t)

DONE Undo tree

  • State "DONE" from "" [2016-05-29 Sun 07:02]</span>

Allow us to visually walk through the changes you've made, undo back to a certain point (or redo), and go down different branches. Shot key binding: (C-x u)

(use-package undo-tree
:defer t
:diminish undo-tree-mode
:config
(progn
(global-undo-tree-mode)
(setq undo-tree-visualizer-timestamps t)
(setq undo-tree-visualizer-diff t)))

DONE Help - guide key

  • State "DONE" from "" [2016-05-29 Sun 07:02]</span>

This library is very helpful, we can use it to help us remember or find the shot key binding. It will pops up a mini-buffer to show us the shot-key when we typed first part with a shot delay. (guide-key) 包可以帮助我们查看操作的快捷键,对于一些不太常用的快捷键想不起来的时候,可以输入快捷键的前缀后,暂停一下,Emacs即会弹出一个子窗口,列出当前前缀下可以选择的快捷键,及其函数名称。以方便我们进行查找。

(use-package guide-key
:defer t
:diminish guide-key-mode
:config
(progn
(setq guide-key/guide-key-sequence '("C-x r" "C-x 4" "C-c"))
(guide-key-mode 1))) ; Enable guide-key-mode

DONE Encoding configruation

  • State "DONE" from "" [2016-05-29 Sun 07:03]</span>

This configuration from: http://www.wisdomandwonder.com/wordpress/wp-content/uploads/2014/03/C3F.html

(prefer-coding-system 'utf-8)
(when (display-graphic-p)
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)))

DONE Helm

  • State "DONE" from "" [2016-05-29 Sun 07:03]</span>

Configuration

(use-package helm
:defer t
:diminish helm-mode
:init
(progn
(require 'helm-config)
(setq helm-candidate-number-limit 100)
;; From https://gist.github.com/antifuchs/9238468
(setq helm-idle-delay 0.0 ; update fast sources immediately (doesn't).
helm-input-idle-delay 0.01 ; this actually updates things
; reeeelatively quickly.
helm-yas-display-key-on-candidate t
helm-quick-update t
helm-buffers-fuzzy-matching t
helm-recentf-fuzzy-match t
helm-buffers-fuzzy-matching t
helm-M-x-fuzzy-match t
helm-mode-fuzzy-match t
helm-completion-in-region-fuzzy-match t
helm-recentf-fuzzy-match t
helm-semantic-fuzzy-match t
helm-imenu-fuzzy-match t
helm-apropos-fuzzy-match t
helm-lisp-fuzzy-completion t
helm-M-x-requires-pattern nil
helm-autoresize-mode 1 ;; resize the window
helm-autoresize-max-height 40 ;; make the max height as 40% percent of current frame height
helm-ff-skip-boring-files t)
(helm-mode))
:bind (("C-c h" . helm-mini)
("C-x c a" . helm-apropos)
("C-x C-b" . helm-buffers-list)
("C-x b" . helm-buffers-list)
("M-y" . helm-show-kill-ring) ("M-x" . helm-M-x)
("C-x c o" . helm-occur)
("C-x c s" . helm-swoop)
("C-x c y" . helm-yas-complete)
("C-x c Y" . helm-yas-create-snippet-on-region)
("C-x c b" . helm-do-grep-book-notes)
("C-x c i" . helm-org-in-buffer-headings)
("C-x c SPC" . helm-all-mark-rings)))
;(ido-mode -1) ;; Turn off ido mode in case I enabled it accidentally
(use-package helm-descbinds
:defer t
:bind (("C-x c b" . helm-descbinds)
("C-x c w" . helm-descbinds)))
;; Use helm to browse my notes files
(defvar book-notes-directory "~/workspace/github/work-notes")
(defun helm-do-grep-book-notes ()
"Search my book notes."
(interactive)
(helm-do-grep-1 (list book-notes-directory)))

DONE Helm-swoop

  • State "DONE" from "" [2016-05-29 Sun 07:03]</span>

    ;; setting for helm-swoop

    ;; https://github.com/ShingoFukuyama/helm-swoop (use-package helm-swoop :defer t :bind (("C-S-s" . helm-swoop) ("M-i" . helm-swoop) ("M-s s" . helm-swoop) ("M-s M-s" . helm-swoop) ("M-I" . helm-swoop-back-to-last-point) ("C-c M-i" . helm-multi-swoop) ("C-x M-i" . helm-multi-swoop-all) ) :config (progn ;; When doing isearch, hand the word over to helm-swoop (define-key isearch-mode-map (kbd "M-i") 'helm-swoop-from-isearch) ;; From helm-swoop to helm-multi-swoop-all (define-key helm-swoop-map (kbd "M-i") 'helm-multi-swoop-all-from-helm-swoop) ;; Move up and down like isearch (define-key helm-swoop-map (kbd "C-r") 'helm-previous-line) (define-key helm-swoop-map (kbd "C-s") 'helm-next-line) (define-key helm-multi-swoop-map (kbd "C-r") 'helm-previous-line) (define-key helm-multi-swoop-map (kbd "C-s") 'helm-next-line)

    ) )

    ;; Save buffer when helm-multi-swoop-edit complete (setq helm-multi-swoop-edit-save t)

    ;; If this value is t, split window inside the current window (setq helm-swoop-split-with-multiple-windows nil)

    ;; Split direcion. 'split-window-vertically or 'split-window-horizontally (setq helm-swoop-split-direction 'split-window-vertically)

    ;; If nil, you can slightly boost invoke speed in exchange for text color (setq helm-swoop-speed-or-color nil)

    ;; ;; Go to the opposite side of line from the end or beginning of line (setq helm-swoop-move-to-line-cycle t)

    ;; Optional face for line numbers ;; Face name is helm-swoop-line-number-face (setq helm-swoop-use-line-number-face t)

DONE Snippets

  • State "DONE" from "" [2016-05-29 Sun 07:04]</span>

Snippets工具可以让我们使用定义好的代码片断,或者文本块,从而可以通过快捷键的方式快速录入。从而提高录入速度。

(use-package yasnippet
:defer t
:diminish yas-minor-mode
:init (yas-global-mode)
:config
(progn
(yas-global-mode)
(add-hook 'hippie-expand-try-functions-list 'yas-hippie-try-expand)
(setq yas-key-syntaxes '("w_" "w_." "^ "))
;;(setq yas-installed-snippets-dir "~/emacs.d-new/yasnippet-snippets")
(setq yas-installed-snippets-dir (expand-file-name "yasnippet-snippets" user-emacs-directory))
(setq yas-expand-only-for-last-commands nil)
(yas-global-mode 1)
(bind-key "\t" 'hippie-expand yas-minor-mode-map)
(add-to-list 'yas-prompt-functions 'shk-yas/helm-prompt)))
(defun shk-yas/helm-prompt (prompt choices &optional display-fn)
"Use helm to select a snippet. Put this into `yas/prompt-functions.'"
(interactive)
(setq display-fn (or display-fn 'identity))
(if (require 'helm-config)
(let (tmpsource cands result rmap)
(setq cands (mapcar (lambda (x) (funcall display-fn x)) choices))
(setq rmap (mapcar (lambda (x) (cons (funcall display-fn x) x)) choices))
(setq tmpsource
(list
(cons 'name prompt)
(cons 'candidates cands)
'(action . (("Expand" . (lambda (selection) selection))))
))
(setq result (helm-other-buffer '(tmpsource) "*helm-select-yasnippet"))
(if (null result)
(signal 'quit "user quit!")
(cdr (assoc result rmap))))
nil))
(setq default-cursor-color "gray")
(setq yasnippet-can-fire-cursor-color "purple")
;; It will test whether it can expand, if yes, cursor color -> green.
(defun yasnippet-can-fire-p (&optional field)
(interactive)
(setq yas--condition-cache-timestamp (current-time))
(let (templates-and-pos)
(unless (and yas-expand-only-for-last-commands
(not (member last-command yas-expand-only-for-last-commands)))
(setq templates-and-pos (if field
(save-restriction
(narrow-to-region (yas--field-start field)
(yas--field-end field))
(yas--templates-for-key-at-point))
(yas--templates-for-key-at-point))))
(and templates-and-pos (first templates-and-pos))))
(defun my/change-cursor-color-when-can-expand (&optional field)
(interactive)
(when (eq last-command 'self-insert-command)
(set-cursor-color (if (my/can-expand)
yasnippet-can-fire-cursor-color
default-cursor-color))))
(defun my/can-expand ()
"Return true if right after an expandable thing."
(or (abbrev--before-point) (yasnippet-can-fire-p)))
; As pointed out by Dmitri, this will make sure it will update color when needed.
(remove-hook 'post-command-hook 'my/change-cursor-color-when-can-expand)
(defun my/insert-space-or-expand ()
"For binding to the SPC SPC keychord."
(interactive)
(condition-case nil (or (my/hippie-expand-maybe nil) (insert " "))))
(defun my/hippie-expand-maybe (arg)
"Try to expand text before point, using multiple methods.
The expansion functions in `hippie-expand-try-functions-list' are
tried in order, until a possible expansion is found. Repeated
application of `hippie-expand' inserts successively possible
expansions.
With a positive numeric argument, jumps directly to the ARG next
function in this list. With a negative argument or just \\[universal-argument],
undoes the expansion."
(interactive "P")
(require 'hippie-exp)
(if (or (not arg)
(and (integerp arg) (> arg 0)))
(let ((first (or (= he-num -1)
(not (equal this-command last-command)))))
(if first
(progn
(setq he-num -1)
(setq he-tried-table nil)))
(if arg
(if (not first) (he-reset-string))
(setq arg 0))
(let ((i (max (+ he-num arg) 0)))
(while (not (or (>= i (length hippie-expand-try-functions-list))
(apply (nth i hippie-expand-try-functions-list)
(list (= he-num i)))))
(setq i (1+ i)))
(setq he-num i))
(if (>= he-num (length hippie-expand-try-functions-list))
(progn (setq he-num -1) nil)
(if (and hippie-expand-verbose
(not (window-minibuffer-p)))
(message "Using %s"
(nth he-num hippie-expand-try-functions-list)))))
(if (and (>= he-num 0)
(eq (marker-buffer he-string-beg) (current-buffer)))
(progn
(setq he-num -1)
(he-reset-string)
(if (and hippie-expand-verbose
(not (window-minibuffer-p)))
(message "Undoing expansions"))))))

DONE Edit-list

  • State "DONE" from "" [2016-05-29 Sun 07:04]</span>

M-x edit-list makes it easier to edit an Emacs Lisp list. \#+ombegin_src emacs-lisp :tangle yes (use-package edit-list

:defer t

:commands edit-list)

\#+end_src

DONE Zap to isearch

  • State "DONE" from "" [2016-05-29 Sun 07:04]</span>

From Steve Purcell, who linked to http://www.emacswiki.org/emacs/ZapToISearch

(defun zap-to-isearch (rbeg rend)
"Kill the region between the mark and the closest portion of
the isearch match string. The behaviour is meant to be analogous
to zap-to-char; let's call it zap-to-isearch. The deleted region
does not include the isearch word. This is meant to be bound only
in isearch mode. The point of this function is that oftentimes
you want to delete some portion of text, one end of which happens
to be an active isearch word. The observation to make is that if
you use isearch a lot to move the cursor around (as you should,
it is much more efficient than using the arrows), it happens a
lot that you could just delete the active region between the mark
and the point, not include the isearch word."
(interactive "r")
(when (not mark-active)
(error "Mark is not active"))
(let* ((isearch-bounds (list isearch-other-end (point)))
(ismin (apply 'min isearch-bounds))
(ismax (apply 'max isearch-bounds))
)
(if (< (mark) ismin)
(kill-region (mark) ismin)
(if (> (mark) ismax)
(kill-region ismax (mark))
(error "Internal error in isearch kill function.")))
(isearch-exit)
))
(define-key isearch-mode-map [(meta z)] 'zap-to-isearch)

WAITING Smartparens :WAITING:

  • State "WAITING" from "" [2016-05-30 Mon 20:36]</span>

Configuration

(use-package smartparens
:config
(require 'smartparens-config)
(setq sp-autoescape-string-quote nil)
(--each '(css-mode-hook
restclient-mode-hook
js-mode-hook
java-mode
ruby-mode
markdown-mode
groovy-mode)
(add-hook it 'turn-on-smartparens-mode))
)

Expand-region

Configuration

(use-package expand-region
:config
;; Don't use expand-region fast keys
(setq expand-region-fast-keys-enabled nil)
;; Show expand-region command used
(setq er--show-expansion-message t)
)

Key bindings for Expand-region

;; Expand region (increases selected region by semantic units)
(global-set-key (kbd "C-'") 'er/expand-region)

Swap-buffer

Configuration

;; add smart swap buffers in multi-windows
(use-package swap-buffers
:config
(global-set-key (kbd "C-x 5") 'swap-buffers)
)

Multiple cursors mode

Multiple cursor是一个非常强大的多位置同时编辑的编辑模式,文档可参考: 这里有一个介绍详细的视频:http://emacsrocks.com/e13.html

Configuration

(use-package multiple-cursors
:defer t
:bind
(("C-c m t" . mc/mark-all-like-this)
("C-c m m" . mc/mark-all-like-this-dwim)
("C-c m l" . mc/edit-lines)
("C-c m e" . mc/edit-ends-of-lines)
("C-c m a" . mc/edit-beginnings-of-lines)
("C-c m n" . mc/mark-next-like-this)
("C-c m p" . mc/mark-previous-like-this)
("C-c m s" . mc/mark-sgml-tag-pair)
("C-c m d" . mc/mark-all-like-this-in-defun)))
(use-package phi-search
:defer t)
(use-package phi-search-mc
:defer t
:config (phi-search-mc/setup-keys))
(use-package mc-extras
:defer t
:config (define-key mc/keymap (kbd "C-. =") 'mc/compare-chars))

Short-key binding

;; add multi cursors:
;;(require 'multiple-cursors)
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
(global-set-key (kbd "C-S-c C-e") 'mc/edit-ends-of-lines)
(global-set-key (kbd "C-S-c C-a") 'mc/edit-beginnings-of-lines)

TODO Wgrep

Wgrep是一个可以允许我们在grep模式下进行直接修改的工具,可以允许我们批量添加上Multiple cursors,然后进行批量修改的工具。在快速修改文件时非常方便,类似于sed的批量匹配,批量修改。

;;; 未配置详细操作,暂时不使用
(use-package wgrep)

Tabbar

Tabbar,在Emacs中显示一个文件的切换标签,并且标签文件按projectile的进行分组显示,以方便在同一个项目中进行维护和切换文件。

Configuration

(use-package tabbar)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Interactive Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun tabbar-select-end-tab ()
"Select end tab of current tabset."
(interactive)
(tabbar-select-beg-tab t))
(defun tabbar-select-beg-tab (&optional backward type)
"Select beginning tab of current tabs.
If BACKWARD is non-nil, move backward, otherwise move forward.
TYPE is default option."
(interactive)
(let* ((tabset (tabbar-current-tabset t))
(ttabset (tabbar-get-tabsets-tabset))
(cycle (if (and (eq tabbar-cycle-scope 'groups)
(not (cdr (tabbar-tabs ttabset))))
'tabs
tabbar-cycle-scope))
selected tab)
(when tabset
(setq selected (tabbar-selected-tab tabset))
(setq tabset (tabbar-tabs tabset)
tab (car (if backward (last tabset) tabset)))
(tabbar-click-on-tab tab type))))
(defun tabbar-backward-tab-other-window (&optional reversed)
"Move to left tab in other window.
Optional argument REVERSED default is move backward, if reversed is non-nil move forward."
(interactive)
(other-window 1)
(if reversed
(tabbar-forward-tab)
(tabbar-backward-tab))
(other-window -1))
(defun tabbar-forward-tab-other-window ()
"Move to right tab in other window."
(interactive)
(tabbar-backward-tab-other-window t))
;;; Code:
(defcustom tabbar-hide-header-button t
"Hide header button at left-up corner.
Default is t."
:type 'boolean
:set (lambda (symbol value)
(set symbol value)
(if value
(setq
tabbar-scroll-left-help-function nil ;don't show help information
tabbar-scroll-right-help-function nil
tabbar-help-on-tab-function nil
tabbar-home-help-function nil
tabbar-buffer-home-button (quote (("") "")) ;don't show tabbar button
tabbar-scroll-left-button (quote (("") ""))
tabbar-scroll-right-button (quote (("") "")))))
:group 'tabbar)
(defun tabbar-filter (condp lst)
(delq nil
(mapcar (lambda (x) (and (funcall condp x) x)) lst)))
(defun tabbar-filter-buffer-list ()
(tabbar-filter
(lambda (x)
(let ((name (format "%s" x)))
(and
(not (string-prefix-p "*epc" name))
(not (string-prefix-p "*helm" name))
(not (string-prefix-p "*Messages*" name))
)))
(delq nil
(mapcar #'(lambda (b)
(cond
;; Always include the current buffer.
((eq (current-buffer) b) b)
((buffer-file-name b) b)
((char-equal ?\ (aref (buffer-name b) 0)) nil)
((buffer-live-p b) b)))
(buffer-list)))))
(setq tabbar-buffer-list-function 'tabbar-filter-buffer-list)
(defvar tabbar-ruler-projectile-tabbar-buffer-group-calc nil
"Buffer group for projectile. Should be buffer local and speed up calculation of buffer groups.")
(defun tabbar-ruler-projectile-tabbar-buffer-groups ()
"Return the list of group names BUFFER belongs to.
Return only one group for each buffer."
(if tabbar-ruler-projectile-tabbar-buffer-group-calc
(symbol-value 'tabbar-ruler-projectile-tabbar-buffer-group-calc)
(set (make-local-variable 'tabbar-ruler-projectile-tabbar-buffer-group-calc)
(cond
((or (get-buffer-process (current-buffer)) (memq major-mode '(comint-mode compilation-mode))) '("Term"))
((string-equal "*" (substring (buffer-name) 0 1)) '("Misc"))
((condition-case err
(projectile-project-root)
(error nil)) (list (projectile-project-name)))
((memq major-mode '(emacs-lisp-mode python-mode emacs-lisp-mode c-mode c++-mode makefile-mode lua-mode vala-mode)) '("Coding"))
((memq major-mode '(javascript-mode js-mode nxhtml-mode html-mode css-mode)) '("HTML"))
((memq major-mode '(org-mode calendar-mode diary-mode)) '("Org"))
((memq major-mode '(dired-mode)) '("Dir"))
(t '("Main"))))
(symbol-value 'tabbar-ruler-projectile-tabbar-buffer-group-calc)))
(defun tabbar-ruler-group-by-projectile-project()
"Group by projectile project."
(interactive)
(setq tabbar-buffer-groups-function 'tabbar-ruler-projectile-tabbar-buffer-groups))
;; group by projectile
(tabbar-ruler-group-by-projectile-project)
(tabbar-mode)

Key binding

;; -----------------------------------------
;; start tabbar-mode
;; -----------------------------------------
(global-set-key (kbd "C-c t") 'tabbar-mode)
;; Tabbar, following is default key binding, no need to set again
;;(global-set-key (kbd "C-c <C-left>") 'tabbar-forward-tab)
;;(global-set-key (kbd "C-c <C-right>") 'tabbar-backward-tab)
;;(global-set-key (kbd "C-c <C-up>") 'tabbar-forward-group)
;;(global-set-key (kbd "C-c <C-down>") 'tabbar-backward-group)

Perspective

Configuration

(use-package perspective
:config
;; Enable perspective mode
(progn
(persp-mode t)
;; TODO: implement persp-last as before-advice on persp-switch (?)
(defmacro custom-persp (name &rest body)
`(let ((initialize (not (gethash ,name perspectives-hash)))
(current-perspective persp-curr))
(persp-switch ,name)
(when initialize ,@body)
(setq persp-last current-perspective)))
;; Jump to last perspective
(defun custom-persp-last ()
(interactive)
(persp-switch (persp-name persp-last)))
(define-key persp-mode-map (kbd "C-x p -") 'custom-persp-last)
)
)

Ido

Ido工具是为在窗口下面的状态栏中选择、显示时更清晰,操作更方便,并支持模糊匹配选择,这里只保留选择文件时启动ido,其它时间切换buffer等,采用helm进行。

Configuration

;; Use C-f during file selection to switch to regular find-file
(ido-mode t)
;;(ido-everywhere t)
(setq ido-enable-flex-matching t)
(setq ido-use-filename-at-point nil)
(setq ido-auto-merge-work-directories-length 0)
(setq ido-use-virtual-buffers t)

Multiple Major Mode

Configuration

(use-package mmm-mode
:config
;;(require 'mmm-auto)
(setq mmm-global-mode 'buffers-with-submode-classes)
(setq mmm-submode-decoration-level 2)
)