]> git.eshelyaron.com Git - emacs.git/commitdiff
README and other updates
authorJohn Wiegley <johnw@newartisans.com>
Sun, 17 Jun 2012 09:40:25 +0000 (04:40 -0500)
committerJohn Wiegley <johnw@newartisans.com>
Sun, 17 Jun 2012 09:40:25 +0000 (04:40 -0500)
lisp/use-package/bind-key.el [new file with mode: 0644]
lisp/use-package/use-package.el [new file with mode: 0644]

diff --git a/lisp/use-package/bind-key.el b/lisp/use-package/bind-key.el
new file mode 100644 (file)
index 0000000..75e3b12
--- /dev/null
@@ -0,0 +1,218 @@
+;;; 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
diff --git a/lisp/use-package/use-package.el b/lisp/use-package/use-package.el
new file mode 100644 (file)
index 0000000..5bd8df7
--- /dev/null
@@ -0,0 +1,322 @@
+;;; 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