1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-24 07:20:37 +00:00

README and other updates

This commit is contained in:
John Wiegley 2012-06-17 04:40:25 -05:00
commit 31ea42e15e
2 changed files with 540 additions and 0 deletions

View File

@ -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.
;;; 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

View File

@ -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.
;;; 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