Permalink
b3e3e5c Aug 21, 2018
2 contributors

Users who have contributed to this file

@redguardtoo @phye
902 lines (838 sloc) 34 KB
;; @see https://bitbucket.org/lyro/evil/issue/360/possible-evil-search-symbol-forward
;; evil 1.0.8 search word instead of symbol
(setq evil-symbol-word-search t)
;; @see https://bitbucket.org/lyro/evil/issue/511/let-certain-minor-modes-key-bindings
(defmacro adjust-major-mode-keymap-with-evil (m &optional r)
`(eval-after-load (quote ,(if r r m))
'(progn
(evil-make-overriding-map ,(intern (concat m "-mode-map")) 'normal)
;; force update evil keymaps after git-timemachine-mode loaded
(add-hook (quote ,(intern (concat m "-mode-hook"))) #'evil-normalize-keymaps))))
(adjust-major-mode-keymap-with-evil "git-timemachine")
(adjust-major-mode-keymap-with-evil "browse-kill-ring")
(require 'evil)
;; @see https://bitbucket.org/lyro/evil/issue/342/evil-default-cursor-setting-should-default
;; Cursor is alway black because of evil.
;; Here is the workaround
(setq evil-default-cursor t)
;; {{ multiple-cursors
;; step 1, select thing in visual-mode (OPTIONAL)
;; step 2, `mc/mark-all-like-dwim' or `mc/mark-all-like-this-in-defun'
;; step 3, `ace-mc-add-multiple-cursors' to remove cursor, press RET to confirm
;; step 4, press s or S to start replace
;; step 5, press C-g to quit multiple-cursors
(define-key evil-visual-state-map (kbd "mn") 'mc/mark-next-like-this)
(define-key evil-visual-state-map (kbd "ma") 'mc/mark-all-like-this-dwim)
(define-key evil-visual-state-map (kbd "md") 'mc/mark-all-like-this-in-defun)
(define-key evil-visual-state-map (kbd "mm") 'ace-mc-add-multiple-cursors)
(define-key evil-visual-state-map (kbd "ms") 'ace-mc-add-single-cursor)
;; }}
;; enable evil-mode
(evil-mode 1)
;; {{ @see https://github.com/timcharper/evil-surround for tutorial
(require 'evil-surround)
(global-evil-surround-mode 1)
(defun evil-surround-prog-mode-hook-setup ()
(push '(47 . ("/" . "/")) evil-surround-pairs-alist)
(push '(40 . ("(" . ")")) evil-surround-pairs-alist)
(push '(41 . ("(" . ")")) evil-surround-pairs-alist)
(push '(91 . ("[" . "]")) evil-surround-pairs-alist)
(push '(93 . ("[" . "]")) evil-surround-pairs-alist))
(add-hook 'prog-mode-hook 'evil-surround-prog-mode-hook-setup)
(defun evil-surround-js-mode-hook-setup ()
;; ES6
(push '(?1 . ("{`" . "`}")) evil-surround-pairs-alist)
(push '(?2 . ("${" . "}")) evil-surround-pairs-alist)
(push '(?4 . ("(e) => " . "(e)")) evil-surround-pairs-alist)
;; ReactJS
(push '(?3 . ("classNames(" . ")")) evil-surround-pairs-alist))
(add-hook 'js-mode-hook 'evil-surround-js-mode-hook-setup)
(defun evil-surround-emacs-lisp-mode-hook-setup ()
(push '(?` . ("`" . "'")) evil-surround-pairs-alist))
(add-hook 'emacs-lisp-mode-hook 'evil-surround-emacs-lisp-mode-hook-setup)
(defun evil-surround-org-mode-hook-setup ()
(push '(91 . ("[" . "]")) evil-surround-pairs-alist)
(push '(93 . ("[" . "]")) evil-surround-pairs-alist)
(push '(?= . ("=" . "=")) evil-surround-pairs-alist))
(add-hook 'org-mode-hook 'evil-surround-org-mode-hook-setup)
;; }}
;; {{ For example, press `viW*`
(require 'evil-visualstar)
(setq evil-visualstar/persistent t)
(global-evil-visualstar-mode t)
;; }}
;; ffip-diff-mode (read only) evil setup
(defun ffip-diff-mode-hook-setup ()
(evil-local-set-key 'normal "K" 'diff-hunk-prev)
(evil-local-set-key 'normal "J" 'diff-hunk-next)
(evil-local-set-key 'normal "P" 'diff-file-prev)
(evil-local-set-key 'normal "N" 'diff-file-next)
(evil-local-set-key 'normal "q" 'ffip-diff-quit)
(evil-local-set-key 'normal (kbd "RET") 'ffip-diff-find-file)
;; "C-c C-a" is binding to `diff-apply-hunk' in `diff-mode'
(evil-local-set-key 'normal "a" 'ffip-diff-apply-hunk)
(evil-local-set-key 'normal "o" 'ffip-diff-find-file))
(add-hook 'ffip-diff-mode-hook 'ffip-diff-mode-hook-setup)
(require 'evil-mark-replace)
;; {{ define my own text objects, works on evil v1.0.9 using older method
;; @see http://stackoverflow.com/questions/18102004/emacs-evil-mode-how-to-create-a-new-text-object-to-select-words-with-any-non-sp
(defmacro define-and-bind-text-object (key start-regex end-regex)
(let ((inner-name (make-symbol "inner-name"))
(outer-name (make-symbol "outer-name")))
`(progn
(evil-define-text-object ,inner-name (count &optional beg end type)
(evil-select-paren ,start-regex ,end-regex beg end type count nil))
(evil-define-text-object ,outer-name (count &optional beg end type)
(evil-select-paren ,start-regex ,end-regex beg end type count t))
(define-key evil-inner-text-objects-map ,key (quote ,inner-name))
(define-key evil-outer-text-objects-map ,key (quote ,outer-name)))))
;; between dollar signs:
(define-and-bind-text-object "$" "\\$" "\\$")
;; between equal signs
(define-and-bind-text-object "=" "=" "=")
;; between pipe characters:
(define-and-bind-text-object "|" "|" "|")
;; regular expression
(define-and-bind-text-object "/" "/" "/")
;; trimmed line
(define-and-bind-text-object "l" "^ *" " *$")
;; angular template
(define-and-bind-text-object "r" "\{\{" "\}\}")
;; }}
;; {{ nearby file path as text object,
;; - "vif" to select base name
;; - "vaf" to select full path
;;
;; example:
;; "/hello/world"
;; "/test/back.exe"
;; "C:hello\\hello\\world\\test.exe"
;; "D:blah\\hello\\world\\base.exe"
(defun evil-filepath-is-separator-char (ch)
"Check ascii table that CH is slash characters.
If the character before and after CH is space or tab, CH is NOT slash"
(let (rlt prefix-ch postfix-ch)
(when (and (> (point) (point-min)) (< (point) (point-max)))
(save-excursion
(backward-char)
(setq prefix-ch (following-char)))
(save-excursion
(forward-char)
(setq postfix-ch (following-char))))
(if (and (not (or (= prefix-ch 32) (= postfix-ch 32)))
(or (= ch 47) (= ch 92)) )
(setq rlt t))
rlt))
(defun evil-filepath-not-path-char (ch)
"Check ascii table for charctater."
(or (and (<= 0 ch) (<= ch 32))
(memq ch
'(34 ; double quotes
?'
40 ; (
41 ; )
?<
?>
91 ; [
93 ; ]
?`
?{
?}
127))))
(defun evil-filepath-calculate-path (b e)
(let (rlt f)
(when (and b e)
(setq b (+ 1 b))
(when (save-excursion
(goto-char e)
(setq f (evil-filepath-search-forward-char 'evil-filepath-is-separator-char t))
(and f (>= f b)))
(setq rlt (list b (+ 1 f) (- e 1)))))
rlt))
(defun evil-filepath-get-path-already-inside ()
(let* (b e)
(save-excursion
(setq b (evil-filepath-search-forward-char 'evil-filepath-not-path-char t)))
(save-excursion
(when (setq e (evil-filepath-search-forward-char 'evil-filepath-not-path-char))
(goto-char (- e 1))
;; example: hello/world,
(if (memq (following-char) '(?, ?.))
(setq e (- e 1)))))
(evil-filepath-calculate-path b e)))
(defun evil-filepath-search-forward-char (fn &optional backward)
(let* (found
rlt
(limit (if backward (point-min) (point-max)))
out-of-loop)
(save-excursion
(while (not out-of-loop)
;; for the char, exit
(if (setq found (apply fn (list (following-char))))
(setq out-of-loop t)
;; reach the limit, exit
(if (= (point) limit)
(setq out-of-loop t)
;; keep moving
(if backward (backward-char) (forward-char)))))
(if found (setq rlt (point))))
rlt))
(defun evil-filepath-extract-region ()
"Find the closest file path"
(let* (rlt
b
f1
f2)
(if (and (not (evil-filepath-not-path-char (following-char)))
(setq rlt (evil-filepath-get-path-already-inside)))
;; maybe (point) is in the middle of the path
t
;; need search forward AND backward to find the right path
(save-excursion
;; path in backward direction
(when (setq b (evil-filepath-search-forward-char 'evil-filepath-is-separator-char t))
(goto-char b)
(setq f1 (evil-filepath-get-path-already-inside))))
(save-excursion
;; path in forward direction
(when (setq b (evil-filepath-search-forward-char 'evil-filepath-is-separator-char))
(goto-char b)
(setq f2 (evil-filepath-get-path-already-inside))))
;; pick one path as the final result
(cond
((and f1 f2)
(if (> (- (point) (nth 2 f1)) (- (nth 0 f2) (point)))
(setq rlt f2)
(setq rlt f1)))
(f1
(setq rlt f1))
(f2
(setq rlt f2))))
rlt))
(evil-define-text-object evil-filepath-inner-text-object (&optional count begin end type)
"File name of nearby path"
(let* ((selected-region (evil-filepath-extract-region)))
(if selected-region
(evil-range (nth 1 selected-region) (nth 2 selected-region) :expanded t))))
(evil-define-text-object evil-filepath-outer-text-object (&optional NUM begin end type)
"Nearby path."
(let* ((selected-region (evil-filepath-extract-region)))
(if selected-region
(evil-range (car selected-region) (+ 1 (nth 2 selected-region)) type :expanded t))))
(define-key evil-inner-text-objects-map "f" 'evil-filepath-inner-text-object)
(define-key evil-outer-text-objects-map "f" 'evil-filepath-outer-text-object)
;; }}
;; {{ https://github.com/syl20bnr/evil-escape
(setq-default evil-escape-delay 0.3)
(setq evil-escape-excluded-major-modes '(dired-mode))
(setq-default evil-escape-key-sequence "kj")
;; disable evil-escape when input method is on
(evil-escape-mode 1)
;; }}
;; Move back the cursor one position when exiting insert mode
(setq evil-move-cursor-back t)
(defun toggle-org-or-message-mode ()
(interactive)
(if (eq major-mode 'message-mode)
(org-mode)
(if (eq major-mode 'org-mode) (message-mode))))
;; (evil-set-initial-state 'org-mode 'emacs)
;; As a general RULE, mode specific evil leader keys started
;; with uppercased character or 'g' or special character except "=" and "-"
(evil-declare-key 'normal org-mode-map
"gh" 'outline-up-heading
"gl" 'outline-next-visible-heading
"$" 'org-end-of-line ; smarter behaviour on headlines etc.
"^" 'org-beginning-of-line ; ditto
"<" (lambda () (interactive) (org-demote-or-promote 1)) ; out-dent
">" 'org-demote-or-promote ; indent
(kbd "TAB") 'org-cycle)
(evil-declare-key 'normal markdown-mode-map
"gh" 'outline-up-heading
"gl" 'outline-next-visible-heading
(kbd "TAB") 'org-cycle)
;; {{ specify major mode uses Evil (vim) NORMAL state or EMACS original state.
;; You may delete this setup to use Evil NORMAL state always.
(loop for (mode . state) in
'((minibuffer-inactive-mode . emacs)
(calendar-mode . emacs)
(special-mode . emacs)
(grep-mode . emacs)
(Info-mode . emacs)
(term-mode . emacs)
(sdcv-mode . emacs)
(anaconda-nav-mode . emacs)
(log-edit-mode . emacs)
(vc-log-edit-mode . emacs)
(magit-log-edit-mode . emacs)
(inf-ruby-mode . emacs)
(direx:direx-mode . emacs)
(yari-mode . emacs)
(erc-mode . emacs)
(neotree-mode . emacs)
(w3m-mode . emacs)
(gud-mode . emacs)
(help-mode . emacs)
(eshell-mode . emacs)
(shell-mode . emacs)
(xref--xref-buffer-mode . emacs)
;;(message-mode . emacs)
(epa-key-list-mode . emacs)
(fundamental-mode . emacs)
(weibo-timeline-mode . emacs)
(weibo-post-mode . emacs)
(woman-mode . emacs)
(sr-mode . emacs)
(profiler-report-mode . emacs)
(dired-mode . emacs)
(compilation-mode . emacs)
(speedbar-mode . emacs)
(ivy-occur-mode . emacs)
(ivy-occur-grep-mode . normal)
(messages-buffer-mode . normal)
(browse-kill-ring-mode . normal)
(js2-error-buffer-mode . emacs)
)
do (evil-set-initial-state mode state))
;; }}
;; I prefer Emacs way after pressing ":" in evil-mode
(define-key evil-ex-completion-map (kbd "C-a") 'move-beginning-of-line)
(define-key evil-ex-completion-map (kbd "C-b") 'backward-char)
(define-key evil-ex-completion-map (kbd "M-p") 'previous-complete-history-element)
(define-key evil-ex-completion-map (kbd "M-n") 'next-complete-history-element)
(define-key evil-normal-state-map "Y" (kbd "y$"))
;; (define-key evil-normal-state-map (kbd "RET") 'ivy-switch-buffer-by-pinyin) ; RET key is preserved for occur buffer
(define-key evil-normal-state-map "go" 'goto-char)
(define-key evil-normal-state-map (kbd "M-y") 'counsel-browse-kill-ring)
(define-key evil-normal-state-map (kbd "C-]") 'counsel-etags-find-tag-at-point)
(define-key evil-visual-state-map (kbd "C-]") 'counsel-etags-find-tag-at-point)
(define-key evil-insert-state-map (kbd "C-x C-n") 'evil-complete-next-line)
(define-key evil-insert-state-map (kbd "C-x C-p") 'evil-complete-previous-line)
(define-key evil-insert-state-map (kbd "C-]") 'aya-expand)
(defun my-search-defun-from-pos (pos)
(evil-search search t t pos)
;; ignore this.f1 = this.fn.bind(this) code
(when (and (memq major-mode '(js-mode js2-mode rjsx-mode))
(string-match-p "^[ \t]*this\.[a-zA-Z0-9]+[ \t]*=[ \t]*this\.[a-zA-Z0-9]*\.bind(this);"
(my-line-str)))
(forward-line 1)
(evil-search search t t (point))))
;; the original "gd" or `evil-goto-definition' now try `imenu', `xref', search string to `point-min'
;; xref part is annoying because I already use `counsel-etags' to search tag.
(evil-define-motion my-evil-goto-definition ()
"Go to definition or first occurrence of symbol under point in current buffer."
:jump t
:type exclusive
(let* ((string (evil-find-symbol t))
(search (format "\\_<%s\\_>" (regexp-quote string)))
ientry ipos)
;; load imenu if available
(unless (featurep 'imenu)
(condition-case nil
(require 'imenu)
(error nil)))
(if (null string)
(user-error "No symbol under cursor")
(setq isearch-forward t)
;; if imenu is available, try it
(cond
((and (derived-mode-p 'js2-mode)
(or (null (get-text-property (point) 'face))
(font-belongs-to (point) '(rjsx-tag))))
(js2-jump-to-definition))
((fboundp 'imenu--make-index-alist)
(condition-case nil
(setq ientry (imenu--make-index-alist))
(error nil))
(setq ientry (assoc string ientry))
(setq ipos (cdr ientry))
(when (and (markerp ipos)
(eq (marker-buffer ipos) (current-buffer)))
(setq ipos (marker-position ipos)))
;; imenu found a position, so go there and
;; highlight the occurrence
(my-search-defun-from-pos (if (numberp ipos) ipos (point-min))))
;; otherwise just go to first occurrence in buffer
(t
(my-search-defun-from-pos (point-min)))))))
;; use "gt", someone might prefer original `evil-goto-definition'
(define-key evil-motion-state-map "gt" 'my-evil-goto-definition)
(require 'evil-matchit)
(global-evil-matchit-mode 1)
;; press ",xx" to expand region
;; then press "z" to contract, "x" to expand
(eval-after-load "evil"
'(progn
(define-key global-map (kbd "C-x C-z") 'switch-to-shell-or-ansi-term)
(setq expand-region-contract-fast-key "z")))
;; I learn this trick from ReneFroger, need latest expand-region
;; @see https://github.com/redguardtoo/evil-matchit/issues/38
(define-key evil-visual-state-map (kbd "v") 'er/expand-region)
(define-key evil-insert-state-map (kbd "C-e") 'move-end-of-line)
(define-key evil-insert-state-map (kbd "C-k") 'kill-line)
(define-key evil-insert-state-map (kbd "M-j") 'yas-expand)
(define-key evil-emacs-state-map (kbd "M-j") 'yas-expand)
(global-set-key (kbd "C-r") 'undo-tree-redo)
;; My frequently used commands are listed here
;; For example, for line like `"ef" 'end-of-defun`
;; You can either press `,ef` or `M-x end-of-defun` to execute it
(local-require 'general)
(general-evil-setup t)
;; {{ use `,` as leader key
(nvmap :prefix ","
"=" 'increase-default-font-height ; GUI emacs only
"-" 'decrease-default-font-height ; GUI emacs only
"bf" 'beginning-of-defun
"bu" 'backward-up-list
"bb" 'back-to-previous-buffer
"ef" 'end-of-defun
"mf" 'mark-defun
"em" 'erase-message-buffer
"eb" 'eval-buffer
"sd" 'sudo-edit
"sc" 'scratch
"ee" 'eval-expression
"aa" 'copy-to-x-clipboard ; used frequently
"aw" 'ace-swap-window
"af" 'ace-maximize-window
"ac" 'aya-create
"zz" 'paste-from-x-clipboard ; used frequently
"cy" 'strip-convert-lines-into-one-big-string
"bs" '(lambda () (interactive) (goto-edge-by-comparing-font-face -1))
"es" 'goto-edge-by-comparing-font-face
"vj" 'my-validate-json-or-js-expression
"kc" 'kill-ring-to-clipboard
"mcr" 'my-create-regex-from-kill-ring
"ntt" 'neotree-toggle
"ntf" 'neotree-find ; open file in current buffer in neotree
"ntd" 'neotree-project-dir
"nth" 'neotree-hide
"nts" 'neotree-show
"fn" 'cp-filename-of-current-buffer
"fp" 'cp-fullpath-of-current-buffer
"dj" 'dired-jump ;; open the dired from current file
"xd" 'dired
"xo" 'ace-window
"ff" 'toggle-full-window ;; I use WIN+F in i3
"ip" 'find-file-in-project
"jj" 'find-file-in-project-at-point
"kk" 'find-file-in-project-by-selected
"kn" 'find-file-with-similar-name ; ffip v5.3.1
"fd" 'find-directory-in-project-by-selected
"trm" 'get-term
"tff" 'toggle-frame-fullscreen
"tfm" 'toggle-frame-maximized
"ti" 'fastdef-insert
"th" 'fastdef-insert-from-history
;; "ci" 'evilnc-comment-or-uncomment-lines
;; "cl" 'evilnc-comment-or-uncomment-to-the-line
;; "cc" 'evilnc-copy-and-comment-lines
;; "cp" 'evilnc-comment-or-uncomment-paragraphs
"ic" 'my-imenu-comments
"epy" 'emmet-expand-yas
"epl" 'emmet-expand-line
"rv" 'evilmr-replace-in-defun
"rb" 'evilmr-replace-in-buffer
"ts" 'evilmr-tag-selected-region ;; recommended
"tua" 'artbollocks-mode
"cby" 'cb-switch-between-controller-and-view
"cbu" 'cb-get-url-from-controller
"ht" 'counsel-etags-find-tag-at-point ; better than find-tag C-]
"rt" 'counsel-etags-recent-tag
"ft" 'counsel-etags-find-tag
"mm" 'counsel-bookmark-goto
"mk" 'bookmark-set
"yy" 'counsel-browse-kill-ring
"cf" 'counsel-grep ; grep current buffer
"gf" 'counsel-git ; find file
"gg" 'counsel-git-grep-by-selected ; quickest grep should be easy to press
"gm" 'counsel-git-find-my-file
"gs" (lambda ()
(interactive)
(let* ((ffip-diff-backends
'(("Show git commit" . (let* ((git-cmd "git --no-pager log --date=short --pretty=format:'%h|%ad|%s|%an'")
(collection (nonempty-lines (shell-command-to-string git-cmd)))
(item (ffip-completing-read "git log:" collection)))
(when item
(shell-command-to-string (format "git show %s" (car (split-string item "|" t))))))))))
(ffip-show-diff 0)))
"gd" 'ffip-show-diff-by-description ;find-file-in-project 5.3.0+
"gl" 'my-git-log-trace-definition ; find history of a function or range
"sf" 'counsel-git-show-file
"sh" 'my-select-from-search-text-history
"df" 'counsel-git-diff-file
"rjs" 'run-js
"jsr" 'js-send-region
"jsb" 'js-clear-send-buffer
"rmz" 'run-mozilla
"rpy" 'run-python
"rlu" 'run-lua
"tci" 'toggle-company-ispell
"kb" 'kill-buffer-and-window ;; "k" is preserved to replace "C-g"
"it" 'issue-tracker-increment-issue-id-under-cursor
"ls" 'highlight-symbol
"lq" 'highlight-symbol-query-replace
"ln" 'highlight-symbol-nav-mode ; use M-n/M-p to navigation between symbols
"bm" 'pomodoro-start ;; beat myself
"ii" 'counsel-imenu
"ij" 'rimenu-jump
"." 'evil-ex
;; @see https://github.com/pidu/git-timemachine
;; p: previous; n: next; w:hash; W:complete hash; g:nth version; q:quit
"tt" 'dumb-jump-go
"tb" 'dumb-jump-back
"tm" 'my-git-timemachine
;; toggle overview, @see http://emacs.wordpress.com/2007/01/16/quick-and-dirty-code-folding/
"ov" 'my-overview-of-current-buffer
"or" 'open-readme-in-git-root-directory
"oo" 'compile
"c$" 'org-archive-subtree ; `C-c $'
;; org-do-demote/org-do-premote support selected region
"c<" 'org-do-promote ; `C-c C-<'
"c>" 'org-do-demote ; `C-c C->'
"cam" 'org-tags-view ; `C-c a m': search items in org-file-apps by tag
"cxi" 'org-clock-in ; `C-c C-x C-i'
"cxo" 'org-clock-out ; `C-c C-x C-o'
"cxr" 'org-clock-report ; `C-c C-x C-r'
"qq" (lambda (n)
(interactive "P")
(cond
((not n)
(counsel-etags-grep))
((= n 1)
;; grep references of current web component
(counsel-etags-grep (format "<%s" (file-name-base buffer-file-name))))
((= n 2)
;; grep web component attribute name
(counsel-etags-grep (format "^ *%s[=:]" (or (thing-at-point 'symbol)
(read-string "Component attribute name?")))))
((= n 3)
;; grep current file name base
(counsel-etags-grep (format "%s" (file-name-nondirectory buffer-file-name))))))
"dd" 'counsel-etags-grep-symbol-at-point
"xc" 'save-buffers-kill-terminal
"rr" 'my-counsel-recentf
"rh" 'counsel-yank-bash-history ; bash history command => yank-ring
"rd" 'counsel-recent-directory
"da" 'diff-region-tag-selected-as-a
"db" 'diff-region-compare-with-b
"di" 'evilmi-delete-items
"si" 'evilmi-select-items
"jb" 'js-beautify
"jp" 'my-print-json-path
"sep" 'string-edit-at-point
"sec" 'string-edit-conclude
"sea" 'string-edit-abort
"xe" 'eval-last-sexp
"x0" 'delete-window
"x1" 'delete-other-windows
"x2" 'my-split-window-vertically
"x3" 'my-split-window-horizontally
"s2" 'ffip-split-window-vertically
"s3" 'ffip-split-window-horizontally
"rw" 'rotate-windows
"ru" 'undo-tree-save-state-to-register ; C-x r u
"rU" 'undo-tree-restore-state-from-register ; C-x r U
"xt" 'toggle-window-split
"uu" 'winner-undo
"UU" 'winner-redo
"to" 'toggle-web-js-offset
"sl" 'sort-lines
"ulr" 'uniquify-all-lines-region
"ulb" 'uniquify-all-lines-buffer
"fs" 'ffip-save-ivy-last
"fr" 'ffip-ivy-resume
"fc" 'cp-ffip-ivy-last
"ss" 'swiper-the-thing ; http://oremacs.com/2015/03/25/swiper-0.2.0/ for guide
"hst" 'hs-toggle-fold
"hsa" 'hs-toggle-fold-all
"hsh" 'hs-hide-block
"hss" 'hs-show-block
"hd" 'describe-function
"hf" 'find-function
"hk" 'describe-key
"hv" 'describe-variable
"gt" 'counsel-gtags-dwim ; jump from reference to definition or vice versa
"gr" 'counsel-gtags-find-symbol
"gu" 'counsel-gtags-update-tags
"fb" 'flyspell-buffer
"fe" 'flyspell-goto-next-error
"fa" 'flyspell-auto-correct-word
"pe" 'flymake-goto-prev-error
"ne" 'flymake-goto-next-error
"bc" '(lambda () (interactive) (wxhelp-browse-class-or-api (thing-at-point 'symbol)))
"og" 'org-agenda
"otl" 'org-toggle-link-display
"oa" '(lambda ()
(interactive)
(unless (featurep 'org) (require 'org))
(counsel-org-agenda-headlines))
"om" 'toggle-org-or-message-mode
"ut" 'undo-tree-visualize
"ar" 'align-regexp
"wrn" 'httpd-restart-now
"wrd" 'httpd-restart-at-default-directory
"bk" 'buf-move-up
"bj" 'buf-move-down
"bh" 'buf-move-left
"bl" 'buf-move-right
"0" 'select-window-0
"1" 'select-window-1
"2" 'select-window-2
"3" 'select-window-3
"4" 'select-window-4
"5" 'select-window-5
"6" 'select-window-6
"7" 'select-window-7
"8" 'select-window-8
"9" 'select-window-9
"xm" 'my-M-x
"xx" 'er/expand-region
"xf" 'counsel-find-file
"xb" 'ivy-switch-buffer-by-pinyin
"xh" 'mark-whole-buffer
"xk" 'kill-buffer
"xs" 'save-buffer
"xz" 'switch-to-shell-or-ansi-term
"vm" 'vc-rename-file-and-buffer
"vc" 'vc-copy-file-and-rename-buffer
"xvv" 'vc-next-action ; 'C-x v v' in original
"va" 'git-add-current-file
"vk" 'git-checkout-current-file
"vg" 'vc-annotate ; 'C-x v g' in original
"vs" 'git-gutter:stage-hunk
"vr" 'git-gutter:revert-hunk
"vl" 'vc-print-log
"vv" 'vc-msg-show
"v=" 'git-gutter:popup-hunk
"hh" 'cliphist-paste-item
"yu" 'cliphist-select-item
"ih" 'my-goto-git-gutter ; use ivy-mode
"ir" 'ivy-resume
"nn" 'my-goto-next-hunk
"pp" 'my-goto-previous-hunk
"ww" 'narrow-or-widen-dwim
"xnw" 'widen
"xnd" 'narrow-to-defun
"xnr" 'narrow-to-region
"ycr" 'my-yas-reload-all
"wf" 'popup-which-function)
;; }}
;; {{ Use `SPC` as leader key
;; all keywords arguments are still supported
(nvmap :prefix "SPC"
"ee" 'my-swap-sexps
"pc" 'my-dired-redo-from-commands-history
"pw" 'pwd
"cc" 'my-dired-redo-last-command
"ss" 'wg-create-workgroup ; save windows layout
"se" 'evil-iedit-state/iedit-mode ; start iedit in emacs
"sc" 'shell-command
"ll" 'my-wg-switch-workgroup ; load windows layout
"kk" 'scroll-other-window
"jj" 'scroll-other-window-up
"rt" 'random-color-theme
"yy" 'hydra-launcher/body
"hh" 'multiple-cursors-hydra/body
"gi" 'gist-region ; only workable on my computer
"tt" 'my-toggle-indentation
"gg" 'magit-status
"gs" 'magit-show-commit
"gl" 'magit-log-all
"gff" 'magit-find-file ; loading file in specific version into buffer
"gdd" 'magit-diff-dwim
"gdc" 'magit-diff-staged
"gau" 'magit-stage-modified
"gcc" 'magit-commit-popup
"gca" 'magit-commit-amend
"gja" 'magit-commit-extend
"gtt" 'magit-stash
"gta" 'magit-stash-apply
"gv" 'git-gutter:set-start-revision
"gh" 'git-gutter-reset-to-head-parent
"gr" 'git-gutter-reset-to-default
"ps" 'profiler-start
"pr" 'profiler-report
"ud" 'my-gud-gdb
"uk" 'gud-kill-yes
"ur" 'gud-remove
"ub" 'gud-break
"uu" 'gud-run
"up" 'gud-print
"ue" 'gud-cls
"un" 'gud-next
"us" 'gud-step
"ui" 'gud-stepi
"uc" 'gud-cont
"uf" 'gud-finish
"ma" 'mc/mark-all-like-this-dwim
"md" 'mc/mark-all-like-this-in-defun
"mm" 'ace-mc-add-multiple-cursors
"mn" 'mc/mark-next-like-this
"ms" 'mc/skip-to-next-like-this
"me" 'mc/edit-lines)
;; per-major-mode setup
(general-define-key :states '(normal motion insert emacs)
:keymaps 'js2-mode-map
:prefix "SPC"
:non-normal-prefix "M-SPC"
"de" 'js2-display-error-list
"nn" 'js2-next-error
"te" 'js2-mode-toggle-element
"tf" 'js2-mode-toggle-hide-functions
"jeo" 'js2r-expand-object
"jco" 'js2r-contract-object
"jeu" 'js2r-expand-function
"jcu" 'js2r-contract-function
"jea" 'js2r-expand-array
"jca" 'js2r-contract-array
"jwi" 'js2r-wrap-buffer-in-iife
"jig" 'js2r-inject-global-in-iife
"jev" 'js2r-extract-var
"jiv" 'js2r-inline-var
"jrv" 'js2r-rename-var
"jvt" 'js2r-var-to-this
"jag" 'js2r-add-to-globals-annotation
"jsv" 'js2r-split-var-declaration
"jss" 'js2r-split-string
"jef" 'js2r-extract-function
"jem" 'js2r-extract-method
"jip" 'js2r-introduce-parameter
"jlp" 'js2r-localize-parameter
"jtf" 'js2r-toggle-function-expression-and-declaration
"jao" 'js2r-arguments-to-object
"juw" 'js2r-unwrap
"jwl" 'js2r-wrap-in-for-loop
"j3i" 'js2r-ternary-to-if
"jlt" 'js2r-log-this
"jsl" 'js2r-forward-slurp
"jba" 'js2r-forward-barf
"jk" 'js2r-kill)
;; }}
;; Press `dd' to delete lines in `wgrep-mode' in evil directly
(defadvice evil-delete (around evil-delete-hack activate)
;; make buffer writable
(if (and (boundp 'wgrep-prepared) wgrep-prepared)
(wgrep-toggle-readonly-area))
ad-do-it
;; make buffer read-only
(if (and (boundp 'wgrep-prepared) wgrep-prepared)
(wgrep-toggle-readonly-area)))
;; {{ Use `;` as leader key, for searching something
(nvmap :prefix ";"
;; Search character(s) at the beginning of word
;; See https://github.com/abo-abo/avy/issues/70
;; You can change the avy font-face in ~/.custom.el:
;; (eval-after-load 'avy
;; '(progn
;; (set-face-attribute 'avy-lead-face-0 nil :foreground "black")
;; (set-face-attribute 'avy-lead-face-0 nil :background "#f86bf3")))
";" 'avy-goto-char-2
"w" 'avy-goto-word-or-subword-1
"a" 'avy-goto-char-timer
"db" 'sdcv-search-pointer ; in buffer
"dt" 'sdcv-search-input+ ; in tip
"dd" 'my-lookup-dict-org
"mm" 'lookup-doc-in-man
"gg" 'w3m-google-search
"gf" 'w3m-google-by-filetype
"gd" 'w3m-search-financial-dictionary
"gj" 'w3m-search-js-api-mdn
"ga" 'w3m-java-search
"gh" 'w3mext-hacker-search ; code search in all engines with firefox
"gq" 'w3m-stackoverflow-search
"mw" 'mpc-which-song
"mn" 'mpc-next-prev-song
"mp" '(lambda () (interactive) (mpc-next-prev-song t)))
;; }}
;; {{ remember what we searched
;; http://emacs.stackexchange.com/questions/24099/how-to-yank-text-to-search-command-after-in-evil-mode/
(defvar my-search-text-history nil "List of text I searched.")
(defun my-select-from-search-text-history ()
(interactive)
(ivy-read "Search text history:" my-search-text-history
:action (lambda (item)
(copy-yank-str item)
(message "%s => clipboard & yank ring" item))))
(defun my-cc-isearch-string ()
(interactive)
(if (and isearch-string (> (length isearch-string) 0))
;; NOT pollute clipboard who has things to paste into Emacs
(add-to-list 'my-search-text-history isearch-string)))
(defadvice evil-search-incrementally (after evil-search-incrementally-after-hack activate)
(my-cc-isearch-string))
(defadvice evil-search-word (after evil-search-word-after-hack activate)
(my-cc-isearch-string))
(defadvice evil-visualstar/begin-search (after evil-visualstar/begin-search-after-hack activate)
(my-cc-isearch-string))
;; }}
;; change mode-line color by evil state
(lexical-let ((default-color (cons (face-background 'mode-line)
(face-foreground 'mode-line))))
(add-hook 'post-command-hook
(lambda ()
(let ((color (cond ((minibufferp) default-color)
((evil-insert-state-p) '("#e80000" . "#ffffff"))
((evil-emacs-state-p) '("#444488" . "#ffffff"))
((buffer-modified-p) '("#006fa0" . "#ffffff"))
(t default-color))))
(set-face-background 'mode-line (car color))
(set-face-foreground 'mode-line (cdr color))))))
;; {{ evil-nerd-commenter
(require 'evil-nerd-commenter)
(evilnc-default-hotkeys)
(defun my-imenu-comments ()
"Imenu display comments."
(interactive)
(unless (featurep 'counsel) (require 'counsel))
(when (fboundp 'evilnc-imenu-create-index-function)
(let* ((imenu-create-index-function 'evilnc-imenu-create-index-function))
(counsel-imenu))))
;; }}
;; {{ evil-exchange
;; press gx twice to exchange, gX to cancel
(require 'evil-exchange)
;; change default key bindings (if you want) HERE
;; (setq evil-exchange-key (kbd "zx"))
(evil-exchange-install)
;; }}
;; {{ evil-lion
;; After pressing `glip=` or `gl2j=` (gl is the operator, ip or 2j is text object, = separator):
;; one = 1
;; three = 3
;; fifteen = 15
;;
;; will become:
;; one = 1
;; three = 3
;; fifteen = 15
;;
;; If the align separator is / you will be prompted for a regular expression instead of a plain character.
(evil-lion-mode)
;; }}
;; {{ @see https://github.com/syl20bnr/spacemacs/blob/master/doc/DOCUMENTATION.org#replacing-text-with-iedit
;; same keybindgs as spacemacs:
;; - "SPC s e" to start `iedit-mode'
;; - "TAB" to toggle current occurrence
;; - "n" next, "N" previous (obviously we use "p" for yank)
;; - "gg" the first occurence, "G" the last occurence
;; - Please note ";;" or `avy-goto-char-timer' is also useful
(require 'evil-iedit-state)
;; }}
;; {{ Evil’s f/F/t/T commands with Pinyin supptt,
(require 'evil-find-char-pinyin)
(evil-find-char-pinyin-mode 1)
;; }}
;; {{ evil-args
;; bind evil-args text objects
(define-key evil-inner-text-objects-map "a" 'evil-inner-arg)
(define-key evil-outer-text-objects-map "a" 'evil-outer-arg)
;; bind evil-forward/backward-args
(define-key evil-normal-state-map "L" 'evil-forward-arg)
(define-key evil-normal-state-map "H" 'evil-backward-arg)
(define-key evil-motion-state-map "L" 'evil-forward-arg)
(define-key evil-motion-state-map "H" 'evil-backward-arg)
;; bind evil-jump-out-args
(define-key evil-normal-state-map "K" 'evil-jump-out-args)
;; }}
(provide 'init-evil)