--- /dev/null
+;;; bind-key --- A simple way to manage personal keybindings
+
+;; Copyright (C) 2012 John Wiegley
+
+;; Author: John Wiegley <jwiegley@gmail.com>
+;; Created: 16 Jun 2012
+;; Version: 1.0
+;; Keywords: keys keybinding config dotemacs
+;; X-URL: https://github.com/jwiegley/bind-key
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+\f
+;;; Commentary:
+
+;; If you have lots of keybindings set in your .emacs file, it can be hard to
+;; know which ones you haven't set yet, and which may now be overriding some
+;; new default in a new Emacs version. This module aims to solve that
+;; problem.
+;;
+;; Bind keys as follows in your .emacs:
+;;
+;; (require 'bind-key)
+;;
+;; (bind-key "C-c x" 'my-ctrl-c-x-command)
+;;
+;; If you want the keybinding to override all minor modes that may also bind
+;; the same key, use the `bind-key*' form:
+;;
+;; (bind*-key "<C-return>" 'other-window)
+;;
+;; If you want to rebind a key only in a particular key, use:
+;;
+;; (bind-key "C-c x" 'my-ctrl-c-x-command some-other-mode-map)
+;;
+;; To unbind a key within a keymap (for example, to stop your favorite major
+;; mode from changing a binding that you don't want to override everywhere),
+;; use `unbind-key':
+;;
+;; (unbind-key "C-c x" some-other-mode-map)
+;;
+;; After Emacs loads, you can see a summary of all your personal keybindings
+;; currently in effect with this command:
+;;
+;; M-x describe-personal-keybindings
+;;
+;; This display will tell you if you've overriden a default keybinding, and
+;; what the default was. Also, it will tell you if the key was rebound after
+;; your binding it with `bind-key', and what it was rebound it to.
+
+(require 'easy-mmode)
+
+(defgroup bind-key nil
+ "A simple way to manage personal keybindings"
+ :group 'emacs)
+
+(defcustom bind-key-segregation-regexp
+ "\\`\\(\\(C-[chx] \\|M-[gso] \\)\\([CM]-\\)?\\|.+-\\)"
+ "Regular expression used to divide key sets in the output from
+\\[describe-personal-keybindings]."
+ :type 'regexp
+ :group 'bind-key)
+
+;; Create override-global-mode to force key remappings
+
+(defvar override-global-map (make-keymap)
+ "override-global-mode keymap")
+
+(define-minor-mode override-global-mode
+ "A minor mode so that keymap settings override other modes."
+ t "" override-global-map)
+
+(add-hook 'after-init-hook
+ (function
+ (lambda ()
+ (override-global-mode 1))))
+
+(defvar personal-keybindings nil)
+
+(defmacro bind-key (key-name command &optional keymap)
+ (let ((namevar (make-symbol "name"))
+ (keyvar (make-symbol "key"))
+ (bindingvar (make-symbol "binding"))
+ (entryvar (make-symbol "entry")))
+ `(let* ((,namevar ,(eval key-name))
+ (,keyvar (read-kbd-macro ,namevar))
+ (,bindingvar (lookup-key (or ,keymap global-map)
+ ,keyvar)))
+ (let ((,entryvar (assoc (cons ,namevar (quote ,keymap))
+ personal-keybindings)))
+ (if ,entryvar
+ (setq personal-keybindings
+ (delq ,entryvar personal-keybindings))))
+ (setq personal-keybindings
+ (cons (list (cons ,namevar (quote ,keymap))
+ ,command
+ (unless (numberp ,bindingvar) ,bindingvar))
+ personal-keybindings))
+ (define-key (or ,keymap global-map) ,keyvar ,command))))
+
+(defmacro unbind-key (key-name &optional keymap)
+ `(bind-key ,key-name nil ,keymap))
+
+(defmacro bind-key* (key-name command)
+ `(progn
+ (bind-key ,key-name ,command)
+ (define-key override-global-map ,(read-kbd-macro key-name) ,command)))
+
+(defun get-binding-description (elem)
+ (cond
+ ((listp elem)
+ (cond
+ ((eq 'lambda (car elem))
+ "#<lambda>")
+ ((eq 'closure (car elem))
+ "#<closure>")
+ ((eq 'keymap (car elem))
+ "#<keymap>")
+ (t
+ elem)))
+ ((keymapp elem)
+ "#<keymap>")
+ ((symbolp elem)
+ elem)
+ (t
+ "#<byte-compiled lambda>")))
+
+(defun compare-keybindings (l r)
+ (let* ((regex bind-key-segregation-regexp)
+ (lgroup (and (string-match regex (caar l))
+ (match-string 0 (caar l))))
+ (rgroup (and (string-match regex (caar r))
+ (match-string 0 (caar r))))
+ (lkeymap (cdar l))
+ (rkeymap (cdar r)))
+ (cond
+ ((and (null lkeymap) rkeymap)
+ (cons t t))
+ ((and lkeymap (null rkeymap))
+ (cons nil t))
+ ((and lkeymap rkeymap
+ (not (string= (symbol-name lkeymap) (symbol-name rkeymap))))
+ (cons (string< (symbol-name lkeymap) (symbol-name rkeymap)) t))
+ ((and (null lgroup) rgroup)
+ (cons t t))
+ ((and lgroup (null rgroup))
+ (cons nil t))
+ ((and lgroup rgroup)
+ (if (string= lgroup rgroup)
+ (cons (string< (caar l) (caar r)) nil)
+ (cons (string< lgroup rgroup) t)))
+ (t
+ (cons (string< (caar l) (caar r)) nil)))))
+
+(defun describe-personal-keybindings ()
+ (interactive)
+ (with-current-buffer (get-buffer-create "*Personal Keybindings*")
+ (delete-region (point-min) (point-max))
+ (insert "Key name Command Comments
+----------------- --------------------------------------- ---------------------
+")
+ (let (last-binding)
+ (dolist (binding
+ (setq personal-keybindings
+ (sort personal-keybindings
+ #'(lambda (l r)
+ (car (compare-keybindings l r))))))
+
+ (if (not (eq (cdar last-binding) (cdar binding)))
+ (insert ?\n (format "\n%s\n%s\n\n"
+ (cdar binding)
+ (make-string 79 ?-)))
+ (if (and last-binding
+ (cdr (compare-keybindings last-binding binding)))
+ (insert ?\n)))
+
+ (let* ((key-name (caar binding))
+ (at-present (lookup-key (or (symbol-value (cdar binding))
+ (current-global-map))
+ (read-kbd-macro key-name)))
+ (command (nth 1 binding))
+ (was-command (nth 2 binding))
+ (command-desc (get-binding-description command))
+ (was-command-desc (and was-command
+ (get-binding-description was-command)))
+ (at-present-desc (get-binding-description at-present))
+ )
+ (insert
+ (format
+ "%-18s%-40s%s\n"
+ key-name command-desc
+ (if (string= command-desc at-present-desc)
+ (if (or (null was-command)
+ (string= command-desc was-command-desc))
+ ""
+ (format "(%s)" was-command-desc))
+ (format "[now: %s]" at-present)))))
+
+ (setq last-binding binding)))
+
+ (goto-char (point-min))
+ (display-buffer (current-buffer))))
+
+(provide 'bind-key)
+
+;;; bind-key.el ends here
--- /dev/null
+;;; use-package --- A use-package declaration for simplifying your .emacs
+
+;; Copyright (C) 2012 John Wiegley
+
+;; Author: John Wiegley <jwiegley@gmail.com>
+;; Created: 17 Jun 2012
+;; Version: 1.0
+;; Keywords: dotemacs startup speed config package
+;; X-URL: https://github.com/jwiegley/use-package
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+\f
+;;; Commentary:
+
+;; The `use-package' declaration macro allows you to isolate package
+;; configuration in your ".emacs" in a way that is performance-oriented and,
+;; well, just tidy. I created it because I have over 80 packages that I use
+;; in Emacs, and things were getting difficult to manage. Yet with this
+;; utility my total load time is just under 1 second, with no loss of
+;; functionality!
+;;
+;; Here is the simplest `use-package' declaration:
+;;
+;; (use-package foo)
+;;
+;; This loads in the package foo, but only if foo is available on your system.
+;; If not, a warning is logged to your `*Messages*' buffer. If it succeeds a
+;; message about "Loading foo" is logged, along with the time it took to load,
+;; if that time is over 0.01s.
+;;
+;; Use the :init keywoard to do some stuff to initialize foo, but only if foo
+;; actually gets loaded:
+;;
+;; (use-package foo
+;; :init
+;; (progn
+;; (setq foo-variable t)
+;; (foo-mode 1)))
+;;
+;; A very command thing to do when loading a module is to bind a key to
+;; primary commands within that module:
+;;
+;; (use-package ace-jump-mode
+;; :bind ("C-." . ace-jump-mode))
+;;
+;; This does two things: first, it creates autoload for the `ace-jump-mode'
+;; command, and defers loading of `ace-jump-mode' until you actually use it.
+;; Second, it binds the key `C-.' to that command. After loading, you can use
+;; `M-x describe-personal-keybindings' to see all such bindings you've set
+;; throughout your Emacs.
+;;
+;; A more literal way to do the exact same thing is:
+;;
+;; (use-package ace-jump-mode
+;; :commands ace-jump-mode
+;; :init
+;; (bind-key "C-." 'ace-jump-mode))
+;;
+;; When you use the `:commands' keyword, it creates autoloads for those
+;; commands and defers loading of the module until they are used. In this
+;; case, the `:init' form is always run -- even if ace-jump-mode might not be
+;; on your system. So remember to keep `:init' activities to only those that
+;; would succeed either way.
+;;
+;; If you aren't used `:commands' or `:bind' (which implies `:commands'), you
+;; can still defer loading with `:defer' keyword:
+;;
+;; (use-package ace-jump-mode
+;; :defer t
+;; :init
+;; (progn
+;; (autoload 'ace-jump-mode "ace-jump-mode" nil t)
+;; (bind-key "C-." 'ace-jump-mode)))
+;;
+;; This does exactly the same thing as the other two commands above.
+;;
+;; A companion to the `:init' keyword is `:config'. Although `:init' always
+;; happens in the case of deferred modules (which are likely to be the most
+;; common kind), `:config' form only run after the module has been loaded by
+;; Emacs:
+;;
+;; (use-package ace-jump-mode
+;; :bind ("C-." . ace-jump-mode)
+;; :config
+;; (message "Yay, ace-jump-mode was actually loaded!"))
+;;
+;; You will see a "Configured..." message in your `*Messages*' log when a
+;; package is configured, and a timing if the configuration time was longer
+;; than 0.01s. You should keep `:init' forms as simple as possible, and put
+;; as much as you can get away with on the `:config' side.
+;;
+;; You can have both `:init' and `:config':
+;;
+;; (use-package haskell-mode
+;; :commands haskell-mode
+;; :init
+;; (add-to-list 'auto-mode-alist '("\\.l?hs$" . haskell-mode))
+;; :config
+;; (progn
+;; (use-package inf-haskell)
+;; (use-package hs-lint)))
+;;
+;; In this case, I want to autoload the command `haskell-mode' from
+;; "haskell-mode.el", add it to `auto-mode-alist' at the time ".emacs" is
+;; loaded, but wait until after I've opened a Haskell file before loading
+;; "inf-haskell.el" and "hs-lint.el".
+;;
+;; The `:bind' keyword takes either a cons or a list of conses:
+;;
+;; (use-package hi-lock
+;; :bind (("M-o l" . highlight-lines-matching-regexp)
+;; ("M-o r" . highlight-regexp)
+;; ("M-o w" . highlight-phrase)))
+;;
+;; The `:commands' keyword likewise takes either a symbol or a list of
+;; symbols.
+;;
+;; You can use the `:if' keyword to predicate the loading and initialization
+;; of a module. For example, I only want an `edit-server' running for my
+;; main, graphical Emacs, not for Emacsen I may start at the command line:
+;;
+;; (use-package edit-server
+;; :if window-system
+;; :init
+;; (progn
+;; (add-hook 'after-init-hook 'server-start t)
+;; (add-hook 'after-init-hook 'edit-server-start t)))
+;;
+;; The `:disabled' keyword can be used to turn off a module that you're having
+;; difficulties with, or to stop loading something you're not really using at
+;; the present time:
+;;
+;; (use-package ess-site
+;; :disabled t
+;; :commands R)
+;;
+;; Another feature of `use-package' is that it always loads every file that it
+;; can when your ".emacs" is being byte-compiled (if you do that, which I
+;; recommend). This helps to silence spurious warnings about unknown
+;; variables and functions.
+;;
+;; However, there are times when this is just not enough. For those times,
+;; use the `:defines' keyword to introduce empty variable definitions solely
+;; for the sake of the byte-compiler:
+;;
+;; (use-package texinfo
+;; :defines texinfo-section-list
+;; :commands texinfo-mode
+;; :init
+;; (add-to-list 'auto-mode-alist '("\\.texi$" . texinfo-mode)))
+;;
+;; If you need to silence a missing function warning, do it with an autoload
+;; stub in your `:init' block:
+;;
+;; (use-package w3m
+;; :commands (w3m-browse-url w3m-session-crash-recovery-remove)
+;; :init
+;; (eval-when-compile
+;; (autoload 'w3m-search-escape-query-string "w3m-search")))
+;;
+;; Lastly, `use-package' provides built-in support for the diminish utility,
+;; if you have that installed. It's purpose is to remove strings from your
+;; mode-line that would otherwise always be there and provide no useful
+;; information. It is invoked with the `:diminish' keyword, which is passed
+;; the minor mode symbol:
+;;
+;; (use-package abbrev
+;; :diminish abbrev-mode
+;; :init
+;; (if (file-exists-p abbrev-file-name)
+;; (quietly-read-abbrev-file))
+;;
+;; :config
+;; (add-hook 'expand-load-hook
+;; (lambda ()
+;; (add-hook 'expand-expand-hook 'indent-according-to-mode)
+;; (add-hook 'expand-jump-hook 'indent-according-to-mode))))
+;;
+;; If you noticed that this declaration has neither a `:bind', `:commands' or
+;; `:defer' keyword: congratulations, you're an A student! What it means is
+;; that both the `:init' and `:config' forms will be executed when ".emacs" is
+;; loaded, with no delays until later. Is this useful? Not really. I just
+;; happen to like separating my configuration into things that must happen at
+;; startup time, and things that could potentioally wait until after the
+;; actual load. In this case, everything could be put inside `:init' and
+;; there would be no difference.
+
+(require 'bind-key)
+
+(defgroup use-package nil
+ "A use-package declaration for simplifying your .emacs"
+ :group 'startup)
+
+;;;_ , Create use-package macro, to simplify customizations
+
+(eval-when-compile
+ (require 'cl))
+
+(require 'bind-key)
+(require 'diminish nil t)
+
+(defvar use-package-verbose t)
+
+(defmacro with-elapsed-timer (text &rest forms)
+ `(let ((now ,(if use-package-verbose
+ '(current-time))))
+ ,(if use-package-verbose
+ `(message "%s..." ,text))
+ ,@forms
+ ,(when use-package-verbose
+ `(let ((elapsed
+ (float-time (time-subtract (current-time) now))))
+ (if (> elapsed 0.01)
+ (message "%s...done (%.3fs)" ,text elapsed)
+ (message "%s...done" ,text))))))
+
+(put 'with-elapsed-timer 'lisp-indent-function 1)
+
+(defmacro use-package (name &rest args)
+ (let* ((commands (plist-get args :commands))
+ (init-body (plist-get args :init))
+ (config-body (plist-get args :config))
+ (diminish-var (plist-get args :diminish))
+ (defines (plist-get args :defines))
+ (keybindings (plist-get args :bind))
+ (predicate (plist-get args :if))
+ (defines-eval (if (null defines)
+ nil
+ (if (listp defines)
+ (mapcar (lambda (var) `(defvar ,var)) defines)
+ `((defvar ,defines)))))
+ (requires (plist-get args :requires))
+ (requires-test (if (null requires)
+ t
+ (if (listp requires)
+ `(not (member nil (mapcar #'featurep
+ (quote ,requires))))
+ `(featurep (quote ,requires)))))
+ (name-string (if (stringp name) name
+ (symbol-name name))))
+
+ (if diminish-var
+ (setq config-body
+ `(progn
+ ,config-body
+ (ignore-errors
+ ,@(if (listp diminish-var)
+ (mapcar (lambda (var) `(diminish (quote ,var)))
+ diminish-var)
+ `((diminish (quote ,diminish-var))))))))
+
+ (when keybindings
+ (if (and commands (symbolp commands))
+ (setq commands (list commands)))
+ (setq init-body
+ `(progn
+ ,init-body
+ ,@(mapcar #'(lambda (binding)
+ (push (cdr binding) commands)
+ `(bind-key ,(car binding)
+ (quote ,(cdr binding))))
+ (if (and (consp keybindings)
+ (stringp (car keybindings)))
+ (list keybindings)
+ keybindings)))))
+
+ (unless (plist-get args :disabled)
+ `(progn
+ (eval-when-compile
+ ,@defines-eval
+ ,(if (stringp name)
+ `(load ,name t)
+ `(require ',name nil t)))
+ ,(if (or commands (plist-get args :defer))
+ (let (form)
+ (unless (listp commands)
+ (setq commands (list commands)))
+ (mapc #'(lambda (command)
+ (push `(autoload (function ,command)
+ ,name-string nil t) form))
+ commands)
+
+ `(when ,(or predicate t)
+ ,@form
+ ,init-body
+ ,(unless (null config-body)
+ `(eval-after-load ,name-string
+ '(if ,requires-test
+ (with-elapsed-timer
+ ,(format "Configuring package %s" name-string)
+ ,config-body))))
+ t))
+ `(if (and ,(or predicate t)
+ ,requires-test)
+ (if ,(if (stringp name)
+ `(load ,name t)
+ `(require ',name nil t))
+ (with-elapsed-timer
+ ,(format "Loading package %s" name-string)
+ ,init-body
+ ,config-body
+ t)
+ (message "Could not load package %s" ,name-string))))))))
+
+(put 'use-package 'lisp-indent-function 1)
+
+(provide 'use-package)
+
+;;; use-package.el ends here