* About
# -*- mode: org; -*-
#+TITLE: Wolfe's Literate Emacs Config
#+AUTHOR: Josh Wolfe
#+HTML_HEAD:
#+HTML_HEAD:
#+HTML_HEAD:
#+HTML_HEAD:
#+HTML_HEAD:
#+HTML_HEAD:
#+LATEX_HEADER: \usepackage[margin=0.7in]{geometry}
#+HTML: 
This literate config is best read [[http://wolfecub.github.io/dotfiles/][here]] or in emacs.
This page is generated and kept up to date using a combination of
[[https://travis-ci.org/WolfeCub/dotfiles/][travis ci]] and [[https://github.com/fniessen/org-html-themes][ReadTheOrg]]. If you want to see the script that travis
uses [[https://github.com/WolfeCub/dotfiles/blob/master/.travis/build_site.sh][here]] is the bash script it runs and [[https://github.com/WolfeCub/dotfiles/blob/master/.travis/generate-html.el][this]] is the =.el= file that
it runs through emacs to generate the html page (this was mostly stolen
from IvanMalison).
Included in this section is also my export headers. These are responsible
for including the ReadTheOrg theme as well as some metadata and options
like title, author, table of contents etc. If you wish to see the headers
I'm using, [[https://raw.githubusercontent.com/WolfeCub/dotfiles/master/emacs/.emacs.d/README.org][this]] is the raw org file.
* Variables
Variables come at the beginning so that they're consistently available.
If you don't care about these [[Startup][click here to skip over them]].
#+BEGIN_SRC emacs-lisp :tangle yes
(defvar wolfe/literate-config-name "README.org"
"The name of my literate config")
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defvar wolfe/init-file (concat user-emacs-directory wolfe/literate-config-name)
"The path to my literate config file")
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defvar wolfe/linux? (eq system-type 'gnu/linux)
"Are we on linux?")
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defvar wolfe/windows? (eq system-type 'windows-nt)
"Are we on windows?")
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defvar wolfe/org-ellipsis
(if (display-graphic-p)
"⤵"
"...")
"The indicates if an `org-mode' tree can be expanded")
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defvar wolfe/project-path
(cond
(wolfe/linux? "~/Projects/")
(wolfe/windows? "C:/dev/")
(:else nil))
"Path to my projects directory")
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defvar wolfe/org-dropbox-path
(cond
(wolfe/linux?
"~/Dropbox/org/")
(wolfe/windows?
"C:\\Users\\Josh\\Dropbox\\org\\")
(:else nil))
"Path to my org files inside dropbox")
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defvar wolfe/using-light nil
"Indicates whether we're using my light theme")
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defvar wolfe/lisp-dir-path "~/.emacs.d/lisp/"
"Path to my custom lisp files")
#+END_SRC
* Startup
My graphical settings change depending on whether I'm in terminal
and if a command line flag (=-light=) was specified.
** Theme Setup
This should be run regardless of whether I'm in terminal vs gui or dark vs light.
#+BEGIN_SRC emacs-lisp :tangle yes
(setq custom-theme-directory "~/.emacs.d/themes")
(setq wolfe/using-light (member "-light" command-line-args))
(setq command-line-args (delete "-light" command-line-args))
#+END_SRC
** Dark
Configuration for my dark theme =base16 default dark= which is loaded by default.
*** Common
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/dark-setup ()
(use-package base16-theme
:config
(load-theme 'base16-default-dark t)
(if (display-graphic-p)
(wolfe/dark-gui-setup)
(wolfe/dark-term-setup))))
#+END_SRC
*** Graphical
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/dark-gui-setup ()
(defvar my/base16-colors base16-default-dark-colors)
(setq evil-emacs-state-cursor `(,(plist-get my/base16-colors :base0D) box)
evil-insert-state-cursor `(,(plist-get my/base16-colors :base0D) bar)
evil-motion-state-cursor `(,(plist-get my/base16-colors :base0E) box)
evil-normal-state-cursor `(,(plist-get my/base16-colors :base07) box)
evil-replace-state-cursor `(,(plist-get my/base16-colors :base08) bar)
evil-visual-state-cursor `(,(plist-get my/base16-colors :base09) box))
(set-face-attribute 'fringe nil :background nil)
(custom-set-faces
'(region ((t (:background "gray19"))))
'(org-block ((t (:foreground "#d8d8d8"))))
'(org-done ((t (:box (:line-width 1) :weight bold))))
'(org-level-1 ((t (:inherit outline-1 :height 1.3))))
'(org-todo ((t (:box (:line-width 1) :weight bold))))))
#+END_SRC
*** Terminal
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/dark-term-setup ()
(setq nlinum-format "%d ")
(custom-set-faces
'(line-number ((t (:background "color-18" :foreground "brightblack"))))
'(ivy-current-match ((t (:background "color-18" :foreground "color-16"))))
'(linum ((t (:background "color-18"))))
'(region ((t :background "color-19")))
'(mode-line ((t (:background "color-19" :foreground "brightblue" :box nil))))
'(mode-line-inactive
((t (:background "color-18" :foreground "color-244"))))))
#+END_SRC
** Light
Configuration for my light theme =leuven=. This is only loaded when the =-light= flag is
specified on the command line.
*** Common
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/light-setup ()
(use-package leuven-theme
:config
(custom-set-faces
'(ivy-subdir ((t (:background "gray88")))))
(load-theme 'leuven t)))
#+END_SRC
** Display check
This checks which setup we're in and calls the appropriate function above.
#+BEGIN_SRC emacs-lisp :tangle yes
(if wolfe/using-light
(wolfe/light-setup)
(wolfe/dark-setup))
#+END_SRC
* General Settings
Basic settings I can't really live without.
** Load Path
Recursively add =~/.emacs.d/lisp/= to my load path.
#+BEGIN_SRC emacs-lisp :tangle yes
(add-to-list 'load-path wolfe/lisp-dir-path)
(let ((default-directory wolfe/lisp-dir-path))
(normal-top-level-add-subdirs-to-load-path))
#+END_SRC
** Splash and Startup
This makes sure I'm presented with a nice blank =*scratch*=
buffer when emacs starts up.
#+BEGIN_SRC emacs-lisp :tangle yes
(setq inhibit-splash-screen t
inhibit-startup-message t
initial-scratch-message "") ; No scratch text
(defun display-startup-echo-area-message ()
(message "Welcome to the church of GNU/Emacs"))
#+END_SRC
** Graphics
*** Bars
I don't really want to have to look at menu bars that I'm not going to use
#+BEGIN_SRC emacs-lisp :tangle yes
(tool-bar-mode -1) ; No toolbar
(scroll-bar-mode -1) ; Hide scrollbars
(menu-bar-mode -1) ; No menubar
#+END_SRC
*** Fonts
Quick macro that tries to load the font. If it loads it return =t= so we
know not to try and load anything else if it returns =nil= then we'll
try a different font.
#+BEGIN_SRC emacs-lisp :tangle yes
(defmacro load-font-if-exists (family size)
(if (member family (font-family-list)) ; Set default font
(progn
(let ((font-and-size (format "%s-%s" family size)))
(add-to-list 'default-frame-alist `(font . ,font-and-size))
(set-face-attribute 'default t :font font-and-size))
t)
nil))
#+END_SRC
I like =Inconsolata-dz= a bit more than =Inconsolata= so use it if installed
otherwise fall back to regular =Inconsolata=.
#+BEGIN_SRC emacs-lisp :tangle yes
(unless (load-font-if-exists "Inconsolata-dz" 15)
(load-font-if-exists "Inconsolata" 15))
#+END_SRC
Make sure that UTF-8 is used everywhere.
#+BEGIN_SRC emacs-lisp :tangle yes
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-language-environment 'utf-8)
(set-selection-coding-system 'utf-8)
(setq locale-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
(set-input-method nil)
#+END_SRC
*** Column Marker
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package column-marker
:ensure nil
:config
(add-hook 'prog-mode-hook (lambda () (interactive) (column-marker-1 81)))
(custom-set-faces
'(column-marker-1 ((t (:background "dim gray"))))))
#+END_SRC
** Personal Defaults
Nothing to crazy here just the type of behaviour I personally
expect as default.
#+BEGIN_SRC emacs-lisp :tangle yes
(show-paren-mode t) ; Highlights matching parens
(fset 'yes-or-no-p 'y-or-n-p) ; y/n instead of yes/no
(blink-cursor-mode -1) ; No need to flash the cursor
(column-number-mode t) ; Show column in mode-line
(delete-selection-mode 1) ; Replace selection on insert
(setq-default truncate-lines t ; Don't wrap
indent-tabs-mode nil)
(setq vc-follow-symlinks t ; Always follow symlinks
tags-revert-without-query t ; Don't ask to reload TAGS file
echo-keystrokes 0.5
custom-file "~/.emacs.d/custom.el" ; Set custom file & don't load it
source-directory "~/Projects/emacs/")
#+END_SRC
** Misc
*** Vim Scrolloff
This makes scrolling gradual rather than by half page. I find that the
half page scroll really makes me lose where I am in the file so here
I make sure to scroll one line at a time. In addition I want to keep
what I'm working on centered so I start scrolling when the cursor is
10 lines away from the margin.
This behaviour in general emulates the =scrolloff= option in vim.
#+BEGIN_SRC emacs-lisp :tangle yes
(setq scroll-margin 10
scroll-step 1
scroll-conservatively 10000
scroll-preserve-screen-position 1)
#+END_SRC
*** Shell Tweaks
#+BEGIN_SRC emacs-lisp :tangle yes
(setq explicit-shell-file-name
(if (file-readable-p "/usr/bin/zsh") "/usr/bin/zsh" "/bin/bash"))
(when (eq system-type 'windows-nt)
(setq explicit-shell-file-name "cmdproxy.exe"))
#+END_SRC
** Mode Line
If we're in GUI emacs we make sure to use =powerline= otherwise we use
a custom mode line configuration.
#+BEGIN_SRC emacs-lisp :tangle yes
(if (display-graphic-p)
(use-package powerline
:init
(defadvice powerline-major-mode (around delight-powerline-major-mode activate)
(let ((inhibit-mode-name-delight nil))
ad-do-it))
:config
(setq powerline-arrow-shape 'curve
powerline-display-buffer-size nil
powerline-display-mule-info nil)
(powerline-default-theme)
(remove-hook 'focus-out-hook 'powerline-unset-selected-window)
(setq powerline-height 24))
(setq-default mode-line-format
(list
" "
;; is this buffer read-only?
'(:eval (when buffer-read-only
(propertize "RO"
'face 'font-lock-type-face
'help-echo "Buffer is read-only")))
;; was this buffer modified since the last save?
'(:eval (when (buffer-modified-p)
(propertize "M"
'face 'font-lock-warning-face
'help-echo "Buffer has been modified")))
" "
;; the buffer name; the file name as a tool tip
'(:eval (propertize "%b " 'face 'font-lock-keyword-face
'help-echo (buffer-file-name)))
;; the current major mode for the buffer.
"["
'(:eval (propertize (format-mode-line mode-name) 'face '(:family "Arial")
'help-echo buffer-file-coding-system))
'(:eval (propertize (format-mode-line minor-mode-alist)
'face '(:family "Arial")))
"] "
;; line and column
"(" ;; '%02' to set to 2 chars at least; prevents flickering
(propertize "%02l" 'face 'font-lock-type-face) ","
(propertize "%02c" 'face 'font-lock-type-face)
") "
;; relative position, size of file
"["
(propertize "%p" 'face 'font-lock-constant-face) ;; % above top
"/"
(propertize "%I" 'face 'font-lock-constant-face) ;; size
"] "
;; add the time, with the date and the emacs uptime in the tooltip
'(:eval (propertize (format-time-string "%H:%M")
'help-echo
(concat (format-time-string "%c; ")
(emacs-uptime "Uptime:%hh"))))
)))
#+END_SRC
** Line Numbers
Vim-like relative line numbering. If we're on the latest versions of emacs
(i.e. =26.0.50= or higher) then we should use the native line numbering
otherwise we fall back to =nlinum-relative=.
#+BEGIN_SRC emacs-lisp :tangle yes
(if (fboundp 'display-line-numbers-mode)
(progn
(setq display-line-numbers 'relative)
(add-hook 'prog-mode-hook 'display-line-numbers-mode))
(progn
(use-package nlinum-relative
:config
(nlinum-relative-setup-evil)
(setq nlinum-relative-redisplay-delay 0.25)
(setq nlinum-relative-current-symbol "")
(add-hook 'prog-mode-hook 'nlinum-relative-mode))))
#+END_SRC
* Functions
** Face Under Point
Returns the font lock face that's under the cursor.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun what-face (pos)
(interactive "d")
(let ((face (or (get-char-property (point) 'read-face-name)
(get-char-property (point) 'face))))
(if face (message "Face: %s" face) (message "No face at %d" pos))))
#+END_SRC
** Compile Project
Compiles the project without a prompt.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/compile-no-prompt ()
(interactive)
(let ((compilation-read-command nil))
(compile (eval compile-command))))
#+END_SRC
** Compile Dotfiles
Compiles all el files in the =~/.emacs.d= directory.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/compile-dot-emacs ()
"Byte-compile dotfiles."
(interactive)
(byte-recompile-directory user-emacs-directory 0))
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/clear-all-elc ()
(interactive)
(shell-command "find ~/.emacs.d/ -name \"*.elc\" -type f -delete"))
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/remove-elc-on-save ()
"If you're saving an emacs-lisp file, likely the .elc is no longer valid."
(add-hook 'after-save-hook
(lambda ()
(if (file-exists-p (concat buffer-file-name "c"))
(delete-file (concat buffer-file-name "c"))))
nil t))
(add-hook 'emacs-lisp-mode-hook 'wolfe/remove-elc-on-save)
#+END_SRC
** Find Tags
Looks up tag under point.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/find-tag ()
"Jump to the tag at point without prompting"
(interactive)
(find-tag (find-tag-default)))
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/create-tags ()
"Create the tags table"
(interactive)
(save-window-excursion (shell-command "etags -R -o ETAGS *")))
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defadvice xref-find-definitions (around refresh-etags activate)
"Rerun etags and reload tags if tag not found and redo find-tag.
If buffer is modified, ask about save before running etags."
(condition-case err
ad-do-it
(error (and (buffer-modified-p) (not (ding))
(save-buffer))
(save-window-excursion (shell-command "etags -R *"))
ad-do-it)))
#+END_SRC
** Terminal Suspend
Fixes =C-z= in terminal.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/controlz ()
(interactive)
(when (eq (display-graphic-p) nil)
(suspend-frame)))
#+END_SRC
** Dropbox
Utility functions for finding Dropbox directories/files.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/org-open (name)
"Opens the file in the dropbox path"
(interactive)
(evil-buffer-new nil (concat wolfe/org-dropbox-path name ".org")))
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/dropbox-start ()
(interactive)
(if (eq nil (file-exists-p "/virtual/wolfejos/dropbox/.dropbox-dist"))
(call-process-shell-command "(python ~/.emacs.d/dropbox.py start -i&)")
(call-process-shell-command "(python ~/.emacs.d/dropbox.py start&)")))
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/dropbox-stop ()
(interactive)
(call-process-shell-command "python ~/.emacs.d/dropbox.py stop&"))
#+END_SRC
** Reload
For reloading =init.el= file without restarting.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/load-init ()
"Reloads init file"
(interactive)
(load-file "~/.emacs.d/init.el"))
#+END_SRC
** Narrowing
Better narrowing.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun narrow-or-widen-dwim (p)
"Widen if buffer is narrowed, narrow-dwim otherwise.
Dwim means: region, org-src-block, org-subtree, or
defun, whichever applies first. Narrowing to
org-src-block actually calls `org-edit-src-code'.
With prefix P, don't widen, just narrow even if buffer
is already narrowed."
(interactive "P")
(declare (interactive-only))
(cond ((and (buffer-narrowed-p) (not p)) (widen))
((region-active-p)
(narrow-to-region (region-beginning)
(region-end)))
((derived-mode-p 'org-mode)
;; `org-edit-src-code' is not a real narrowing
;; command. Remove this first conditional if
;; you don't want it.
(cond ((ignore-errors (org-edit-src-code) t)
(delete-other-windows))
((ignore-errors (org-narrow-to-block) t))
(t (org-narrow-to-subtree))))
((derived-mode-p 'latex-mode)
(LaTeX-narrow-to-environment))
(t (narrow-to-defun))))
(defun wolfe/man ()
(if (executable-find "man")
(man (word-at-point))
(woman)))
#+END_SRC
** Open C# Project File
This function prompts for a file. It then opens that file and looks for a src/
directory above it. The dir can be any number of levels higher. In that folder
it looks for a C# .sln file and starts the an omnisharp server for that project.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/csharp-project ()
(interactive)
(setq path (read-file-name "File: " wolfe/project-path))
(setq split-path (split-string path "/"))
(if (member "src" split-path)
(catch 'loop
(dolist (item (reverse split-path))
(if (string-equal item "src")
(throw 'loop nil)
(delete item split-path)))
(message "src/ directory not found")))
(if (or (equal '("c:") split-path) (equal '() split-path))
(message "Could not find src directory for specified project")
(progn
(omnisharp-start-omnisharp-server (mapconcat 'identity split-path "/"))
(find-file path))))
#+END_SRC
** Hot Expand
Is used in one of my [[Hydra][hydras]] =wolfe/hydra-org-expand=. For inserting org-templates.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun hot-expand (str &optional additional-text)
"Expand org template."
(insert str)
(org-try-structure-completion)
(when additional-text
(insert additional-text)
(next-line)))
#+END_SRC
** Ag Project If In Project
If we're inside of a projectile project we'll use =projectile-ag= to
search the project otherwise just normal ag frow our working directory
does the job.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/ag-try-project ()
(interactive)
(if (projectile-project-p)
(call-interactively 'projectile-ag)
(call-interactively 'ag)))
#+END_SRC
** Projectile Invalidate From List
Select project from list of projectile projects to invalidate.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/projectile-invalidate-list ()
(interactive)
(projectile-invalidate-cache t))
#+END_SRC
** User Pass Tupple
Uses GPG to decrypt =file= and returns a list of the contents split on spaces.
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/get-user-pass (file)
(split-string
(car (last (split-string
(shell-command-to-string (concat "gpg --output - --decrypt "
(expand-file-name file)))
"[|\n]" t "[ \n]"))) " "))
#+END_SRC
* Org Mode
** General
Setup some basic quality of life org settings.
#+BEGIN_SRC emacs-lisp :tangle yes
(setq org-pretty-entities t
org-src-fontify-natively t
org-src-tab-acts-natively t
org-src-window-setup 'current-window
org-fontify-whole-heading-line t
org-fontify-done-headline t
org-fontify-quote-and-verse-blocks t
org-log-done 'time
org-agenda-use-time-grid nil
org-agenda-skip-deadline-if-done t
org-agenda-skip-scheduled-if-done t
org-ellipsis wolfe/org-ellipsis)
(org-babel-do-load-languages
'org-babel-load-languages
'((shell . t)
( dot . t)))
(global-set-key "\C-cl" 'org-store-link)
;; ispell ignores SRC blocks
(add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC"))
(add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_LATEX" . "#\\+END_LATEX"))
;; Refresh images after executing a src block
(add-hook 'org-babel-after-execute-hook
'(lambda ()
(when org-inline-image-overlays
(org-redisplay-inline-images))))
;; Open PDFs with zathura
(add-hook 'org-mode-hook
'(lambda ()
(setq org-file-apps
(append '(("\\.pdf\\'" . "zathura \"%s\"")) org-file-apps))))
#+END_SRC
** Bullets
Replaces the asterisks with nice UTF-8 bullets.
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package org-bullets
:config
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))
#+END_SRC
** Agenda
Setup org agenda for managing my life.
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package org-agenda
:ensure nil
:bind (("C-c a" . org-agenda)
:map org-agenda-mode-map
("j" . org-agenda-next-item)
("k" . org-agenda-previous-item))
:config
;; Formats the agenda into nice columns
(setq org-agenda-prefix-format
'((agenda . " %i %-12t% s %-12(car (last (org-get-outline-path)))")
(timeline . " % s")
(todo . " %i %-12:c")
(tags . " %i %-12:c")
(search . " %i %-12:c")))
;; Sets location of org files
(setq org-agenda-files '((concat wolfe/org-dropbox-path "everything.org")))
(setq browse-url-browser-function 'browse-url-chromium))
#+END_SRC
** Export
Setup html for syntax highlighting on export and add the apppropriate
minted package for PDF export.
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package htmlize)
(require 'ox-latex)
(add-to-list 'org-latex-packages-alist '("" "minted"))
(setq org-latex-listings 'minted)
(setq org-latex-pdf-process
'("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
#+END_SRC
* Keymaps
** Hydra
Customizable popup menus.
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package hydra)
#+END_SRC
*** Major Modes
**** C#
#+BEGIN_SRC emacs-lisp :tangle yes
(setq wolfe/hydra-csharp
(defhydra hydra-csharp (:color blue)
"Omnisharp"
("d" omnisharp-go-to-definition "Goto definition")
("D" omnisharp-go-to-definition-other-window "Pop-open definition")
("u" omnisharp-find-usages "Find usages")
("r" omnisharp-rename "Rename symbol")
("R" omnisharp-reload-solution "Reload solution")
("i" omnisharp-code-format-region "Indent region")
("I" omnisharp-code-format-entire-file "Indent entire file")
))
#+END_SRC
**** Org Mode
#+BEGIN_SRC emacs-lisp :tangle yes
(setq wolfe/hydra-org
(defhydra hydra-org (:color blue)
"Org Mode"
("t" (funcall wolfe/hydra-org-expand) "Expand template")))
#+END_SRC
**** Org Templates
#+BEGIN_SRC emacs-lisp :tangle yes
(setq wolfe/hydra-org-expand
(defhydra hydra-org-template (:color blue :hint nil)
"
_c_enter _q_uote _L_aTeX:
_l_atex _e_xample _i_ndex:
_a_scii _v_erse _I_NCLUDE:
_s_rc _t_angle _H_TML:
_h_tml _d_ot src _A_SCII:
"
("s" (hot-expand " for evil mode's use
(setq evil-want-C-i-jump nil)
:config
(evil-mode t)
(setq evil-split-window-below t
evil-vsplit-window-right t
evil-lookup-func #'wolfe/man)
(setq-default evil-symbol-word-search t)
(custom-set-variables '(evil-search-module (quote evil-search)))
(evil-ex-define-cmd "re[load]" 'wolfe/load-init) ; Custom reload command
(evil-ex-define-cmd "Q" 'save-buffers-kill-terminal) ; For typos
(define-key evil-ex-map "e " 'counsel-find-file) ; Trigger file completion :e
(global-unset-key (kbd "M-SPC")) ; Unbind secondary leader
(general-create-definer wolfe/bind-leader
:keymaps 'global
:states '(normal insert visual emacs)
:prefix "SPC"
:non-normal-prefix "M-SPC")
:general
(:states 'motion
"k" 'evil-previous-visual-line
"j" 'evil-next-visual-line)
(:states 'operator
"k" 'evil-previous-line
"j" 'evil-next-line)
(:states 'visual
"<" (lambda ()
(interactive)
(evil-shift-left (region-beginning) (region-end))
(evil-normal-state)
(evil-visual-restore))
">" (lambda ()
(interactive)
(evil-shift-right (region-beginning) (region-end))
(evil-normal-state)
(evil-visual-restore)))
(:states 'normal
"C-z" 'wolfe/controlz
"C-l" 'evil-ex-nohighlight)
(:states 'normal :prefix "g"
"a" (lambda (beginning end)
(interactive "r")
(if (use-region-p)
(align beginning end)
(align-current)))
"A" 'align-regexp)
(wolfe/bind-leader
"w" 'save-buffer
"S" 'eval-buffer
"s" 'eval-defun
"b" 'mode-line-other-buffer
"k" 'kill-buffer
"m" 'ivy-switch-buffer
"t" 'wolfe/find-tag
"e" 'iedit-mode
"c" 'wolfe/compile-no-prompt
"n" 'narrow-or-widen-dwim
"a" 'org-agenda
"g" 'magit-status
"f" 'wolfe/ag-try-project
"''" 'org-edit-src-exit
"#" 'wolfe/csharp-project
"p" (lambda() (interactive) (funcall wolfe/hydra-projectile))
";" (lambda() (interactive) (save-excursion (end-of-line) (insert-char ?\;)))
"id" (lambda() (interactive) (indent-region (point-min) (point-max)))
"o" (lambda() (interactive) (wolfe/org-open "everything"))
"SPC" (lambda() (interactive) (funcall (wolfe/hydra-selector)))
"init" (lambda() (interactive) (evil-buffer-new nil wolfe/init-file))))
#+END_SRC
*** Evil Surround
Tpope's surround
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package evil-surround
:config
(global-evil-surround-mode 1))
#+END_SRC
*** Evil Magit
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package evil-magit)
#+END_SRC
*** Evil Machit
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package evil-matchit
:config
(global-evil-matchit-mode 1))
#+END_SRC
* Project Management
** Ag
Emacs interface for ag
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package ag)
#+END_SRC
** Magit
Magic git interface from within emacs
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package magit
:config
(setq magit-bury-buffer-function
(lambda (con)
(kill-buffer)
(delete-window)))
(global-set-key "\C-x\g" 'magit-status))
#+END_SRC
** Projectile
Project management
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package projectile
:config
(use-package counsel-projectile
:config
(counsel-projectile-on))
(setq projectile-enable-caching t)
(setq projectile-indexing-method 'alien)
(setq projectile-globally-ignored-file-suffixes '(".dll" ".exe"))
(projectile-global-mode))
#+END_SRC
* Languages
** Generic Web
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package web-mode
:config
(add-to-list 'auto-mode-alist '("\\.html\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.php\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.js\\'" . web-mode))
(setq web-mode-enable-auto-closing t)
(setq web-mode-enable-auto-opening t)
(setq web-mode-enable-auto-indentation t))
(use-package json-mode)
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package company-restclient
:after company
:config
(add-to-list 'company-backends 'company-restclient))
#+END_SRC
** Javascript
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package company-tern
:after company
:config
(add-to-list 'company-backends 'company-tern)
(add-hook 'web-mode-hook 'tern-mode))
#+END_SRC
** Lisp Family
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package parinfer
:bind
(("C-," . parinfer-toggle-mode))
:init
(setq
parinfer-extensions '(defaults pretty-parens evil smart-tab smart-yank)
parinfer-lighters '(" Φi" . " Φp"))
(add-hook 'clojure-mode-hook #'parinfer-mode)
(add-hook 'emacs-lisp-mode-hook #'parinfer-mode)
(add-hook 'common-lisp-mode-hook #'parinfer-mode)
(add-hook 'scheme-mode-hook #'parinfer-mode)
(add-hook 'lisp-mode-hook #'parinfer-mode))
#+END_SRC
** Racket
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package racket-mode)
#+END_SRC
** Latex
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package latex-preview-pane
:ensure f)
#+END_SRC
** C/C++
#+BEGIN_SRC emacs-lisp :tangle yes
(setq gdb-many-windows t
gdb-show-main t
company-clang-insert-arguments nil)
(use-package company-irony
:after company
:config
(add-hook 'c++-mode-hook 'irony-mode)
(add-hook 'c-mode-hook 'irony-mode)
(eval-after-load 'company
'(add-to-list 'company-backends 'company-irony)))
#+END_SRC
** C#
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package omnisharp
:after company
:config
(setq omnisharp-server-executable-path "C:/emacs/omnisharp/Omnisharp.exe")
(add-hook 'csharp-mode-hook 'omnisharp-mode)
(add-to-list 'company-backends 'company-omnisharp))
#+END_SRC
** Python
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package company-jedi
:after company
:config
(add-to-list 'company-backends 'company-jedi))
#+END_SRC
** Shell Scripts
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package company-shell
:after company
:config
(add-to-list 'company-backends '(company-shell company-shell-env)))
#+END_SRC
* Utility
** Ranger
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package ranger
:config
(setq ranger-cleanup-on-disable t)
(ranger-override-dired-mode t))
#+END_SRC
** Iedit
Edit all instances of a string
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package iedit
:config
(setq iedit-toggle-key-default nil))
#+END_SRC
** Restclient
Postman inside of emacs.
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package restclient)
#+END_SRC
** Rainbow Mode
Shows hex colors inline.
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package rainbow-mode)
#+END_SRC
** Help Fns+
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package help-fns+)
#+END_SRC
** Org Jira
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package org-jira
:config
(setq jiralib-url "https://indigoca.atlassian.net"))
#+END_SRC
** Delight
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package delight
:config
(delight '((emacs-lisp-mode "ξ" :major)
(lisp-interaction-mode "λ" :major)
(python-mode "π" :major)
(org-mode "Ø" :major)
(company-mode " C" company)
(ivy-mode " ι" ivy)
(projectile-mode " ρ" projectile)
(eldoc-mode " ε" eldoc)
(flycheck-mode " ƒ" flycheck)
(undo-tree-mode "" undo-tree)
(auto-revert-mode "" autorevert))))
#+END_SRC
* Completion
** Ivy & Counsel
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package ivy
:demand
:bind (("M-x" . counsel-M-x)
("C-x C-f" . counsel-find-file)
:map ivy-minibuffer-map
("TAB" . ivy-next-line)
("RET" . ivy-alt-done))
:init
(use-package smex)
(use-package counsel)
:config
(setq ivy-re-builders-alist
'((t . ivy--regex-ignore-order)))
(setq ivy-wrap t)
(ivy-mode 1)
(eval-after-load "hydra" (use-package ivy-hydra)))
#+END_SRC
** Swiper
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package swiper
:bind (("C-s" . swiper)))
#+END_SRC
** Company
Autocomplete engine
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package company
:bind (:map company-active-map
("C-n" . company-select-next)
("C-p" . company-select-previous))
:init
(global-company-mode)
:config
(setq company-idle-delay 0) ; Delay to complete
(setq company-minimum-prefix-length 1)
(setq company-selection-wrap-around t) ; Loops around suggestions
(if (display-graphic-p)
(define-key company-active-map [tab] 'company-select-next)
(define-key company-active-map (kbd "C-i") 'company-select-next))
#+END_SRC
#+BEGIN_SRC emacs-lisp :tangle yes
(ignore-errors
(require 'color)
(let ((bg (face-attribute 'default :background)))
(custom-set-faces
`(company-tooltip ((t (:inherit default :background ,(color-lighten-name bg 2)))))
`(company-scrollbar-bg ((t (:background ,(color-lighten-name bg 10)))))
`(company-scrollbar-fg ((t (:background ,(color-lighten-name bg 5)))))
`(company-tooltip-selection ((t (:inherit font-lock-function-name-face))))
`(company-tooltip-common ((t (:inherit font-lock-constant-face))))))))
#+END_SRC
** Flycheck Linting
On the fly syntax checking
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package flycheck
:config
(global-flycheck-mode)
(with-eval-after-load 'flycheck
(setq-default flycheck-disabled-checkers '(emacs-lisp-checkdoc))))
#+END_SRC
* Misc
** Email
#+BEGIN_SRC emacs-lisp :tangle yes
(when (require 'mu4e nil 'noerror)
(setq mu4e-msg2pdf "/usr/bin/msg2pdf")
(setq
;; set mu4e as default mail client
mail-user-agent 'mu4e-user-agent
;; root mail directory - can't be switched
;; with context, can only be set once
mu4e-maildir "~/.mail"
mu4e-attachments-dir "~/Downloads/Attachments"
;; update command
mu4e-get-mail-command "mbsync -q -a"
;; update database every seven minutes
mu4e-update-interval (* 60 7)
;; use smtpmail (bundled with emacs) for sending
message-send-mail-function 'smtpmail-send-it
;; optionally log smtp output to a buffer
smtpmail-debug-info t
;; close sent message buffers
message-kill-buffer-on-exit t
;; customize list columns
mu4e-headers-fields '((:flags . 4)
(:from . 20)
(:human-date . 10)
(:subject))
;; for mbsync
mu4e-change-filenames-when-moving t
;; pick first context automatically on launch
mu4e-context-policy 'pick-first
;; use current context for new mail
mu4e-compose-context-policy nil
mu4e-confirm-quit nil)
(global-set-key (kbd "") 'mu4e)
(global-set-key (kbd "") 'mu4e-update-mail-and-index)
(setq mu4e-contexts
`(,(make-mu4e-context
:name "gmail"
:match-func (lambda(msg)
(when msg
(mu4e-message-contact-field-matches msg :to "@gmail.com")))
:vars '(
;; local directories, relative to mail root
(mu4e-sent-folder . "/gmail/[Gmail]/.Sent Mail")
(mu4e-drafts-folder . "/gmail/[Gmail]/.Drafts")
(mu4e-trash-folder . "/gmail/[Gmail]/.Trash")
(mu4e-refile-folder . "/gmail/[Gmail]/.All Mail")
;; account details
(user-mail-address . "joshuafwolfe@gmail.com")
(user-full-name . "Josh Wolfe")
(mu4e-user-mail-address-list . ( "@gmail.com" ))
;; gmail saves every outgoing message automatically
(mu4e-sent-messages-behavior . delete)
(mu4e-maildir-shortcuts . (("/gmail/INBOX" . ?j)
("/gmail/[Gmail]/.All Mail" . ?a)
("/gmail/[Gmail]/.Trash" . ?t)
("/gmail/[Gmail]/.Drafts" . ?d)))
;; outbound mail server
(smtpmail-smtp-server . "smtp.gmail.com")
;; outbound mail port
(smtpmail-smtp-service . 465)
;; use ssl
(smtpmail-stream-type . ssl)
;; the All Mail folder has a copy of every other folder's contents,
;; and duplicates search results, which is confusing
(mue4e-headers-skip-duplicates . t)))))
(use-package evil-mu4e))
#+END_SRC
** IRC
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package erc
:ensure nil
:config
(add-hook 'window-configuration-change-hook
'(lambda ()
(setq erc-fill-column (- (window-width) 2))))
(add-hook 'erc-mode-hook
'(lambda ()
(setq-local scroll-margin 1)))
(setq erc-rename-buffers t
erc-interpret-mirc-color t
erc-lurker-hide-list '("JOIN" "PART" "QUIT")
erc-autojoin-channels-alist '(("freenode.net" "#emacs")))
(defun wolfe/irc ()
(interactive)
(let* ((tupple (wolfe/get-user-pass "~/.authinfo.gpg"))
(user (car tupple))
(pass (cadr tupple)))
(erc
:server "irc.freenode.net"
:port 6667
:nick user
:password pass))))
#+END_SRC
** Meme
Meme creator from within emacs... what more is there to say?
#+BEGIN_SRC emacs-lisp :tangle yes
(use-package meme
:ensure nil
:commands (meme meme-file))
#+END_SRC
* Backups
Stores all backups and temp files in =~/.bak.emacs/=
#+BEGIN_SRC emacs-lisp :tangle yes
(setq backup-by-copying t) ; Stop shinanigans with links
(setq backup-directory-alist '((".*" . "~/.bak.emacs/backup/")))
;; Creates directory if it doesn't already exist
(if (eq nil (file-exists-p "~/.bak.emacs/"))
(make-directory "~/.bak.emacs/"))
;; Creates auto directory if it doesn't already exist
(if (eq nil (file-exists-p "~/.bak.emacs/auto"))
(make-directory "~/.bak.emacs/auto"))
;; backup in one place. flat, no tree structure
(setq auto-save-file-name-transforms '((".*" "~/.bak.emacs/auto/" t)))
#+END_SRC
* Testing
** Org Project
#+BEGIN_SRC emacs-lisp :tangle yes
(cond ((file-exists-p "~/Projects/org-project/")
(load-file "~/Projects/org-project/org-project.el")
(setq org-project-use-ag t))
((file-exists-p "C:/dev/SideProjects/org-project/")
(load-file "C:/dev/SideProjects/org-project/org-project.el")
(setq org-project-use-ag t)))
#+END_SRC
** Extract Dates
#+BEGIN_SRC emacs-lisp :tangle yes
(defun wolfe/extract-dates (file-path)
"Parse through a file for a list of all the comments"
(let (already-open
buf
start
(comments '()))
(setq already-open (find-buffer-visiting file-path)
buf (find-file-noselect file-path))
(with-current-buffer buf
(goto-char (point-min))
(while (setq start (text-property-any
(point) (point-max)
'face 'org-date))
(goto-char start)
(goto-char (next-single-char-property-change (point) 'face))
(let ((item (string-trim (buffer-substring-no-properties start (point)))))
(setq comments (cons item comments)))))
(unless already-open (kill-buffer buf))
(reverse comments)))
#+END_SRC