Vim (Evil) Style Emacs

Formatted for use with emacs2rst.

Original init.el can be downloaded here.

Application Options

;; handy troubleshooting
(toggle-debug-on-error)

;; disable toolbar
(tool-bar-mode -1)
;; disable menu
(menu-bar-mode -1)
;; disable scrollbar
(scroll-bar-mode -1)
;; startup message
(defun display-startup-echo-area-message () (message ""))
;; visual bell (no beeps)
;; (setq visible-bell t)

;; No blinking
(blink-cursor-mode 0)

;; Window Title
(setq-default frame-title-format
  '
  (
    (:eval
      (if (buffer-file-name)
        (abbreviate-file-name (buffer-file-name))
        "%b")
      )
    (:eval
      (if (buffer-modified-p)
        " *")
      )
    " emacs")
  )

UTF-8 Everywhere

(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(setq default-buffer-file-coding-system 'utf-8)

Misc Application Options

;; Garbage-collect on focus-out, Emacs should feel snappier.
(add-hook 'focus-out-hook #'garbage-collect)

;; Don't open with splits
(add-hook 'window-setup-hook #'delete-other-windows)

;; allow y/n
(defalias 'yes-or-no-p 'y-or-n-p)

;; ~~~~~~~~~~
;; No Backups

;; disable backup
(setq backup-inhibited t)
;; disable auto save
(setq auto-save-default nil)

(setq backup-directory-alist `(("." . "/tmp/emacs-backup")))

;; show text instead of popups
(setq use-dialog-box nil)

(setq ispell-personal-dictionary "~/.vim/spell/en.utf-8.add")

;; Always reuse existing compilation window
(push '("\\*compilation\\*" . (nil (reusable-frames . t))) display-buffer-alist)


(setq
  mode-line-default-help-echo nil ; don't say anything on mode-line mouseover
  indicate-buffer-boundaries nil  ; don't show where buffer starts/ends
  indicate-empty-lines nil        ; don't show empty lines
  ;; Keep cursors and highlights in current window only
  cursor-in-non-selected-windows nil
  highlight-nonselected-windows nil
  ;; Disable bidirectional text support for slight performance bonus
  bidi-display-reordering nil

  blink-matching-paren nil ; don't blink--too distracting
  show-paren-delay 0.2
  show-paren-highlight-openparen t
  show-paren-when-point-inside-paren t
  uniquify-buffer-name-style nil
  visible-bell nil
  visible-cursor nil

  ;; quiet warning, see:
  ;; https://github.com/syl20bnr/spacemacs/issues/192
  ad-redefinition-action 'accept

  ;; don't show buffer list on startup
  inhibit-startup-buffer-menu t

  ;; wide when over tabs
  x-stretch-cursor t
  ;; hide cursor while typing
  make-pointer-invisible t

  redisplay-dont-pause t            ; don't pause display on input

  ;; never split the window (nice for rtags and compile errors).
  ;; https://stackoverflow.com/a/3389904/432509
  split-width-threshold nil
  )

Scrolling

(setq
  ;; only 'jump' when moving this far off the screen
  scroll-conservatively 10000
  ;; scroll N lines to screen edge
  scroll-margin 8
  ;; keyboard scroll one line at a time
  scroll-step 1
  ;; mouse scroll N lines
  mouse-wheel-scroll-amount '(6 ((shift) . 1))
  ;; don't accelerate scrolling
  mouse-wheel-progressive-speed nil

  ;; preserve line/column (nicer page up/down)
  scroll-preserve-screen-position t
  ;; Move the cursor to top/bottom even if the screen is viewing top/bottom (for page up/down)
  scroll-error-top-bottom t

  ;; center after going to the next error
  next-error-recenter (quote (4))

  ;; Always redraw immediately when scrolling,
  ;; more responsive and doesn't hang!
  ;; http://emacs.stackexchange.com/a/31427/2418
  fast-but-imprecise-scrolling nil
  jit-lock-defer-time 0

  )

Platform (Linux)

(setq x-select-enable-clipboard t)
;; Treat clipboard input as UTF-8 string first; compound text next, etc.
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))
;; Selecting sets primary clipboard
(setq x-select-enable-primary t)

(setq undo-tree-enable-undo-in-region nil)

Local Options

Options we may want to tweak within this configuration. These options can cause conflicts, allow to easily switch off!

Display

(defvar local-cfg/use-fci t)
(defvar local-cfg/use-hline t)
(defvar local-cfg/use-hline-indent t)
(defvar local-cfg/use-highlight-indent-hig nil) ;; highlight-indent-mode
(defvar local-cfg/use-highlight-indent-vim t) ;; visual-indent-mode
(defvar local-cfg/use-linum nil)
(defvar local-cfg/use-number-color t)
(defvar local-cfg/use-custom-mode-line t)
(defvar local-cfg/use-show-whitespace t) ;; XXX, fails to init true for some reason, key-toggle works though

Behavior

;; use only one of these!
(defvar local-cfg/use-helm nil)
(defvar local-cfg/use-ivy t)

(defvar local-cfg/use-neotree t)
(defvar local-cfg/use-company t)
(defvar local-cfg/use-minimap nil)

;; use only one of these!
(defvar local-cfg/use-search-evil t)
(defvar local-cfg/use-search-isearch nil)

Packages

(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))
(setq package-enable-at-startup nil)

Ensure Packages Installed

See: http://blog.aaronbieber.com/2015/05/24/from-vim-to-emacs-in-fourteen-days.html

(defun ensure-package-installed (&rest packages) "
Assure every package is installed, ask for installation if it’s not.
Return a list of installed packages or nil for every skipped package.
"
  (mapcar
    (lambda (package)
      ;; Allow nil values, so we can conditionally list packages.
      (if package
        (if (package-installed-p package)
          nil
          (if (y-or-n-p (format "Package %s is missing. Install it? " package))
            (package-install package)
            package
            )
          )
        )
      )
    packages
    )
  )

;; Make sure to have downloaded archive description.
(or (file-exists-p package-user-dir)
  (package-refresh-contents)
  )

;; Activate installed packages
(package-initialize)

;; Own selection of packages
(ensure-package-installed
  ;; application plug-ins
  'counsel
  'default-text-scale
  (if local-cfg/use-minimap 'minimap)
  (if local-cfg/use-neotree 'neotree)
  'package-utils ;; used so we can update from the command line.

  'run-stuff ;; own package

  ;; display plug-ins
  (if local-cfg/use-fci 'fill-column-indicator)
  (if local-cfg/use-highlight-indent-hig 'highlight-indent-guides)
  'highlight-numbers

  ;; navigation plug-ins
  'ace-jump-mode
  'find-file-in-project

  ;; editing plug-ins
  'linum-relative
  'drag-stuff
  (if local-cfg/use-ivy 'ivy)
  'auto-complete
  'company
  'rainbow-mode

  ;; evil (vim emulation)
  'evil
  'evil-leader
  'evil-numbers
  'evil-surround
  ;; 'evil-visual-mark-mode

  ;; ; helm and its users
  ;; 'helm
  ;; 'projectile
  ;; 'helm-projectile

  ;; filetype modes
  'cmake-mode
  'rust-mode
  'toml-mode
  'lua-mode
  'markdown-mode

  ;; for rust auto-completion
  'racer

  ;; for C++
  'rtags
  ;; 'irony
  ;; 'irony-eldoc
  ;; 'flycheck
  ;; 'company-clang
  'cmake-ide
  ;; tabs for indent, spaces to align
  'smart-tabs-mode

  ;; glsl
  'glsl-mode

  ;; haskell
  'haskell-mode

  ;; themes
  'inkpot-theme
  )

Local Packages

These are installed locally, (files in home dir) not part of a package manager.

(add-to-list 'load-path "~/.emacs.d/local/")
(when local-cfg/use-highlight-indent-vim
  (load "visual-indentation-mode"))


;; grr, only used for git-grep, local override to use comment color
;; otherwise we get horrible bold green!
(set-face-attribute 'success nil :foreground "#888888" :weight 'normal)

;; vim style search
(when local-cfg/use-search-evil
  (setq evil-search-module 'evil-search)
  )

;; enable evil-mode leader (must come before evil mode)
(global-evil-leader-mode)
;; enable evil-mode
(evil-mode 1)
;; enable evil-mode surround
(global-evil-surround-mode 1)

;; disable, modes can explicitly enable
(global-eldoc-mode -1)

;; Store registers on exit (nice for macros)
(savehist-mode 1)
(setq
  savehist-additional-variables
  '(register-alist))


(when local-cfg/use-helm
  (require 'helm-config)
  (helm-mode 1)
  )

(when local-cfg/use-ivy
  (require 'ivy)
  (ivy-mode 1)
  (setq ivy-display-style 'fancy)
  (setq ivy-height 32)
  ;; does not count candidates
  (setq ivy-count-format "")

  ;; Case sensitive search (no '-i')
  (setq counsel-git-grep-cmd-default "git --no-pager grep --full-name -n --no-color -e %S")
  )

(when local-cfg/use-company
  ;; auto-complete size
  (setq company-tooltip-limit 40)
  ;; this can be slow, only perform explicit complete
  (setq company-idle-delay nil)
  (setq company-tooltip-idle-delay nil)
  )

Local Library Functions

Could be moved externally.

;; Wrapper for 'shell-command-on-region', keeps the selection.
(defun shell-command-on-region-and-select
  (start end command
    &optional output-buffer replace
    error-buffer display-error-buffer
    region-noncontiguous-p) "
Wrapper for 'shell-command-on-region', re-selecting the output.

Useful when called with a selection, so it can be modified in-place
"
  (interactive)
  (let ((buffer-size-init (buffer-size)))
    (when fci-mode-enabled (turn-off-fci-mode))
    (shell-command-on-region
      start end command output-buffer replace
      error-buffer display-error-buffer
      region-noncontiguous-p)
    (setq deactivate-mark nil)
    (setq end (+ end (- (buffer-size) buffer-size-init)))
    (set-mark start)
    (goto-char end)
    (activate-mark)
    ;; needed for evil line mode
    (when (string= evil-state "visual")
      (when (eq (evil-visual-type) evil-visual-line)
        (evil-visual-select start end 'line)
        )
      )
    )
  )


(defmacro without-fci-mode (&rest body) "
Run expression without fci mode, evaluates to the result of 'body'
"
  `
  (let ((fci-mode-enabled (bound-and-true-p fci-mode)))
    (when fci-mode-enabled (turn-off-fci-mode))
    (let ((result ,@body))
      (when fci-mode-enabled (turn-on-fci-mode))
      result
      )
    )
  )

(defun custom-popup (menu-def) "
Pop up menu
Takes a triple (content, prompt, default-index).
Where the content is any number of (string, function) pairs, each representing a menu item.
User can hit just the first char of a menu item to choose it.
Or click it with `mouse-1' or `mouse-2' to select it.
Or hit RET immediately to select the default item.
"
  (interactive)
  (let*
    (
      (menu-content (nth 0 menu-def))
      (menu-prompt (nth 1 menu-def))
      (menu-index (nth 2 menu-def))
      (icicle-Completions-max-columns               1)
      (icicle-show-Completions-initially-flag       t)
      (icicle-incremental-completion-delay          0.01)
      (icicle-top-level-when-sole-completion-flag   t)
      (icicle-top-level-when-sole-completion-delay  0.01)
      (icicle-default-value                         t)
      (icicle-show-Completions-help-flag            nil)
      (choice
        (completing-read
          ;; menu prompt & content
          menu-prompt menu-content nil t nil nil
          ;; default index
          (nth menu-index menu-content)
          )
        )
      (action  (cdr (assoc choice menu-content)))
      )
    (funcall action)
    )
  )

Display Options

;; show parens
(show-paren-mode 1)

;; hide the right fringe
;; (fringe-mode '(nil . 0))
;; disable entirely
(set-fringe-mode 0)

;; no startup screen
(setq inhibit-startup-screen t)
;; disable word-wrap
(set-default 'truncate-lines t)

;; line numbers
(when local-cfg/use-linum
  (global-linum-mode t)
  )

(when local-cfg/use-number-color
  (add-hook
    'prog-mode-hook
    (lambda ()
      ;; Now set by the theme
      (highlight-numbers-mode)
      )
    )
  )

Font Cycle

(when (display-graphic-p)
  (setq
    font-cycle-list
    (list
      ;; "Inconsolata-g 13" ;; broken
      ;; "Sudo 14"
      "Anonymous Pro Medium 14"
      "Consolas 15"
      "Fantasque Sans Mono Medium 14"
      "Fira Code Medium 13"
      "GohuFont Medium 11"
      "GohuFont Medium 8"
      "Hermit Medium 13"
      "IBM\ 3270 Medium 17"
      "Input Mono Light 15"
      "Iosevka Medium 17"
      "Luculent Medium 16"
      "Meslo LG S DZ Medium 13"
      ;; "Monoid Medium 13"
      "Tamzen Medium 16"
      "k knxt Medium 11"
      ; "IBM Plex Mono 13"
      ;; "Source Code Pro Semi-Bold 10" ;; 14 for 100 width
      "Source Code Pro Medium 12" ;; 14 for 100 width
      ;; "System1-iso" ;; cause continuous errors
      ;; "System2-iso"
      "Triskweline Medium 11"
      )
    )


  (defun font-index-update ()
    (set-face-attribute 'default nil :font (nth font-index font-cycle-list))
    )

  (defun font-index-cycle-forward ()
    (interactive)
    (progn
      (setq font-index (mod (+ font-index 1) (length font-cycle-list)))
      (font-index-update)
      (message (nth font-index font-cycle-list))
      )
    )

  (defun font-index-cycle-backward ()
    (interactive)
    (progn
      (setq font-index (mod (- font-index 1) (length font-cycle-list)))
      (font-index-update)
      (message (nth font-index font-cycle-list))
      )
    )

  ;; defaults
  (setq default-font-index 14)
  ;; (setq default-font-index 13)
  (setq font-index default-font-index)
  (font-index-update)
  )

Line Highlight

(when local-cfg/use-hline
  ;; highlight line
  (global-hl-line-mode 1)

  (when local-cfg/use-hline-indent
    ;; don't draw over indentation (annoying/distracting with indent guides)
    (defun my-hl-line-range-function ()
      (cons
        ;; (point)  ;; works nice too, cursor instead of indentation
        (save-excursion (back-to-indentation) (point))
        (line-beginning-position 2)
        )
      )
    (setq hl-line-range-function #'my-hl-line-range-function)
    )
  )

White Space

;; highlight non-aligning indent offset
(defun highlight-indent-offset () "
Draw the highlight line after indentation.
"
  (font-lock-add-keywords nil
    `
    (
      (,
        (lambda (limit)
          (re-search-forward
            ;; evaluates to "^ \\{4\\}*\\( \\{1,3\\}\\)[^ ]" when tab width is 4.
            (format "^ \\{%d\\}*\\( \\{1,%d\\}\\)[^ ]" tab-width (- tab-width 1))
            limit t))
        1 'whitespace-trailing
        )
      )
    )
  )

;; White Space: XXX, we can't use this else realtime toggle doesn't work.
;; (global-whitespace-mode t)

;; make whitespace-mode use just basic coloring
(defun local-cfg/display-whitespace-on ()
  (whitespace-mode 1)
  (setq
    whitespace-style
    '(face spaces space space-mark tabs tab tab-mark space-before-tab trailing))
  (setq
    whitespace-display-mappings '
    (
      (space-mark 32 [183] [46]) ; middle-dot
      (tab-mark 9 [9654 9] [92 9]) ; arrow
      )
    )

  (whitespace-toggle-options '(whitespace-style))
  )

(defun local-cfg/display-whitespace-off ()
  (whitespace-mode 0)

  (setq whitespace-style '(face trailing tabs))
  (setq whitespace-display-mappings '())

  (whitespace-toggle-options '(whitespace-style))
  )

;; for key binding
(defun show-whitespace-toggle ()
  (interactive)
  (if local-cfg/use-show-whitespace
    (setq local-cfg/use-show-whitespace nil)
    (setq local-cfg/use-show-whitespace t))

  (if local-cfg/use-show-whitespace
    (local-cfg/display-whitespace-on) (local-cfg/display-whitespace-off))
  )

;; Modes will likely override

(add-hook
  'text-mode-hook
  (lambda ()
    (if local-cfg/use-show-whitespace
      (local-cfg/display-whitespace-on)
      (local-cfg/display-whitespace-off)
      )
    )
  )

(add-hook
  'prog-mode-hook
  (lambda ()
    (if local-cfg/use-show-whitespace
      (local-cfg/display-whitespace-on)
      (local-cfg/display-whitespace-off)
      )
    )
  )

;; override white-space warning color, it becomes too distracting for code which already has it.
;; (set-face-attribute 'whitespace-trailing nil :background "#660000" :foreground nil)

;; Don't show trailing space in insert mode.

;; Need temp enable whitespace so font is available.
(whitespace-mode 1)
(set-face-attribute 'whitespace-trailing nil :background "#343443" :foreground nil)
(defvar local-cfg/whitespace-trailing-bg (face-attribute 'whitespace-trailing :background))

(defun local-cfg/enter-insert-mode ()
  (set-face-attribute 'whitespace-trailing nil :background nil :foreground nil))
(defun local-cfg/exit-insert-mode ()
  (set-face-attribute 'whitespace-trailing nil :background local-cfg/whitespace-trailing-bg :foreground nil))
(add-hook 'evil-insert-state-entry-hook 'local-cfg/enter-insert-mode)
(add-hook 'evil-insert-state-exit-hook  'local-cfg/exit-insert-mode)
(whitespace-mode 0)

Mode Line

Keep it simple!

;; Show column in status, not the line
(when local-cfg/use-linum
  (setq line-number-mode nil)
  )
(setq column-number-mode t)

;; write a function to do the spacing
;; disable for now
(when local-cfg/use-custom-mode-line
  (defun simple-mode-line-render (left right)
    "Return a string of `window-width' length containing LEFT, and RIGHT aligned respectively."
    (let* ((available-width (- (window-width) (length left))))
      (format (format "%%s %%%ds" available-width) left right)
      )
    )

  (setq-default
    mode-line-format
    '
    (
      (:eval
        (simple-mode-line-render
          ;; left
          (format-mode-line
            (quote
              (
                "%e "
                mode-line-buffer-identification
                " %l : %c"
                evil-mode-line-tag
                "[%*]"
                )
              )
            )
          ;; right
          (format-mode-line
            (quote
              (
                "%p%% "
                mode-line-frame-identification
                mode-line-modes
                mode-line-misc-info
                )
              )
            )
          )
        )
      )
    )
  )

;; MMB, copy filepath
(define-key
  mode-line-buffer-identification-keymap
  [mode-line mouse-2]
  (lambda ()
    (interactive)
    (let
      (
        (filename
          (if (equal major-mode 'dired-mode)
            default-directory
            (buffer-file-name)
            )
          )
        )
      (if filename
        (progn (gui-set-selection 'PRIMARY filename)
          (message "Copied to primary clipboard")
          )
        (progn (message "Unable to copy the filename")
          (sit-for 2)
          )
        )
      )
    )
  )

Display for Packages

Neo-Tree

(when local-cfg/use-neotree
  (setq
    neo-theme 'ascii
    neo-window-width 40
    )

  ;; See: find-file-in-project
  ;; https://www.emacswiki.org/emacs/NeoTree
  ;;
  ;; Used this answer with some edits:
  ;; https://github.com/jaypei/emacs-neotree/issues/149#issuecomment-263074312
  (defun neotree-project-dir-toggle () "
  Open NeoTree using the project root, using find-file-in-project,
  or the current buffer directory.
  "
    (interactive)
    (let
      (
        (project-dir
          (ignore-errors
            ;; Pick one: projectile or find-file-in-project
            ;; (projectile-project-root)
            (ffip-project-root)
            )
          )
        (file-name (buffer-file-name))
        (neo-smart-open t)
        )
      (if
        (and (fboundp 'neo-global--window-exists-p)
          (neo-global--window-exists-p))
        (neotree-hide)
        (progn
          (neotree-show)
          (if project-dir
            (neotree-dir project-dir))
          (if file-name
            (neotree-find file-name)
            )
          )
        )
      )
    )
  )

Mini-Map

(when local-cfg/use-minimap
  (setq
    minimap-width-fraction 0.01
    minimap-minimum-width 16
    minimap-hide-fringes t
    minimap-update-delay 0.2
    minimap-window-location 'right
    minimap-recenter-type 'middle
    ;; never enlarge fonts
    minimap-display-semantic-overlays nil
    minimap-enlarge-certain-faces nil
    ;; only explicitly enable
    minimap-major-modes '()
    )
  ;; background color of minimap
  (custom-set-faces
    '
    (minimap-active-region-background
      ((((background dark)) (:background "#333333")) (t (:background "#D3D3D3222222"))) "" :group 'minimap)
    '
    (minimap-font-face
      ((t (:family "Source Code Pro Black" :height 20 :bold t))) "" :group 'minimap)
    )

  (defun minimap-toggle ()
    "Toggle minimap for current buffer."
    (interactive)
    (if (minimap-get-window)
      (minimap-kill)
      (progn
        (setq minimap-major-modes (list major-mode))
        (minimap-mode 0)
        (minimap-mode 1)
        (setq minimap-major-modes '())
        )
      )
    )
  )

Fill Column Indicator (fci)

(when local-cfg/use-fci
  (add-hook 'text-mode-hook 'turn-on-fci-mode)
  (add-hook 'after-init-hook 'turn-on-fci-mode)

  (turn-on-fci-mode)
  (setq fci-rule-column 80)
  (setq fci-rule-width 4)
  (setq fci-rule-color "#4a2a4a")

  ;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ;; fci & autocomplete workaround!
  ;;
  ;; See: http://emacs.stackexchange.com/a/155/2418

  (defun sanityinc/fci-enabled-p () (symbol-value 'fci-mode))

  (defvar sanityinc/fci-mode-suppressed nil)
  (make-variable-buffer-local 'sanityinc/fci-mode-suppressed)

  (defadvice popup-create (before suppress-fci-mode activate)
    "Suspend fci-mode while popups are visible"
    (let ((fci-enabled (sanityinc/fci-enabled-p)))
      (when fci-enabled
        (setq sanityinc/fci-mode-suppressed fci-enabled)
        (turn-off-fci-mode)
        )
      )
    )

  (defadvice popup-delete (after restore-fci-mode activate)
    "Restore fci-mode when all popups have closed"
    (when (and sanityinc/fci-mode-suppressed (null popup-instances))
      (setq sanityinc/fci-mode-suppressed nil)
      (turn-on-fci-mode)
      )
    )

  ;; ~~~~~~~~~~~~~~~~~~~~~~~~~~
  ;; and again for company-mode
  (defvar-local company-fci-mode-on-p nil)
  (defun company-turn-off-fci (&rest ignore)
    (when (boundp 'fci-mode)
      (setq company-fci-mode-on-p fci-mode)
      (when fci-mode (fci-mode -1))
      )
    )
  (defun company-maybe-turn-on-fci (&rest ignore)
    (when company-fci-mode-on-p (fci-mode 1))
    )
  (add-hook 'company-completion-started-hook 'company-turn-off-fci)
  (add-hook 'company-completion-finished-hook 'company-maybe-turn-on-fci)
  (add-hook 'company-completion-cancelled-hook 'company-maybe-turn-on-fci)

  ;; end workaround
  ;; ~~~~~~~~~~~~~~


  ;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ;; fci out-of-window workaround

  (defvar local-cfg/fci-mode-suppressed nil)
  (make-variable-buffer-local 'local-cfg/fci-mode-suppressed)

  (defun fci-width-workaround (frame)
    (let
      (
        (fci-enabled (symbol-value 'fci-mode))
        (fci-column (if fci-rule-column fci-rule-column fill-column))
        )
      (if local-cfg/fci-mode-suppressed
        (when
          (and
            (eq fci-enabled nil)
            (< fci-column (+ (frame-width frame) (window-hscroll)))
            )
          (setq local-cfg/fci-mode-suppressed nil)
          (turn-on-fci-mode))
        ;; local-cfg/fci-mode-suppressed == nil
        (when
          (and
            fci-enabled
            (>= fci-column (+ (frame-width frame) (window-hscroll)))
            )
          (setq local-cfg/fci-mode-suppressed t)
          (turn-off-fci-mode)
          )
        )
      )
    )

  (add-hook 'window-size-change-functions 'fci-width-workaround)

  ;; end workaround
  ;; ~~~~~~~~~~~~~~

  ;; end local-cfg/use-fci
  )

(setq run-stuff-terminal-command "roxterm")

Theme Options

;; Theme doesn't set mode-line
(set-face-attribute
  'mode-line nil
  :background "#3e3e5e"
  :foreground "#b9b9b9"
  ;; no 3d-emboss
  :box '(:line-width 1 :color "#3e3e5e")
  )


;; end of display options
;; (needed for 'paren' display)
(load-theme 'inkpot t)

Editing Options

Case Sensitivity

;; case sensitive search
(setq-default case-fold-search nil)

(when local-cfg/use-search-evil
  (setq evil-ex-search-case 'sensitive)
  )

;; center on search next/previous (convenient)

(defadvice evil-ex-search-next (after advice-for-evil-ex-search-next activate)
  (evil-scroll-line-to-center (line-number-at-pos)))
(defadvice evil-ex-search-previous (after advice-for-evil-ex-search-previous activate)
  (evil-scroll-line-to-center (line-number-at-pos)))
(defadvice evil-jump-forward (after advice-for-evil-jump-forward activate)
  (evil-scroll-line-to-center (line-number-at-pos)))
(defadvice evil-jump-backward (after advice-for-evil-jump-backward activate)
  (evil-scroll-line-to-center (line-number-at-pos)))

;; case sensitive auto-complete
(setq ac-ignore-case nil)
;; auto-complete used by evil
(setq dabbrev-case-fold-search nil)

;; paste at cursor instead of cursor
(setq mouse-yank-at-point t)

;; don't delimit on _'s.
;; note that some modes need this to be set for their own syntax table.
(modify-syntax-entry ?_ "w")

;; (with-eval-after-load 'evil
;;   (defalias #'forward-evil-word #'forward-evil-symbol))

Indentation

;; yes, both are needed!
(setq default-tab-width 4)
(setq tab-width 4)
(setq-default evil-indent-convert-tabs nil)
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
(setq-default evil-shift-round nil)

;; needs to be done before python hook
(setq-default python-indent-guess-indent-offset nil)

(add-hook 'text-mode-hook 'auto-complete-mode)
(add-hook 'prog-mode-hook 'auto-complete-mode)

Packages

;; drag-stuff package
(drag-stuff-global-mode 1)

;; spelling
(when (not noninteractive)
  (add-hook 'flyspell-mode-hook 'flyspell-buffer)
  (add-hook 'text-mode-hook 'flyspell-mode)
  (add-hook 'prog-mode-hook 'flyspell-prog-mode)
  (setq flyspell-issue-message-flag nil)
  (setq flyspell-issue-welcome-flag nil)
  )

;; display bookmarks
;; .. disable, it's a little annoying.
;; (evil-visual-mark-mode)

;; Extend evil mode
(eval-after-load 'evil-ex
  '(evil-ex-define-cmd "retab" 'untabify))

File Type Hooks

(when local-cfg/use-fci
  (add-hook
    'prog-mode-hook
    (lambda ()
      (turn-on-fci-mode)
      )
    )
  )

Languages

(require 'cc-mode)

;; Generic doxygen formatting
(defconst custom-font-lock-doc-comments
  (let ((symbol "[a-zA-Z0-9_]+"))
    `
    (
      (,
        (concat "</?\\sw"                    ; HTML tags.
          "\\("
          (concat "\\sw\\|\\s \\|[=\n\r*.:]\\|"
            "\"[^\"]*\"\\|'[^']*'")
          "\\)*>")
        0 ,c-doc-markup-face-name prepend nil)
      (,(concat "\'" symbol "\'") ; 'symbol'
        0 ,c-doc-markup-face-name prepend nil)
      (,(concat "\`" symbol "\`") ; `symbol`
        0 ,c-doc-markup-face-name prepend nil)
      (,(concat "\`\`" symbol "\`\`") ; ``symbol``
        0 ,c-doc-markup-face-name prepend nil)
      (,
        (concat
          "[\\@]"           ;; start of Doxygen special command
          "\\(?:"
          "[a-z]+\\|"       ;; typical word Doxygen special @cmd or \cmd
          "[[:punct:]]+"    ;; non-word commands
          "\\)")
        0 ,c-doc-markup-face-name prepend nil)
      (,(concat "#" symbol) ; #some_c_synbol
        0 ,c-doc-markup-face-name prepend nil)
      )
    )
  )

;; Matches: /** doxy */  but not /***/
(defconst custom-font-lock-keywords
  `
  (
    (,
      (lambda (limit)
        (c-font-lock-doc-comments
          ;; While technically correct regarding Doxygen,
          ;; I only use: /** ... */
          ;; "/\\(//\\|\\*[\\*!][^\\*!]\\)"
          ;;
          ;; So use simple check.
          "/\\*\\*[^\\*]"
          limit custom-font-lock-doc-comments
          )
        )
      )
    )
  )
(setq-default c-doc-comment-style (quote (custom)))
;; end doxygen style

;; Operator Fonts
(defface font-lock-operator-face '((t (:foreground "#8b8bcd"))) "Basic face for operator." :group 'basic-faces)
(defface font-lock-delimit-face '((t (:foreground "#a09386"))) "Basic face for delimiters." :group 'basic-faces)

;; C-Like
(dolist (mode-iter '(c-mode c++-mode glsl-mode java-mode javascript-mode rust-mode))
  (font-lock-add-keywords mode-iter '(("\\([~^&\|!<>=,.\\+*/%-]\\)" 0 'font-lock-operator-face keep)))
  (font-lock-add-keywords mode-iter '(("\\([\]\[}{)(:;]\\)" 0 'font-lock-delimit-face keep)))
  ;; functions
  (font-lock-add-keywords mode-iter '(("\\([_a-zA-Z][_a-zA-Z0-9]*\\)\s*(" 1 'font-lock-function-name-face keep)))
  )

;; Scripting
(dolist (mode-iter '(python-mode lua-mode toml-mode))
  ;; additional @
  (font-lock-add-keywords mode-iter '(("\\([@~^&\|!<>:=,.\\+*/%-]\\)" 0 'font-lock-operator-face keep)))
  (font-lock-add-keywords mode-iter '(("\\([\]\[}{)(:;]\\)" 0 'font-lock-delimit-face keep)))
  )

;; Lisp-Like
(dolist (mode-iter '(emacs-lisp-mode))
  (font-lock-add-keywords mode-iter '(("\\([\]\[}{)(:;\\'`]\\)" 1 'font-lock-delimit-face keep)))
  )

;; CMake
(dolist (mode-iter '(cmake-mode))
  (font-lock-add-keywords mode-iter '(("\\([${}]\\)" 0 'font-lock-operator-face t)))
  (font-lock-add-keywords mode-iter '(("\\([\]\[<>)(:;]\\)" 0 'font-lock-delimit-face keep)))
  )

(defun c-generic-mode ()
  (setq-local indent-tabs-mode t)

  (setq-local fci-rule-column 120)
  ;; (setq-local c-default-style "blender-style")
  (setq-local c-basic-offset 4)
  (setq-local c-default-style "k&r")

  (setq-local c-block-comment-prefix "* ")
  ;; don't right align slashes.
  (setq-local c-auto-align-backslashes nil)

  ;; for C
  (setq
    comment-start "//"
    comment-end   "")

  ;; never re-indent while typing?, its infact handy for braces,
  ;; (when (fboundp 'electric-indent-mode) (electric-indent-mode -1))

  ;; Prefer no indentation for comment chars.
  (define-key c-mode-map (kbd "/") nil)
  (define-key c-mode-map (kbd "*") nil)
  (define-key c-mode-map (kbd ",") nil)
  (define-key c-mode-map (kbd "(") nil)
  (define-key c-mode-map (kbd ")") nil)
  (define-key c-mode-map (kbd ";") nil)
  (define-key c-mode-map (kbd ":") nil)
  ;; (define-key c-mode-map (kbd "{") nil)
  ;; (define-key c-mode-map (kbd "}") nil)

  ;; I use this already!
  (define-key c-mode-map (kbd "M-e") nil)
  (define-key c++-mode-map (kbd "M-e") nil)
  (define-key c-mode-map (kbd "M-q") nil)
  (define-key c++-mode-map (kbd "M-q") nil)

  ;; correct but tabs only, conflicts with smart-tabs
  ;; (c-set-offset 'arglist-intro '++)
  (c-set-offset 'arglist-intro (lambda (pair) 8))
  ;; Don't indent '{' when it's on it's own line.
  (c-set-offset 'substatement-open 0)
  ;; indent contents of switch statement
  (c-set-offset 'case-label '+)

  ;; Plugins
  (smart-tabs-advice c-indent-line c-basic-offset)
  (smart-tabs-advice c-indent-region c-basic-offset)
  (smart-tabs-mode)

  (setq-local ffip-patterns '("*.c" "*.cc" "*.cpp" "*.cxx" "*.m" "*.mm" "*.h" "*.hh" "*.hpp" "*.hxx" "*.inl"))
  (setq-local ffip-prune-patterns '("*/.*"))

  (setq-local
    counsel-git-grep-cmd-default
    (concat
      counsel-git-grep-cmd-default
      " -- "
      "'*.c' '*.cc' '*.cpp' '*.cxx' '*.m' '*.mm' '*.h' '*.hh' '*.hpp' '*.hxx' '*.inl'"
      ;; ignore
      ;; Keep intern/gawain, ghost
      "\
':!extern/**' \
':!intern/atomic/**' \
':!intern/audaspace/**' \
':!intern/container/**' \
':!intern/cycles/**' \
':!intern/decklink/**' \
':!intern/dualcon/**' \
':!intern/eigen/**' \
':!intern/elbeem/**' \
':!intern/ffmpeg/**' \
':!intern/glew-mx/**' \
':!intern/gpudirect/**' \
':!intern/guardedalloc/**' \
':!intern/iksolver/**' \
':!intern/itasc/**' \
':!intern/libmv/**' \
':!intern/locale/**' \
':!intern/memutil/**' \
':!intern/mikktspace/**' \
':!intern/moto/**' \
':!intern/opencolorio/**' \
':!intern/opensubdiv/**' \
':!intern/openvdb/**' \
':!intern/rigidbody/**' \
':!intern/smoke/**' \
':!intern/string/**' \
':!intern/utfconv/**' \
':!release/**' \
':!build_files/**' ':!doc/**'"
      )
    )

  ;; don't delimit on '_'
  (modify-syntax-entry ?_ "w")

  ;; https://github.com/atilaneves/cmake-ide

  ;; (flycheck-mode) ;; fails with GCC warnings!
  (setq-local cmake-ide-build-dir "/src/cmake_debug")
  (setq-local cmake-ide-make-command "make --no-print-directory")

  ;; (require 'irony) ;; optional, must have rtags installed
  ;; (add-hook 'irony-mode-hook #'irony-eldoc)

  (require 'rtags) ;; optional, must have rtags installed
  (require 'subr-x)  ;; grr, cmake-ide should do this!
  ;; (cmake-ide-setup)

  (company-mode) ;; rtags uses for auto-complete

  ;; disable, I dont want to use this!
  (setq-local abbrev-mode nil)

  ;; eldoc can be slow!
  (setq-local eldoc-documentation-function #'ignore)
  )

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

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

(add-hook
  'glsl-mode-hook
  (lambda ()
    (setq-local fci-rule-column 120)
    (setq-local indent-tabs-mode t)

    (when local-cfg/use-highlight-indent-hig
      (highlight-indent-guides-mode))

    ;; don't delimit on '_'
    (modify-syntax-entry ?_ "w")

    (setq-local ffip-patterns '("*.glsl"))
    (setq-local ffip-prune-patterns '("*/.*"))
    )
  )

(add-hook
  'haskell-mode-hook
  (lambda ()
    (setq-local fci-rule-column 120)
    (setq-local indent-tabs-mode nil)

    (when local-cfg/use-highlight-indent-hig
      (highlight-indent-guides-mode))

    (setq-local ffip-patterns '("*.hs"))
    (setq-local ffip-prune-patterns '("*/.*"))
    )
  )

(add-hook
  'rust-mode-hook
  (lambda ()
    (setq-local fci-rule-column 100)
    (setq-local indent-tabs-mode nil)
    (highlight-indent-offset)

    (setq-local ffip-patterns '("*.rs" "*.toml"))
    (setq-local ffip-prune-patterns '("*/.*" "*/target/*"))

    (company-mode)
    (racer-mode)
    ;; racer's eldoc can be very slow
    ;; (eldoc-mode)
    (setq-local eldoc-documentation-function #'ignore)
    )
  )

;; keep toml similar to rust
(add-hook
  'toml-mode-hook
  (lambda ()
    (setq-local fci-rule-column 100)
    (setq-local indent-tabs-mode nil)

    (setq-local ffip-patterns '("*.rs" "*.toml"))
    (setq-local ffip-prune-patterns '("*/.*" "*/target/*"))
    )
  )

Scripts

(add-hook
  'lua-mode-hook
  (lambda ()
    (setq-local fci-rule-column 120)
    (setq-local tab-width 4)
    (setq-local lua-indent-level 4)
    (setq-local indent-tabs-mode nil)
    (highlight-indent-offset)

    (setq-local ffip-patterns '("*.lua"))
    (setq-local ffip-prune-patterns '("*/.*"))
    )
  )

(add-hook
  'python-mode-hook
  (lambda ()
    ;; (setq-local fci-rule-column 80)
    (setq-local fci-rule-column 120)
    (setq-local tab-width 4)
    (setq-local indent-tabs-mode nil)

    (when local-cfg/use-highlight-indent-hig
      (highlight-indent-mode))
    (when local-cfg/use-highlight-indent-vim
      (setq-local visual-indentation-width tab-width)
      (visual-indentation-mode)
      )
    (highlight-indent-offset)

    ;; Prefer no indentation for some chars.
    (setq-local electric-indent-chars (delq ?: electric-indent-chars))

    (setq-local ffip-patterns '("*.py"))
    (setq-local ffip-prune-patterns '("*/.*"))

    ;; annoying, nicer to disable always
    (local-cfg/display-whitespace-off)
    )
  )

(add-hook
  'sh-mode-hook
  (lambda ()
    (setq-local fci-rule-column 120)
    (setq-local tab-width 4)
    (setq-local indent-tabs-mode t)
    (highlight-indent-offset)

    (setq-local ffip-patterns '("*.sh"))
    (setq-local ffip-prune-patterns '("*/.*"))
    )
  )

(add-hook
  'emacs-lisp-mode-hook
  (lambda ()
    (setq-local fci-rule-column 120)
    (setq-local tab-width 2)
    (setq-local evil-shift-width 2)
    (setq-local indent-tabs-mode nil)

    (if local-cfg/use-highlight-indent-vim
      (progn
        (setq-local visual-indentation-width tab-width)
        (visual-indentation-mode)
        )
      (when local-cfg/use-highlight-indent-hig
        (highlight-indent-guides-mode))
      )

    (setq-local ffip-patterns '("*.el"))
    (setq-local ffip-prune-patterns '("*/.*"))

    (setq-local lisp-indent-function nil)
    (setq-local lisp-indent-offset 2)

    (eldoc-mode)

    ;; annoying, nicer to disable always
    (local-cfg/display-whitespace-off)

    )
  )

Build-System

(add-hook
  'makefile-mode-hook
  (lambda ()
    (setq-local fci-rule-column 120)
    (setq-local indent-tabs-mode t)
    (setq-local tab-width 4)
    (setq-local evil-shift-width 4)
    (setq-local ffip-patterns '("Makefile" "GNUmakefile" "*.make"))

    (setq-local
      counsel-git-grep-cmd-default
      (concat
        counsel-git-grep-cmd-default
        " -- "
        "'Makefile' 'GNUmakefile' '*.make'"
        ))

    )
  )

(add-hook
  'cmake-mode-hook
  (lambda ()
    (setq-local fci-rule-column 120)
    (setq-local indent-tabs-mode t)
    (setq-local tab-width 4)
    (setq-local evil-shift-width 4)
    (setq-local ffip-patterns '("*.cmake" "*.txt"))

    ;; cmake-mode options
    (setq-local cmake-tab-width 4)

    (setq-local
      counsel-git-grep-cmd-default
      (concat
        counsel-git-grep-cmd-default
        " -- "
        "'CMakeLists.txt' '*.cmake'"
        ))

    )
  )

Markup

(add-hook
  'org-mode-hook
  (lambda ()
    (setq-local fci-rule-column 120)
    (setq-local indent-tabs-mode nil)
    (setq-local tab-width 4)
    (setq-local evil-shift-width 4)

    (when local-cfg/use-highlight-indent-hig
      (highlight-indent-guides-mode))

    ;; don't delimit on '_'
    (modify-syntax-entry ?_ "w")

    (setq-local ffip-patterns '("*.org"))
    )
  )

(add-hook
  'rst-mode-hook
  (lambda ()
    (setq-local fci-rule-column 120)
    (setq-local indent-tabs-mode nil)
    (setq-local tab-width 3)
    (setq-local evil-shift-width 3)

    (when local-cfg/use-highlight-indent-hig
      (highlight-indent-guides-mode))


    ;; ignore RST keys
    (define-key rst-mode-map (kbd "C-=") nil)

    ;; don't delimit on '_'
    (modify-syntax-entry ?_ "w")

    (setq-local ffip-patterns '("*.rst" "*.py"))
    )
  )

Utility Macros

Undo Collapse Macro

http://emacs.stackexchange.com/a/7560/2418

(defun undo-collapse-begin (marker) "
Mark the beginning of a collapsible undo block.
This must be followed with a call to undo-collapse-end with a marker
eq to this one.
"
  (push marker buffer-undo-list))

(defun undo-collapse-end (marker) "
Collapse undo history until a matching marker.
"
  (cond
    ((eq (car buffer-undo-list) marker)
      (setq buffer-undo-list (cdr buffer-undo-list))
      )
    (t
      (let ((l buffer-undo-list))
        (while (not (eq (cadr l) marker))
          (cond
            ((null (cdr l))
              (error "undo-collapse-end with no matching marker"))
            ((eq (cadr l) nil)
              (setf (cdr l) (cddr l))
              )
            (t (setq l (cdr l)))
            )
          )
        ;; remove the marker
        (setf (cdr l) (cddr l))
        )
      )
    )
  )

(defmacro with-undo-collapse (&rest body) "
Execute body, then collapse any resulting undo boundaries.
"
  (declare (indent 0))
  (let
    (
      (marker (list 'apply 'identity nil)) ; build a fresh list
      (buffer-var (make-symbol "buffer")))
    `
    (let ((,buffer-var (current-buffer)))
      (unwind-protect
        (progn
          (undo-collapse-begin ',marker)
          ,@body)
        (with-current-buffer ,buffer-var
          (undo-collapse-end ',marker)
          )
        )
      )
    )
  )

KeyMap Macro (kmacro) Collapses Undo

(defmacro kmacro-fn (keys)
  `
  (lambda (&optional arg) "" (interactive "p")
    (with-undo-collapse
      (kmacro-exec-ring-item (quote (,keys 0 "%d")) arg)
      )
    )
  )

(defmacro kmacro-call (keys)
  `
  (with-undo-collapse
    (kmacro-exec-ring-item (quote (,keys 0 "%d")) arg)
    )
  )

Key Bindings

;; First unbind keys!
(dolist
  (key
    '
    (
      ;; electric indent mode, gets in way of evil-style keys for plugins
      "\C-j"
      "\C-k"
      "\C-m"
      "\C-u"
      ))
  (global-unset-key key)
  )


(evil-leader/set-leader "<SPC>")

Application Keys

(global-set-key (kbd "C-M-w") 'make-frame-command)
(global-set-key (kbd "<C-escape>") 'kill-this-buffer)

;; scale entire UI, solves annoying mismatches
(global-set-key (kbd "C-=") 'default-text-scale-increase)
(global-set-key (kbd "C--") 'default-text-scale-decrease)

(global-set-key (kbd "<C-mouse-4>") 'default-text-scale-increase)
(global-set-key (kbd "<C-mouse-5>") 'default-text-scale-decrease)

(global-set-key (kbd "C-0") 'text-scale-mode)

(defun save-buffer-always () "
Save the buffer even if it is not modified.
"
  (interactive)
  (set-buffer-modified-p t)
  (save-buffer)
  ;; weak! ensure we're mostly refreshed though
  (font-lock-fontify-buffer)
  )
;; Don't register for redo.
(evil-declare-abort-repeat 'save-buffer-always)

(global-set-key (kbd "C-s") 'save-buffer-always)

;; execute current line in a terminal! (ctrl-alt-shift-enter to avoid accidents!)
(global-set-key (kbd "<C-M-S-return>") 'run-stuff-command-on-region-or-line)


(defun doxygen-preview () "
Show the doxygen for the current file
"
  (interactive)
  ;; (call-process-shell-command
  (shell-command
    (concat
      "~/.emacs.d/bin/doxygen_single_file --browse doc/doxygen/Doxyfile "
      (buffer-file-name)
      )
    )
  )

(global-set-key (kbd "<f1>") 'doxygen-preview)

(global-set-key (kbd "<f2>") 'delete-trailing-whitespace)

(global-set-key (kbd "<f6>") 'next-error)
(global-set-key (kbd "<S-f6>") 'previous-error)


;; (define-key global-map (kbd "M-e") 'neotree-toggle)

(when local-cfg/use-minimap
  (define-key global-map (kbd "M-q") 'minimap-toggle))
(define-key global-map (kbd "M-w") 'show-whitespace-toggle)
(when local-cfg/use-neotree
  (define-key global-map (kbd "M-e") 'neotree-project-dir-toggle))

(define-key global-map (kbd "<C-iso-lefttab>") 'bs-cycle-previous)
(define-key global-map (kbd "<C-tab>") 'bs-cycle-next)

(when (display-graphic-p)
  (define-key global-map (read-kbd-macro "<M-prior>") 'font-index-cycle-backward)
  (define-key global-map (read-kbd-macro "<M-next>") 'font-index-cycle-forward)
  )


(when local-cfg/use-helm
  (global-set-key (kbd "M-x") #'helm-M-x)
  (global-set-key (kbd "C-k") 'helm-projectile-find-file-dwim)
  )

(when local-cfg/use-ivy
  (global-set-key (kbd "M-x") 'counsel-M-x)
  (global-set-key (kbd "C-k") 'find-file-in-project)
  (global-set-key (kbd "C-S-k") 'ivy-switch-buffer)
  )

Normal Mode Keys

;; (define-key evil-normal-state-map (kbd "C-J") 'evil-forward-paragraph)
;; (define-key evil-normal-state-map (kbd "C-K") 'evil-backward-paragraph)

(define-key evil-normal-state-map (kbd "C-a") 'evil-numbers/inc-at-pt)
(define-key evil-normal-state-map (kbd "C-x") 'evil-numbers/dec-at-pt)

(define-key evil-normal-state-map (kbd "C-n") 'linum-relative-toggle)
(define-key evil-normal-state-map (kbd "C-M-n") 'linum-mode)

(define-key evil-normal-state-map (kbd "M-f") 'ace-jump-mode)
;; C-f is a vim shortcut for scrolling, but I rarely use it!
(define-key evil-normal-state-map (kbd "C-f") 'counsel-git-grep)
(define-key evil-normal-state-map (kbd "C-M-f") 'swiper)

(defun copy-line-up () "
Copy the current line up.
"
  (interactive)
  (copy-line 1)
  (forward-line -1))

(defun copy-line-down () "
Copy the current line down.
"
  (interactive)
  (copy-line 1))

(define-key evil-normal-state-map (kbd "M-j") 'drag-stuff-down)
(define-key evil-normal-state-map (kbd "M-k") 'drag-stuff-up)

(define-key evil-normal-state-map (kbd "C-M-j") 'copy-line-down)
(define-key evil-normal-state-map (kbd "C-M-k") 'copy-line-up)

Quick single line indent

;; ... now used for go to definition, and back
;; (define-key evil-normal-state-map (kbd "M-h") 'evil-shift-left-line)
;; (define-key evil-normal-state-map (kbd "M-l") 'evil-shift-right-line)

Surround

Uses macros, see: http://emacs.stackexchange.com/questions/70 for how to define.

(fset 'delete-surround-backtick                 (kmacro-fn [?d ?s ?`]))
(fset 'delete-surround-single_quote             (kmacro-fn [?d ?s ?']))
(fset 'delete-surround-double_quote             (kmacro-fn [?d ?s ?\"]))
(fset 'delete-surround-paren                    (kmacro-fn [?d ?s ?(]))
(fset 'delete-surround-bracket                  (kmacro-fn [?d ?s ?[]))
(fset 'delete-surround-brace                    (kmacro-fn [?d ?s ?{]))

(define-key evil-normal-state-map (kbd "M-`") 'delete-surround-backtick)
(define-key evil-normal-state-map (kbd "M-'") 'delete-surround-single_quote)
(define-key evil-normal-state-map (kbd "M-\"") 'delete-surround-double_quote)

(define-key evil-normal-state-map (kbd "M-(") 'delete-surround-paren)
(define-key evil-normal-state-map (kbd "M-)") 'delete-surround-paren)
(define-key evil-normal-state-map (kbd "M-[") 'delete-surround-bracket)
(define-key evil-normal-state-map (kbd "M-]") 'delete-surround-bracket)
(define-key evil-normal-state-map (kbd "M-{") 'delete-surround-brace)
(define-key evil-normal-state-map (kbd "M-}") 'delete-surround-brace)

(fset 'insert-surround-backtick                 (kmacro-fn [?S ?`]))
(fset 'insert-surround-single_quote             (kmacro-fn [?S ?']))
(fset 'insert-surround-double_quote             (kmacro-fn [?S ?\"]))
(fset 'insert-surround-paren                    (kmacro-fn [?S ?)]))
(fset 'insert-surround-bracket                  (kmacro-fn [?S ?]]))
(fset 'insert-surround-brace                    (kmacro-fn [?S ?}]))

(define-key evil-visual-state-map (kbd "M-`") 'insert-surround-backtick)
(define-key evil-visual-state-map (kbd "M-'") 'insert-surround-single_quote)
(define-key evil-visual-state-map (kbd "M-\"") 'insert-surround-double_quote)
(define-key evil-visual-state-map (kbd "M-(") 'insert-surround-paren)
(define-key evil-visual-state-map (kbd "M-)") 'insert-surround-paren)
(define-key evil-visual-state-map (kbd "M-[") 'insert-surround-bracket)
(define-key evil-visual-state-map (kbd "M-]") 'insert-surround-bracket)
(define-key evil-visual-state-map (kbd "M-{") 'insert-surround-brace)
(define-key evil-visual-state-map (kbd "M-}") 'insert-surround-brace)

;; special case, use for leader version
(fset
  'insert-surround-double-backtick`
  (lambda (&optional arg) "``" (interactive "p")
    (cond
      ((string= evil-state "visual") (kmacro-call [?S ?` ?g ?v ?S ?` ?g ?v]))
      ((string= evil-state "normal") (kmacro-call [?v ?i ?W ?S ?` ?g ?v ?S ?` ?l ?l]))
      )
    )
  )

(evil-leader/set-key "`" 'insert-surround-double-backtick)

;; end surround

Pointer Paste / Secondaty Selection

;; use secondary selection in insert mode
(define-key evil-insert-state-map (kbd "<down-mouse-1>") 'mouse-drag-secondary)
(define-key evil-insert-state-map (kbd "<drag-mouse-1>") 'mouse-drag-secondary)
(define-key evil-insert-state-map (kbd "<mouse-1>") 'mouse-start-secondary)
;;(define-key evil-insert-state-map (kbd "<mouse-2>") 'mouse-yank-secondary)
(define-key evil-insert-state-map (kbd "<mouse-2>") 'mouse-yank-secondary-and-deselect)
(define-key evil-insert-state-map (kbd "<M-down-mouse-1>") 'evil-mouse-drag-region)
(define-key evil-insert-state-map (kbd "<M-drag-mouse-1>") 'evil-mouse-drag-region)
(define-key evil-insert-state-map (kbd "<M-mouse-1>") 'mouse-set-point)
(define-key evil-insert-state-map (kbd "<M-mouse-2>") 'mouse-yank-primary)

(defun mouse-yank-secondary-and-deselect (click) "
Deselect after yanking, for quick select-copy. Uses primary as fallback.
"
  (interactive "*p")
  (if (overlay-start mouse-secondary-overlay)
    (progn
      ;; use the secondary buffer and clear it
      (mouse-yank-secondary click)
      (delete-overlay mouse-secondary-overlay)
      )
    (progn
      ;; fallback to primary buffer
      (mouse-yank-primary click)
      )
    )
  )

Line Dragging/Moving

see: http://stackoverflow.com/a/998472/432509

(defun copy-line (arg) "
Duplicate current line, leaving point in lower line.
"
  (interactive "*p")

  ;; save the point for undo
  (setq buffer-undo-list (cons (point) buffer-undo-list))

  ;; local variables for start and end of line
  (let
    (
      (bol (save-excursion (beginning-of-line) (point)))
      eol)
    (save-excursion

      ;; don't use forward-line for this, because you would have
      ;; to check whether you are at the end of the buffer
      (end-of-line)
      (setq eol (point))

      ;; store the line and disable the recording of undo information
      (let
        (
          (line (buffer-substring bol eol))
          (buffer-undo-list t)
          (count arg)
          )
        ;; insert the line arg times
        (while (> count 0)
          (newline)         ;; because there is no newline in 'line'
          (insert line)
          (setq count (1- count))
          )
        )

      ;; create the undo information
      (setq buffer-undo-list (cons (cons eol (point)) buffer-undo-list))
      )
    ) ; end-of-let

  ;; put the point in the lowest line and return
  (next-line arg))

Return Key Behavior

;; enter insert newline
(defun vi-open-line-above () "
Insert a newline above the current line and put point at beginning.
"
  (interactive)
  (unless (bolp)
    (beginning-of-line))
  (newline)
  (forward-line -1)
  )

(defun vi-open-line-below () "
Insert a newline below the current line and put point at beginning.
"
  (interactive)
  (unless (eolp)
    (end-of-line))
  (newline)
  )

;; simulate return in insert mode
(define-key evil-normal-state-map (kbd "<S-return>") 'generic-line-break-split)
(define-key evil-normal-state-map (kbd "<C-return>") 'generic-line-break-above)

(defun generic-line-break () "
Add a newline, without splitting the current line.
"
  (interactive)
  (cond
    ((or (string= major-mode "c-mode") (string= major-mode "c++-mode"))
      (unless (eolp)
        (end-of-line))
      (c-context-line-break)
      )
    ;; fallback
    (t
      (call-interactively 'vi-open-line-below))
    ))

(defun generic-line-break-above () "
Add a newline above the current line, without splitting the current line.
"
  (interactive)
  (cond
    ((or (string= major-mode "c-mode") (string= major-mode "c++-mode"))
      ;; note, this isn't perfect - if you perform it on the last line of a comment.
      (unless (eolp)
        (end-of-line))
      (c-context-line-break)
      ;; move line up and goto end
      (transpose-lines 1)
      (forward-line -2)
      (unless (eolp)
        (end-of-line))
      )
    ;; fallback
    (t
      (call-interactively 'vi-open-line-above))
    )
  )


(defun generic-line-break-split () "
Add a newline, splitting the current line.
"
  (interactive)
  (cond
    ((or (string= major-mode "c-mode") (string= major-mode "c++-mode"))
      (c-context-line-break)
      )
    ;; fallback
    (t
      (call-interactively 'indent-new-comment-line))
    )
  )

;; (define-key evil-normal-state-map (kbd "RET") 'vi-open-line-below)
(define-key evil-normal-state-map (kbd "RET") 'generic-line-break)

(defun generic-next () "
Follow link/goto declaration at point.
"
  (interactive)
  (cond
    ((string= major-mode "c-mode")
      ;; (call-interactively 'rtags-find-symbol-at-point))
      (call-interactively 'evil-jump-forward))
    ((string= major-mode "c++-mode")
      ;; (call-interactively 'rtags-find-symbol-at-point))
      (call-interactively 'evil-jump-forward))
    ((string= major-mode "rust-mode")
      ;; (call-interactively 'racer-find-definition))
      (call-interactively 'evil-jump-forward))
    ((string= major-mode "diff-mode")
      (call-interactively 'diff-goto-source-and-close))
    ;; fallback
    (t
      (call-interactively 'evil-jump-forward))
    )
  )

(defun generic-prev () "
Go back/out of the current location.
"
  (interactive)
  (cond
    ((string= major-mode "c-mode")
      ;; (call-interactively 'rtags-location-stack-back))
      (call-interactively 'evil-jump-backward))
    ((string= major-mode "c++-mode")
      ;; (call-interactively 'rtags-location-stack-back))
      (call-interactively 'evil-jump-backward))
    ((string= major-mode "rust-mode")
      ;; (call-interactively 'pop-tag-mark))
      (call-interactively 'evil-jump-backward))
    ((string= major-mode "diff-mode")
      (call-interactively 'kill-buffer-and-window))
    ;; fallback
    (t
      (call-interactively 'evil-jump-backward))
    )
  )

;; access as a different kind of 'lookup'
(defun generic-lookup () "
Follow link/goto line.
"
  (interactive)
  (cond
    ((string= major-mode "c-mode")
      (call-interactively 'rtags-find-symbol-at-point))
    ((string= major-mode "c++-mode")
      (call-interactively 'rtags-find-symbol-at-point))
    ((string= major-mode "rust-mode")
      (call-interactively 'racer-find-definition))
    ((string= major-mode "diff-mode")
      (call-interactively 'diff-goto-source-and-close))
    ;; fallback
    (t
      (call-interactively 'evil-jump-forward))
    )
  )

;; access as a different kind of 'usage'
(defun generic-usage () "
Go back/into references (find usage).
"
  (interactive)
  (cond
    ((string= major-mode "c-mode")
      (call-interactively 'rtags-find-references-at-point))
    ((string= major-mode "c++-mode")
      (call-interactively 'rtags-find-references-at-point))
    )
  )


;; Override pop-up-windows
(defun vc-root-diff-fullscreen () "
Open a diff of the repository in the current frame.
"
  (interactive)
  (let
    (
      (pop-up-windows nil)
      )
    (call-interactively 'vc-root-diff)
    )
  )

(defun diff-goto-source-and-close () "
Go to the source and close the current diff buffer.
"
  (interactive)
  (let
    (
      (buf (current-buffer))
      (pop-up-windows nil)
      )
    (diff-goto-source)
    (kill-buffer buf)
    )
  )

(define-key evil-normal-state-map (kbd "M-d") 'vc-root-diff-fullscreen)

;; go to next
(define-key evil-normal-state-map (kbd "M-l") 'generic-next)
;; go back
(define-key evil-normal-state-map (kbd "M-h") 'generic-prev)
;; lookup declaration
(define-key evil-normal-state-map (kbd "M-RET") 'generic-lookup)
;; lookup usage
(define-key evil-normal-state-map (kbd "C-M-h") 'generic-usage)

(add-hook
  'diff-mode-hook
  (lambda ()
    ;; go to definition (rust only)
    ;; (define-key diff-mode-shared-map (kbd "M-l") 'diff-goto-source-and-close)
    (define-key diff-mode-shared-map (kbd "M-l") 'diff-goto-source-and-close)
    (define-key diff-mode-shared-map (kbd "C-M-l") 'diff-goto-source)
    ;; go back
    (define-key diff-mode-shared-map (kbd "M-h") 'kill-buffer-and-window)
    )
  )

(defun c-doc-next () "
Follow link/goto line
"
  (interactive)
  (if (search-forward-regexp "\\(\\\\}\\|\\\\{\\)" nil t 1)
    (pcase (preceding-char)
      (?{ ;; Section Start
        (search-backward "/*" nil t 1)    ;; find start of comment
        (move-beginning-of-line nil)      ;; line start
        (recenter 6)                      ;; place view
        (search-forward "*/" nil t 1)     ;; comment end
        (next-line)                       ;; step out of the comment
        )
      (?} ;; Section End
        (search-forward "*/" nil t 1)     ;; comment end
        (move-beginning-of-line nil)      ;; un-indent
        (recenter)                        ;; place view (likely its already been moved down)
        (next-line)                       ;; step out of the comment
        )
      )
    ;; fallback
    (end-of-buffer)
    )
  )
(defun c-doc-prev () "
Follow link/goto line
"
  (interactive)
  (if (search-backward-regexp "\\(\\\\}\\|\\\\{\\)" nil t 1)
    (pcase (char-after (+ 1 (point)))
      (?{ ;; Section Start
        (search-backward "/*" nil t 1)    ;; find start of comment
        (move-beginning-of-line nil)      ;; line start
        (recenter 6)                      ;; place view
        (previous-line)                   ;; step out of the comment
        )
      (?} ;; Section End
        (search-backward "/*" nil t 1)    ;; comment end
        (move-beginning-of-line nil)      ;; line start
        (previous-line)                   ;; step out of the comment
        (recenter)                        ;; place view (likely its already been moved down)
        )
      )
    ;; fallback
    (beginning-of-buffer)
    )
  )

(defun generic-doc-next () "
Follow link/goto line
"
  (interactive)
  (cond
    ((string= major-mode "c-mode")
      (call-interactively 'c-doc-next))
    ((string= major-mode "c++-mode")
      (call-interactively 'c-doc-next))
    ((string= major-mode "diff-mode")
      (call-interactively 'diff-hunk-next))
    ;; TODO, other modes
    )
  )

(defun generic-doc-prev () "
Go back/out of
"
  (interactive)
  (cond
    ((string= major-mode "c-mode")
      (call-interactively 'c-doc-prev))
    ((string= major-mode "c++-mode")
      (call-interactively 'c-doc-prev))
    ((string= major-mode "diff-mode")
      (call-interactively 'diff-hunk-prev))
    ;; TODO, other modes
    )
  )

;; Handy in-document next/prev (based on doxy groups for eg)
(global-set-key (kbd "C-}") 'generic-doc-next)
(global-set-key (kbd "C-{") 'generic-doc-prev)
;; alternate access (page up/down)
(global-set-key (kbd "<C-next>") 'generic-doc-next)
(global-set-key (kbd "<C-prior>") 'generic-doc-prev)

;; handy, Same as S-{}

;; (global-set-key (kbd "<S-next>") 'evil-forward-paragraph)
;; (global-set-key (kbd "<S-prior>") 'evil-backward-paragraph)

;; Re-center is nicer
(global-set-key (kbd "<S-next>") (lambda () (interactive) (evil-forward-paragraph) (recenter)))
(global-set-key (kbd "<S-prior>") (lambda () (interactive) (evil-backward-paragraph) (recenter)))

;; https://emacs.stackexchange.com/questions/31454
(defun paste-and-indent-after ()
  (interactive)
  (with-undo-collapse
    (evil-paste-after 1)
    (evil-indent (evil-get-marker ?\[) (evil-get-marker ?\]))))
(defun paste-and-indent-before ()
  (interactive)
  (with-undo-collapse
    (evil-paste-before 1)
    (evil-indent (evil-get-marker ?\[) (evil-get-marker ?\]))))

(evil-leader/set-key "p" 'paste-and-indent-after)
(evil-leader/set-key "P" 'paste-and-indent-before)

Motion State Keys

Similar to normal mode?

;; jump between sections of a file
(define-key evil-motion-state-map (kbd "K") 'imenu)

Visual Mode Keys

(define-key evil-visual-state-map (kbd "M-h") 'evil-shift-left)
(define-key evil-visual-state-map (kbd "M-l") 'evil-shift-right)

;; Paste selection into the last edit-point
;; Useful so you can quickly exit insert mode, find the text and select it
;; then place it back where you were in insert mode - in a single step.
;;
;; Use '`^' to get us back to the last insert point:

;;   yank, last-insert-mark, paste, insert-mode
(fset 'paste-last-insert-from-selected (kmacro-fn [?y ?` ?^ ?P ?a]))
;;   yank-in-word, last-insert-mark, paste, insert-mode
(fset 'paste-last-insert-from-word (kmacro-fn [?y ?i ?W ?` ?^ ?P ?a]))

(define-key evil-visual-state-map (kbd "M-p") 'paste-last-insert-from-selected)
(define-key evil-normal-state-map (kbd "M-P") 'paste-last-insert-from-word)

(defun eval-region-as-py () "
Evaluate selection as a python expression, replacing it with the result
"
  (interactive)
  (without-fci-mode
    (shell-command-on-region-and-select
      (region-beginning)
      (region-end)
      "python -c 'import sys; sys.stdout.write(str((eval(sys.stdin.read()))))'" 0 t
      )
    )
  )

(define-key evil-visual-state-map (kbd "RET") 'eval-region-as-py)

Insert Mode Keys

;; default
(define-key evil-insert-state-map (kbd "RET") 'comment-indent-new-line)
;; for other modes
;; (evil-define-key 'insert c-mode-map (kbd "RET") 'c-indent-new-comment-line)
;; Smart tabs
;; (evil-define-key 'insert c-mode-map (kbd "RET") 'newline-and-indent)
(evil-define-key 'insert c-mode-map (kbd "RET") 'c-context-line-break)

;; Shift-Space -> 8 spaces
(defun insert-8-spaces () "Insert tab width as spaces" (interactive) (insert (make-string (* 2 tab-width) ?\s)))
(defun insert-4-spaces () "Insert tab width as spaces" (interactive) (insert (make-string tab-width ?\s)))

(define-key evil-insert-state-map (kbd "S-SPC") 'insert-8-spaces)

(define-key evil-insert-state-map (kbd "<backtab>") 'insert-4-spaces)

(define-key evil-insert-state-map (kbd "C-v") 'x-clipboard-yank)

(define-key evil-insert-state-map (kbd "M-h") 'backward-char)
(define-key evil-insert-state-map (kbd "M-j") 'evil-next-line)
(define-key evil-insert-state-map (kbd "M-k") 'evil-previous-line)
(define-key evil-insert-state-map (kbd "M-l") 'forward-char)

;; avoid using home/end in insert mode
(define-key evil-insert-state-map (kbd "M-^") 'move-beginning-of-line)
(define-key evil-insert-state-map (kbd "M-$") 'move-end-of-line)

(require 'auto-complete)
(require 'auto-complete-config)
(ac-config-default)
(setq ac-use-menu-map t)
(define-key ac-menu-map (kbd "C-j") 'ac-next)
(define-key ac-menu-map (kbd "C-k") 'ac-previous)
(define-key ac-menu-map (kbd "C-l") 'ac-complete)
(define-key ac-menu-map (kbd "C-h") 'ac-stop)

;; Simple auto-complete
(define-key evil-insert-state-map (kbd "C-n") 'auto-complete)

;; company
(when local-cfg/use-company
  ;; Context sensitive auto-complete (company mode).
  (define-key evil-insert-state-map (kbd "C-SPC") 'company-complete-common)
  )

;; jump words when C is held
(defun evil-forward-word-end-plusone () "
Forward word end, then right one.
"
  (interactive)
  (evil-forward-word-end)
  (forward-char))

(define-key evil-insert-state-map (kbd "C-M-h") 'evil-backward-word-begin)
;; (define-key evil-insert-state-map (kbd "C-M-l") 'evil-forward-word-end)
(define-key evil-insert-state-map (kbd "C-M-l") 'evil-forward-word-end-plusone)

(define-key evil-insert-state-map (kbd "<C-backspace>") 'evil-delete-backward-word)


(define-key evil-insert-state-map (kbd "<backspace>") 'backspace-whitespace-to-tab-stop)

(defun backspace-whitespace-to-tab-stop () "
Delete whitespace backwards to the next tab-stop, otherwise delete one character.
"
  (interactive)
  (if
    (or indent-tabs-mode
      (region-active-p)
      (save-excursion
        (> (point) (progn (back-to-indentation) (point)))))
    (call-interactively 'backward-delete-char)
    (let
      (
        (movement (% (current-column) tab-width))
        (p (point)))
      (when (= movement 0) (setq movement tab-width))
      ;; Account for edge case near beginning of buffer
      (setq movement (min (- p 1) movement))
      (save-match-data
        (if (string-match "[^\t ]*\\([\t ]+\\)$" (buffer-substring-no-properties (- p movement) p))
          (backward-delete-char (- (match-end 1) (match-beginning 1)))
          (call-interactively 'backward-delete-char)
          )
        )
      )
    )
  )


;; use dumb indentation (for now)
(define-key evil-insert-state-map (kbd "TAB") 'tab-to-tab-stop)

Build

(defun generic-build () "
Build for any language
"
  (interactive)
  (cond
    ((string= major-mode "c-mode")
      (call-interactively 'cmake-ide-compile))
    ((string= major-mode "c++-mode")
      (call-interactively 'cmake-ide-compile))
    )
  )

(global-set-key (kbd "C-b") 'generic-build)
(eval-after-load "evil-maps"
  (define-key evil-motion-state-map "\C-b" nil))

Comment Block (insert mode)

Add multi-line comment, leaving the cursor in the middle.

;; TODO, other languages? - add as needed.
(fset 'insert-comment-block-c (kmacro-fn [?/ ?* ?\s ?\s ?* ?/ ?\M-h ?\M-h ?\M-h]))
(fset 'insert-comment-block-python (kmacro-fn [?\" ?\" ?\" ?\s ?\s ?\" ?\" ?\" ?\M-h ?\M-h ?\M-h ?\M-h]))

(defun generic-comment-block () "
Enter multi-line comment
"
  (interactive)
  (cond
    ((string= major-mode "c-mode")
      (insert-comment-block-c))
    ((string= major-mode "c++-mode")
      (insert-comment-block-c))
    ((string= major-mode "rust-mode")
      (insert-comment-block-c))
    ((string= major-mode "python-mode")
      (insert-comment-block-python))
    )
  )

;; Handy way to insert a comment block in insert mode.
(define-key evil-insert-state-map (kbd "C-M-/") 'generic-comment-block)

Toggle Comments

(defun comment-or-uncomment-region-or-line () "
Comments or uncomments the region or the current line if there's no active region.
"
  (interactive)
  (let (beg end)
    (if (region-active-p)
      (setq beg (region-beginning) end (region-end))
      (setq beg (line-beginning-position) end (line-end-position))
      )
    (comment-or-uncomment-region beg end)
    )
  )
(define-key evil-normal-state-map (kbd "C-SPC") 'comment-or-uncomment-region-or-line)


;; Toggle Multi-Line Comments

(defun comment-or-uncomment-region-multi-line-py () "
Multi-line comment toggle (Python)
"
  (interactive)
  (without-fci-mode
    (shell-command-on-region-and-select
      (region-beginning) (region-end) "~/.emacs.d/bin/toggle_multi_line_comment_py" 0 t)))

(defun comment-or-uncomment-region-multi-line-c () "
Multi-line comment toggle (C)
"
  (interactive)
  (without-fci-mode
    (shell-command-on-region-and-select
      (region-beginning) (region-end) "~/.emacs.d/bin/toggle_multi_line_comment_c" 0 t)))

(evil-define-key 'visual c-mode-map (kbd "C-?") 'comment-or-uncomment-region-multi-line-c)
(evil-define-key 'visual python-mode-map (kbd "C-?") 'comment-or-uncomment-region-multi-line-py)

Keys for Packages

(when local-cfg/use-search-isearch
  (define-key isearch-mode-map (kbd "<down>") 'isearch-ring-advance)
  (define-key isearch-mode-map (kbd "<up>") 'isearch-ring-retreat)
  )


(evil-define-key 'normal neotree-mode-map (kbd "SPC") 'neotree-enter)
(evil-define-key 'normal neotree-mode-map (kbd "RET") 'neotree-enter)
(evil-define-key 'normal neotree-mode-map (kbd "M-l") 'neotree-enter)
(evil-define-key 'normal neotree-mode-map (kbd "M-h") 'neotree-select-up-node)
(evil-define-key 'normal neotree-mode-map (kbd "M-j") 'neotree-next-line)
(evil-define-key 'normal neotree-mode-map (kbd "M-k") 'neotree-previous-line)
(evil-define-key 'normal neotree-mode-map (kbd "q") 'neotree-hide)

Helm Keys

(when local-cfg/use-helm
  (define-key helm-map (kbd "C-j") 'helm-next-line)
  (define-key helm-map (kbd "C-k") 'helm-previous-line)
  (define-key helm-map (kbd "<C-return>") 'helm-maybe-exit-minibuffer)
  (define-key helm-map (kbd "C-l")        'helm-maybe-exit-minibuffer)
  (define-key helm-map (kbd "C-h")        'helm-keyboard-quit)
  )
;; --------
;; Ivy Keys
;; --------
;;
(when local-cfg/use-ivy
  (require 'ivy)
  (define-key ivy-minibuffer-map (kbd "C-j") 'next-line)
  (define-key ivy-minibuffer-map (kbd "C-k") 'previous-line)

  ;; open and next
  (define-key ivy-minibuffer-map (kbd "C-M-j") 'ivy-next-line-and-call)
  (define-key ivy-minibuffer-map (kbd "C-M-k") 'ivy-previous-line-and-call)

  (define-key ivy-minibuffer-map (kbd "<C-return>") 'ivy-done)
  )
;; ------------
;; Company Keys
;; ------------
;;
(when local-cfg/use-company
  (require 'company)
  (define-key company-search-map (kbd "C-j") 'company-select-next)
  (define-key company-search-map (kbd "C-k") 'company-select-previous)

  (define-key company-active-map (kbd "C-j") 'company-select-next)
  (define-key company-active-map (kbd "C-k") 'company-select-previous)

  (define-key company-active-map (kbd "C-h")        'company-abort)
  (define-key company-active-map (kbd "<C-return>") 'company-complete-selection)
  (define-key company-active-map (kbd "C-l")        'company-complete-selection)
  )

RTags (C/C++) Keys

;; (defun rtags-select-other-window-and-close ()
;;   "Go to the source and close the current diff buffer."
;;   (interactive)
;;   (let ((buf (current-buffer))
;;         (pop-up-windows nil))
;;     (rtags-select-other-window)
;;     (kill-buffer buf)))

(evil-define-key 'normal rtags-mode-map (kbd "M-l") 'rtags-select-other-window)
(evil-define-key 'normal rtags-mode-map (kbd "M-h") 'kill-buffer-and-window)
(evil-define-key 'normal rtags-mode-map (kbd "M-j") 'next-line)
(evil-define-key 'normal rtags-mode-map (kbd "M-k") 'previous-line)
(evil-define-key 'normal c-mode-map (kbd "C-S-u") 'rtags-find-all-references-at-point)
(evil-define-key 'normal c++-mode-map (kbd "C-S-u") 'rtags-find-all-references-at-point)

Package-Menu

doesn’t get basic evil-mode keys set!

(define-key package-menu-mode-map (kbd "j") 'next-line)
(define-key package-menu-mode-map (kbd "k") 'previous-line)
(define-key package-menu-mode-map (kbd "/") 'evil-ex-search-forward)
(define-key package-menu-mode-map (kbd "?") 'evil-ex-search-backward)

Custom Variables

(setq custom-file "~/.emacs.d/custom.el")
(load custom-file 'noerror)

Final Application Tasks

Anything that needs to be put last (keep to a minimum!).

;; Own env var to skip loading server.
(when (getenv "EMACS_USE_SERVER")
  (load "server")
  (unless (server-running-p) (server-start))
  )