mirror of
https://github.com/gburd/nix-config.git
synced 2024-11-20 10:36:25 +00:00
1058 lines
37 KiB
Org Mode
1058 lines
37 KiB
Org Mode
#+TITLE: Gregory Burd's Emacs 24 Configuration
|
|
#+AUTHOR: Gregory Burd
|
|
#+EMAIL: greg@burd.me
|
|
#+OPTIONS: toc:3 num:nil
|
|
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="http://thomasf.github.io/solarized-css/solarized-light.min.css" />
|
|
|
|
* Configuration
|
|
Emacs is a special beast. Taming it takes a lot of care. In an
|
|
attempt to document/explain/share with the rest of the world, this
|
|
is my attempt at configuration as a literate program. It also shows
|
|
off the awesome power of org-mode, which makes all of this possible.
|
|
** User details
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: user-info
|
|
:END:
|
|
|
|
Emacs will normally pick this up automatically, but this way I can
|
|
be sure the right information is always present.
|
|
#+begin_src emacs-lisp
|
|
(setq user-full-name "Gregory Burd")
|
|
(setq user-mail-address "greg@burd.me")
|
|
#+end_src
|
|
** Environment
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: environment
|
|
:END:
|
|
|
|
There are plenty of things installed outside of the default
|
|
=PATH=. This allows me to establish additional =PATH= information. At
|
|
the moment, the only things that added are =/usr/local/bin= for
|
|
homebrew on OS X and =.cabal/bin= for [[http://www.haskell.org/cabal/][Haskell package binaries]].
|
|
|
|
Emacs lisp is really only a subset of common lisp, and I need to
|
|
have some of the additional functionality to make the configuration
|
|
and its dependencies work properly, which we get by requiring
|
|
[[http://www.emacswiki.org/emacs/CommonLispForEmacs][Common Lisp for Emacs]].
|
|
#+begin_src emacs-lisp
|
|
;(setq debug-on-error t)
|
|
;(setq debug-on-signal t)
|
|
(setenv "PATH" (concat "/usr/local/bin:/opt/local/bin:/usr/bin:/bin" (getenv "PATH")))
|
|
(require 'cl-lib)
|
|
#+end_src
|
|
*** Define default packages
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: default-packages
|
|
:END:
|
|
|
|
This is the list of packages used in this configuration.
|
|
#+begin_src emacs-lisp
|
|
(setq burd-packages '(
|
|
; clojure-mode
|
|
; clojure-test-mode
|
|
; csharp-mode
|
|
; nrepl
|
|
ac-slime
|
|
ag
|
|
;; auto-complete
|
|
;; electric-pair-mode
|
|
;; cc-guess
|
|
cc-mode
|
|
cmake-mode
|
|
coffee-mode
|
|
company
|
|
company-c-headers
|
|
company-cmake
|
|
deft
|
|
dockerfile-mode
|
|
editorconfig
|
|
elixir-mix
|
|
elixir-mode
|
|
eredis
|
|
erlang
|
|
feature-mode
|
|
flx
|
|
flx-ido
|
|
flx-isearch
|
|
flycheck
|
|
flycheck-google-cpplint
|
|
flycheck-ocaml
|
|
flycheck-pos-tip
|
|
flycheck-rust
|
|
gh
|
|
gist
|
|
git-commit
|
|
go-mode
|
|
graphviz-dot-mode
|
|
haml-mode
|
|
haskell-mode
|
|
htmlize
|
|
intellij-theme
|
|
lua-mode
|
|
magit
|
|
markdown-mode
|
|
marmalade
|
|
multi-web-mode
|
|
nix-mode
|
|
nodejs-repl
|
|
o-blog
|
|
org
|
|
paredit
|
|
pastebin
|
|
php-mode
|
|
puppet-mode
|
|
python-mode
|
|
python-pep8
|
|
restclient
|
|
rust-mode
|
|
rvm
|
|
scala-mode
|
|
smex
|
|
sml-mode
|
|
solarized-theme
|
|
toml-mode
|
|
web-mode
|
|
writegood-mode
|
|
ws-butler
|
|
yaml-mode))
|
|
#+end_src
|
|
** Package Management
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: package-management
|
|
:END:
|
|
|
|
Since Emacs 24, Emacs includes the Emacs Lisp Package Archive
|
|
([[http://www.emacswiki.org/emacs/ELPA][ELPA]]) by default. This provides a nice way to install additional
|
|
packages. Since the default package archive doesn't include
|
|
everything necessary, the [[http://marmalade-repo.org/][marmalade]], and [[http://melpa.milkbox.net/#][melpa]] repositories are
|
|
also added.
|
|
#+begin_src emacs-lisp
|
|
(add-to-list 'package-archives
|
|
'("melpa" . "http://melpa.org/packages/"))
|
|
(add-to-list 'package-archives
|
|
'("org" . "http://orgmode.org/elpa/"))
|
|
|
|
;; install any packages in burd-packages, if they are not installed already
|
|
(let ((refreshed nil))
|
|
(when (not package-archive-contents)
|
|
(package-refresh-contents)
|
|
(setq refreshed t))
|
|
(dolist (pkg burd-packages)
|
|
(when (and (not (package-installed-p pkg))
|
|
(assoc pkg package-archive-contents))
|
|
(unless refreshed
|
|
(package-refresh-contents)
|
|
(setq refreshed t))
|
|
(package-install pkg))))
|
|
|
|
(defun package-list-unaccounted-packages ()
|
|
"Like `package-list-packages', but shows only the packages that
|
|
are installed and are not in `burd-packages'. Useful for
|
|
cleaning out unwanted packages."
|
|
(interactive)
|
|
(package-show-package-list
|
|
(remove-if-not (lambda (x) (and (not (memq x burd-packages))
|
|
(not (package-built-in-p x))
|
|
(package-installed-p x)))
|
|
(mapcar 'car package-archive-contents))))
|
|
|
|
#+end_src
|
|
** Start-up options
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: start-up-options
|
|
:END:
|
|
|
|
*** Splash Screen
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: splash-screen
|
|
:END:
|
|
|
|
I want to skip straight to the scratch buffer. This turns off the
|
|
splash screen and puts me straight into the scratch buffer. I
|
|
don't really care to have anything in there either, so turn off
|
|
the message while we're at it. Since I end up using =org-mode=
|
|
most of the time, set the default mode accordingly.
|
|
#+begin_src emacs-lisp
|
|
(setq inhibit-splash-screen t
|
|
initial-scratch-message nil
|
|
initial-major-mode 'org-mode)
|
|
#+end_src
|
|
*** Scroll bar, Tool bar, Menu bar
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: menu-bars
|
|
:END:
|
|
|
|
Emacs starts up with way too much enabled. Turn off the scroll
|
|
bar, menu bar, and tool bar. There isn't really a reason to have
|
|
them on.
|
|
#+begin_src emacs-lisp
|
|
(when window-system
|
|
(scroll-bar-mode -1)
|
|
(tool-bar-mode -1)
|
|
(menu-bar-mode -1))
|
|
#+end_src
|
|
*** Marking text
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: regions
|
|
:END:
|
|
|
|
There are some behaviors in Emacs that aren't intuitive. Since I
|
|
pair with others that don't know how Emacs handles highlighting,
|
|
treat regions like other text editors. This means typing when the
|
|
mark is active will write over the marked region. Also, make the
|
|
common highlighting keystrokes work the way most people expect
|
|
them to. This saves a lot of time explaining how to highlight
|
|
areas of text. Emacs also has it's own clipboard and doesn't
|
|
respond to the system clipboard by default, so tell Emacs that
|
|
we're all friends and can get along.
|
|
#+begin_src emacs-lisp
|
|
(delete-selection-mode t)
|
|
(transient-mark-mode t)
|
|
(setq x-select-enable-clipboard t)
|
|
#+end_src
|
|
*** Display Settings
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: buffers
|
|
:END:
|
|
|
|
I have some modifications to the default display. First, a minor
|
|
tweak to the frame title. It's also nice to be able to see when a
|
|
file actually ends. This will put empty line markers into the left
|
|
hand side.
|
|
#+begin_src emacs-lisp
|
|
(when window-system
|
|
(setq frame-title-format '(buffer-file-name "%f" ("%b")))
|
|
(set-face-attribute 'default nil
|
|
:family "Fira Code"
|
|
:height 134
|
|
:weight 'normal
|
|
:width 'normal)
|
|
|
|
(when (functionp 'set-fontset-font)
|
|
(set-fontset-font "fontset-default"
|
|
'unicode
|
|
(font-spec :family "DejaVu Sans Mono"
|
|
:width 'normal
|
|
:size 12.4
|
|
:weight 'normal))))
|
|
|
|
(setq-default indicate-empty-lines t)
|
|
(setq-default fill-column 80)
|
|
; (setq-default auto-fill-mode nil)
|
|
(require 'newcomment)
|
|
(setq comment-auto-fill-only-comments 1)
|
|
(setq-default auto-fill-function 'do-auto-fill)
|
|
(when (not indicate-empty-lines)
|
|
(toggle-indicate-empty-lines))
|
|
#+end_src
|
|
*** Font Ligature
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: ligature
|
|
:END:
|
|
|
|
Modern fonts such as Fira Code and PragmataPro provide ligatures for common useful
|
|
programming constructs (for example -> to ⟶ or lambda to λ).
|
|
https://github.com/tonsky/FiraCode/wiki/Emacs-instructions
|
|
https://emacs.stackexchange.com/questions/9586/otf-ligature-support-in-emacs
|
|
https://www.reddit.com/r/emacs/comments/4sm6fa/how_to_enable_pragmatapro_ligatures/
|
|
#+begin_src emacs-lisp
|
|
(cl-defun fira-code-mode--make-alist (list)
|
|
"Generate prettify-symbols alist from LIST."
|
|
(let ((idx -1))
|
|
(mapcar
|
|
(lambda (s)
|
|
(setq idx (1+ idx))
|
|
(let* ((code (+ #Xe100 idx))
|
|
(width (string-width s))
|
|
(prefix ())
|
|
(suffix '(?\s (Br . Br)))
|
|
(n 1))
|
|
(while (< n width)
|
|
(setq prefix (append prefix '(?\s (Br . Bl))))
|
|
(setq n (1+ n)))
|
|
(cons s (append prefix suffix (list (decode-char 'ucs code))))))
|
|
list)))
|
|
|
|
(defconst fira-code-mode--ligatures
|
|
'("www" "**" "***" "**/" "*>" "*/" "\\\\" "\\\\\\"
|
|
"{-" "[]" "::" ":::" ":=" "!!" "!=" "!==" "-}"
|
|
"--" "---" "-->" "->" "->>" "-<" "-<<" "-~"
|
|
"#{" "#[" "##" "###" "####" "#(" "#?" "#_" "#_("
|
|
".-" ".=" ".." "..<" "..." "?=" "??" ";;" "/*"
|
|
"/**" "/=" "/==" "/>" "//" "///" "&&" "||" "||="
|
|
"|=" "|>" "^=" "$>" "++" "+++" "+>" "=:=" "=="
|
|
"===" "==>" "=>" "=>>" "<=" "=<<" "=/=" ">-" ">="
|
|
">=>" ">>" ">>-" ">>=" ">>>" "<*" "<*>" "<|" "<|>"
|
|
"<$" "<$>" "<!--" "<-" "<--" "<->" "<+" "<+>" "<="
|
|
"<==" "<=>" "<=<" "<>" "<<" "<<-" "<<=" "<<<" "<~"
|
|
"<~~" "</" "</>" "~@" "~-" "~=" "~>" "~~" "~~>" "%%"
|
|
"x" ":" "+" "+" "*"))
|
|
|
|
(defvar fira-code-mode--old-prettify-alist)
|
|
|
|
(cl-defun fira-code-mode--enable ()
|
|
"Enable Fira Code ligatures in current buffer."
|
|
(setq-local fira-code-mode--old-prettify-alist prettify-symbols-alist)
|
|
(setq-local prettify-symbols-alist (append (fira-code-mode--make-alist fira-code-mode--ligatures) fira-code-mode--old-prettify-alist))
|
|
(prettify-symbols-mode t))
|
|
|
|
(cl-defun fira-code-mode--disable ()
|
|
"Disable Fira Code ligatures in current buffer."
|
|
(setq-local prettify-symbols-alist fira-code-mode--old-prettify-alist)
|
|
(prettify-symbols-mode -1))
|
|
|
|
(define-minor-mode fira-code-mode
|
|
"Fira Code ligatures minor mode"
|
|
:lighter " Fira Code"
|
|
(setq-local prettify-symbols-unprettify-at-point 'right-edge)
|
|
(if fira-code-mode
|
|
(fira-code-mode--enable)
|
|
(fira-code-mode--disable)))
|
|
|
|
(cl-defun fira-code-mode--setup ()
|
|
"Setup Fira Code Symbols"
|
|
(set-fontset-font t '(#Xe100 . #Xe16f) "Fira Code Symbol"))
|
|
|
|
(provide 'fira-code-mode)
|
|
#+end_src
|
|
*** Indentation
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: indentation
|
|
:END:
|
|
|
|
There's nothing I dislike more than tabs in my files. Make sure I
|
|
don't share that discomfort with others.
|
|
#+begin_src emacs-lisp
|
|
(setq tab-width 4
|
|
indent-tabs-mode nil)
|
|
#+end_src
|
|
*** Backup files
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: backup-files
|
|
:END:
|
|
|
|
Some people like to have them. I don't. Rather than pushing them
|
|
to a folder, never to be used, just turn the whole thing off.
|
|
#+begin_src emacs-lisp
|
|
(setq make-backup-files nil)
|
|
#+end_src
|
|
*** Yes and No
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: yes-and-no
|
|
:END:
|
|
|
|
Nobody likes to have to type out the full yes or no when Emacs
|
|
asks. Which it does often. Make it one character.
|
|
#+begin_src emacs-lisp
|
|
(defalias 'yes-or-no-p 'y-or-n-p)
|
|
#+end_src
|
|
*** Key bindings
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: key-bindings
|
|
:END:
|
|
|
|
Miscellaneous key binding stuff that doesn't fit anywhere else.
|
|
#+begin_src emacs-lisp
|
|
(global-set-key (kbd "RET") 'newline-and-indent)
|
|
(global-set-key (kbd "C-;") 'comment-or-uncomment-region)
|
|
(global-set-key (kbd "M-/") 'hippie-expand)
|
|
(global-set-key (kbd "C-+") 'text-scale-increase)
|
|
(global-set-key (kbd "C--") 'text-scale-decrease)
|
|
(global-set-key (kbd "C-c C-k") 'compile)
|
|
(global-set-key (kbd "C-x g") 'magit-status)
|
|
(if (eq system-type 'darwin)
|
|
(progn
|
|
(setq mac-option-modifier 'meta)))
|
|
#+end_src
|
|
*** Misc
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: misc
|
|
:END:
|
|
|
|
Turn down the time to echo keystrokes so I don't have to wait
|
|
around for things to happen. Dialog boxes are also a bit annoying,
|
|
so just have Emacs use the echo area for everything. Beeping is
|
|
for robots, and I am not a robot. Use a visual indicator instead
|
|
of making horrible noises. Oh, and always highlight parentheses. A
|
|
person could go insane without that. Finally, Magit's behaviour
|
|
changed, let's ack that change and prevent an potentially bad
|
|
outcome.
|
|
#+begin_src emacs-lisp
|
|
(setq echo-keystrokes 0.1
|
|
use-dialog-box nil
|
|
visible-bell t)
|
|
(show-paren-mode t)
|
|
(setq magit-auto-revert-mode nil)
|
|
(setq magit-last-seen-setup-instructions "1.4.0")
|
|
#+end_src
|
|
*** Vendor directory
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: vendor-directory
|
|
:END:
|
|
|
|
I have a couple of things that don't come from package
|
|
managers. This includes the directory for use.
|
|
#+begin_src emacs-lisp
|
|
(defvar burd/vendor-dir (expand-file-name "vendor" user-emacs-directory))
|
|
(add-to-list 'load-path burd/vendor-dir)
|
|
|
|
(dolist (project (directory-files burd/vendor-dir t "\\w+"))
|
|
(when (file-directory-p project)
|
|
(add-to-list 'load-path project)))
|
|
#+end_src
|
|
** Org
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: org-mode
|
|
:END:
|
|
|
|
=org-mode= is one of the most powerful and amazing features of
|
|
Emacs. I mostly use it for task/day organization and generating
|
|
code snippets in HTML. Just a few tweaks here to make the
|
|
experience better.
|
|
*** Settings
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: org-mode-settings
|
|
:END:
|
|
|
|
Enable logging when tasks are complete. This puts a time-stamp on
|
|
the completed task. Since I usually am doing quite a few things at
|
|
once, I added the =INPROGRESS= keyword and made the color
|
|
blue. Finally, enable =flyspell-mode= and =writegood-mode= when
|
|
=org-mode= is active.
|
|
#+begin_src emacs-lisp
|
|
(setq org-log-done t
|
|
org-todo-keywords '((sequence "TODO" "INPROGRESS" "DONE"))
|
|
org-todo-keyword-faces '(("INPROGRESS" . (:foreground "blue" :weight bold))))
|
|
(add-hook 'org-mode-hook
|
|
(lambda ()
|
|
(flyspell-mode)))
|
|
(add-hook 'org-mode-hook
|
|
(lambda ()
|
|
(writegood-mode)))
|
|
#+end_src
|
|
*** org-agenda
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: org-agenda
|
|
:END:
|
|
|
|
First, create the global binding for =org-agenda=. This allows it
|
|
to be quickly accessed. The agenda view requires that org files be
|
|
added to it. The =personal.org= and =groupon.org= files are my
|
|
daily files for review. I have a habit to plan the next day. I do
|
|
this by assessing my calendar and my list of todo items. If a todo
|
|
item is already scheduled or has a deadline, don't show it in the
|
|
global todo list.
|
|
#+begin_src emacs-lisp
|
|
(global-set-key (kbd "C-c a") 'org-agenda)
|
|
(setq org-agenda-show-log t
|
|
org-agenda-todo-ignore-scheduled t
|
|
org-agenda-todo-ignore-deadlines t)
|
|
(setq org-agenda-files (list "~/Dropbox/org/personal.org"
|
|
"~/Dropbox/org/agenda.org"))
|
|
#+end_src
|
|
*** org-habit
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: org-habit
|
|
:END:
|
|
|
|
I have severial habits that I also track. In order to take full
|
|
advantage of this feature =org-habit= has to be required and added
|
|
to =org-modules=. A few settings are also tweaked for habit mode to
|
|
make the tracking a little more palatable. The most significant of
|
|
these is =org-habit-graph-column=. This specifies where the graph
|
|
should start. The default is too low and cuts off a lot, so I start
|
|
it at 80 characters.
|
|
#+begin_src emacs-lisp
|
|
;; (require 'org)
|
|
;; (require 'org-loaddefs)
|
|
;; (require 'org-habit)
|
|
;; (add-to-list 'org-modules "org-habit")
|
|
;; (setq org-habit-preceding-days 7
|
|
;; org-habit-following-days 1
|
|
;; org-habit-graph-column 80
|
|
;; org-habit-show-habits-only-for-today t
|
|
;; org-habit-show-all-today t)
|
|
#+end_src
|
|
*** org-babel
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: org-babel
|
|
:END:
|
|
|
|
=org-babel= is a feature inside of =org-mode= that makes this
|
|
document possible. It allows for embedding languages inside of an
|
|
=org-mode= document with all the proper font-locking. It also
|
|
allows you to extract and execute code. It isn't aware of
|
|
=Clojure= by default, so the following sets that up.
|
|
#+begin_src emacs-lisp
|
|
(require 'ob)
|
|
|
|
(org-babel-do-load-languages
|
|
'org-babel-load-languages
|
|
'((shell . t)
|
|
(ditaa . t)
|
|
(plantuml . t)
|
|
(dot . t)
|
|
(ruby . t)
|
|
(js . t)
|
|
(C . t)))
|
|
|
|
(add-to-list 'org-src-lang-modes (quote ("dot". graphviz-dot)))
|
|
(add-to-list 'org-src-lang-modes (quote ("plantuml" . fundamental)))
|
|
(add-to-list 'org-babel-tangle-lang-exts '("clojure" . "clj"))
|
|
|
|
(defvar org-babel-default-header-args:clojure
|
|
'((:results . "silent") (:tangle . "yes")))
|
|
|
|
(cl-defun org-babel-execute:clojure (body params)
|
|
(lisp-eval-string body)
|
|
"Done!")
|
|
|
|
(provide 'ob-clojure)
|
|
|
|
(setq org-src-fontify-natively t
|
|
org-confirm-babel-evaluate nil)
|
|
|
|
(add-hook 'org-babel-after-execute-hook (lambda ()
|
|
(condition-case nil
|
|
(org-display-inline-images)
|
|
(error nil)))
|
|
'append)
|
|
#+end_src
|
|
*** org-abbrev
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: org-abbrev
|
|
:END:
|
|
|
|
#+begin_src emacs-lisp
|
|
(add-hook 'org-mode-hook (lambda () (abbrev-mode 1)))
|
|
|
|
(define-skeleton skel-org-block-elisp
|
|
"Insert an emacs-lisp block"
|
|
""
|
|
"#+begin_src emacs-lisp\n"
|
|
_ - \n
|
|
"#+end_src\n")
|
|
|
|
(define-abbrev org-mode-abbrev-table "elsrc" "" 'skel-org-block-elisp)
|
|
|
|
(define-skeleton skel-org-block-js
|
|
"Insert a JavaScript block"
|
|
""
|
|
"#+begin_src js\n"
|
|
_ - \n
|
|
"#+end_src\n")
|
|
|
|
(define-abbrev org-mode-abbrev-table "jssrc" "" 'skel-org-block-js)
|
|
|
|
(define-skeleton skel-header-block
|
|
"Creates my default header"
|
|
""
|
|
"#+TITLE: " str "\n"
|
|
"#+AUTHOR: Greg Burd\n"
|
|
"#+EMAIL: greg@burd.me\n"
|
|
"#+OPTIONS: toc:3 num:nil\n"
|
|
"#+STYLE: <link rel=\"stylesheet\" type=\"text/css\" href=\"http://thomasf.github.io/solarized-css/solarized-light.min.css\" />\n")
|
|
|
|
(define-abbrev org-mode-abbrev-table "sheader" "" 'skel-header-block)
|
|
|
|
(define-skeleton skel-org-html-file-name
|
|
"Insert an HTML snippet to reference the file by name"
|
|
""
|
|
"#+HTML: <strong><i>"str"</i></strong>")
|
|
|
|
(define-abbrev org-mode-abbrev-table "fname" "" 'skel-org-html-file-name)
|
|
|
|
(define-skeleton skel-ngx-config
|
|
"Template for NGINX module config file"
|
|
""
|
|
"ngx_addon_name=ngx_http_" str "_module\n"
|
|
"HTTP_MODULES=\"$HTTP_MODULES ngx_http_" str "_module\"\n"
|
|
"NGX_ADDON_SRCS=\"$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_" str "_module.c\"")
|
|
|
|
(define-abbrev fundamental-mode-abbrev-table "ngxcnf" "" 'skel-ngx-config)
|
|
|
|
(define-skeleton skel-ngx-module
|
|
"Template for NGINX modules"
|
|
""
|
|
"#include <nginx.h>\n"
|
|
"#include <ngx_config.h>\n"
|
|
"#include <ngx_core.h>\n"
|
|
"#include <ngx_http.h>\n\n"
|
|
|
|
"ngx_module_t ngx_http_" str "_module;\n\n"
|
|
|
|
"static ngx_int_t\n"
|
|
"ngx_http_" str "_handler(ngx_http_request_t *r)\n"
|
|
"{\n"
|
|
>"if (r->main->internal) {\n"
|
|
>"return NGX_DECLINED;\n"
|
|
"}" > \n
|
|
\n
|
|
>"ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, \"My new module\");\n\n"
|
|
> _ \n
|
|
>"return NGX_OK;\n"
|
|
"}" > "\n\n"
|
|
|
|
"static ngx_int_t\n"
|
|
"ngx_http_"str"_init(ngx_conf_t *cf)\n"
|
|
"{\n"
|
|
>"ngx_http_handler_pt *h;\n"
|
|
>"ngx_http_core_main_conf_t *cmcf;\n\n"
|
|
|
|
>"cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);\n"
|
|
>"h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);\n\n"
|
|
|
|
>"if (h == NULL) {\n"
|
|
>"return NGX_ERROR;\n"
|
|
"}" > \n
|
|
\n
|
|
>"*h = ngx_http_"str"_handler;\n\n"
|
|
|
|
>"return NGX_OK;\n"
|
|
"}" > \n
|
|
\n
|
|
"static ngx_http_module_t ngx_http_"str"_module_ctx = {\n"
|
|
>"NULL, /* preconfiguration */\n"
|
|
>"ngx_http_"str"_init, /* postconfiguration */\n"
|
|
>"NULL, /* create main configuration */\n"
|
|
>"NULL, /* init main configuration */\n"
|
|
>"NULL, /* create server configuration */\n"
|
|
>"NULL, /* merge server configuration */\n"
|
|
>"NULL, /* create location configuration */\n"
|
|
>"NULL /* merge location configuration */\n"
|
|
"};" > \n
|
|
\n
|
|
|
|
"ngx_module_t ngx_http_"str"_module = {\n"
|
|
>"NGX_MODULE_V1,\n"
|
|
>"&ngx_http_"str"_module_ctx, /* module context */\n"
|
|
>"NULL, /* module directives */\n"
|
|
>"NGX_HTTP_MODULE, /* module type */\n"
|
|
>"NULL, /* init master */\n"
|
|
>"NULL, /* init module */\n"
|
|
>"NULL, /* init process */\n"
|
|
>"NULL, /* init thread */\n"
|
|
>"NULL, /* exit thread */\n"
|
|
>"NULL, /* exit process */\n"
|
|
>"NULL, /* exit master */\n"
|
|
>"NGX_MODULE_V1_PADDING\n"
|
|
"};" >)
|
|
|
|
(require 'cc-mode)
|
|
(define-abbrev c-mode-abbrev-table "ngxmod" "" 'skel-ngx-module)
|
|
|
|
(define-skeleton skel-ngx-append-header
|
|
"Template for header appending function for NGINX modules"
|
|
""
|
|
"static void append_header(ngx_http_request_t *r)\n"
|
|
"{\n"
|
|
> "ngx_table_elt_t *h;\n"
|
|
> "h = ngx_list_push(&r->headers_out.headers);\n"
|
|
> "h->hash = 1;\n"
|
|
> "ngx_str_set(&h->key, \"X-NGINX-Hello\");\n"
|
|
> "ngx_str_set(&h->value, \"Hello NGINX!\");\n"
|
|
"}\n")
|
|
|
|
(define-abbrev c-mode-abbrev-table "ngxhdr" "" 'skel-ngx-append-header)
|
|
#+end_src
|
|
** Utilities
|
|
*** ditaa
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: ditaa
|
|
:END:
|
|
There's no substitute for real drawings, but it's nice to be able
|
|
to sketch things out and produce a picture right from
|
|
=org-mode=. This sets up =ditaa= for execution from inside a babel
|
|
block.
|
|
#+begin_src emacs-lisp
|
|
(setq org-ditaa-jar-path "~/.emacs.d/vendor/ditaa0_9.jar")
|
|
#+end_src
|
|
*** plantuml
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: plantuml
|
|
:END:
|
|
#+begin_src emacs-lisp
|
|
(setq org-plantuml-jar-path "~/.emacs.d/vendor/plantuml.jar")
|
|
#+end_src
|
|
|
|
*** deft
|
|
=deft= provides random note taking with history and
|
|
searching. Since I use =org-mode= for everything else, I turn that
|
|
on as the default mode for =deft= and put the files in Dropbox.
|
|
#+begin_src emacs-lisp
|
|
(setq deft-directory "~/Dropbox/deft")
|
|
(setq deft-use-filename-as-title t)
|
|
(setq deft-extension "org")
|
|
(setq deft-text-mode 'org-mode)
|
|
#+end_src
|
|
*** Smex
|
|
=smex= is a necessity. It provides history and searching on top of =M-x=.
|
|
#+begin_src emacs-lisp
|
|
(setq smex-save-file (expand-file-name ".smex-items" user-emacs-directory))
|
|
(smex-initialize)
|
|
(global-set-key (kbd "M-x") 'smex)
|
|
(global-set-key (kbd "M-X") 'smex-major-mode-commands)
|
|
#+end_src
|
|
*** Ido
|
|
=Ido= mode provides a nice way to navigate the filesystem.
|
|
#+begin_src emacs-lisp
|
|
(ido-mode t)
|
|
(setq ido-enable-flex-matching t
|
|
ido-use-virtual-buffers t)
|
|
#+end_src
|
|
*** Column number mode
|
|
Turn on column numbers.
|
|
#+begin_src emacs-lisp
|
|
(setq column-number-mode t)
|
|
#+end_src
|
|
*** Temporary file management
|
|
Deal with temporary files. I don't care about them and this makes
|
|
them go away.
|
|
#+begin_src emacs-lisp
|
|
(setq backup-directory-alist `((".*" . ,temporary-file-directory)))
|
|
(setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t)))
|
|
#+end_src
|
|
*** electric-pair-mode
|
|
This makes sure that brace structures =(), [], {}=, etc. are closed
|
|
as soon as the opening character is typed.
|
|
#+begin_src emacs-lisp
|
|
;(require 'electric-pair-mode)
|
|
#+end_src
|
|
*** Power lisp
|
|
A bunch of tweaks for programming in LISP dialects. It defines the
|
|
modes that I want to apply these hooks to. To add more just add
|
|
them to =lisp-modes=. This also creates its own minor mode to
|
|
properly capture the behavior. It remaps some keys to make paredit
|
|
work a little easier as well. It also sets =clisp= as the default
|
|
lisp program and =racket= as the default scheme program.
|
|
#+begin_src emacs-lisp
|
|
(setq lisp-modes '(lisp-mode
|
|
emacs-lisp-mode
|
|
common-lisp-mode
|
|
scheme-mode
|
|
clojure-mode))
|
|
|
|
(defvar lisp-power-map (make-keymap))
|
|
(define-minor-mode lisp-power-mode "Fix keybindings; add power."
|
|
:lighter " (power)"
|
|
:keymap lisp-power-map
|
|
(paredit-mode t))
|
|
(define-key lisp-power-map [delete] 'paredit-forward-delete)
|
|
(define-key lisp-power-map [backspace] 'paredit-backward-delete)
|
|
|
|
(cl-defun burd/engage-lisp-power ()
|
|
(lisp-power-mode t))
|
|
|
|
(dolist (mode lisp-modes)
|
|
(add-hook (intern (format "%s-hook" mode))
|
|
#'burd/engage-lisp-power))
|
|
|
|
(setq inferior-lisp-program "clisp")
|
|
(setq scheme-program-name "racket")
|
|
#+end_src
|
|
*** auto-complete
|
|
Turn on auto complete.
|
|
#+begin_src emacs-lisp
|
|
;(require 'auto-complete-config)
|
|
;(ac-config-default)
|
|
#+end_src
|
|
*** Indentation and buffer cleanup
|
|
This re-indents, untabifies, and cleans up whitespace. It is stolen
|
|
directly from the emacs-starter-kit.
|
|
#+begin_src emacs-lisp
|
|
(cl-defun untabify-buffer ()
|
|
(interactive)
|
|
(untabify (point-min) (point-max)))
|
|
|
|
(cl-defun indent-buffer ()
|
|
(interactive)
|
|
(indent-region (point-min) (point-max)))
|
|
|
|
(cl-defun cleanup-buffer ()
|
|
"Perform a bunch of operations on the whitespace content of a buffer."
|
|
(interactive)
|
|
(indent-buffer)
|
|
(untabify-buffer)
|
|
(delete-trailing-whitespace))
|
|
|
|
(cl-defun cleanup-region (beg end)
|
|
"Remove tmux artifacts from region."
|
|
(interactive "r")
|
|
(dolist (re '("\\\\│\·*\n" "\W*│\·*"))
|
|
(replace-regexp re "" nil beg end)))
|
|
|
|
(global-set-key (kbd "C-x M-t") 'cleanup-region)
|
|
(global-set-key (kbd "C-c n") 'cleanup-buffer)
|
|
|
|
(setq-default show-trailing-whitespace t)
|
|
#+end_src
|
|
*** editorconfig
|
|
EditorConfig helps maintain consistent coding styles for multiple developers
|
|
working on the same project across various editors and IDEs.
|
|
https://editorconfig.org/
|
|
#+begin_src emacs-lisp
|
|
(require 'editorconfig)
|
|
(editorconfig-mode 1)
|
|
#+end_src
|
|
*** flyspell
|
|
The built-in Emacs spell checker. Turn off the welcome flag because
|
|
it is annoying and breaks on quite a few systems. Specify the
|
|
location of the spell check program so it loads properly.
|
|
#+begin_src emacs-lisp
|
|
(setq flyspell-issue-welcome-flag nil)
|
|
(if (eq system-type 'darwin)
|
|
(setq-default ispell-program-name "/usr/local/bin/aspell")
|
|
(setq-default ispell-program-name "/usr/bin/aspell"))
|
|
(setq-default ispell-list-command "list")
|
|
#+end_src
|
|
*** multi-web-mode
|
|
When editing HTML it's a jumble of languages embedded into a single
|
|
file. Emacs can choose the major-mode based on the section of the
|
|
file if you enable it.
|
|
#+begin_src emacs-lisp
|
|
(require 'multi-web-mode)
|
|
(setq mweb-default-major-mode 'html-mode)
|
|
(setq mweb-tags
|
|
'((php-mode "<\\?php\\|<\\? \\|<\\?=" "\\?>")
|
|
(js-mode "<script[^>]*>" "</script>")
|
|
(css-mode "<style[^>]*>" "</style>")))
|
|
(setq mweb-filename-extensions '("php" "htm" "html" "ctp" "phtml" "php4" "php5"))
|
|
(multi-web-global-mode 1)
|
|
#+end_src
|
|
** Language Hooks
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: languages
|
|
:END:
|
|
*** Erlang Mode
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: erlang-mode
|
|
:END:
|
|
#+begin_src emacs-lisp
|
|
(add-hook 'erlang-mode-hook
|
|
(lambda ()
|
|
(setq inferior-erlang-machine-options
|
|
'("-sname" "emacs"
|
|
"-pz" "ebin deps/*/ebin apps/*/ebin"
|
|
"-boot" "start_sasl"))
|
|
(imenu-add-to-menubar "imenu")))
|
|
#+end_src
|
|
*** C/C++ Mode
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: c-mode
|
|
:END:
|
|
#+begin_src emacs-lisp
|
|
(semantic-mode +1)
|
|
(require 'semantic/bovine/gcc)
|
|
|
|
(flx-ido-mode 1)
|
|
(add-hook 'c-mode-hook (lambda () (
|
|
(setq flycheck-check-syntax-automatically '(save mode-enabled))
|
|
(setq flycheck-standard-error-navigation nil)
|
|
;; flycheck errors on a tooltip (doesnt work on console)
|
|
(when (display-graphic-p (selected-frame))
|
|
(eval-after-load 'flycheck
|
|
'(custom-set-variables
|
|
'(flycheck-display-errors-function #'flycheck-pos-tip-error-messages)))))))
|
|
#+end_src
|
|
*** Elixir Mode
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: elixir-mode
|
|
:END:
|
|
#+begin_src emacs-lisp
|
|
|
|
#+end_src
|
|
*** GDB/GUD Mode
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: gdb-mode
|
|
:END:
|
|
|
|
#+begin_src emacs-lisp
|
|
(defvar gdb-libtool-command-name "libtool"
|
|
"Pathname for executing gdb.")
|
|
|
|
(cl-defun gdb-libtool (path &optional corefile)
|
|
"Run gdb on a libtool program FILE in buffer *gdb-FILE*.
|
|
The directory containing FILE becomes the initial working
|
|
directory and source-file directory for GDB. If you wish to
|
|
change this, use the GDB commands `cd DIR' and `directory'."
|
|
(interactive "FRun gdb-libtool on file: ")
|
|
(load "gud")
|
|
(setq path (file-truename (expand-file-name path)))
|
|
(let ((file (file-name-nondirectory path)))
|
|
(switch-to-buffer (concat "*gud-" file "*"))
|
|
(setq default-directory (file-name-directory path))
|
|
(or (bolp) (newline))
|
|
(insert "Current directory is " default-directory "\n")
|
|
; M-x gud-gdb libtool --mode=execute gdb -fullname ___
|
|
(apply 'make-comint
|
|
(concat "gud-" file)
|
|
(substitute-in-file-name gdb-libtool-command-name)
|
|
nil
|
|
"--mode=execute"
|
|
(substitute-in-file-name gdb-command-name)
|
|
"-fullname"
|
|
"-cd" default-directory
|
|
file
|
|
(and corefile (list corefile)))
|
|
; (set-process-filter (get-buffer-process (current-buffer)) 'gud-filter)
|
|
; (set-process-sentinel (get-buffer-process (current-buffer)) 'gud-sentinel)
|
|
;; XEmacs change: turn on gdb mode after setting up the proc filters
|
|
;; for the benefit of shell-font.el
|
|
(gud-mode)
|
|
(gud-set-buffer)))
|
|
|
|
(setq gdb-show-main t)
|
|
#+end_src
|
|
*** shell-script-mode
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: shell-script-mode
|
|
:END:
|
|
Use =shell-script-mode= for =.zsh= files.
|
|
#+begin_src emacs-lisp
|
|
(add-to-list 'auto-mode-alist '("\\.zsh$" . shell-script-mode))
|
|
#+end_src
|
|
*** dockerfile-mode
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: dockerfile-model
|
|
:END:
|
|
Use =dockerfile-mode= for =Dockerfile= files.
|
|
#+begin_src emacs-lisp
|
|
(require 'dockerfile-mode)
|
|
(add-to-list 'auto-mode-alist '("^Dockerflie$" . dockerfile-mode))
|
|
#+end_src
|
|
*** make
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: make-mode
|
|
:END:
|
|
Use =shell-script-mode= for =.zsh= files.
|
|
#+begin_src emacs-lisp
|
|
;; http://stackoverflow.com/a/9059906/366692
|
|
(cl-defun get-closest-pathname (&optional (max-level 3) (file "Makefile"))
|
|
(let ((root (expand-file-name "/"))
|
|
(level 0))
|
|
(expand-file-name file
|
|
(loop
|
|
for d = default-directory then (expand-file-name ".." d)
|
|
do (setq level (+ level 1))
|
|
if (file-exists-p (expand-file-name file d))
|
|
return d
|
|
if (> level max-level)
|
|
return nil
|
|
if (equal d root)
|
|
return nil))))
|
|
(add-hook 'c-mode-hook
|
|
(lambda ()
|
|
(unless (file-exists-p "Makefile")
|
|
(set (make-local-variable 'compile-command)
|
|
(let ((file (file-name-nondirectory buffer-file-name))
|
|
(mkfile (get-closest-pathname)))
|
|
(if mkfile
|
|
(progn (format "cd %s; make -f %s"
|
|
(file-name-directory mkfile) mkfile))
|
|
(format "%s -c -o %s.o %s %s %s"
|
|
(or (getenv "CC") "gcc")
|
|
(file-name-sans-extension file)
|
|
(or (getenv "CPPFLAGS") "-DDEBUG=9")
|
|
(or (getenv "CFLAGS") "-ansi -pedantic -Wall -g")
|
|
file)))))))
|
|
(provide 'make)
|
|
#+end_src
|
|
*** conf-mode
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: conf-mode
|
|
:END:
|
|
#+begin_src emacs-lisp
|
|
(add-to-list 'auto-mode-alist '("\\.gitconfig$" . conf-mode))
|
|
#+end_src
|
|
*** Web Mode
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: web-mode
|
|
:END:
|
|
|
|
#+begin_src emacs-lisp
|
|
(add-to-list 'auto-mode-alist '("\\.hbs$" . web-mode))
|
|
(add-to-list 'auto-mode-alist '("\\.erb$" . web-mode))
|
|
#+end_src
|
|
*** YAML
|
|
Add additional file extensions that trigger =yaml-mode=.
|
|
#+begin_src emacs-lisp
|
|
(add-to-list 'auto-mode-alist '("\\.yml$" . yaml-mode))
|
|
(add-to-list 'auto-mode-alist '("\\.yaml$" . yaml-mode))
|
|
#+end_src
|
|
*** TOML
|
|
Add additional file extensions that trigger =toml-mode=.
|
|
#+begin_src emacs-lisp
|
|
(add-to-list 'auto-mode-alist '("\\.tml$" . toml-mode))
|
|
(add-to-list 'auto-mode-alist '("\\.toml$" . toml-mode))
|
|
#+end_src
|
|
*** CoffeeScript Mode
|
|
The default CoffeeScript mode makes terrible choices. This turns
|
|
everything into 2 space indentations and makes it so the mode
|
|
functions rather than causing you indentation errors every time you
|
|
modify a file.
|
|
#+begin_src emacs-lisp
|
|
(cl-defun coffee-custom ()
|
|
"coffee-mode-hook"
|
|
(make-local-variable 'tab-width)
|
|
(set 'tab-width 4))
|
|
|
|
(add-hook 'coffee-mode-hook 'coffee-custom)
|
|
#+end_src
|
|
*** JavaScript Mode
|
|
=js-mode= defaults to using 4 spaces for indentation. Change it to 2
|
|
#+begin_src emacs-lisp
|
|
(cl-defun js-custom ()
|
|
"js-mode-hook"
|
|
(setq indent-tabs-mode nil
|
|
tab-width 2
|
|
js-indent-level 2))
|
|
(add-hook 'js-mode-hook 'js-custom)
|
|
#+end_src
|
|
*** Markdown Mode
|
|
Enable Markdown mode and setup additional file extensions. Use
|
|
pandoc to generate HTML previews from within the mode, and use a
|
|
custom css file to make it a little prettier.
|
|
#+begin_src emacs-lisp
|
|
(add-to-list 'auto-mode-alist '("\\.md$" . markdown-mode))
|
|
(add-to-list 'auto-mode-alist '("\\.mdown$" . markdown-mode))
|
|
(add-hook 'markdown-mode-hook
|
|
(lambda ()
|
|
(visual-line-mode t)
|
|
(writegood-mode t)
|
|
(flyspell-mode t)))
|
|
(setq markdown-command "pandoc --smart -f markdown -t html")
|
|
(setq markdown-css-paths (expand-file-name "markdown.css" burd/vendor-dir))
|
|
#+end_src
|
|
*** CPSA Mode
|
|
Enable support for Cryptographic Protocol Shapes Analyzer. This is
|
|
a scheme-ish dialect, so it's a derived from =scheme-mode=.
|
|
#+begin_src emacs-lisp
|
|
(define-derived-mode cpsa-mode scheme-mode
|
|
(setq mode-name "CPSA")
|
|
(setq cpsa-keywords '("defmacro" "defprotocol" "defrole" "defskeleton" "defstrand"))
|
|
(setq cpsa-functions '("cat" "hash" "enc" "string" "ltk" "privk" "pubk" "invk" "send" "recv" "non-orig" "uniq-orig" "trace" "vars"))
|
|
(setq cpsa-types '("skey" "akey" "name" "text"))
|
|
(setq cpsa-keywords-regexp (regexp-opt cpsa-keywords 'words))
|
|
(setq cpsa-functions-regexp (regexp-opt cpsa-functions 'words))
|
|
(setq cpsa-types-regexp (regexp-opt cpsa-types 'words))
|
|
(setq cpsa-font-lock-keywords
|
|
`(
|
|
(,cpsa-keywords-regexp . font-lock-keyword-face)
|
|
(,cpsa-functions-regexp . font-lock-function-name-face)
|
|
(,cpsa-types-regexp . font-lock-type-face)))
|
|
(setq font-lock-defaults '((cpsa-font-lock-keywords))))
|
|
|
|
(add-to-list 'auto-mode-alist '("\\.cpsa$" . cpsa-mode))
|
|
#+end_src
|
|
*** Themes
|
|
Load solarized-light if in a graphical environment. Load the
|
|
wombat theme if in a terminal.
|
|
#+begin_src emacs-lisp
|
|
(load-theme 'tsdh-dark t)
|
|
; (load-theme 'intellij t)
|
|
; (load-theme 'wombat t)
|
|
; (load-theme 'solarized-dark t)
|
|
;(when window-system
|
|
; (load-theme 'intellij t)
|
|
; (load-theme 'tsdh-dark t))
|
|
#+end_src
|