Skip to content

Instantly share code, notes, and snippets.

@CsBigDataHub
Created January 15, 2020 02:57
Show Gist options
  • Save CsBigDataHub/8b67b4c36025092afa3feb829970f399 to your computer and use it in GitHub Desktop.
Save CsBigDataHub/8b67b4c36025092afa3feb829970f399 to your computer and use it in GitHub Desktop.
;; -*- coding: utf-8; lexical-binding: t; -*-
;;
;; My frequently used commands are listed here
;; enable evil-mode
(evil-mode 1)
(defvar my-use-m-for-matchit nil
"If t, use \"m\" key for `evil-matchit-mode'.
And \"%\" key is also retored to `evil-jump-item'.")
;; {{ @see https://github.com/timcharper/evil-surround for tutorial
(global-evil-surround-mode 1)
(defun evil-surround-prog-mode-hook-setup ()
(push '(?$ . ("${" . "}")) evil-surround-pairs-alist)
(push '(?/ . ("/" . "/")) evil-surround-pairs-alist))
(add-hook 'prog-mode-hook 'evil-surround-prog-mode-hook-setup)
(defun evil-surround-js-mode-hook-setup ()
;; ES6
(push '(?> . ("(e) => " . "(e)")) 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)
(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 '(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*`
(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 "q" (lambda () (interactive) (quit-window t)))
(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)
;; {{ 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.
(dolist (p '((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)
(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)
(ffip-file-mode . emacs)
(ivy-occur-grep-mode . normal)
(messages-buffer-mode . normal)
(js2-error-buffer-mode . emacs)))
(evil-set-initial-state (car p) (cdr p)))
;; }}
;; 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 "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 (search 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
(my-ensure 'imenu)
(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 search (if (numberp ipos) ipos (point-min))))
;; otherwise just go to first occurrence in buffer
(t
(my-search-defun-from-pos search (point-min)))))))
;; use "gt", someone might prefer original `evil-goto-definition'
(define-key evil-motion-state-map "gt" 'my-evil-goto-definition)
;; 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)
;; {{
(defvar evil-global-markers-history nil)
(defadvice evil-set-marker (before evil-set-marker-before-hack activate)
(let* ((args (ad-get-args 0))
(c (nth 0 args))
(pos (or (nth 1 args) (point))))
;; only rememeber global markers
(when (and (>= c ?A) (<= c ?Z) buffer-file-name)
(setq evil-global-markers-history
(delq nil
(mapcar `(lambda (e)
(unless (string-match (format "^%s@" (char-to-string ,c)) e)
e))
evil-global-markers-history)))
(setq evil-global-markers-history
(add-to-list 'evil-global-markers-history
(format "%s@%s:%d:%s"
(char-to-string c)
(file-truename buffer-file-name)
(line-number-at-pos pos)
(string-trim (my-line-str))))))))
(defadvice evil-goto-mark-line (around evil-goto-mark-line-hack activate)
(let* ((args (ad-get-args 0))
(c (nth 0 args))
(orig-pos (point)))
(condition-case nil
ad-do-it
(error (progn
(when (and (eq orig-pos (point)) evil-global-markers-history)
(let* ((markers evil-global-markers-history)
(i 0)
m
file
found)
(while (and (not found) (< i (length markers)))
(setq m (nth i markers))
(when (string-match (format "\\`%s@\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'"
(char-to-string c))
m)
(setq file (match-string-no-properties 1 m))
(setq found (match-string-no-properties 2 m)))
(setq i (1+ i)))
(when file
(find-file file)
(counsel-etags-forward-line found)))))))))
(defun counsel-evil-goto-global-marker ()
"Goto global evil marker."
(interactive)
(my-ensure 'counsel-etags)
(ivy-read "Goto global evil marker"
evil-global-markers-history
:action (lambda (m)
(when (string-match "\\`[A-Z]@\\(.*?\\):\\([0-9]+\\):\\(.*\\)\\'" m)
(let* ((file (match-string-no-properties 1 m))
(linenum (match-string-no-properties 2 m)))
;; item's format is like '~/proj1/ab.el:39: (defun hello() )'
(counsel-etags-push-marker-stack (point-marker))
;; open file, go to certain line
(find-file file)
(counsel-etags-forward-line linenum))
;; flash, Emacs v25 only API
(xref-pulse-momentarily)))))
;; }}
(local-require 'general)
(general-evil-setup t)
;; {{ use `,` as leader key
(general-create-definer my-comma-leader-def
:prefix ","
:states '(normal visual))
(my-comma-leader-def
"bf" 'beginning-of-defun
"bu" 'backward-up-list
"bb" (lambda () (interactive) (switch-to-buffer nil)) ; to previous buffer
"ef" 'end-of-defun
"m" 'evil-set-marker
"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
"pp" 'paste-from-x-clipboard ; used frequently
"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
"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
"tt" 'find-file-in-current-directory
"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-quick-comment-or-uncomment-to-the-line
"cc" 'evilnc-copy-and-comment-lines
"cp" 'my-evilnc-comment-or-uncomment-paragraphs
"ct" 'evilnc-comment-or-uncomment-html-tag ; evil-nerd-commenter v3.3.0 required
"ic" 'my-imenu-comments
;; {{ window move
"wh" 'evil-window-left
"wl" 'evil-window-right
"wk" 'evil-window-up
"wj" 'evil-window-down
;; }}
"rv" 'evilmr-replace-in-defun
"rb" 'evilmr-replace-in-buffer
"ts" 'evilmr-tag-selected-region ;; recommended
"cby" 'cb-switch-between-controller-and-view
"cbu" 'cb-get-url-from-controller
"rt" 'counsel-etags-recent-tag
"ft" 'counsel-etags-find-tag
"yy" 'counsel-browse-kill-ring
"cf" 'counsel-grep ; grep current buffer
"gf" 'counsel-git ; find file
"gg" 'my-counsel-git-grep ; quickest grep should be easy to press
"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
"sh" 'my-select-from-search-text-history
"rjs" 'run-js
"jsr" 'js-send-region
"jsb" 'js-clear-send-buffer
"kb" 'kill-buffer-and-window ;; "k" is preserved to replace "C-g"
"ls" 'highlight-symbol
"lq" 'highlight-symbol-query-replace
"ln" 'highlight-symbol-nav-mode ; use M-n/M-p to navigation between symbols
"ii" 'my-imenu-or-list-tag-in-current-file
"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
"tg" '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
"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" 'my-multi-purpose-grep
"dd" 'counsel-etags-grep-current-directory
"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
"xe" 'eval-last-sexp
"x0" 'delete-window
"x1" 'delete-other-windows
"x2" 'my-split-window-vertically
"x3" 'my-split-window-horizontally
"s1" 'delete-other-windows
"s2" 'fip-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-two-split-window
"uu" 'winner-undo
"ur" 'winner-redo
"to" 'toggle-web-js-offset
"fs" 'ffip-save-ivy-last
"fr" 'ffip-ivy-resume
"fc" 'cp-ffip-ivy-last
"ss" (lambda ()
(interactive)
;; better performance, got Cygwin grep installed on Windows always
(counsel-grep-or-swiper (if (region-active-p) (my-selected-str))))
"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
"lb" 'langtool-check-buffer
"ll" 'langtool-goto-next-error
"pe" 'flymake-goto-prev-error
"ne" 'flymake-goto-next-error
"og" 'org-agenda
"otl" 'org-toggle-link-display
"oa" '(lambda ()
(interactive)
(my-ensure '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" 'winum-select-window-0-or-10
"1" 'winum-select-window-1
"2" 'winum-select-window-2
"3" 'winum-select-window-3
"4" 'winum-select-window-4
"5" 'winum-select-window-5
"6" 'winum-select-window-6
"7" 'winum-select-window-7
"8" 'winum-select-window-8
"9" 'winum-select-window-9
"xm" 'counsel-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
"xc" 'my-switch-to-shell
"xz" 'my-switch-to-shell
"vf" 'vc-rename-file-and-buffer
"vc" 'vc-copy-file-and-rename-buffer
"xv" '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
"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
"ww" 'narrow-or-widen-dwim
"ycr" 'my-yas-reload-all
"wf" 'popup-which-function)
;; }}
;; {{ Use `SPC` as leader key
;; all keywords arguments are still supported
(general-create-definer my-space-leader-def
:prefix "SPC"
:states '(normal visual))
(my-space-leader-def
"ee" 'my-swap-sexps
"nn" 'my-goto-next-hunk
"pp" 'my-goto-previous-hunk
"pc" 'my-dired-redo-from-commands-history
"pw" 'pwd
"mm" 'counsel-evil-goto-global-marker
"mf" 'mark-defun
"xc" 'save-buffers-kill-terminal ; not used frequently
"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-healthy-color-theme
"yy" 'hydra-launcher/body
"tt" 'my-toggle-indentation
"g" 'hydra-git/body
"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)
;; per-major-mode setup
(general-create-definer my-javascript-leader-def
:prefix "SPC"
:non-normal-prefix "M-SPC"
:states '(normal motion insert emacs)
:keymaps 'js2-mode-map)
(my-javascript-leader-def
"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
(general-create-definer my-semicolon-leader-def
:prefix ";"
:states '(normal visual))
(my-semicolon-leader-def
;; 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")))
";" 'ace-pinyin-jump-char-2
"w" 'avy-goto-word-or-subword-1
"a" 'avy-goto-char-timer
"db" 'sdcv-search-input ; details
"dt" 'sdcv-search-input+ ; summary
"dd" 'my-lookup-dict-org
"mm" 'lookup-doc-in-man
"gg" 'w3m-google-search
"gd" 'w3m-search-financial-dictionary
"ga" 'w3m-java-search
"gh" 'w3mext-hacker-search ; code search in all engines with firefox
"gq" 'w3m-stackoverflow-search)
;; }}
;; {{ 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
(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
(evilnc-default-hotkeys t)
(defun my-current-line-html-p (paragraph-region)
(let* ((line (buffer-substring-no-properties (line-beginning-position)
(line-end-position)))
(re (format "^[ \t]*\\(%s\\)?[ \t]*</?[a-zA-Z]+"
(regexp-quote evilnc-html-comment-start))))
;; current paragraph does contain html tag
(if (and (>= (point) (car paragraph-region))
(string-match-p re line))
t)))
(defun my-evilnc-comment-or-uncomment-paragraphs (&optional num)
"Comment or uncomment NUM paragraphs which might contain html tags."
(interactive "p")
(my-ensure 'evil-nerd-commenter)
(let* ((paragraph-region (evilnc--get-one-paragraph-region))
(html-p (ignore-errors
(or (save-excursion
(sgml-skip-tag-backward 1)
(my-current-line-html-p paragraph-region))
(save-excursion
(sgml-skip-tag-forward 1)
(my-current-line-html-p paragraph-region))))))
(if html-p (evilnc-comment-or-uncomment-html-paragraphs num)
(evilnc-comment-or-uncomment-paragraphs num))))
(defun my-imenu-comments ()
"Imenu display comments."
(interactive)
(my-ensure 'counsel)
(when (fboundp 'evilnc-imenu-create-index-function)
(let* ((imenu-create-index-function 'evilnc-imenu-create-index-function))
(counsel-imenu))))
;; }}
;; {{ `evil-matchit'
(global-evil-matchit-mode 1)
;; }}
;; {{ evil-exchange
;; press gx twice to exchange, gX to cancel
;; 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
;; }}
;; {{ Evil’s f/F/t/T command can search PinYin ,
(evil-find-char-pinyin-mode 1)
;; }}
;; {{ Port of vim-textobj-syntax.
;; It provides evil text objects for consecutive items with same syntax highlight.
(require 'evil-textobj-syntax)
;; }}
;; {{ 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)
;; }}
(defun my-switch-to-shell ()
"Switch to built in or 3rd party shell."
(interactive)
(cond
((display-graphic-p)
(switch-to-builtin-shell))
(t
(suspend-frame))))
;; press ",xx" to expand region
;; then press "c" to contract, "x" to expand
(eval-after-load "evil"
'(progn
;; evil re-assign "M-." to `evil-repeat-pop-next` which I don't use actually.
;; Restore "M-." to original binding command
(define-key evil-normal-state-map (kbd "M-.") 'xref-find-definitions)
(setq expand-region-contract-fast-key "c")
;; @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://emacs.stackexchange.com/questions/9583/how-to-treat-underscore-as-part-of-the-word
;; uncomment below line to make "dw" has exact same behaviour in evil as as in vim
;; (defalias #'forward-evil-word #'forward-evil-symbol)
;; @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")
;; @see https://bitbucket.org/lyro/evil/issue/342/evil-default-cursor-setting-should-default
;; Cursor is always black because of evil.
;; Here is the workaround
(setq evil-default-cursor t)))
(provide 'init-evil)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment