updates
authorJoerg Jaspert <joerg@debian.org>
Wed, 25 Feb 2015 00:21:06 +0000 (01:21 +0100)
committerJoerg Jaspert <joerg@debian.org>
Wed, 25 Feb 2015 00:21:06 +0000 (01:21 +0100)
.emacs.d/config/emacs.org
.emacs.d/elisp/local/bind-key.el
.emacs.d/elisp/local/use-package.el

index dee1126..61d5706 100644 (file)
@@ -538,6 +538,8 @@ In this day and age, UTF-8 is the way to go.
 (prefer-coding-system 'utf-8)
 (set-charset-priority 'unicode)
 (setq default-process-coding-system '(utf-8-unix . utf-8-unix))
+(when (display-graphic-p)
+  (setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)))
 #+END_SRC
 
 *** Hilight matching parentheses
@@ -1092,6 +1094,7 @@ than electric-indent-mode.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package aggressive-indent
   :ensure aggressive-indent
+  :commands (aggressive-indent-mode global-aggressive-indent-mode)
   :config
   (progn
     (global-aggressive-indent-mode 0)
@@ -1107,7 +1110,8 @@ information in the mode-line in various search modes.
 (use-package anzu
   :ensure anzu
   :diminish anzu-mode
-  :init
+  :defer t
+  :idle
   (progn
     (global-anzu-mode 1))
   :config
@@ -1148,12 +1152,8 @@ already had typed.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package auto-complete-config
   :ensure auto-complete
-  :init
-  (progn
-    (use-package pos-tip
-      :ensure t)
-    (ac-config-default)
-    )
+  :idle
+  (ac-config-default)
   :config
   (progn
     ;; hook AC into completion-at-point
@@ -1168,6 +1168,9 @@ already had typed.
     (defun sanityinc/dabbrev-friend-buffer (other-buffer)
       (< (buffer-size other-buffer) (* 1 1024 1024)))
 
+    (use-package pos-tip
+      :ensure t)
+
     ;; custom keybindings to use tab, enter and up and down arrows
     (bind-key "\t" 'ac-expand ac-complete-mode-map)
     (bind-key "\r" 'ac-complete ac-complete-mode-map)
@@ -1235,7 +1238,7 @@ with it. Not to have to revert buffers myself
 (use-package autorevert
   :commands auto-revert-mode
   :diminish auto-revert-mode
-  :init
+  :idle
   (progn
     (setq global-auto-revert-mode t)
     (setq global-auto-revert-non-file-buffers t)
@@ -1320,32 +1323,28 @@ are saved automatically when they are killed"
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package cal
   :commands (cal/insert)
-  :bind ("C-c c" . cal/insert))
-#+END_SRC
-
-Weeks start on Monday, not sunday.
-#+BEGIN_SRC emacs-lisp :tangle yes
-(setq calendar-week-start-day 1)
-#+END_SRC
+  :bind ("C-c c" . cal/insert)
+  :config
+  (progn
+    ; Weeks start on Monday, not sunday.
+    (setq calendar-week-start-day 1)
+
+    ; Display ISO week numbers in Calendar Mode
+    (copy-face font-lock-constant-face 'calendar-iso-week-face)
+    (set-face-attribute 'calendar-iso-week-face nil :height 0.7)
+    (setq calendar-intermonth-text
+          '(propertize
+            (format "%2d"
+                    (car
+                     (calendar-iso-from-absolute
+                      (calendar-absolute-from-gregorian (list month day year)))))
+            'font-lock-face 'calendar-iso-week-face))
+    (copy-face 'default 'calendar-iso-week-header-face)
+    (set-face-attribute 'calendar-iso-week-header-face nil :height 0.7)
+    (setq calendar-intermonth-header
+          (propertize "Wk"                  ; or e.g. "KW" in Germany
+                      'font-lock-face 'calendar-iso-week-header-face))))
 
-Display ISO week numbers in Calendar Mode
-#+BEGIN_SRC emacs-lisp :tangle yes
-(copy-face font-lock-constant-face 'calendar-iso-week-face)
-(set-face-attribute 'calendar-iso-week-face nil
-                    :height 0.7)
-(setq calendar-intermonth-text
-      '(propertize
-        (format "%2d"
-                (car
-                 (calendar-iso-from-absolute
-                  (calendar-absolute-from-gregorian (list month day year)))))
-        'font-lock-face 'calendar-iso-week-face))
-(copy-face 'default 'calendar-iso-week-header-face)
-(set-face-attribute 'calendar-iso-week-header-face nil
-                    :height 0.7)
-(setq calendar-intermonth-header
-      (propertize "Wk"                  ; or e.g. "KW" in Germany
-                  'font-lock-face 'calendar-iso-week-header-face))
 #+END_SRC
 
 ** crontab-mode
@@ -1425,6 +1424,7 @@ movement keys.
 (use-package dired
   :commands (dired dired-other-window dired-other-frame dired-noselect
                    dired-mode dired-jump)
+  :defines (dired-omit-regexp-orig)
   :init
   (progn
     (setq diredp-hide-details-initially-flag nil))
@@ -1581,6 +1581,7 @@ Discover key bindings and their meaning for the current Emacs major mode.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package discover-my-major
   :ensure discover-my-major
+  :commands discover-my-major
   :bind ("C-h C-m" . discover-my-major))
 #+END_SRC
 ** easypg
@@ -1630,8 +1631,7 @@ ediff - don't start another frame
   :config (progn
             (setq ediff-window-setup-function 'ediff-setup-windows-plain)
             (setq ediff-split-window-function 'split-window-horizontally)
-            (bind-key "j" 'ediff-next-difference ediff-mode-map)
-            (bind-key "k" 'ediff-previous-difference ediff-mode-map))
+            )
 )
 #+END_SRC
 ** emms
@@ -1809,7 +1809,8 @@ Proper whitespace handling
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package expand-region
   :ensure expand-region
-  :bind ("C-M-+" . er/expand-region))
+  :bind ("C-M-+" . er/expand-region)
+  :commands er/expand-region)
 #+END_SRC
 ** filladapt
 [2013-05-02 Thu 00:04]
@@ -1819,7 +1820,7 @@ bullet points like “1.” or “*”.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package filladapt
   :diminish filladapt-mode
-  :init
+  :idle
   (setq-default filladapt-mode t))
 #+END_SRC
 ** flycheck
@@ -1833,7 +1834,7 @@ understand for me.
   :diminish flycheck-mode
   :bind (("M-n" . next-error)
          ("M-p" . previous-error))
-  :init
+  :idle
   (progn
     (add-hook 'find-file-hook
           (lambda ()
@@ -1886,7 +1887,7 @@ And I want to have it everywhere.
          ("C-x s" . git-gutter+-stage-hunks)
          ("C-x c" . git-gutter+-commit)
          )
-  :init
+  :idle
   (progn
     (setq git-gutter+-disabled-modes '(org-mode))
     (global-git-gutter+-mode 1))
@@ -1921,7 +1922,8 @@ useful when you want to know why this line was changed.
 Browse historic versions of a file with p (previous) and n (next).
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package git-timemachine
-  :ensure git-timemachine)
+  :ensure git-timemachine
+  :commands git-timemachine)
 #+END_SRC
 ** gnus
 Most of my gnus config is in an own file, [[file:gnus.org][gnus.org]], here I only have
@@ -2004,6 +2006,7 @@ tries to expand it in various ways.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package hippie-exp
   :bind ("M-/" . hippie-expand)
+  :commands hippie-expand
   :config
   (progn
     (setq hippie-expand-try-functions-list '(try-expand-dabbrev
@@ -2112,8 +2115,19 @@ _l_ linum-mode:         % 4`linum-mode     _k_ linum relative:    %`linum-format
          ("<XF86WebCam>" . ibuffer)
          )
   :commands (ibuffer)
-  :init
+  :defines (ibuffer-filtering-alist
+            ibuffer-filter-groups ibuffer-compile-formats ibuffer-git-column-length
+            ibuffer-show-empty-filter-groups ibuffer-saved-filter-groups)
+  :config
   (progn
+    (defvar my-ibufffer-separator " • ")
+    (setq ibuffer-filter-group-name-face 'variable-pitch
+          ibuffer-use-header-line t
+          ibuffer-old-time 12)
+    (unbind-key "M-o" ibuffer-mode-map)
+    (bind-key "s" 'isearch-forward-regexp ibuffer-mode-map)
+    (bind-key "." 'ibuffer-invert-sorting ibuffer-mode-map)
+
     (use-package ibuffer-vc
       :ensure t
       :commands
@@ -2130,16 +2144,7 @@ _l_ linum-mode:         % 4`linum-mode     _k_ linum relative:    %`linum-format
         ad-do-it
         (ibuffer-update nil t)
         (unless (string= recent-buffer-name "*Ibuffer*")
-          (ibuffer-jump-to-buffer recent-buffer-name)))))
-  :config
-  (progn
-    (defvar my-ibufffer-separator " • ")
-    (setq ibuffer-filter-group-name-face 'variable-pitch
-          ibuffer-use-header-line t
-          ibuffer-old-time 12)
-    (unbind-key "M-o" ibuffer-mode-map)
-    (bind-key "s" 'isearch-forward-regexp ibuffer-mode-map)
-    (bind-key "." 'ibuffer-invert-sorting ibuffer-mode-map)
+          (ibuffer-jump-to-buffer recent-buffer-name))))
 
     (defun ibuffer-magit-status ()
       (interactive)
@@ -2426,7 +2431,7 @@ list of matching commands is echoed
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package info
   :bind ("C-h C-i" . info-lookup-symbol)
-
+  :commands info-lookup-symbol
   :config
   (progn
     ;; (defadvice info-setup (after load-info+ activate)
@@ -2464,14 +2469,19 @@ gnus, so we have a list of modes where we don't want to see it.
         ad-do-it))
 
     (ad-activate 'linum-on)
+
     (use-package linum-relative
-      :ensure linum-relative)
-    )
+      :ensure linum-relative
+      :init
+      (progn
+        (setq linum-format 'dynamic)
+        )))
   :init
   (global-linum-mode 1))
 #+END_SRC
 
 ** lisp editing stuff
+
 [2013-04-21 So 21:00]
 I'm not doing much of it, except for my emacs and gnus configs, but
 then I like it nice too...
@@ -2509,7 +2519,6 @@ then I like it nice too...
 (after "eldoc"
   '(diminish 'eldoc-mode))
 #+END_SRC
-
 ** magit
 [2013-04-21 So 20:48]
 magit is a mode for interacting with git.
@@ -2530,13 +2539,16 @@ magit is a mode for interacting with git.
                             )
           magit-repo-dirs-depth 4
           magit-log-auto-more t)
+
     (use-package magit-blame
-      :commands magit-blame-mode)
+      :commands magit-blame-mode
+      :defer t)
 
     (use-package magit-svn
       :ensure magit-svn
       :commands (magit-svn-mode
-                 turn-on-magit-svn))
+                 turn-on-magit-svn)
+      :defer t)
 
     (add-hook 'magit-mode-hook 'hl-line-mode)
     (defun magit-status-with-prefix ()
@@ -2588,8 +2600,10 @@ magit is a mode for interacting with git.
 #+END_SRC
 ** message
 #+BEGIN_SRC emacs-lisp :tangle yes
-(require 'message)
-(setq message-kill-buffer-on-exit t)
+(use-package message
+  :idle
+  (progn
+    (setq message-kill-buffer-on-exit t)))
 #+END_SRC
 ** mingus
 [[https://github.com/pft/mingus][Mingus]] is a nice interface to mpd, the Music Player Daemon.
@@ -2615,6 +2629,7 @@ Edit minibuffer in a full (text-mode) buffer by pressing *M-C-e*.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package miniedit
   :ensure miniedit
+  :commands miniedit
   :config
   (progn
     (bind-key "M-C-e" 'miniedit minibuffer-local-map)
@@ -2629,7 +2644,7 @@ Edit minibuffer in a full (text-mode) buffer by pressing *M-C-e*.
 [2013-05-21 Tue 23:39]
 MMM Mode is a minor mode for Emacs that allows Multiple Major Modes to
 coexist in one buffer.
-#+BEGIN_SRC emacs-lisp :tangle yes
+#+BEGIN_SRC emacs-lisp :tangle no
 (use-package mmm-auto
   :ensure mmm-mode
   :init
@@ -2668,7 +2683,6 @@ coexist in one buffer.
 ** mo-git-blame
 This is [[https://github.com/mbunkus/mo-git-blame][mo-git-blame -- An interactive, iterative 'git blame' mode for
 Emacs]].
-
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package mo-git-blame
   :ensure mo-git-blame
@@ -2691,6 +2705,10 @@ Use multiple cursors mode. See [[http://emacsrocks.com/e13.html][Emacs Rocks! mu
              mc/create-fake-cursor-at-point
              mc/pop-state-from-overlay
              mc/maybe-multiple-cursors-mode)
+  :defines (multiple-cursors-mode
+            mc--read-char
+            mc--read-quoted-char
+            rectangular-region-mode)
   :bind (("C-S-c C-S-c" . mc/edit-lines)
          ("C->"     . mc/mark-next-like-this)
          ("C-<"     . mc/mark-previous-like-this)
@@ -2716,7 +2734,7 @@ A emacs tree plugin
   :commands (neotree-find
              neotree-toggle
              neotree)
-  :init
+  :idle
   (progn
     (setq neo-smart-open t))
   :config
@@ -3816,7 +3834,7 @@ up here to be used.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package cperl-mode
   :commands cperl-mode
-  :init
+  :idle
   (progn
     (defalias 'perl-mode 'cperl-mode)
     (add-auto-mode 'cperl-mode "\\.\\([pP][Llm]\\|al\\)\\'")
@@ -3863,15 +3881,19 @@ up here to be used.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package puppet-mode
   :mode ("\\.pp\\'" . puppet-mode)
-  :config
-  (use-package puppet-ext
-  :init
+  :commands puppet-mode
+  :idle
   (progn
-    (bind-key "C-x ?" 'puppet-set-anchor puppet-mode-map)
-    (bind-key "C-c C-r" 'puppet-create-require puppet-mode-map)
     (defun my-puppet-mode-hook ()
       (setq require-final-newline nil))
-    (add-hook 'puppet-mode-hook 'my-puppet-mode-hook))))
+    (add-hook 'puppet-mode-hook 'my-puppet-mode-hook))
+  :config
+  (progn
+    (use-package puppet-ext
+      :init
+      (progn
+        (bind-key "C-x ?" 'puppet-set-anchor puppet-mode-map)
+        (bind-key "C-c C-r" 'puppet-create-require puppet-mode-map)))))
 #+END_SRC
 
 ** python
@@ -4036,6 +4058,7 @@ and tell which statements are at the same depth.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package rainbow-delimiters
   :ensure rainbow-delimiters
+  :commands rainbow-delimiters-mode
   :init
   (add-hook 'prog-mode-hook #'rainbow-delimiters-mode))
 #+END_SRC
@@ -4043,6 +4066,7 @@ and tell which statements are at the same depth.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package rainbow-mode
   :ensure rainbow-mode
+  :defer t
   :diminish rainbow-mode)
 #+END_SRC
 
@@ -4050,7 +4074,7 @@ and tell which statements are at the same depth.
 Saner regex syntax
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package re-builder
-  :command re-builder
+  :commands re-builder
   :defer t
   :config
   (setq reb-re-syntax 'string))
@@ -4295,6 +4319,15 @@ Settings for shell scripts
 (use-package sh-toggle
   :bind ("C-. C-z" . shell-toggle))
 #+END_SRC
+** smartscan
+[2015-02-24 Tue 23:35]
+Make =M-n= and =M-p= go forward/backword to the symbol at point.
+#+BEGIN_SRC emacs-lisp :tangle yes
+(use-package smartscan
+  :ensure smartscan
+  :defer t
+  :idle (global-smartscan-mode t))
+#+END_SRC
 ** timestamp
 By default, Emacs can update the time stamp for the following two
 formats if one exists in the first 8 lines of the file.
@@ -4303,7 +4336,7 @@ formats if one exists in the first 8 lines of the file.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package time-stamp
   :commands time-stamp
-  :init
+  :idle
   (progn
     (add-hook 'write-file-hooks 'time-stamp)
     (setq time-stamp-active t))
@@ -4374,26 +4407,23 @@ keeping the full power of emacs undo/redo.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package undo-tree
   :ensure undo-tree
+  :diminish undo-tree-mode
   :init
-  (global-undo-tree-mode)
-  :diminish undo-tree-mode)
-#+END_SRC
-
-Additionally I would like to keep the region active should I undo
-while I have one.
-
-#+BEGIN_SRC emacs-lisp :tangle yes
-;; Keep region when undoing in region
-(defadvice undo-tree-undo (around keep-region activate)
-  (if (use-region-p)
-      (let ((m (set-marker (make-marker) (mark)))
-            (p (set-marker (make-marker) (point))))
-        ad-do-it
-        (goto-char p)
-        (set-mark m)
-        (set-marker p nil)
-        (set-marker m nil))
-    ad-do-it))
+  (progn
+    (global-undo-tree-mode)
+    (setq undo-tree-visualizer-timestamps t)
+    (setq undo-tree-visualizer-diff t)
+    ;; Keep region when undoing in region
+    (defadvice undo-tree-undo (around keep-region activate)
+      (if (use-region-p)
+          (let ((m (set-marker (make-marker) (mark)))
+                (p (set-marker (make-marker) (point))))
+            ad-do-it
+            (goto-char p)
+            (set-mark m)
+            (set-marker p nil)
+            (set-marker m nil))
+        ad-do-it))))
 #+END_SRC
 ** uniquify
 Always have unique buffernames. See [[http://www.gnu.org/software/emacs/manual/html_node/emacs/Uniquify.html][Uniquify - GNU Emacs Manual]]
@@ -4435,10 +4465,22 @@ your operation actually changed in the buffer.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package volatile-highlights
   :ensure volatile-highlights
-  :init
+  :idle
   (volatile-highlights-mode t)
   :diminish volatile-highlights-mode)
 #+END_SRC
+** winner mode - undo and redo window configuration
+[2015-02-24 Tue 23:11]
+=winner-mode= lets you use =C-c <left>= and =C-c <right>= to switch between
+window configurations. This is handy when something has popped up a
+buffer that you want to look at briefly before returning to whatever
+you were working on. When you're done, press =C-c <left>=.
+#+BEGIN_SRC emacs-lisp :tangle yes
+(use-package winner
+  :ensure t
+  :defer t
+  :idle (winner-mode 1))
+#+END_SRC
 ** writegood
 This highlights some /weaselwords/, a mode to /aid in finding common
 writing problems/...
@@ -4455,6 +4497,7 @@ writing problems/...
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package web-mode
   :ensure web-mode
+  :defer t
   :mode (("\\.phtml\\'" . web-mode)
          ("\\.tpl\\.php\\'" . web-mode)
          ("\\.jsp\\'" . web-mode)
@@ -4476,8 +4519,14 @@ writing problems/...
                 (setq web-mode-enable-current-element-highlight t))))
   :config
   (progn
+    (setq web-mode-enable-current-element-highlight t)
+    (setq web-mode-ac-sources-alist
+          '(("css" . (ac-source-css-property))
+            ("html" . (ac-source-words-in-buffer ac-source-abbrev))))
     (use-package impatient-mode
-      :ensure impatient-mode))
+      :ensure impatient-mode
+      :defer t
+      :commands impatient-mode))
   )
 
 #+END_SRC
@@ -4499,7 +4548,6 @@ readable/editable without getting a big headache.
 #+BEGIN_SRC emacs-lisp :tangle yes
 (use-package yaml-mode
   :ensure yaml-mode
-
   :mode ("\\.ya?ml\\'" . yaml-mode)
   :config
     (bind-key "C-m" 'newline-and-indent yaml-mode-map ))
@@ -4513,12 +4561,17 @@ whatever the snippet holds.
 (setq yas-snippet-dirs (expand-file-name "yasnippet/snippets" jj-elisp-dir))
 (use-package yasnippet
   :ensure yasnippet
-  :init
+  :defer t
+  :diminish yas-minor-mode
+  :commands yas-global-mode
+  :idle
   (progn
-    (yas-global-mode 1)
     ;; Integrate hippie-expand with ya-snippet
     (add-to-list 'hippie-expand-try-functions-list
                  'yas-hippie-try-expand)
+    (yas-global-mode 1)
+    (setq yas-expand-only-for-last-commands '(self-insert-command))
+    (bind-key "\t" 'hippie-expand yas-minor-mode-map)
     ))
 #+END_SRC
 * Thats it
index 95dc0c8..fd14388 100644 (file)
@@ -1,4 +1,4 @@
-;;; bind-key --- A simple way to manage personal keybindings
+;;; bind-key.el --- A simple way to manage personal keybindings
 
 ;; Copyright (C) 2012 John Wiegley
 
@@ -6,7 +6,7 @@
 ;; Created: 16 Jun 2012
 ;; Version: 1.0
 ;; Keywords: keys keybinding config dotemacs
-;; X-URL: https://github.com/jwiegley/bind-key
+;; 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
@@ -41,7 +41,7 @@
 ;;
 ;;   (bind-key* "<C-return>" 'other-window)
 ;;
-;; If you want to rebind a key only in a particular key, use:
+;; If you want to rebind a key only in a particular keymap, use:
 ;;
 ;;   (bind-key "C-c x" 'my-ctrl-c-x-command some-other-mode-map)
 ;;
 ;;
 ;;   (unbind-key "C-c x" some-other-mode-map)
 ;;
+;; To bind multiple keys at once, or set up a prefix map, a
+;; `bind-keys' macro is provided.  It accepts keyword arguments, see
+;; its documentation for detailed description.
+;;
+;; To add keys into a specific map, use :map argument
+;;
+;;    (bind-keys :map dired-mode-map
+;;               ("o" . dired-omit-mode)
+;;               ("a" . some-custom-dired-function))
+;;
+;; To set up a prefix map, use :prefix-map and :prefix
+;; arguments (both are required)
+;;
+;;    (bind-keys :prefix-map my-customize-prefix-map
+;;               :prefix "C-c c"
+;;               ("f" . customize-face)
+;;               ("v" . customize-variable))
+;;
+;; You can combine all the keywords together.
+;; Additionally, :prefix-docstring can be specified to set
+;; documentation of created :prefix-map variable.
+;;
+;; To bind multiple keys in a `bind-key*' way (to be sure that your bindings
+;; will not be overridden by other modes), you may use `bind-keys*' macro:
+;;
+;;    (bind-keys*
+;;     ("C-o" . other-window)
+;;     ("C-M-n" . forward-page)
+;;     ("C-M-p" . backward-page))
+;;
 ;; After Emacs loads, you can see a summary of all your personal keybindings
 ;; currently in effect with this command:
 ;;
   "A simple way to manage personal keybindings"
   :group 'emacs)
 
+(defcustom bind-key-column-widths '(18 . 40)
+  "Width of columns in `describe-personal-keybindings'."
+  :type '(cons integer integer)
+  :group 'bind-key)
+
 (defcustom bind-key-segregation-regexp
   "\\`\\(\\(C-[chx] \\|M-[gso] \\)\\([CM]-\\)?\\|.+-\\)"
   "Regular expression used to divide key sets in the output from
   :type 'regexp
   :group 'bind-key)
 
+(defcustom bind-key-describe-special-forms nil
+  "If non-nil, extract docstrings from lambdas, closures and keymaps if possible."
+  :type 'boolean
+  :group 'bind-key)
+
 ;; Create override-global-mode to force key remappings
 
 (defvar override-global-map (make-keymap)
 (add-to-list 'emulation-mode-map-alists
              `((override-global-mode . ,override-global-map)))
 
-(add-hook 'after-init-hook
-          (function
-           (lambda ()
-             (override-global-mode 1))))
+(defvar personal-keybindings nil
+  "List of bindings performed by `bind-key'.
 
-(defvar personal-keybindings nil)
+Elements have the form ((KEY . [MAP]) CMD ORIGINAL-CMD)")
 
 (defmacro bind-key (key-name command &optional keymap)
+  "Bind KEY-NAME to COMMAND in KEYMAP (`global-map' if not passed).
+
+KEY-NAME may be a vector, in which case it is passed straight to
+`define-key'. Or it may be a string to be interpreted as
+spelled-out keystrokes, e.g., \"C-c C-z\". See documentation of
+`edmacro-mode' for details."
   (let ((namevar (make-symbol "name"))
         (keyvar (make-symbol "key"))
+        (kdescvar (make-symbol "kdesc"))
         (bindingvar (make-symbol "binding"))
         (entryvar (make-symbol "entry")))
-    `(let* ((,namevar ,(eval key-name))
-            (,keyvar (read-kbd-macro ,namevar))
+    `(let* ((,namevar ,key-name)
+            (,keyvar (if (vectorp ,namevar) ,namevar
+                       (read-kbd-macro ,namevar)))
+            (,kdescvar (cons (if (stringp ,namevar) ,namevar
+                               (key-description ,namevar))
+                             (quote ,keymap)))
             (,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))
+                                     ,keyvar))
+            (,entryvar (assoc ,kdescvar personal-keybindings)))
+       (when ,entryvar
+         (setq personal-keybindings
+               (delq ,entryvar personal-keybindings)))
+       (push (list ,kdescvar ,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 ,command)
      (define-key override-global-map ,(read-kbd-macro key-name) ,command)))
 
+(defmacro bind-keys (&rest args)
+  "Bind multiple keys at once.
+
+Accepts keyword arguments:
+:map - a keymap into which the keybindings should be added
+:prefix-map - name of the prefix map that should be created for
+              these bindings
+:prefix - prefix key for these bindings
+:prefix-docstring - docstring for the prefix-map variable
+:menu-name - optional menu string for prefix map
+
+The rest of the arguments are conses of keybinding string and a
+function symbol (unquoted)."
+  (let ((map (plist-get args :map))
+        (doc (plist-get args :prefix-docstring))
+        (prefix-map (plist-get args :prefix-map))
+        (prefix (plist-get args :prefix))
+        (menu-name (plist-get args :menu-name))
+        (key-bindings (progn
+                        (while (keywordp (car args))
+                          (pop args)
+                          (pop args))
+                        args)))
+    (when (or (and prefix-map
+                   (not prefix))
+              (and prefix
+                   (not prefix-map)))
+      (error "Both :prefix-map and :prefix must be supplied"))
+    (when (and menu-name (not prefix))
+      (error "If :menu-name is supplied, :prefix must be too"))
+    `(progn
+       ,@(when prefix-map
+           `((defvar ,prefix-map)
+             ,@(when doc `((put ',prefix-map 'variable-documentation ,doc)))
+             ,@(if menu-name
+                   `((define-prefix-command ',prefix-map nil ,menu-name))
+                   `((define-prefix-command ',prefix-map)))
+             (bind-key ,prefix ',prefix-map ,map)))
+       ,@(mapcar (lambda (form)
+                   `(bind-key ,(car form) ',(cdr form)
+                              ,(or prefix-map map)))
+                 key-bindings))))
+
+(defmacro bind-keys* (&rest args)
+  `(bind-keys :map override-global-map
+              ,@args))
+
 (defun get-binding-description (elem)
   (cond
    ((listp elem)
     (cond
      ((eq 'lambda (car elem))
-      "#<lambda>")
+      (if (and bind-key-describe-special-forms
+               (stringp (nth 2 elem)))
+          (nth 2 elem)
+        "#<lambda>"))
      ((eq 'closure (car elem))
-      "#<closure>")
+      (if (and bind-key-describe-special-forms
+               (stringp (nth 3 elem)))
+          (nth 3 elem)
+        "#<closure>"))
      ((eq 'keymap (car elem))
       "#<keymap>")
      (t
       elem)))
    ((keymapp elem)
-    "#<keymap>")
+    (if (and bind-key-describe-special-forms
+             (symbolp elem)
+             (get elem 'variable-documentation))
+        (format "%s" (get elem 'variable-documentation))
+      "#<keymap>"))
    ((symbolp elem)
     elem)
    (t
       (cons (string< (caar l) (caar r)) nil)))))
 
 (defun describe-personal-keybindings ()
+  "Display all the personal keybindings defined by `bind-key'."
   (interactive)
-  (with-current-buffer (get-buffer-create "*Personal Keybindings*")
-    (delete-region (point-min) (point-max))
-    (insert "Key name          Command                                 Comments
------------------ --------------------------------------- ---------------------
-")
+  (with-output-to-temp-buffer "*Personal Keybindings*"
+    (princ (format "Key name%s Command%s Comments\n%s %s ---------------------\n"
+                   (make-string (- (car bind-key-column-widths) 9) ? )
+                   (make-string (- (cdr bind-key-column-widths) 8) ? )
+                   (make-string (1- (car bind-key-column-widths)) ?-)
+                   (make-string (1- (cdr bind-key-column-widths)) ?-)))
     (let (last-binding)
       (dolist (binding
                (setq personal-keybindings
                      (sort personal-keybindings
-                           #'(lambda (l r)
-                               (car (compare-keybindings l r))))))
-
+                           (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 ?-)))
+            (princ (format "\n\n%s\n%s\n\n"
+                           (cdar binding)
+                           (make-string (+ 21 (car bind-key-column-widths) (cdr bind-key-column-widths)) ?-)))
           (if (and last-binding
                    (cdr (compare-keybindings last-binding binding)))
-              (insert ?\n)))
-
+              (princ "\n")))
+        
         (let* ((key-name (caar binding))
                (at-present (lookup-key (or (symbol-value (cdar binding))
                                            (current-global-map))
                                       (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))))
+          (let ((line
+                 (format
+                  (format "%%-%ds%%-%ds%%s\n" (car bind-key-column-widths) (cdr bind-key-column-widths))
+                  key-name (format "`%s\'" command-desc)
+                  (if (string= command-desc at-present-desc)
+                      (if (or (null was-command)
+                              (string= command-desc was-command-desc))
+                          ""
+                        (format "was `%s\'" was-command-desc))
+                    (format "[now: `%s\']" at-present)))))
+            (princ (if (string-match "[ \t]+\n" line)
+                       (replace-match "\n" t t line)
+                     line))))
+        
+        (setq last-binding binding)))))
 
 (provide 'bind-key)
 ;; Local Variables:
index 50fa4ed..28d8587 100644 (file)
@@ -1,4 +1,4 @@
-;;; use-package --- A use-package declaration for simplifying your .emacs
+;;; use-package.el --- A use-package declaration for simplifying your .emacs
 
 ;; Copyright (C) 2012 John Wiegley
 
 ;; 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 common 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.
-;;
-;; Similar to `:bind', you can use `:mode' and `:interpreter' to establish a
-;; deferred binding within `auto-mode-alist' and `interpreter-mode-alist'.
-;; The specifier to either keyword can be a single cons or a list:
-;;
-;;   (use-package python-mode
-;;     :mode ("\\.py$" . python-mode)
-;;     :interpreter ("python" . python-mode))
-;;
-;; If you aren't using `:commands', `:bind', `:mode', or `:interpreter' (all
-;; of which imply `:commands'), you can still defer loading with the `: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".
-;;
-;; Another similar option to `:init' is `:idle'. Like `:init' this always run,
-;; however, it does so when Emacs is idle at some time in the future after
-;; load. This is particularly useful for convienience minor modes which can be
-;; slow to load. For instance, in this case, I want Emacs to always use
-;; `global-pabbrev-mode'. `:commands' creates an appropriate autoload; `:idle'
-;; will run this command at some point in the future. If you start Emacs and
-;; beginning typing straight-away, loading will happen eventually.
-;;
-;; (use-package pabbrev
-;;   :commands global-pabbrev-mode
-;;   :idle (global-pabbrev-mode))
-;;
-;; Idle functions are run in the order in which they are evaluated. If you
-;; have many, it may take sometime for all to run. `use-package' will always
-;; tell you if there is an error in the form which can otherwise be difficult
-;; to debug. It may tell you about functions being eval'd, depending on the
-;; value of `use-package-verbose'. Other good candidates for `:idle' are
-;; `yasnippet', `auto-complete' and `autopair'.
-;;
-;; 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")))
-;;
-;; If your package needs a directory added to the `load-path' in order load,
-;; use `:load-path'.  It takes a string or a list of strings.  If the path is
-;; relative, it will be expanded within `user-emacs-directory':
-;;
-;;   (use-package ess-site
-;;     :disabled t
-;;     :load-path "site-lisp/ess/lisp/"
-;;     :commands R)
-;;
-;; 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
-;; either the minor mode symbol, a cons of the symbol and a replacement string,
-;; or just a replacement string in which case the minor mode symbol is guessed
-;; to be the package name with "-mode" at the end:
-;;
-;;   (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.
-;;
-;; * For el-get users
-;;
-;; You can use `use-package' as a way to create source definitions for el-get.
-;; All that's needed is to add a `:type' keyword to your declaration.  When
-;; this is present, certain keywords get translated to what el-get expects in
-;; the `el-get-sources' list:
-;;
-;;   :config   -> :after
-;;   :requires -> :depends
-;;
-;; A `:name' will be added also, if one is not provided explicitly, which will
-;; be the same as the name of the package.
-;;
-;; But why would you want to use `use-package' when you have el-get?  My
-;; answer is that I'd like to use el-get to install and update some packages,
-;; but I don't want it managing configuration.  Just loading el-get -- without
-;; call (el-get 'sync) -- takes a quarter second on my machine.  That's 25% of
-;; my load time!  `use-package' is designed for performance, so I only want to
-;; load el-get when it's time to install or update on of my used packages.
-;;
-;; Here is the `use-package' declaration I use for setting up el-get, but only
-;; when I want to install or update:
-;;
-;;   (defvar el-get-sources nil)
-;;
-;;   (use-package el-get
-;;     :commands (el-get
-;;                el-get-install
-;;                el-get-update
-;;                el-get-list-packages)
-;;     :config
-;;     (defun el-get-read-status-file ()
-;;       (mapcar #'(lambda (entry)
-;;                   (cons (plist-get entry :symbol)
-;;                         `(status "installed" recipe ,entry)))
-;;               el-get-sources)))
+;; Please see README.md from the same repository for documentation.
 \f
 ;;; Code:
 
 (require 'bytecomp)
 (require 'diminish nil t)
 
-(eval-when-compile
-  (require 'cl))
-
 (declare-function package-installed-p 'package)
-(declare-function el-get-read-recipe 'el-get)
 
 (defgroup use-package nil
   "A use-package declaration for simplifying your `.emacs'."
   :group 'startup)
 
-(defcustom use-package-verbose t
-  "Whether to report about loading and configuration details."
-  :type 'boolean
-  :group 'use-package)
+(defcustom use-package-verbose nil
+  "Whether to report about loading and configuration details.
 
-(defcustom use-package-debug nil
-  "Whether to report more information, mostly regarding el-get."
+If you customize this, then you should require the `use-package'
+feature in files that use one of the macros `use-package' or
+`use-package-with-elapsed-timer', even if these files only
+contain compiled expansions of the macros.  If you don't do so,
+then the expanded macros do their job silently."
   :type 'boolean
   :group 'use-package)
 
 (defcustom use-package-minimum-reported-time 0.01
-  "Minimal load time that will be reported"
+  "Minimal load time that will be reported.
+
+Note that `use-package-verbose' has to be set to t, for anything
+to be reported at all.
+
+If you customize this, then you should require the `use-package'
+feature in files that use one of the macros `use-package' or
+`use-package-with-elapsed-timer', even if these files only
+contain compiled expansions of the macros.  If you don't do so,
+then the expanded macros do their job silently."
+  :type 'number
+  :group 'use-package)
+
+(defcustom use-package-idle-interval 3
+  "Time to wait when using :idle in a `use-package' specification."
   :type 'number
   :group 'use-package)
 
-(defmacro with-elapsed-timer (text &rest forms)
-  `(let ((now ,(if use-package-verbose
-                   '(current-time))))
-     ,(if use-package-verbose
-          `(message "%s..." ,text))
-     (prog1
-         ,@forms
-       ,(when use-package-verbose
-          `(let ((elapsed
-                  (float-time (time-subtract (current-time) now))))
-             (if (> elapsed ,use-package-minimum-reported-time)
-                 (message "%s...done (%.3fs)" ,text elapsed)
-               (message "%s...done" ,text)))))))
-
-(put 'with-elapsed-timer 'lisp-indent-function 1)
-
-(defun use-package-discover-el-get-type (args)
-  (let* ((pkg-name (plist-get args :name))
-         (git-config  (expand-file-name
-                       (concat pkg-name "/.git/config")
-                       (if (boundp 'user-site-lisp-directory)
-                           user-site-lisp-directory
-                         user-emacs-directory))))
-
-    (catch 'found
-      ;; Look for a readable .git/config with at least one defined remote.
-      (if (file-readable-p git-config)
-          (with-temp-buffer
-            (insert-file-contents-literally git-config)
-            (while (re-search-forward "\\[remote" nil t)
-              (if (re-search-forward "url = \\(.+\\)"
-                                     (save-excursion
-                                       (re-search-forward "\\[remote" nil t)
-                                       (point)) t)
-                  (nconc args (list :type 'git
-                                    :url (match-string 1))))))))
-    args))
+(defmacro use-package-with-elapsed-timer (text &rest body)
+  (declare (indent 1))
+  (let ((nowvar (make-symbol "now")))
+    `(if (bound-and-true-p use-package-verbose)
+         (let ((,nowvar (current-time)))
+           (message "%s..." ,text)
+           (prog1 (progn ,@body)
+             (let ((elapsed
+                    (float-time (time-subtract (current-time) ,nowvar))))
+               (if (> elapsed
+                      (or (bound-and-true-p use-package-minimum-reported-time)
+                          "0.01"))
+                   (message "%s...done (%.3fs)" ,text elapsed)
+                 (message "%s...done" ,text)))))
+       ,@body)))
+
+(put 'use-package-with-elapsed-timer 'lisp-indent-function 1)
 
 (defvar use-package-idle-timer nil)
-(defvar use-package-idle-forms nil)
+(defvar use-package-idle-forms (make-hash-table))
 
 (defun use-package-start-idle-timer ()
   "Ensure that the idle timer is running."
   (unless use-package-idle-timer
     (setq use-package-idle-timer
           (run-with-idle-timer
-           3 t
+           use-package-idle-interval t
            'use-package-idle-eval))))
 
-(defun use-package-init-on-idle (form)
+(defun use-package-init-on-idle (form priority)
   "Add a new form to the idle queue."
   (use-package-start-idle-timer)
-  (if use-package-idle-forms
-      (add-to-list 'use-package-idle-forms
-                   form t)
-    (setq use-package-idle-forms (list form))))
+  (puthash priority
+           (append (gethash priority use-package-idle-forms)
+                   (list form))
+           use-package-idle-forms))
+
+(defun use-package-idle-priorities ()
+  "Get a list of all priorities in the idle queue.
+The list is sorted in the order forms should be run."
+  (let ((priorities nil))
+    (maphash (lambda (priority forms)
+               (setq priorities (cons priority priorities)))
+             use-package-idle-forms)
+    (sort priorities '<)))
+
+(defun use-package-idle-pop ()
+  "Pop the top-priority task from the idle queue.
+Return nil when the queue is empty."
+  (let* ((priority        (car (use-package-idle-priorities)))
+         (forms           (gethash priority use-package-idle-forms))
+         (first-form      (car forms))
+         (forms-remaining (cdr forms)))
+    (if forms-remaining
+        (puthash priority forms-remaining use-package-idle-forms)
+      (remhash priority use-package-idle-forms))
+    first-form))
 
 (defun use-package-idle-eval()
   "Start to eval idle-commands from the idle queue."
-  (let ((next (pop use-package-idle-forms)))
+  (let ((next (use-package-idle-pop)))
     (if next
         (progn
           (when use-package-verbose
               "Failure on use-package idle. Form: %s, Error: %s"
               next e)))
           ;; recurse after a bit
-          (when (sit-for 3)
+          (when (sit-for use-package-idle-interval)
             (use-package-idle-eval)))
       ;; finished (so far!)
       (cancel-timer use-package-idle-timer)
       (setq use-package-idle-timer nil))))
 
+(defun use-package-pin-package (package archive)
+  "Pin PACKAGE to ARCHIVE."
+  (unless (boundp 'package-pinned-packages)
+    (setq package-pinned-packages ()))
+  (let ((archive-symbol (if (symbolp archive) archive (intern archive)))
+        (archive-name   (if (stringp archive) archive (symbol-name archive))))
+    (if (use-package--archive-exists-p archive-symbol)
+        (add-to-list 'package-pinned-packages (cons package archive-name))
+      (error (message  "Archive '%s' requested for package '%s' is not available." archive-name package)))
+    (package-initialize t)))
+
+(defun use-package--archive-exists-p (archive)
+  "Check if a given ARCHIVE is enabled.
+
+ARCHIVE can be a string or a symbol or 'manual to indicate a manually updated package."
+  (if (member archive '(manual "manual"))
+      't
+    (let ((valid nil))
+      (dolist (pa package-archives)
+        (when (member archive (list (car pa) (intern (car pa))))
+          (setq valid 't)))
+      valid)))
+
 (defun use-package-ensure-elpa (package)
   (when (not (package-installed-p package))
     (package-install package)))
 
+(defvar use-package-keywords
+  '(
+    :bind
+    :bind*
+    :commands
+    :config
+    :defer
+    :defines
+    :demand
+    :diminish
+    :disabled
+    :ensure
+    :idle
+    :idle-priority
+    :if
+    :init
+    :interpreter
+    :load-path
+    :mode
+    :pin
+    :pre-init
+    :pre-load
+    :requires
+    :bind-keymap
+    :bind-keymap*
+    )
+  "Keywords recognized by `use-package'.")
+
+(defun use-package-mplist-get (plist prop)
+  "Get the values associated to PROP in PLIST, a modified plist.
+
+A modified plist is one where keys are keywords and values are
+all non-keywords elements that follow it.
+
+As a special case : if the first occurrence of the keyword PROP
+is followed by another keyword or is the last element in the
+list, the function returns t.
+
+Currently this function infloops when the list is circular."
+  (let ((tail plist)
+        found
+        result)
+    (while (and
+            (consp tail)
+            (not
+             (eq prop (car tail))))
+      (pop tail))
+    (when (eq prop (pop tail))
+      (setq found t))
+    (while (and (consp tail)
+                (not (keywordp (car tail))))
+      (push (pop tail) result))
+    (or (nreverse result) found)))
+
+(defun use-package-plist-get (plist prop &optional eval-backquote no-progn)
+  "Compatibility layer between classical and modified plists.
+
+If `use-package-mplist-get' returns exactly one value, that is
+returned ; otherwise the list is returned wrapped in a `progn'
+unless NO-PROGN is non-nil.
+
+When EVAL-BACKQUOTE is non-nil, the value is first evaluated as
+if it were backquoted."
+  (let ((values (use-package-mplist-get plist prop)))
+    (when eval-backquote
+      (setq values (eval (list 'backquote values))))
+    (when values
+      (cond ((not (listp values))
+             values)
+            ((eq 1 (length values))
+             (car values))
+            (t (if no-progn
+                   values
+                 (cons 'progn values)))))))
+
+(defun use-package-mplist-keys (plist)
+  "Get the keys in PLIST, a modified plist.
+
+A modified plist is one where properties are keywords and values
+are all non-keywords elements that follow it."
+  (let ((result))
+    (mapc (lambda (elt)
+            (when (keywordp elt)
+              (push elt result)))
+          plist)
+    (nreverse result)))
+
+(defun use-package-validate-keywords (args)
+  "Error if any keyword given in ARGS is not recognized.
+Return the list of recognized keywords."
+  (mapc
+   (function
+    (lambda (keyword)
+      (unless (memq keyword use-package-keywords)
+        (error "Unrecognized keyword: %s" keyword))))
+   (use-package-mplist-keys args)))
 
 (defmacro use-package (name &rest args)
-"Use a package with configuration options.
+  "Use a package with configuration options.
 
 For full documentation. please see commentary.
 
@@ -400,36 +291,63 @@ For full documentation. please see commentary.
 :init Code to run when `use-package' form evals.
 :bind Perform key bindings, and define autoload for bound
       commands.
+:bind* Perform key bindings, and define autoload for bound
+      commands, overriding all minor mode bindings.
+:bind-keymap Bind key prefix to an auto-loaded keymap that
+      is defined in the package.  Like bind but for keymaps
+      instead of commands.
+:bind-keymap* like bind-keymap, but overrides all minor mode bindings
 :commands Define autoloads for given commands.
+:pre-load Code to run when `use-package' form evals and before
+       anything else. Unlike :init this form runs before the
+       package is required or autoloads added.
 :mode Form to be added to `auto-mode-alist'.
 :interpreter Form to be added to `interpreter-mode-alist'.
 :defer Defer loading of package -- automatic
-       if :commands, :bind, :mode or :interpreter are used.
+       if :commands, :bind, :bind*, :mode or :interpreter are used.
+:demand Prevent deferred loading in all cases.
 :config Runs if and when package loads.
 :if Conditional loading.
 :disabled Ignore everything.
 :defines Define vars to silence byte-compiler.
 :load-path Add to `load-path' before loading.
 :diminish Support for diminish package (if it's installed).
-:idle adds a form to run on an idle timer"
-  (let* ((commands (plist-get args :commands))
-         (pre-init-body (plist-get args :pre-init))
-         (init-body (plist-get args :init))
-         (config-body (plist-get args :config))
-         (diminish-var (plist-get args :diminish))
-         (defines (plist-get args :defines))
-         (idle-body (plist-get args :idle))
-         (keybindings )
-         (mode-alist )
-         (interpreter-alist )
-         (predicate (plist-get args :if))
-         (pkg-load-path (plist-get args :load-path))
+:idle adds a form to run on an idle timer
+:idle-priority schedules the :idle form to run with the given
+       priority (lower priorities run first). Default priority
+       is 5; forms with the same priority are run in the order in
+       which they are evaluated.
+:ensure loads package using package.el if necessary.
+:pin pin package to archive."
+  (use-package-validate-keywords args) ; error if any bad keyword, ignore result
+  (let* ((commands (use-package-plist-get args :commands t t))
+         (pre-init-body (use-package-plist-get args :pre-init))
+         (pre-load-body (use-package-plist-get args :pre-load))
+         (init-body (use-package-plist-get args :init))
+         (config-body (use-package-plist-get args :config))
+         (diminish-var (use-package-plist-get args :diminish t))
+         (defines (use-package-plist-get args :defines t t))
+         (idle-body (use-package-plist-get args :idle))
+         (idle-priority (use-package-plist-get args :idle-priority))
+         (keybindings-alist (use-package-plist-get args :bind t t))
+         (overriding-keybindings-alist (use-package-plist-get args :bind* t t))
+         (keymap-alist (use-package-plist-get args :bind-keymap t t))
+         (overriding-keymap-alist (use-package-plist-get args :bind-keymap* t t))
+         (mode (use-package-plist-get args :mode t t))
+         (mode-alist
+          (if (stringp mode) (cons mode name) mode))
+         (interpreter (use-package-plist-get args :interpreter t t))
+         (interpreter-alist
+          (if (stringp interpreter) (cons interpreter name) interpreter))
+         (predicate (use-package-plist-get args :if))
+         (pkg-load-path (use-package-plist-get args :load-path t t))
+         (archive-name (use-package-plist-get args :pin))
          (defines-eval (if (null defines)
                            nil
                          (if (listp defines)
                              (mapcar (lambda (var) `(defvar ,var)) defines)
                            `((defvar ,defines)))))
-         (requires (plist-get args :requires))
+         (requires (use-package-plist-get args :requires t))
          (requires-test (if (null requires)
                             t
                           (if (listp requires)
@@ -440,8 +358,12 @@ For full documentation. please see commentary.
          (name-symbol (if (stringp name) (intern name) name)))
 
     ;; force this immediately -- one off cost
-    (unless (plist-get args :disabled)
-      (let* ((ensure (plist-get args :ensure))
+    (unless (use-package-plist-get args :disabled)
+
+      (when archive-name
+        (use-package-pin-package name archive-name))
+
+      (let* ((ensure (use-package-plist-get args :ensure))
              (package-name
               (or (and (eq ensure t)
                        name)
@@ -465,7 +387,7 @@ For full documentation. please see commentary.
                          `((diminish (quote ,diminish-var))))
                         ((and (consp diminish-var) (stringp (cdr diminish-var)))
                          `((diminish (quote ,(car diminish-var)) ,(cdr diminish-var))))
-                        (t ; list of symbols or (symbol . "string") pairs
+                        (t      ; list of symbols or (symbol . "string") pairs
                          (mapcar (lambda (var)
                                    (if (listp var)
                                        `(diminish (quote ,(car var)) ,(cdr var))
@@ -477,14 +399,16 @@ For full documentation. please see commentary.
 
 
       (when idle-body
+        (when (null idle-priority)
+          (setq idle-priority 5))
         (setq init-body
               `(progn
-                 (use-package-init-on-idle (lambda () ,idle-body))
-                   ,init-body)))
-
+                 (require 'use-package)
+                 (use-package-init-on-idle (lambda () ,idle-body) ,idle-priority)
+                 ,init-body)))
 
-      (let ((init-for-commands
-             (lambda (func sym-or-list)
+      (let ((init-for-commands-or-keymaps
+             (lambda (func sym-or-list &optional keymap)
                (let ((cons-list (if (and (consp sym-or-list)
                                          (stringp (car sym-or-list)))
                                     (list sym-or-list)
@@ -493,36 +417,66 @@ For full documentation. please see commentary.
                      (setq init-body
                            `(progn
                               ,init-body
-                              ,@(mapcar #'(lambda (elem)
-                                            (push (cdr elem) commands)
-                                            (funcall func elem))
+                              ,@(mapcar (lambda (elem)
+                                          (when (not keymap)
+                                              (push (cdr elem) commands))
+                                          (funcall func elem))
                                         cons-list))))))))
 
-        (funcall init-for-commands
-                 #'(lambda (binding)
-                     `(bind-key ,(car binding)
-                                (quote ,(cdr binding))))
-                 (plist-get args :bind))
-
-        (funcall init-for-commands
-                 #'(lambda (mode)
-                     `(add-to-list 'auto-mode-alist
-                                   (quote ,mode)))
-                 (plist-get args :mode))
-
-        (funcall init-for-commands
-                 #'(lambda (interpreter)
-                     `(add-to-list 'interpreter-mode-alist
-                                   (quote ,interpreter)))
-                 (plist-get args :interpreter)))
+        (funcall init-for-commands-or-keymaps
+                 (lambda (binding)
+                   `(bind-key ,(car binding)
+                              (lambda () (interactive)
+                                (use-package-autoload-keymap
+                                 (quote ,(cdr binding))
+                                 ,(if (stringp name) name `',name)
+                                 nil))))
+                 keymap-alist
+                 t)
+
+        (funcall init-for-commands-or-keymaps
+                 (lambda (binding)
+                   `(bind-key ,(car binding)
+                              (lambda () (interactive)
+                                (use-package-autoload-keymap
+                                 (quote ,(cdr binding))
+                                 ,(if (stringp name) name `',name)
+                                 t))))
+                 overriding-keymap-alist
+                 t)
+
+        (funcall init-for-commands-or-keymaps
+                 (lambda (binding)
+                   `(bind-key ,(car binding)
+                              (quote ,(cdr binding))))
+                 keybindings-alist)
+
+        (funcall init-for-commands-or-keymaps
+                 (lambda (binding)
+                   `(bind-key* ,(car binding)
+                               (quote ,(cdr binding))))
+                 overriding-keybindings-alist)
+
+        (funcall init-for-commands-or-keymaps
+                 (lambda (mode)
+                   `(add-to-list 'auto-mode-alist
+                                 (quote ,mode)))
+                 mode-alist)
+
+        (funcall init-for-commands-or-keymaps
+                 (lambda (interpreter)
+                   `(add-to-list 'interpreter-mode-alist
+                                 (quote ,interpreter)))
+                 interpreter-alist))
 
       `(progn
+         ,pre-load-body
          ,@(mapcar
-            #'(lambda (path)
-                `(add-to-list 'load-path
-                              ,(if (file-name-absolute-p path)
-                                   path
-                                 (expand-file-name path user-emacs-directory))))
+            (lambda (path)
+              `(add-to-list 'load-path
+                            ,(if (file-name-absolute-p path)
+                                 path
+                               (expand-file-name path user-emacs-directory))))
             (cond ((stringp pkg-load-path)
                    (list pkg-load-path))
                   ((functionp pkg-load-path)
@@ -530,54 +484,25 @@ For full documentation. please see commentary.
                   (t
                    pkg-load-path)))
 
-         (when byte-compile-current-file
-           ,@defines-eval
-           ,(if (stringp name)
-                `(load ,name t)
-              `(require ',name nil t)))
-
-         ,(when (boundp 'el-get-sources)
-            (require 'el-get)
-
-            (let ((recipe (ignore-errors
-                            (el-get-read-recipe name-symbol))))
-              (if (null recipe)
-                  (if use-package-debug
-                      (message "No el-get recipe found for package `%s'"
-                               name-symbol))
-                (setq args
-                      (mapcar #'(lambda (arg)
-                                  (cond
-                                   ((eq arg :config)
-                                    :after)
-                                   ((eq arg :requires)
-                                    :depends)
-                                   (t
-                                    arg)))
-                              args))
-
-                (nconc args (list :symbol (intern name-string)))
-
-                (let ((elem args))
-                  (while elem
-                    (unless (plist-get recipe (car elem))
-                      (plist-put recipe (car elem) (cadr elem)))
-                    (setq elem (cddr elem))))
-
-                (unless (plist-get recipe :name)
-                  (nconc recipe (list :name name-string)))
-
-                (unless (plist-get recipe :type)
-                  (setq recipe (use-package-discover-el-get-type recipe)))
-
-                (ignore
-                 (setq el-get-sources (cons recipe el-get-sources))))))
-
-         ,(if (or commands (plist-get args :defer))
+         (eval-when-compile
+           (when (bound-and-true-p byte-compile-current-file)
+             ,@defines-eval
+             (condition-case err
+                 ,(if (stringp name)
+                      `(load ,name t)
+                    `(require ',name nil t))
+               (error (message "Error requiring %s: %s" ',name err) nil))))
+
+         ,(if (and (or commands (use-package-plist-get args :defer)
+                       (use-package-plist-get args :bind-keymap)
+                       (use-package-plist-get args :bind-keymap*))
+                   (not (use-package-plist-get args :demand)))
               (let (form)
-                (mapc #'(lambda (command)
-                          (push `(autoload (function ,command)
-                                   ,name-string nil t) form))
+                (mapc (lambda (command)
+                   (push `(unless (fboundp (quote ,command))
+                            (autoload (function ,command)
+                              ,name-string nil t))
+                         form))
                       commands)
 
                 `(when ,(or predicate t)
@@ -585,17 +510,16 @@ For full documentation. please see commentary.
                    ,@form
                    ,init-body
                    ,(unless (null config-body)
-                      `(eval-after-load ,name-string
-                         (quote
-                           (if ,requires-test
-                               ,(macroexpand-all
-                                  `(with-elapsed-timer
-                                       ,(format "Configuring package %s" name-string)
-                                     ,config-body))))))
+                      `(eval-after-load ,(if (stringp name) name `',name)
+                         `(,(lambda ()
+                              (if ,requires-test
+                                  (use-package-with-elapsed-timer
+                                      ,(format "Configuring package %s" name-string)
+                                    ,config-body))))))
                    t))
             `(if (and ,(or predicate t)
                       ,requires-test)
-                 (with-elapsed-timer
+                 (use-package-with-elapsed-timer
                      ,(format "Loading package %s" name-string)
                    (if (not ,(if (stringp name)
                                  `(load ,name t)
@@ -606,12 +530,37 @@ For full documentation. please see commentary.
                      ,config-body
                      t))))))))
 
-(put 'use-package 'lisp-indent-function 1)
+(defun use-package-autoload-keymap (keymap-symbol package override)
+  "Loads PACKAGE and then binds the key sequence used to invoke this function to
+KEYMAP-SYMBOL.  It then simulates pressing the same key sequence a again, so
+that the next key pressed is routed to the newly loaded keymap.
+
+This function supports use-package's :bind-keymap keyword.  It works
+by binding the given key sequence to an invocation of this function for a
+particular keymap.  The keymap is expected to be defined by the package.  In
+this way, loading the package is deferred until the prefix key sequence is
+pressed."
+  (if (if (stringp package) (load package t) (require package nil t))
+      (if (and (boundp keymap-symbol) (keymapp (symbol-value keymap-symbol)))
+          (let ((key (key-description (this-command-keys-vector)))
+                (keymap (symbol-value keymap-symbol)))
+            (progn
+              (if override
+                  `(eval `(bind-key* ,key ,keymap)) ; eval form is necessary to avoid compiler error
+                (bind-key key keymap))
+              (setq unread-command-events
+                    (listify-key-sequence (this-command-keys-vector)))))
+        (error
+         "use-package: package %s failed to define keymap %s"
+         package keymap-symbol))
+    (error "Could not load package %s" package)))
+
+(put 'use-package 'lisp-indent-function 'defun)
 
 (defconst use-package-font-lock-keywords
-  '(("(\\(use-package\\)\\> *\\(\\sw+\\)?"
+  '(("(\\(use-package\\(?:-with-elapsed-timer\\)?\\)\\_>[ \t']*\\(\\(?:\\sw\\|\\s_\\)+\\)?"
      (1 font-lock-keyword-face)
-     (2 font-lock-constant-face))))
+     (2 font-lock-constant-face nil t))))
 
 (font-lock-add-keywords 'emacs-lisp-mode use-package-font-lock-keywords)